Added the API to create the recurring payment

This commit is contained in:
ashutosh.nehete 2025-11-07 17:51:01 +05:30
parent e6b66479d5
commit 1615dde267
3 changed files with 127 additions and 0 deletions

View File

@ -242,6 +242,20 @@ namespace Marco.Pms.Services.Controllers
var response = await _expensesService.GetRecurringPaymentDetailsAsync(id, recurringPaymentUId, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPost("recurring-payment/create")]
public async Task<IActionResult> CreateRecurringPayment([FromBody] CreateRecurringTemplateDto model)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.CreateRecurringPaymentAsync(model, loggedInEmployee, tenantId);
if (response.Success)
{
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Payment_Request", Response = response.Data };
await _signalR.SendNotificationAsync(notification);
}
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Payment Request Functions ===================================================================

View File

@ -2785,6 +2785,118 @@ namespace Marco.Pms.Services.Service
_logger.LogInfo("End GetRecurringPaymentDetailsAsync called by EmployeeId: {EmployeeId}", loggedInEmployee.Id);
}
}
public async Task<ApiResponse<object>> CreateRecurringPaymentAsync(CreateRecurringTemplateDto model, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("Start CreateRecurringPaymentAsync called by EmployeeId: {EmployeeId} for TenantId: {TenantId}", loggedInEmployee.Id, tenantId);
try
{
// Check if user has permission to create recurring payment templates
using var scope = _serviceScopeFactory.CreateScope();
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
var hasPermission = await permissionService.HasPermission(PermissionsMaster.ManageRecurring, loggedInEmployee.Id);
if (!hasPermission)
{
_logger.LogWarning("Access denied: Employee {EmployeeId} attempted to create recurring payment template without required permission.", loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("You do not have access to create recurring template.", "Permission denied.", 403);
}
// Concurrently fetch related entities required for validation and response mapping
var expenseCategoryTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.ExpenseCategoryMasters.FirstOrDefaultAsync(et => et.Id == model.ExpenseCategoryId && et.IsActive);
});
var recurringStatusTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.RecurringPaymentStatus.FirstOrDefaultAsync(rs => rs.Id == model.StatusId);
});
var currencyTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.CurrencyMaster.FirstOrDefaultAsync(c => c.Id == model.CurrencyId);
});
var projectTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return model.ProjectId.HasValue ? await context.Projects.FirstOrDefaultAsync(p => p.Id == model.ProjectId.Value) : null;
});
await Task.WhenAll(expenseCategoryTask, recurringStatusTask, currencyTask, projectTask);
var expenseCategory = await expenseCategoryTask;
if (expenseCategory == null)
{
_logger.LogWarning("Expense Category not found with Id: {ExpenseCategoryId}", model.ExpenseCategoryId);
return ApiResponse<object>.ErrorResponse("Expense Category not found.", "Expense Category not found.", 404);
}
var recurringStatus = await recurringStatusTask;
if (recurringStatus == null)
{
_logger.LogWarning("Recurring Payment Status not found with Id: {StatusId}", model.StatusId);
return ApiResponse<object>.ErrorResponse("Recurring Payment Status not found.", "Recurring Payment Status not found.", 404);
}
var currency = await currencyTask;
if (currency == null)
{
_logger.LogWarning("Currency not found with Id: {CurrencyId}", model.CurrencyId);
return ApiResponse<object>.ErrorResponse("Currency not found.", "Currency not found.", 404);
}
var project = await projectTask; // Optional, can be null
// Generate unique UID prefix and postfix per current month/year
string uIDPrefix = $"RP/{DateTime.Now:MMyy}";
var lastRecurringPayment = await _context.RecurringPayments
.Where(e => e.UIDPrefix == uIDPrefix)
.OrderByDescending(e => e.UIDPostfix)
.FirstOrDefaultAsync();
int uIDPostfix = lastRecurringPayment == null ? 1 : lastRecurringPayment.UIDPostfix + 1;
// Map input DTO to entity and set additional fields
var recurringPayment = _mapper.Map<RecurringPayment>(model);
recurringPayment.UIDPrefix = uIDPrefix;
recurringPayment.UIDPostfix = uIDPostfix;
recurringPayment.IsActive = true;
recurringPayment.CreatedAt = DateTime.UtcNow;
recurringPayment.CreatedById = loggedInEmployee.Id;
recurringPayment.TenantId = tenantId;
_context.RecurringPayments.Add(recurringPayment);
await _context.SaveChangesAsync();
// Prepare response view model with enriched data
var response = _mapper.Map<RecurringPaymentVM>(recurringPayment);
response.RecurringPaymentUId = $"{recurringPayment.UIDPrefix}/{recurringPayment.UIDPostfix:D5}";
response.CreatedBy = _mapper.Map<BasicEmployeeVM>(loggedInEmployee);
response.ExpenseCategory = _mapper.Map<ExpenseCategoryMasterVM>(expenseCategory);
response.Status = recurringStatus;
response.Currency = currency;
response.Project = _mapper.Map<BasicProjectVM>(project);
_logger.LogInfo("Recurring Payment Template created successfully with UID: {RecurringPaymentUId} by EmployeeId: {EmployeeId}", response.RecurringPaymentUId, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, "Recurring Payment Template created successfully.", 201);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in CreateRecurringPaymentAsync called by EmployeeId: {EmployeeId}: {Message}", loggedInEmployee.Id, ex.Message);
return ApiResponse<object>.ErrorResponse("An error occurred while creating the recurring payment template.", ex.Message, 500);
}
finally
{
_logger.LogInfo("End CreateRecurringPaymentAsync called by EmployeeId: {EmployeeId}", loggedInEmployee.Id);
}
}
#endregion

View File

@ -32,6 +32,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
#region =================================================================== Recurring Payment Functions ===================================================================
Task<ApiResponse<object>> GetRecurringPaymentListAsync(string? searchString, string? filter, bool isActive, int pageSize, int pageNumber, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetRecurringPaymentDetailsAsync(Guid? id, string? recurringPaymentUId, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateRecurringPaymentAsync(CreateRecurringTemplateDto model, Employee loggedInEmployee, Guid tenantId);
#endregion