From 3b0c9583421132d3b873deff67cd7246a604c988 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Wed, 29 Oct 2025 16:28:55 +0530 Subject: [PATCH] Added the self subscription API --- .../Dtos/Tenant/SelfSubscriptionDto.cs | 9 +++ .../Tenant/SubscriptionPlanDetailsVM.cs | 2 + .../Controllers/PaymentController.cs | 1 - .../Controllers/TenantController.cs | 76 +++++++++++++------ Marco.Pms.Services/Service/RazorpayService.cs | 19 +++++ .../ServiceInterfaces/IRazorpayService.cs | 1 + 6 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 Marco.Pms.Model/Dtos/Tenant/SelfSubscriptionDto.cs diff --git a/Marco.Pms.Model/Dtos/Tenant/SelfSubscriptionDto.cs b/Marco.Pms.Model/Dtos/Tenant/SelfSubscriptionDto.cs new file mode 100644 index 0000000..950f7e2 --- /dev/null +++ b/Marco.Pms.Model/Dtos/Tenant/SelfSubscriptionDto.cs @@ -0,0 +1,9 @@ +namespace Marco.Pms.Model.Dtos.Tenant +{ + public class SelfSubscriptionDto + { + public Guid TenantEnquireId { get; set; } + public Guid PaymentDetailId { get; set; } + public Guid PlanId { get; set; } + } +} diff --git a/Marco.Pms.Model/ViewModels/Tenant/SubscriptionPlanDetailsVM.cs b/Marco.Pms.Model/ViewModels/Tenant/SubscriptionPlanDetailsVM.cs index e137ef4..4fa669e 100644 --- a/Marco.Pms.Model/ViewModels/Tenant/SubscriptionPlanDetailsVM.cs +++ b/Marco.Pms.Model/ViewModels/Tenant/SubscriptionPlanDetailsVM.cs @@ -1,6 +1,7 @@ using Marco.Pms.Model.Master; using Marco.Pms.Model.TenantModels; using Marco.Pms.Model.ViewModels.Activities; +using Marco.Pms.Model.ViewModels.PaymentGetway; namespace Marco.Pms.Model.ViewModels.Tenant { @@ -16,6 +17,7 @@ namespace Marco.Pms.Model.ViewModels.Tenant public DateTime EndDate { get; set; } public DateTime CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } + public PaymentDetailsVM? PaymentDetail { get; set; } public BasicEmployeeVM? CreatedBy { get; set; } public BasicEmployeeVM? updatedBy { get; set; } public CurrencyMaster? Currency { get; set; } diff --git a/Marco.Pms.Services/Controllers/PaymentController.cs b/Marco.Pms.Services/Controllers/PaymentController.cs index 9752f42..9671800 100644 --- a/Marco.Pms.Services/Controllers/PaymentController.cs +++ b/Marco.Pms.Services/Controllers/PaymentController.cs @@ -79,7 +79,6 @@ namespace Marco.Pms.Services.Controllers // Fetch complete payment details from Razorpay including card details var response = await _razorpayService.GetPaymentDetails(request.PaymentId); - var tenant = await _tenantService.CreateTenantAsync(request.TenantEnquireId, response.Id, request.PlanId); _logger.LogInfo("Invoice generated and saved for OrderId: {OrderId}", request.OrderId); diff --git a/Marco.Pms.Services/Controllers/TenantController.cs b/Marco.Pms.Services/Controllers/TenantController.cs index 3dd30d3..9a2233a 100644 --- a/Marco.Pms.Services/Controllers/TenantController.cs +++ b/Marco.Pms.Services/Controllers/TenantController.cs @@ -16,6 +16,7 @@ using Marco.Pms.Model.ViewModels.Activities; using Marco.Pms.Model.ViewModels.Tenant; using Marco.Pms.Services.Helpers; using Marco.Pms.Services.Service; +using Marco.Pms.Services.Service.ServiceInterfaces; using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; @@ -238,34 +239,31 @@ namespace Marco.Pms.Services.Controllers return StatusCode(403, ApiResponse.ErrorResponse("Unauthorized", "User must be logged in.", 403)); } + using var scope = _serviceScopeFactory.CreateScope(); + // Check permissions using a single service scope to avoid overhead bool hasManagePermission, hasModifyPermission, hasViewPermission; - using (var scope = _serviceScopeFactory.CreateScope()) + var manageTask = Task.Run(async () => { + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id); + }); + var modifyTask = Task.Run(async () => + { + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasPermission(PermissionsMaster.ModifyTenant, loggedInEmployee.Id); + }); + var viewTask = Task.Run(async () => + { + var permissionService = scope.ServiceProvider.GetRequiredService(); + return await permissionService.HasPermission(PermissionsMaster.ViewTenant, loggedInEmployee.Id); + }); + await Task.WhenAll(manageTask, modifyTask, viewTask); - var manageTask = Task.Run(async () => - { - var permissionService = scope.ServiceProvider.GetRequiredService(); - return await permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id); - }); - var modifyTask = Task.Run(async () => - { - var permissionService = scope.ServiceProvider.GetRequiredService(); - return await permissionService.HasPermission(PermissionsMaster.ModifyTenant, loggedInEmployee.Id); - }); - var viewTask = Task.Run(async () => - { - var permissionService = scope.ServiceProvider.GetRequiredService(); - return await permissionService.HasPermission(PermissionsMaster.ViewTenant, loggedInEmployee.Id); - }); - - await Task.WhenAll(manageTask, modifyTask, viewTask); - - hasManagePermission = manageTask.Result; - hasModifyPermission = modifyTask.Result; - hasViewPermission = viewTask.Result; - } + hasManagePermission = manageTask.Result; + hasModifyPermission = modifyTask.Result; + hasViewPermission = viewTask.Result; if (!hasManagePermission && !hasModifyPermission && !hasViewPermission) { @@ -351,6 +349,11 @@ namespace Marco.Pms.Services.Controllers var plans = plansTask.Result; var projects = projectsTask.Result; + var _razorpayService = scope.ServiceProvider.GetRequiredService(); + + var paymentDetailIds = plans.Where(ts => ts.PaymentDetailId.HasValue).Select(ts => ts.PaymentDetailId!.Value).ToList(); + var paymentsDetails = await _razorpayService.GetPaymentDetailsListFromDataBase(paymentDetailIds); + // Calculate active/inactive employees count var activeEmployeesCount = employees.Count(e => e.IsActive); var inActiveEmployeesCount = employees.Count - activeEmployeesCount; @@ -379,9 +382,16 @@ namespace Marco.Pms.Services.Controllers response.CreatedBy = createdBy; response.CurrentPlan = _mapper.Map(currentPlan); + response.CurrentPlan.PaymentDetail = paymentsDetails.FirstOrDefault(pd => currentPlan != null && pd.Id == currentPlan.PaymentDetailId); + response.CurrentPlanFeatures = await _featureDetailsHelper.GetFeatureDetails(currentPlan?.Plan?.FeaturesId ?? Guid.Empty); // Map subscription history plans to DTO - response.SubscriptionHistery = _mapper.Map>(plans); + response.SubscriptionHistery = plans.Select(ts => + { + var result = _mapper.Map(ts); + result.PaymentDetail = paymentsDetails.FirstOrDefault(pd => ts != null && pd.Id == ts.PaymentDetailId); + return result; + }).ToList(); _logger.LogInfo("Tenant details fetched successfully for TenantId: {TenantId}", tenant.Id); @@ -1574,6 +1584,24 @@ namespace Marco.Pms.Services.Controllers } } + [AllowAnonymous] + [HttpPost("self/subscription")] + public async Task SelfSubscriptionAsync(SelfSubscriptionDto model) + { + try + { + using var scope = _serviceScopeFactory.CreateScope(); + var _tenantService = scope.ServiceProvider.GetRequiredService(); + var tenant = await _tenantService.CreateTenantAsync(model.TenantEnquireId, model.PaymentDetailId, model.PlanId); + return Ok(ApiResponse.SuccessResponse(tenant, "Tenant Registration Successfully", 201)); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occured while add self subscription"); + return StatusCode(500, ApiResponse.ErrorResponse("Error Occured while self subscription", "Error Occured while self subscription", 500)); + } + } + #endregion #region =================================================================== Subscription Plan APIs =================================================================== diff --git a/Marco.Pms.Services/Service/RazorpayService.cs b/Marco.Pms.Services/Service/RazorpayService.cs index fa6cc98..e4ccf71 100644 --- a/Marco.Pms.Services/Service/RazorpayService.cs +++ b/Marco.Pms.Services/Service/RazorpayService.cs @@ -240,6 +240,25 @@ namespace Marco.Pms.Services.Service } } + public async Task> GetPaymentDetailsListFromDataBase(List paymentDetailsIds) + { + var projectDetails = await _context.PaymentDetails.Where(pd => paymentDetailsIds.Contains(pd.Id)).ToListAsync(); + List response = new List(); + + foreach (var projectDetail in projectDetails) + { + string decrypedData = _aesEncryption.Decrypt(projectDetail.EncryptedDetails ?? new byte[32], projectDetail.Nonce ?? new byte[12], projectDetail.Tag ?? new byte[16], encryptionKey); + // Deserialize JSON string to a Department object + PaymentDetailsVM? vm = JsonConvert.DeserializeObject(decrypedData); + if (vm != null) + { + response.Add(vm); + } + } + + return response; + } + /// /// Extract card details from payment /// diff --git a/Marco.Pms.Services/Service/ServiceInterfaces/IRazorpayService.cs b/Marco.Pms.Services/Service/ServiceInterfaces/IRazorpayService.cs index d4e6dc9..6152713 100644 --- a/Marco.Pms.Services/Service/ServiceInterfaces/IRazorpayService.cs +++ b/Marco.Pms.Services/Service/ServiceInterfaces/IRazorpayService.cs @@ -9,6 +9,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces string GetExpectedSignature(string payload); Task GetPaymentDetails(string paymentId); Task GetPaymentDetailsFromDataBase(Guid id); + Task> GetPaymentDetailsListFromDataBase(List paymentDetailsIds); RazorpayOrderDetails? GetOrderDetails(string orderId); } }