Added the renew Subscription API
This commit is contained in:
parent
c3b93022fd
commit
ee48d7372a
8
Marco.Pms.Model/Dtos/Tenant/RenewSubscriptionDto.cs
Normal file
8
Marco.Pms.Model/Dtos/Tenant/RenewSubscriptionDto.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class RenewSubscriptionDto
|
||||
{
|
||||
public Guid PaymentDetailId { get; set; }
|
||||
public Guid PlanId { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1377,7 +1377,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
PlanId = model.PlanId,
|
||||
StatusId = activePlanStatus,
|
||||
CreatedAt = utcNow,
|
||||
MaxUsers = model.MaxUsers ?? (currentSubscription?.MaxUsers ?? subscriptionPlan.MaxUser),
|
||||
MaxUsers = subscriptionPlan.MaxUser,
|
||||
CreatedById = loggedInEmployee.Id,
|
||||
CurrencyId = model.CurrencyId,
|
||||
StartDate = utcNow,
|
||||
@ -1610,8 +1610,8 @@ namespace Marco.Pms.Services.Controllers
|
||||
{
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var _tenantService = scope.ServiceProvider.GetRequiredService<ITenantService>();
|
||||
var tenant = await _tenantService.CreateTenantAsync(model.TenantEnquireId, model.PaymentDetailId, model.PlanId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(tenant, "Tenant Registration Successfully", 201));
|
||||
var response = await _tenantService.CreateTenantAsync(model.TenantEnquireId, model.PaymentDetailId, model.PlanId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -1620,6 +1620,25 @@ namespace Marco.Pms.Services.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("renew/subscription")]
|
||||
public async Task<IActionResult> RenewSubscriptionAsync(RenewSubscriptionDto model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var _tenantService = scope.ServiceProvider.GetRequiredService<ITenantService>();
|
||||
var response = await _tenantService.RenewSubscriptionAsync(tenantId, loggedInEmployee.Id, model.PaymentDetailId, model.PlanId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occured while add renewing subscription");
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Error Occured while renewing subscription", "Error Occured while renewing subscription", 500));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Subscription Plan APIs ===================================================================
|
||||
|
||||
@ -5,5 +5,6 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
public interface ITenantService
|
||||
{
|
||||
Task<ApiResponse<object>> CreateTenantAsync(Guid enquireId, Guid paymentDetailId, Guid planId);
|
||||
Task<ApiResponse<object>> RenewSubscriptionAsync(Guid tenantId, Guid employeeId, Guid paymentDetailId, Guid planId);
|
||||
}
|
||||
}
|
||||
@ -14,11 +14,11 @@ using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.Tenant;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Net;
|
||||
using Tenant = Marco.Pms.Model.TenantModels.Tenant;
|
||||
|
||||
namespace Marco.Pms.Services.Service
|
||||
{
|
||||
@ -29,7 +29,6 @@ namespace Marco.Pms.Services.Service
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly UserHelper _userHelper;
|
||||
private readonly FeatureDetailsHelper _featureDetailsHelper;
|
||||
|
||||
private readonly static Guid projectActiveStatus = Guid.Parse("b74da4c2-d07e-46f2-9919-e75e49b12731");
|
||||
@ -47,7 +46,6 @@ namespace Marco.Pms.Services.Service
|
||||
ILoggingService logger,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
IMapper mapper,
|
||||
UserHelper userHelper,
|
||||
FeatureDetailsHelper featureDetailsHelper)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory ?? throw new ArgumentNullException(nameof(dbContextFactory));
|
||||
@ -55,7 +53,6 @@ namespace Marco.Pms.Services.Service
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
|
||||
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
|
||||
_userHelper = userHelper ?? throw new ArgumentNullException(nameof(userHelper));
|
||||
_featureDetailsHelper = featureDetailsHelper ?? throw new ArgumentNullException(nameof(featureDetailsHelper));
|
||||
}
|
||||
|
||||
@ -72,21 +69,15 @@ namespace Marco.Pms.Services.Service
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.TenantEnquires.FirstOrDefaultAsync(te => te.Id == enquireId);
|
||||
});
|
||||
var paymentDetailTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.PaymentDetails.FirstOrDefaultAsync(pd => pd.Id == paymentDetailId);
|
||||
});
|
||||
var subscriptionPlanTask = Task.Run(async () =>
|
||||
{
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await context.SubscriptionPlanDetails.Include(sp => sp.Plan).FirstOrDefaultAsync(sp => sp.Id == planId);
|
||||
});
|
||||
|
||||
await Task.WhenAll(tenantEnquireTask, paymentDetailTask, subscriptionPlanTask);
|
||||
await Task.WhenAll(tenantEnquireTask, subscriptionPlanTask);
|
||||
|
||||
var tenantEnquire = tenantEnquireTask.Result;
|
||||
var paymentDetail = paymentDetailTask.Result;
|
||||
var subscriptionPlan = subscriptionPlanTask.Result;
|
||||
|
||||
if (tenantEnquire == null)
|
||||
@ -94,11 +85,6 @@ namespace Marco.Pms.Services.Service
|
||||
_logger.LogWarning("Tenant Enquire {TenantEnquireId} not found in database", enquireId);
|
||||
return ApiResponse<object>.ErrorResponse("Tenant Enquire not found", "Tenant Enquire not found", 404);
|
||||
}
|
||||
if (paymentDetail == null)
|
||||
{
|
||||
_logger.LogWarning("Payment Details {PaymentDetailsId} not found in database", paymentDetailId);
|
||||
return ApiResponse<object>.ErrorResponse("Payment Details not found", "Payment Details not found", 404);
|
||||
}
|
||||
if (subscriptionPlan == null)
|
||||
{
|
||||
_logger.LogWarning("Subscription plan {PlanId} not found in database", planId);
|
||||
@ -333,7 +319,6 @@ namespace Marco.Pms.Services.Service
|
||||
return ApiResponse<object>.ErrorResponse("An unexpected internal error occurred.", ExceptionMapper(ex), 500);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse<object>> AddSubscriptionAsync(Guid tenantId, Guid employeeId, Guid paymentDetailId, Guid planId)
|
||||
{
|
||||
|
||||
@ -342,7 +327,12 @@ namespace Marco.Pms.Services.Service
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
|
||||
var subscriptionPlan = await _context.SubscriptionPlanDetails.Include(sp => sp.Plan).FirstOrDefaultAsync(sp => sp.Id == planId);
|
||||
var paymentDetail = await _context.PaymentDetails.FirstOrDefaultAsync(pd => pd.Id == paymentDetailId);
|
||||
if (paymentDetail == null)
|
||||
{
|
||||
_logger.LogWarning("Payment Details {PaymentDetailsId} not found in database", paymentDetailId);
|
||||
return ApiResponse<object>.ErrorResponse("Payment Details not found", "Payment Details not found", 404);
|
||||
}
|
||||
|
||||
var tenant = await _context.Tenants.FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||
if (tenant == null)
|
||||
@ -350,6 +340,8 @@ namespace Marco.Pms.Services.Service
|
||||
_logger.LogWarning("Tenant {TenantId} not found in database", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Tenant not found", "Tenant not found", 404);
|
||||
}
|
||||
|
||||
var subscriptionPlan = await _context.SubscriptionPlanDetails.Include(sp => sp.Plan).FirstOrDefaultAsync(sp => sp.Id == planId);
|
||||
if (subscriptionPlan == null)
|
||||
{
|
||||
_logger.LogWarning("Subscription plan {PlanId} not found in database", planId);
|
||||
@ -554,6 +546,318 @@ namespace Marco.Pms.Services.Service
|
||||
return ApiResponse<object>.ErrorResponse("Internal error occured", ExceptionMapper(ex), 500);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> RenewSubscriptionAsync(Guid tenantId, Guid employeeId, Guid paymentDetailId, Guid planId)
|
||||
{
|
||||
// 2. Create a new DbContext instance for this request.
|
||||
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
// 3. Get PermissionServices from DI inside a fresh scope (rarely needed, but retained for your design).
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||
var _updateLogHelper = scope.ServiceProvider.GetRequiredService<UtilityMongoDBHelper>();
|
||||
|
||||
// 4. Check user permissions: must be both Root user and have ManageTenants permission.
|
||||
var hasPermission = await permissionService.HasPermission(PermissionsMaster.ManageTenants, employeeId);
|
||||
|
||||
if (!hasPermission)
|
||||
{
|
||||
_logger.LogWarning("Permission denied for EmployeeId={EmployeeId}. HasPermission: {HasPermission}",
|
||||
employeeId, hasPermission);
|
||||
return ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions.", 403);
|
||||
}
|
||||
|
||||
// 5. Fetch Tenant, SubscriptionPlan, and TenantSubscription in parallel (efficiently).
|
||||
var tenantTask = _dbContextFactory.CreateDbContextAsync().ContinueWith(ctx =>
|
||||
ctx.Result.Tenants.AsNoTracking().FirstOrDefaultAsync(t => t.Id == tenantId)).Unwrap();
|
||||
|
||||
var planDetailsTask = _dbContextFactory.CreateDbContextAsync().ContinueWith(ctx =>
|
||||
ctx.Result.SubscriptionPlanDetails.Include(sp => sp.Plan).AsNoTracking().FirstOrDefaultAsync(sp => sp.Id == planId)).Unwrap();
|
||||
|
||||
var currentSubscriptionTask = _dbContextFactory.CreateDbContextAsync().ContinueWith(ctx =>
|
||||
ctx.Result.TenantSubscriptions.Include(ts => ts.Currency).AsNoTracking().FirstOrDefaultAsync(ts => ts.TenantId == tenantId && !ts.IsCancelled)).Unwrap();
|
||||
|
||||
var paymentDetailsTask = _dbContextFactory.CreateDbContextAsync().ContinueWith(ctx =>
|
||||
ctx.Result.PaymentDetails.AsNoTracking().FirstOrDefaultAsync(pd => pd.Id == paymentDetailId)).Unwrap();
|
||||
|
||||
|
||||
await Task.WhenAll(tenantTask, planDetailsTask, currentSubscriptionTask, paymentDetailsTask);
|
||||
|
||||
var tenant = tenantTask.Result;
|
||||
if (tenant == null)
|
||||
{
|
||||
_logger.LogWarning("Tenant {TenantId} not found.", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Tenant not found", "Tenant not found", 404);
|
||||
}
|
||||
|
||||
var subscriptionPlan = planDetailsTask.Result;
|
||||
if (subscriptionPlan == null)
|
||||
{
|
||||
_logger.LogWarning("Subscription plan {PlanId} not found.", planId);
|
||||
return ApiResponse<object>.ErrorResponse("Subscription plan not found", "Subscription plan not found", 404);
|
||||
}
|
||||
|
||||
var paymentDetail = paymentDetailsTask.Result;
|
||||
if (paymentDetail == null)
|
||||
{
|
||||
_logger.LogWarning("Payment details {PaymentDetailId} not found", paymentDetailId);
|
||||
return ApiResponse<object>.ErrorResponse("Payment details not found", "Payment details not found", 404);
|
||||
}
|
||||
|
||||
var currentSubscription = currentSubscriptionTask.Result;
|
||||
var utcNow = DateTime.UtcNow;
|
||||
|
||||
var activeUsers = await context.Employees.CountAsync(e => e.Email != null && e.ApplicationUserId != null && e.TenantId == tenant.Id && e.IsActive);
|
||||
if (activeUsers > subscriptionPlan.MaxUser)
|
||||
{
|
||||
_logger.LogWarning("Employee {EmployeeId} add less max user than the active user in the tenant {TenantId}", employeeId, tenant.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Invalid Max user count", "Max User count must be higher than active user count", 400);
|
||||
}
|
||||
|
||||
// 7. Else, change plan: new subscription record, close the old if exists.
|
||||
await using var transaction = await context.Database.BeginTransactionAsync();
|
||||
try
|
||||
{
|
||||
// 7a. Compute new plan dates
|
||||
var endDate = subscriptionPlan.Frequency switch
|
||||
{
|
||||
PLAN_FREQUENCY.MONTHLY => utcNow.AddDays(30),
|
||||
PLAN_FREQUENCY.QUARTERLY => utcNow.AddDays(90),
|
||||
PLAN_FREQUENCY.HALF_YEARLY => utcNow.AddDays(120),
|
||||
PLAN_FREQUENCY.YEARLY => utcNow.AddDays(360),
|
||||
_ => utcNow // default if unknown
|
||||
};
|
||||
|
||||
var newSubscription = new TenantSubscriptions
|
||||
{
|
||||
TenantId = tenantId,
|
||||
PlanId = planId,
|
||||
StatusId = activePlanStatus,
|
||||
CreatedAt = utcNow,
|
||||
MaxUsers = subscriptionPlan.MaxUser,
|
||||
CreatedById = employeeId,
|
||||
CurrencyId = subscriptionPlan.CurrencyId,
|
||||
PaymentDetailId = paymentDetailId,
|
||||
StartDate = utcNow,
|
||||
EndDate = endDate,
|
||||
NextBillingDate = endDate,
|
||||
IsTrial = currentSubscription?.IsTrial ?? false,
|
||||
AutoRenew = currentSubscription?.AutoRenew ?? false
|
||||
};
|
||||
context.TenantSubscriptions.Add(newSubscription);
|
||||
|
||||
// 7b. If an old subscription exists, cancel it.
|
||||
if (currentSubscription != null)
|
||||
{
|
||||
currentSubscription.IsCancelled = true;
|
||||
currentSubscription.CancellationDate = utcNow;
|
||||
currentSubscription.UpdateAt = utcNow;
|
||||
currentSubscription.UpdatedById = employeeId;
|
||||
context.TenantSubscriptions.Update(currentSubscription);
|
||||
}
|
||||
await context.SaveChangesAsync();
|
||||
_logger.LogInfo("Subscription plan changed: Tenant={TenantId}, NewPlan={PlanId}",
|
||||
tenantId, planId);
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await ClearPermissionForTenant(tenantId);
|
||||
});
|
||||
|
||||
// 8. Update tenant permissions based on subscription features.
|
||||
var features = await _featureDetailsHelper.GetFeatureDetails(subscriptionPlan.FeaturesId);
|
||||
if (features == null)
|
||||
{
|
||||
_logger.LogInfo("No features for Plan={PlanId}.", planId);
|
||||
await transaction.CommitAsync();
|
||||
return ApiResponse<object>.SuccessResponse(newSubscription, "Tenant subscription updated (no features)", 200);
|
||||
}
|
||||
|
||||
// 8a. Async helper to get all permission IDs for a given module.
|
||||
async Task<List<Guid>> GetPermissionsForFeaturesAsync(List<Guid>? featureIds)
|
||||
{
|
||||
if (featureIds == null || featureIds.Count == 0) return new List<Guid>();
|
||||
|
||||
await using var ctx = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await ctx.FeaturePermissions.AsNoTracking()
|
||||
.Where(fp => featureIds.Contains(fp.FeatureId))
|
||||
.Select(fp => fp.Id)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
// 8b. Fetch all module permissions concurrently.
|
||||
var projectPermTask = GetPermissionsForFeaturesAsync(features.Modules?.ProjectManagement?.FeatureId);
|
||||
var attendancePermTask = GetPermissionsForFeaturesAsync(features.Modules?.Attendance?.FeatureId);
|
||||
var directoryPermTask = GetPermissionsForFeaturesAsync(features.Modules?.Directory?.FeatureId);
|
||||
var expensePermTask = GetPermissionsForFeaturesAsync(features.Modules?.Expense?.FeatureId);
|
||||
var employeePermTask = GetPermissionsForFeaturesAsync(new List<Guid> { EmployeeFeatureId }); // assumed defined
|
||||
|
||||
await Task.WhenAll(projectPermTask, attendancePermTask, directoryPermTask, expensePermTask, employeePermTask);
|
||||
|
||||
// 8c. Find root employee & role for this tenant.
|
||||
var rootEmployee = await context.Employees
|
||||
.Include(e => e.ApplicationUser)
|
||||
.FirstOrDefaultAsync(e => e.ApplicationUser != null && (e.ApplicationUser.IsRootUser ?? false) && e.TenantId == tenantId);
|
||||
|
||||
if (rootEmployee == null)
|
||||
{
|
||||
_logger.LogWarning("No root employee for Tenant={TenantId}.", tenantId);
|
||||
await transaction.CommitAsync();
|
||||
return ApiResponse<object>.SuccessResponse(newSubscription, "Tenant subscription updated (no root employee)", 200);
|
||||
}
|
||||
|
||||
var rootRoleId = await context.EmployeeRoleMappings
|
||||
.AsNoTracking()
|
||||
.Where(er => er.EmployeeId == rootEmployee.Id && er.TenantId == tenantId)
|
||||
.Select(er => er.RoleId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (rootRoleId == Guid.Empty)
|
||||
{
|
||||
_logger.LogWarning("No root role for Employee={EmployeeId}, Tenant={TenantId}.", rootEmployee.Id, tenantId);
|
||||
await transaction.CommitAsync();
|
||||
return ApiResponse<object>.SuccessResponse(newSubscription, "Tenant subscription updated (no root role)", 200);
|
||||
}
|
||||
|
||||
var dbOldRolePerms = await context.RolePermissionMappings.Where(x => x.ApplicationRoleId == rootRoleId).ToListAsync();
|
||||
var oldPermIds = dbOldRolePerms.Select(rp => rp.FeaturePermissionId).ToList();
|
||||
|
||||
// 8d. Prepare add and remove permission lists.
|
||||
var newPermissionIds = new List<Guid>();
|
||||
var revokePermissionIds = new List<Guid>();
|
||||
var employeePerms = employeePermTask.Result;
|
||||
var isOldEmployeePermissionIdExist = oldPermIds.Any(fp => employeePerms.Contains(fp));
|
||||
|
||||
void ProcessPerms(bool? enabled, List<Guid> ids)
|
||||
{
|
||||
var isOldPermissionIdExist = oldPermIds.Any(fp => ids.Contains(fp) && !employeePerms.Contains(fp));
|
||||
|
||||
if (enabled == true && !isOldPermissionIdExist) newPermissionIds.AddRange(ids);
|
||||
if (enabled == true && !isOldEmployeePermissionIdExist) newPermissionIds.AddRange(ids);
|
||||
if (enabled == false && isOldPermissionIdExist)
|
||||
revokePermissionIds.AddRange(ids);
|
||||
}
|
||||
ProcessPerms(features.Modules?.ProjectManagement?.Enabled, projectPermTask.Result);
|
||||
ProcessPerms(features.Modules?.Attendance?.Enabled, attendancePermTask.Result);
|
||||
ProcessPerms(features.Modules?.Directory?.Enabled, directoryPermTask.Result);
|
||||
ProcessPerms(features.Modules?.Expense?.Enabled, expensePermTask.Result);
|
||||
|
||||
newPermissionIds = newPermissionIds.Distinct().ToList();
|
||||
revokePermissionIds = revokePermissionIds.Distinct().ToList();
|
||||
|
||||
|
||||
// 8e. Prevent accidental loss of basic employee permissions.
|
||||
if ((features.Modules?.ProjectManagement?.Enabled == true ||
|
||||
features.Modules?.Attendance?.Enabled == true ||
|
||||
features.Modules?.Directory?.Enabled == true ||
|
||||
features.Modules?.Expense?.Enabled == true) && isOldEmployeePermissionIdExist)
|
||||
{
|
||||
revokePermissionIds = revokePermissionIds.Where(pid => !employeePerms.Contains(pid)).ToList();
|
||||
}
|
||||
|
||||
// 8f. Prepare permission-mapping records to add/remove.
|
||||
var mappingsToRemove = dbOldRolePerms.Where(rp => revokePermissionIds.Contains(rp.FeaturePermissionId)).ToList();
|
||||
var mappingsToAdd = newPermissionIds
|
||||
.Where(pid => !oldPermIds.Contains(pid))
|
||||
.Select(pid => new RolePermissionMappings { ApplicationRoleId = rootRoleId, FeaturePermissionId = pid })
|
||||
.ToList();
|
||||
|
||||
if (mappingsToAdd.Any())
|
||||
{
|
||||
context.RolePermissionMappings.AddRange(mappingsToAdd);
|
||||
_logger.LogInfo("Permissions granted: {Count} for Role={RoleId}", mappingsToAdd.Count, rootRoleId);
|
||||
}
|
||||
if (mappingsToRemove.Any())
|
||||
{
|
||||
context.RolePermissionMappings.RemoveRange(mappingsToRemove);
|
||||
_logger.LogInfo("Permissions revoked: {Count} for Role={RoleId}", mappingsToRemove.Count, rootRoleId);
|
||||
}
|
||||
|
||||
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||
await _cache.ClearAllEmployeesFromCacheByTenantId(tenant.Id);
|
||||
|
||||
var _masteData = scope.ServiceProvider.GetRequiredService<MasterDataService>();
|
||||
|
||||
if (features.Modules?.ProjectManagement?.Enabled ?? false)
|
||||
{
|
||||
var workCategoryMaster = _masteData.GetWorkCategoriesData(tenant.Id);
|
||||
var workStatusMaster = _masteData.GetWorkStatusesData(tenant.Id);
|
||||
|
||||
var workCategoryTask = Task.Run(async () =>
|
||||
{
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await _context.WorkCategoryMasters.AnyAsync(wc => wc.IsSystem && wc.TenantId == tenant.Id);
|
||||
});
|
||||
var workStatusTask = Task.Run(async () =>
|
||||
{
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
return await _context.WorkStatusMasters.AnyAsync(ws => ws.IsSystem && ws.TenantId == tenant.Id);
|
||||
});
|
||||
|
||||
await Task.WhenAll(workCategoryTask, workStatusTask);
|
||||
|
||||
var workCategoryExist = workCategoryTask.Result;
|
||||
var workStatusExist = workStatusTask.Result;
|
||||
if (!workCategoryExist)
|
||||
{
|
||||
context.WorkCategoryMasters.AddRange(workCategoryMaster);
|
||||
}
|
||||
if (!workStatusExist)
|
||||
{
|
||||
context.WorkStatusMasters.AddRange(workStatusMaster);
|
||||
}
|
||||
}
|
||||
if (features.Modules?.Expense?.Enabled ?? false)
|
||||
{
|
||||
var expensesTypeMaster = _masteData.GetExpensesTypeesData(tenant.Id);
|
||||
var paymentModeMatser = _masteData.GetPaymentModesData(tenant.Id);
|
||||
|
||||
var expensesTypeTask = Task.Run(async () =>
|
||||
{
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
var expensesTypeNames = expensesTypeMaster.Select(et => et.Name).ToList();
|
||||
return await _context.ExpensesTypeMaster.AnyAsync(et => expensesTypeNames.Contains(et.Name) && et.TenantId == tenant.Id);
|
||||
});
|
||||
var paymentModeTask = Task.Run(async () =>
|
||||
{
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
var paymentModeNames = paymentModeMatser.Select(py => py.Name).ToList();
|
||||
return await _context.PaymentModeMatser.AnyAsync(py => paymentModeNames.Contains(py.Name) && py.TenantId == tenant.Id);
|
||||
});
|
||||
|
||||
await Task.WhenAll(expensesTypeTask, paymentModeTask);
|
||||
|
||||
var expensesTypeExist = expensesTypeTask.Result;
|
||||
var paymentModeExist = paymentModeTask.Result;
|
||||
if (!expensesTypeExist)
|
||||
{
|
||||
context.ExpensesTypeMaster.AddRange(expensesTypeMaster);
|
||||
}
|
||||
if (!paymentModeExist)
|
||||
{
|
||||
context.PaymentModeMatser.AddRange(paymentModeMatser);
|
||||
}
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
|
||||
_logger.LogInfo("Tenant subscription and permissions updated: Tenant={TenantId}", tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(newSubscription, "Tenant subscription successfully updated", 200);
|
||||
}
|
||||
catch (DbUpdateException dbEx)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
_logger.LogError(dbEx, "Database exception updating subscription for TenantId={TenantId}", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Internal database error", ExceptionMapper(dbEx), 500);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
_logger.LogError(ex, "General exception for TenantId={TenantId}", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Internal error occurred", ExceptionMapper(ex), 500);
|
||||
}
|
||||
}
|
||||
|
||||
#region =================================================================== Helper Functions ===================================================================
|
||||
private static object ExceptionMapper(Exception ex)
|
||||
@ -677,6 +981,19 @@ namespace Marco.Pms.Services.Service
|
||||
return ApiResponse<SubscriptionPlanVM>.SuccessResponse(VM, "Success", 200);
|
||||
}
|
||||
|
||||
private async Task ClearPermissionForTenant(Guid tenantId)
|
||||
{
|
||||
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
|
||||
var _cache = scope.ServiceProvider.GetRequiredService<CacheUpdateHelper>();
|
||||
var _cacheLogger = scope.ServiceProvider.GetRequiredService<ILoggingService>();
|
||||
|
||||
var employeeIds = await _context.Employees.Where(e => e.TenantId == tenantId).Select(e => e.Id).ToListAsync();
|
||||
await _cache.ClearAllEmployeesFromCacheByEmployeeIds(employeeIds, tenantId);
|
||||
_cacheLogger.LogInfo("{EmployeeCount} number of employee deleted", employeeIds.Count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user