Added the API to create payment request from recurring payment
This commit is contained in:
parent
5910517d01
commit
c71343d550
@ -257,6 +257,15 @@ namespace Marco.Pms.Services.Controllers
|
||||
|
||||
}
|
||||
|
||||
[HttpPost("recurring-payment/convert/payment-request")]
|
||||
public async Task<IActionResult> PaymentRequestConversion(PaymentRequestConversionDto model)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _expensesService.PaymentRequestConversionAsync(model.RecurringTemplateIds, loggedInEmployee, tenantId);
|
||||
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpPut("recurring-payment/edit/{id}")]
|
||||
public async Task<IActionResult> EditRecurringPaymentAsync(Guid id, [FromBody] UpdateRecurringTemplateDto model)
|
||||
{
|
||||
|
||||
@ -2897,6 +2897,133 @@ namespace Marco.Pms.Services.Service
|
||||
_logger.LogInfo("End CreateRecurringPaymentAsync called by EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> PaymentRequestConversionAsync(List<Guid> recurringTemplateIds, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("Start PaymentRequestConversionAsync called by EmployeeId: {EmployeeId} for TenantId: {TenantId} with RecurringTemplateIds: {RecurringTemplateIds}",
|
||||
loggedInEmployee.Id, tenantId, recurringTemplateIds);
|
||||
|
||||
// SuperAdmin check - restrict access only to specific user
|
||||
var superAdminId = Guid.Parse("08dd8b35-d98b-44f1-896d-12aec3f035aa");
|
||||
if (loggedInEmployee.Id != superAdminId)
|
||||
{
|
||||
_logger.LogWarning("Access denied for EmployeeId: {EmployeeId}. Only super admin can perform this operation.", loggedInEmployee.Id);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied", "User does not have permission to access this function", 403);
|
||||
}
|
||||
|
||||
// Get active recurring payments matching the provided IDs and tenant
|
||||
var recurringPayments = await _context.RecurringPayments
|
||||
.AsNoTracking()
|
||||
.Where(rp => recurringTemplateIds.Contains(rp.Id)
|
||||
&& rp.IsActive
|
||||
&& rp.StatusId == ActiveTemplateStatus
|
||||
&& rp.TenantId == tenantId)
|
||||
.ToListAsync();
|
||||
|
||||
if (!recurringPayments.Any())
|
||||
{
|
||||
_logger.LogWarning("No active recurring payments found for TenantId: {TenantId} and given IDs.", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Recurring template not found", "Recurring template not found", 404);
|
||||
}
|
||||
|
||||
var updatedRecurringPayments = new List<RecurringPayment>();
|
||||
var paymentRequests = new List<PaymentRequest>();
|
||||
|
||||
// Generate UID prefix for payment requests for this period (month/year)
|
||||
string uIDPrefix = $"PR/{DateTime.Now:MM.yy}";
|
||||
|
||||
// Get last generated payment request for UID postfixing (to maintain unique numbering)
|
||||
var lastPR = await _context.PaymentRequests
|
||||
.Where(pr => pr.UIDPrefix == uIDPrefix)
|
||||
.OrderByDescending(pr => pr.UIDPostfix)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
int uIDPostfix = lastPR == null ? 1 : lastPR.UIDPostfix + 1;
|
||||
|
||||
foreach (var recurringPayment in recurringPayments)
|
||||
{
|
||||
// Check if recurring payment is applicable for generating a new payment request
|
||||
var isApplicable = IsRecurringApplicable(
|
||||
recurringPayment.NumberOfIteration,
|
||||
recurringPayment.Frequency,
|
||||
recurringPayment.StrikeDate.Date,
|
||||
recurringPayment.LatestPRGeneratedAt);
|
||||
|
||||
if (isApplicable)
|
||||
{
|
||||
// Update latest generated date to today (UTC)
|
||||
recurringPayment.LatestPRGeneratedAt = DateTime.UtcNow.Date;
|
||||
updatedRecurringPayments.Add(recurringPayment);
|
||||
|
||||
// Create new payment request mapped from recurring payment data
|
||||
var newPaymentRequest = new PaymentRequest
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Title = recurringPayment.Title,
|
||||
Description = recurringPayment.Description,
|
||||
UIDPrefix = uIDPrefix,
|
||||
UIDPostfix = uIDPostfix,
|
||||
Payee = recurringPayment.Payee,
|
||||
IsAdvancePayment = false,
|
||||
CurrencyId = recurringPayment.CurrencyId,
|
||||
Amount = recurringPayment.Amount,
|
||||
DueDate = DateTime.UtcNow.AddDays(recurringPayment.PaymentBufferDays),
|
||||
ProjectId = recurringPayment.ProjectId,
|
||||
RecurringPaymentId = recurringPayment.Id,
|
||||
ExpenseCategoryId = recurringPayment.ExpenseCategoryId,
|
||||
ExpenseStatusId = Review,
|
||||
IsExpenseCreated = false,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
CreatedById = loggedInEmployee.Id,
|
||||
IsActive = true,
|
||||
TenantId = recurringPayment.TenantId
|
||||
};
|
||||
paymentRequests.Add(newPaymentRequest);
|
||||
|
||||
uIDPostfix++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!updatedRecurringPayments.Any())
|
||||
{
|
||||
_logger.LogWarning("No applicable recurring payments for conversion found for TenantId: {TenantId}.", tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("No applicable recurring templates found to convert", "No applicable recurring templates found", 404);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Update recurring payments with latest generated dates
|
||||
_context.RecurringPayments.UpdateRange(updatedRecurringPayments);
|
||||
|
||||
// Add newly created payment requests
|
||||
if (paymentRequests.Any())
|
||||
{
|
||||
_context.PaymentRequests.AddRange(paymentRequests);
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
_logger.LogInfo("{Count} payment requests created successfully from recurring payments by EmployeeId: {EmployeeId} for TenantId: {TenantId}",
|
||||
paymentRequests.Count, loggedInEmployee.Id, tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(recurringTemplateIds, $"{paymentRequests.Count} conversion(s) to payment request completed successfully.", 201);
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Database error during PaymentRequestConversionAsync for TenantId: {TenantId}, EmployeeId: {EmployeeId}: {Message}. Inner exception: {InnerException}",
|
||||
tenantId, loggedInEmployee.Id, ex.Message, ex.InnerException?.Message ?? "");
|
||||
return ApiResponse<object>.ErrorResponse("Database error occurred", ExceptionMapper(ex), 500);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unexpected error during PaymentRequestConversionAsync for TenantId: {TenantId}, EmployeeId: {EmployeeId}: {Message}",
|
||||
tenantId, loggedInEmployee.Id, ex.Message);
|
||||
return ApiResponse<object>.ErrorResponse("An unexpected error occurred", ex.Message, 500);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_logger.LogInfo("End PaymentRequestConversionAsync called by EmployeeId: {EmployeeId} for TenantId: {TenantId}", loggedInEmployee.Id, tenantId);
|
||||
}
|
||||
}
|
||||
public async Task<ApiResponse<object>> EditRecurringPaymentAsync(Guid id, UpdateRecurringTemplateDto model, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("Start EditRecurringPaymentAsync called by EmployeeId: {EmployeeId} for TenantId: {TenantId}, RecurringPaymentId: {RecurringPaymentId}",
|
||||
|
||||
@ -33,6 +33,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
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);
|
||||
Task<ApiResponse<object>> PaymentRequestConversionAsync(List<Guid> RecurringTemplateIds, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> EditRecurringPaymentAsync(Guid id, UpdateRecurringTemplateDto model, Employee loggedInEmployee, Guid tenantId);
|
||||
#endregion
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user