Added new subscription details in add-subscription API

This commit is contained in:
ashutosh.nehete 2025-08-06 09:47:16 +05:30
parent 54bf49a005
commit c65d73ff87
2 changed files with 181 additions and 184 deletions

View File

@ -1,6 +1,4 @@
using Marco.Pms.Model.TenantModels; namespace Marco.Pms.Model.Dtos.Tenant
namespace Marco.Pms.Model.Dtos.Tenant
{ {
public class AddSubscriptionDto public class AddSubscriptionDto
{ {
@ -8,7 +6,6 @@ namespace Marco.Pms.Model.Dtos.Tenant
public Guid PlanId { get; set; } public Guid PlanId { get; set; }
public Guid CurrencyId { get; set; } public Guid CurrencyId { get; set; }
public double MaxUsers { get; set; } public double MaxUsers { get; set; }
public PLAN_FREQUENCY Frequency { get; set; }
public bool IsTrial { get; set; } = false; public bool IsTrial { get; set; } = false;
public bool AutoRenew { get; set; } = true; public bool AutoRenew { get; set; } = true;
} }

View File

@ -564,221 +564,221 @@ namespace Marco.Pms.Services.Controllers
#region =================================================================== Subscription APIs =================================================================== #region =================================================================== Subscription APIs ===================================================================
//[HttpPost("add-subscription")] [HttpPost("add-subscription")]
//public async Task<IActionResult> AddSubscriptionAsync(AddSubscriptionDto model) public async Task<IActionResult> AddSubscriptionAsync(AddSubscriptionDto model)
//{ {
// var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
// _logger.LogInfo("AddSubscription called by employee {EmployeeId} for Tenant {TenantId} and Plan {PlanId}", _logger.LogInfo("AddSubscription called by employee {EmployeeId} for Tenant {TenantId} and Plan {PlanId}",
// loggedInEmployee.Id, model.TenantId, model.PlanId); loggedInEmployee.Id, model.TenantId, model.PlanId);
// if (loggedInEmployee == null) if (loggedInEmployee == null)
// { {
// _logger.LogWarning("No logged-in employee found."); _logger.LogWarning("No logged-in employee found.");
// return Unauthorized(ApiResponse<object>.ErrorResponse("Unauthorized", "User must be logged in.", 401)); return Unauthorized(ApiResponse<object>.ErrorResponse("Unauthorized", "User must be logged in.", 401));
// } }
// await using var _context = await _dbContextFactory.CreateDbContextAsync(); await using var _context = await _dbContextFactory.CreateDbContextAsync();
// using var scope = _serviceScopeFactory.CreateScope(); using var scope = _serviceScopeFactory.CreateScope();
// var _permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>(); var _permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
// var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false; var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
// var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id); var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
// if (!hasPermission || !isRootUser) if (!hasPermission || !isRootUser)
// { {
// _logger.LogWarning("Permission denied: User {EmployeeId} attempted to add subscription without permission or root access.", _logger.LogWarning("Permission denied: User {EmployeeId} attempted to add subscription without permission or root access.",
// loggedInEmployee.Id); loggedInEmployee.Id);
// return StatusCode(403, return StatusCode(403,
// ApiResponse<object>.ErrorResponse("Access denied", ApiResponse<object>.ErrorResponse("Access denied",
// "User does not have the required permissions for this action.", 403)); "User does not have the required permissions for this action.", 403));
// } }
// var subscriptionPlan = await _context.SubscriptionPlans.FirstOrDefaultAsync(sp => sp.Id == model.PlanId); var subscriptionPlan = await _context.SubscriptionPlanDetails.Include(sp => sp.Plan).FirstOrDefaultAsync(sp => sp.Id == model.PlanId);
// var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.Id == model.TenantId); var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.Id == model.TenantId);
// if (tenant == null) if (tenant == null)
// { {
// _logger.LogWarning("Tenant {TenantId} not found in database", model.TenantId); _logger.LogWarning("Tenant {TenantId} not found in database", model.TenantId);
// return NotFound(ApiResponse<object>.ErrorResponse("Tenant not found", "Tenant not found", 404)); return NotFound(ApiResponse<object>.ErrorResponse("Tenant not found", "Tenant not found", 404));
// } }
// if (subscriptionPlan == null) if (subscriptionPlan == null)
// { {
// _logger.LogWarning("Subscription plan {PlanId} not found in database", model.PlanId); _logger.LogWarning("Subscription plan {PlanId} not found in database", model.PlanId);
// return NotFound(ApiResponse<object>.ErrorResponse("Subscription plan not found", "Subscription plan not found", 404)); return NotFound(ApiResponse<object>.ErrorResponse("Subscription plan not found", "Subscription plan not found", 404));
// } }
// await using var transaction = await _context.Database.BeginTransactionAsync(); await using var transaction = await _context.Database.BeginTransactionAsync();
// var utcNow = DateTime.UtcNow; var utcNow = DateTime.UtcNow;
// // Prepare subscription dates based on frequency // Prepare subscription dates based on frequency
// var endDate = model.Frequency switch var endDate = subscriptionPlan.Frequency switch
// { {
// PLAN_FREQUENCY.MONTHLY => utcNow.AddMonths(1), PLAN_FREQUENCY.MONTHLY => utcNow.AddMonths(1),
// PLAN_FREQUENCY.QUARTERLY => utcNow.AddMonths(3), PLAN_FREQUENCY.QUARTERLY => utcNow.AddMonths(3),
// PLAN_FREQUENCY.HALF_MONTHLY => utcNow.AddMonths(6), PLAN_FREQUENCY.HALF_MONTHLY => utcNow.AddMonths(6),
// PLAN_FREQUENCY.YEARLY => utcNow.AddMonths(12), PLAN_FREQUENCY.YEARLY => utcNow.AddMonths(12),
// _ => utcNow // default if unknown _ => utcNow // default if unknown
// }; };
// var tenantSubscription = new TenantSubscriptions var tenantSubscription = new TenantSubscriptions
// { {
// TenantId = model.TenantId, TenantId = model.TenantId,
// PlanId = model.PlanId, PlanId = model.PlanId,
// StatusId = activePlanStatus, StatusId = activePlanStatus,
// CreatedAt = utcNow, CreatedAt = utcNow,
// MaxUsers = model.MaxUsers, MaxUsers = model.MaxUsers,
// CreatedById = loggedInEmployee.Id, CreatedById = loggedInEmployee.Id,
// CurrencyId = model.CurrencyId, CurrencyId = model.CurrencyId,
// IsTrial = model.IsTrial, IsTrial = model.IsTrial,
// StartDate = utcNow, StartDate = utcNow,
// EndDate = endDate, EndDate = endDate,
// NextBillingDate = endDate, NextBillingDate = endDate,
// AutoRenew = model.AutoRenew AutoRenew = model.AutoRenew
// }; };
// _context.TenantSubscriptions.Add(tenantSubscription); _context.TenantSubscriptions.Add(tenantSubscription);
// try try
// { {
// await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
// _logger.LogInfo("Tenant subscription added successfully for Tenant {TenantId}, Plan {PlanId}", _logger.LogInfo("Tenant subscription added successfully for Tenant {TenantId}, Plan {PlanId}",
// model.TenantId, model.PlanId); model.TenantId, model.PlanId);
// } }
// catch (DbUpdateException dbEx) catch (DbUpdateException dbEx)
// { {
// _logger.LogError(dbEx, "Database exception while adding subscription plan to tenant {TenantId}", model.TenantId); _logger.LogError(dbEx, "Database exception while adding subscription plan to tenant {TenantId}", model.TenantId);
// return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal error occured", ExceptionMapper(dbEx), 500)); return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal error occured", ExceptionMapper(dbEx), 500));
// } }
// try try
// { {
// var features = await _featureDetailsHelper.GetFeatureDetails(subscriptionPlan.FeaturesId); var features = await _featureDetailsHelper.GetFeatureDetails(subscriptionPlan.FeaturesId);
// if (features == null) if (features == null)
// { {
// _logger.LogInfo("No features found for subscription plan {PlanId}", model.PlanId); _logger.LogInfo("No features found for subscription plan {PlanId}", model.PlanId);
// await transaction.CommitAsync(); await transaction.CommitAsync();
// return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant subscription successfully added", 200)); return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant subscription successfully added", 200));
// } }
// // Helper to get permissions for a module asynchronously // Helper to get permissions for a module asynchronously
// async Task<List<Guid>> GetPermissionsForModuleAsync(List<Guid>? featureIds) async Task<List<Guid>> GetPermissionsForModuleAsync(List<Guid>? featureIds)
// { {
// if (featureIds == null || featureIds.Count == 0) return new List<Guid>(); if (featureIds == null || featureIds.Count == 0) return new List<Guid>();
// await using var ctx = await _dbContextFactory.CreateDbContextAsync(); await using var ctx = await _dbContextFactory.CreateDbContextAsync();
// return await ctx.FeaturePermissions.AsNoTracking() return await ctx.FeaturePermissions.AsNoTracking()
// .Where(fp => featureIds.Contains(fp.FeatureId)) .Where(fp => featureIds.Contains(fp.FeatureId))
// .Select(fp => fp.Id) .Select(fp => fp.Id)
// .ToListAsync(); .ToListAsync();
// } }
// // Fetch permission tasks for all modules in parallel // Fetch permission tasks for all modules in parallel
// var projectPermissionTask = GetPermissionsForModuleAsync(features.Modules?.ProjectManagement?.FeatureId); var projectPermissionTask = GetPermissionsForModuleAsync(features.Modules?.ProjectManagement?.FeatureId);
// var attendancePermissionTask = GetPermissionsForModuleAsync(features.Modules?.Attendance?.FeatureId); var attendancePermissionTask = GetPermissionsForModuleAsync(features.Modules?.Attendance?.FeatureId);
// var directoryPermissionTask = GetPermissionsForModuleAsync(features.Modules?.Directory?.FeatureId); var directoryPermissionTask = GetPermissionsForModuleAsync(features.Modules?.Directory?.FeatureId);
// var expensePermissionTask = GetPermissionsForModuleAsync(features.Modules?.Expense?.FeatureId); var expensePermissionTask = GetPermissionsForModuleAsync(features.Modules?.Expense?.FeatureId);
// var employeePermissionTask = GetPermissionsForModuleAsync(new List<Guid> { EmployeeFeatureId }); var employeePermissionTask = GetPermissionsForModuleAsync(new List<Guid> { EmployeeFeatureId });
// await Task.WhenAll(projectPermissionTask, attendancePermissionTask, directoryPermissionTask, expensePermissionTask, employeePermissionTask); await Task.WhenAll(projectPermissionTask, attendancePermissionTask, directoryPermissionTask, expensePermissionTask, employeePermissionTask);
// var newPermissionIds = new List<Guid>(); var newPermissionIds = new List<Guid>();
// var deletePermissionIds = new List<Guid>(); var deletePermissionIds = new List<Guid>();
// // Add or remove permissions based on modules enabled status // Add or remove permissions based on modules enabled status
// void ProcessPermissions(bool? enabled, List<Guid> permissions) void ProcessPermissions(bool? enabled, List<Guid> permissions)
// { {
// if (enabled == true) if (enabled == true)
// newPermissionIds.AddRange(permissions); newPermissionIds.AddRange(permissions);
// else else
// deletePermissionIds.AddRange(permissions); deletePermissionIds.AddRange(permissions);
// } }
// ProcessPermissions(features.Modules?.ProjectManagement?.Enabled, projectPermissionTask.Result); ProcessPermissions(features.Modules?.ProjectManagement?.Enabled, projectPermissionTask.Result);
// ProcessPermissions(features.Modules?.Attendance?.Enabled, attendancePermissionTask.Result); ProcessPermissions(features.Modules?.Attendance?.Enabled, attendancePermissionTask.Result);
// ProcessPermissions(features.Modules?.Directory?.Enabled, directoryPermissionTask.Result); ProcessPermissions(features.Modules?.Directory?.Enabled, directoryPermissionTask.Result);
// ProcessPermissions(features.Modules?.Expense?.Enabled, expensePermissionTask.Result); ProcessPermissions(features.Modules?.Expense?.Enabled, expensePermissionTask.Result);
// newPermissionIds = newPermissionIds.Distinct().ToList(); newPermissionIds = newPermissionIds.Distinct().ToList();
// deletePermissionIds = deletePermissionIds.Distinct().ToList(); deletePermissionIds = deletePermissionIds.Distinct().ToList();
// // Get root employee and role for this tenant // Get root employee and role for this tenant
// var rootEmployee = await _context.Employees var rootEmployee = await _context.Employees
// .Include(e => e.ApplicationUser) .Include(e => e.ApplicationUser)
// .FirstOrDefaultAsync(e => e.ApplicationUser != null && (e.ApplicationUser.IsRootUser ?? false) && e.TenantId == model.TenantId); .FirstOrDefaultAsync(e => e.ApplicationUser != null && (e.ApplicationUser.IsRootUser ?? false) && e.TenantId == model.TenantId);
// if (rootEmployee == null) if (rootEmployee == null)
// { {
// _logger.LogWarning("Root employee not found for tenant {TenantId}", model.TenantId); _logger.LogWarning("Root employee not found for tenant {TenantId}", model.TenantId);
// await transaction.CommitAsync(); await transaction.CommitAsync();
// return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant subscription successfully added", 200)); return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant subscription successfully added", 200));
// } }
// var roleId = await _context.EmployeeRoleMappings var roleId = await _context.EmployeeRoleMappings
// .AsNoTracking() .AsNoTracking()
// .Where(er => er.EmployeeId == rootEmployee.Id && er.TenantId == model.TenantId) .Where(er => er.EmployeeId == rootEmployee.Id && er.TenantId == model.TenantId)
// .Select(er => er.RoleId) .Select(er => er.RoleId)
// .FirstOrDefaultAsync(); .FirstOrDefaultAsync();
// if (roleId == Guid.Empty) if (roleId == Guid.Empty)
// { {
// _logger.LogWarning("RoleId for root employee {EmployeeId} in tenant {TenantId} not found", rootEmployee.Id, model.TenantId); _logger.LogWarning("RoleId for root employee {EmployeeId} in tenant {TenantId} not found", rootEmployee.Id, model.TenantId);
// await transaction.CommitAsync(); await transaction.CommitAsync();
// return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant subscription successfully added", 200)); return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant subscription successfully added", 200));
// } }
// var oldRolePermissionMappings = await _context.RolePermissionMappings var oldRolePermissionMappings = await _context.RolePermissionMappings
// .Where(rp => rp.ApplicationRoleId == roleId) .Where(rp => rp.ApplicationRoleId == roleId)
// .ToListAsync(); .ToListAsync();
// var oldPermissionIds = oldRolePermissionMappings.Select(rp => rp.FeaturePermissionId).ToList(); var oldPermissionIds = oldRolePermissionMappings.Select(rp => rp.FeaturePermissionId).ToList();
// // Prevent accidentally deleting essential employee permissions // Prevent accidentally deleting essential employee permissions
// var permissionIdCount = oldPermissionIds.Count - deletePermissionIds.Count; var permissionIdCount = oldPermissionIds.Count - deletePermissionIds.Count;
// if (permissionIdCount <= 4 && deletePermissionIds.Any()) if (permissionIdCount <= 4 && deletePermissionIds.Any())
// { {
// var employeePermissionIds = employeePermissionTask.Result; var employeePermissionIds = employeePermissionTask.Result;
// deletePermissionIds = deletePermissionIds.Where(p => !employeePermissionIds.Contains(p)).ToList(); deletePermissionIds = deletePermissionIds.Where(p => !employeePermissionIds.Contains(p)).ToList();
// } }
// // Prepare mappings to delete and add // Prepare mappings to delete and add
// var deleteMappings = oldRolePermissionMappings.Where(rp => deletePermissionIds.Contains(rp.FeaturePermissionId)).ToList(); var deleteMappings = oldRolePermissionMappings.Where(rp => deletePermissionIds.Contains(rp.FeaturePermissionId)).ToList();
// var addRolePermissionMappings = newPermissionIds var addRolePermissionMappings = newPermissionIds
// .Where(p => !oldPermissionIds.Contains(p)) .Where(p => !oldPermissionIds.Contains(p))
// .Select(p => new RolePermissionMappings .Select(p => new RolePermissionMappings
// { {
// ApplicationRoleId = roleId, ApplicationRoleId = roleId,
// FeaturePermissionId = p FeaturePermissionId = p
// }) })
// .ToList(); .ToList();
// if (addRolePermissionMappings.Any()) if (addRolePermissionMappings.Any())
// { {
// _context.RolePermissionMappings.AddRange(addRolePermissionMappings); _context.RolePermissionMappings.AddRange(addRolePermissionMappings);
// _logger.LogInfo("Added {Count} new role permission mappings for role {RoleId}", addRolePermissionMappings.Count, roleId); _logger.LogInfo("Added {Count} new role permission mappings for role {RoleId}", addRolePermissionMappings.Count, roleId);
// } }
// if (deleteMappings.Any()) if (deleteMappings.Any())
// { {
// _context.RolePermissionMappings.RemoveRange(deleteMappings); _context.RolePermissionMappings.RemoveRange(deleteMappings);
// _logger.LogInfo("Removed {Count} role permission mappings for role {RoleId}", deleteMappings.Count, roleId); _logger.LogInfo("Removed {Count} role permission mappings for role {RoleId}", deleteMappings.Count, roleId);
// } }
// await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
// await transaction.CommitAsync(); await transaction.CommitAsync();
// _logger.LogInfo("Permissions updated successfully for tenant {TenantId} subscription", model.TenantId); _logger.LogInfo("Permissions updated successfully for tenant {TenantId} subscription", model.TenantId);
// return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant Subscription Successfully", 200)); return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant Subscription Successfully", 200));
// } }
// catch (Exception ex) catch (Exception ex)
// { {
// await transaction.RollbackAsync(); await transaction.RollbackAsync();
// _logger.LogError(ex, "Exception occurred while updating permissions for tenant {TenantId}", model.TenantId); _logger.LogError(ex, "Exception occurred while updating permissions for tenant {TenantId}", model.TenantId);
// return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal error occured", ExceptionMapper(ex), 500)); return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal error occured", ExceptionMapper(ex), 500));
// } }
//} }
//[HttpPut("update-subscription")] //[HttpPut("update-subscription")]
//public async Task<IActionResult> UpdateSubscriptionAsync(UpdateSubscriptionDto model) //public async Task<IActionResult> UpdateSubscriptionAsync(UpdateSubscriptionDto model)