Added new subscription details in add-subscription API
This commit is contained in:
parent
54bf49a005
commit
c65d73ff87
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user