Added the API to get details of recurring payment

This commit is contained in:
ashutosh.nehete 2025-11-07 17:48:58 +05:30
parent 46806b34bb
commit e6b66479d5
3 changed files with 139 additions and 0 deletions

View File

@ -234,6 +234,14 @@ namespace Marco.Pms.Services.Controllers
var response = await _expensesService.GetRecurringPaymentListAsync(searchString, filter, isActive, pageSize, pageNumber, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpGet("get/recurring-payment/details/{id?}")]
public async Task<IActionResult> GetRecurringPaymentDetailsAsync(Guid? id, [FromQuery] string? recurringPaymentUId)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _expensesService.GetRecurringPaymentDetailsAsync(id, recurringPaymentUId, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
#endregion
#region =================================================================== Payment Request Functions ===================================================================

View File

@ -2655,6 +2655,136 @@ namespace Marco.Pms.Services.Service
_logger.LogInfo("End GetRecurringPaymentListAsync called by EmployeeId: {EmployeeId}", loggedInEmployee.Id);
}
}
public async Task<ApiResponse<object>> GetRecurringPaymentDetailsAsync(Guid? id, string? recurringPaymentUId, Employee loggedInEmployee, Guid tenantId)
{
_logger.LogInfo("Start GetRecurringPaymentDetailsAsync called by EmployeeId: {EmployeeId} for TenantId: {TenantId} with Id: {Id}, UID: {UID}",
loggedInEmployee.Id, tenantId, id ?? Guid.Empty, recurringPaymentUId ?? "");
try
{
// Validate input: require at least one identifier
if (!id.HasValue && string.IsNullOrWhiteSpace(recurringPaymentUId))
{
_logger.LogWarning("Invalid parameters: Both Id and RecurringPaymentUID are null or empty.");
return ApiResponse<object>.ErrorResponse("At least one parameter (Id or RecurringPaymentUID) must be provided.", "Invalid argument.", 400);
}
// Concurrent permission checks for view-self, view-all, and manage recurring payments
var hasViewSelfPermissionTask = Task.Run(async () =>
{
using var scope = _serviceScopeFactory.CreateScope();
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
return await permissionService.HasPermission(PermissionsMaster.ViewSelfRecurring, loggedInEmployee.Id);
});
var hasViewAllPermissionTask = Task.Run(async () =>
{
using var scope = _serviceScopeFactory.CreateScope();
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
return await permissionService.HasPermission(PermissionsMaster.ViewAllRecurring, loggedInEmployee.Id);
});
var hasManagePermissionTask = Task.Run(async () =>
{
using var scope = _serviceScopeFactory.CreateScope();
var permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
return await permissionService.HasPermission(PermissionsMaster.ManageRecurring, loggedInEmployee.Id);
});
await Task.WhenAll(hasViewSelfPermissionTask, hasViewAllPermissionTask, hasManagePermissionTask);
bool hasViewSelfPermission = hasViewSelfPermissionTask.Result;
bool hasViewAllPermission = hasViewAllPermissionTask.Result;
bool hasManagePermission = hasManagePermissionTask.Result;
// Deny access if user lacks all relevant permissions
if (!hasViewSelfPermission && !hasViewAllPermission && !hasManagePermission)
{
_logger.LogWarning("Access DENIED: Employee {EmployeeId} has no permission to view recurring payments.", loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(new { }, "You do not have permission to view any recurring payment.", 200);
}
// Query recurring payment by Id or UID with navigation and tenant checks
var recurringPayment = await _context.RecurringPayments
.Include(rp => rp.Currency)
.Include(rp => rp.Project)
.Include(rp => rp.ExpenseCategory)
.Include(rp => rp.Status)
.Include(rp => rp.CreatedBy).ThenInclude(e => e!.JobRole)
.Include(rp => rp.UpdatedBy).ThenInclude(e => e!.JobRole)
.Where(rp =>
(rp.Id == id || (rp.UIDPrefix + "/" + rp.UIDPostfix.ToString().PadLeft(5, '0')) == recurringPaymentUId) &&
rp.TenantId == tenantId &&
rp.Currency != null &&
rp.ExpenseCategory != null &&
rp.Status != null &&
rp.CreatedBy != null &&
rp.CreatedBy.JobRole != null)
.FirstOrDefaultAsync();
if (recurringPayment == null)
{
_logger.LogWarning("Recurring Payment not found: Id={Id}, UID={UID}, TenantId={TenantId}", id ?? Guid.Empty, recurringPaymentUId ?? "N/A", tenantId);
return ApiResponse<object>.ErrorResponse("Recurring Payment not found.", "Recurring payment not found.", 404);
}
// If user has only view-self permission and the recurring payment belongs to another employee, deny access
bool selfCheck = hasViewSelfPermission && !hasViewAllPermission && !hasManagePermission &&
recurringPayment.CreatedById != loggedInEmployee.Id;
if (selfCheck)
{
_logger.LogWarning("Access DENIED: Employee {EmployeeId} lacks permission to view RecurringPayment {RecurringPaymentId} created by another employee.",
loggedInEmployee.Id, recurringPayment.Id);
return ApiResponse<object>.SuccessResponse(new { }, "You do not have permission to view this recurring payment.", 200);
}
// Concurrently fetch employees notified on this recurring payment and relevant active payment requests
var employeeTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
var emails = recurringPayment.NotifyTo.Split(",", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
return await context.Employees
.Include(e => e.JobRole)
.Where(e => emails.Contains(e.Email) && e.TenantId == tenantId && e.IsActive)
.ToListAsync();
});
var paymentRequestTask = Task.Run(async () =>
{
await using var context = await _dbContextFactory.CreateDbContextAsync();
return await context.PaymentRequests
.Where(pr => pr.RecurringPaymentId == recurringPayment.Id && pr.TenantId == tenantId && pr.IsActive)
.Select(pr => _mapper.Map<BasicPaymentRequestVM>(pr))
.ToListAsync();
});
await Task.WhenAll(employeeTask, paymentRequestTask);
var employees = employeeTask.Result;
var paymentRequests = paymentRequestTask.Result;
// Map main response DTO and enrich with notification employees and payment requests
var response = _mapper.Map<RecurringPaymentDetailsVM>(recurringPayment);
response.NotifyTo = _mapper.Map<List<BasicEmployeeVM>>(employees);
response.PaymentRequests = paymentRequests;
_logger.LogInfo("Recurring payment details fetched successfully for RecurringPaymentId: {RecurringPaymentId} by EmployeeId: {EmployeeId}",
recurringPayment.Id, loggedInEmployee.Id);
return ApiResponse<object>.SuccessResponse(response, "Recurring payment details fetched successfully.", 200);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in GetRecurringPaymentDetailsAsync for TenantId={TenantId}, EmployeeId={EmployeeId}: {Message}", tenantId, loggedInEmployee.Id, ex.Message);
return ApiResponse<object>.ErrorResponse("An error occurred while fetching the recurring payment details.", ex.Message, 500);
}
finally
{
_logger.LogInfo("End GetRecurringPaymentDetailsAsync called by EmployeeId: {EmployeeId}", loggedInEmployee.Id);
}
}
#endregion

View File

@ -31,6 +31,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);
#endregion