Added the API to get details of recurring payment
This commit is contained in:
parent
46806b34bb
commit
e6b66479d5
@ -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 ===================================================================
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user