Updated the action API for payment requests to create the expense after expense is processed
This commit is contained in:
parent
a6d5dfa1fc
commit
643501ee9e
@ -1,4 +1,6 @@
|
|||||||
namespace Marco.Pms.Model.Dtos.Expenses
|
using Marco.Pms.Model.Utilities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.Dtos.Expenses
|
||||||
{
|
{
|
||||||
public class PaymentRequestRecordDto
|
public class PaymentRequestRecordDto
|
||||||
{
|
{
|
||||||
@ -11,5 +13,9 @@
|
|||||||
public double? TaxAmount { get; set; }
|
public double? TaxAmount { get; set; }
|
||||||
public DateTime? PaidAt { get; set; }
|
public DateTime? PaidAt { get; set; }
|
||||||
public Guid? PaidById { get; set; }
|
public Guid? PaidById { get; set; }
|
||||||
|
public Guid? PaymentModeId { get; set; }
|
||||||
|
public string? Location { get; set; }
|
||||||
|
public string? GSTNumber { get; set; }
|
||||||
|
public List<FileUploadModel>? BillAttachments { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -184,19 +184,6 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("payment-request/expense/create")]
|
|
||||||
public async Task<IActionResult> ChangeToExpanseFromPaymentRequest(ExpenseConversionDto model)
|
|
||||||
{
|
|
||||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
|
||||||
var response = await _expensesService.ChangeToExpanseFromPaymentRequestAsync(model, loggedInEmployee, tenantId);
|
|
||||||
if (response.Success)
|
|
||||||
{
|
|
||||||
var notification = new { LoggedInUserId = loggedInEmployee.Id, Keyword = "Expanse", Response = response.Data };
|
|
||||||
await _signalR.SendNotificationAsync(notification);
|
|
||||||
}
|
|
||||||
return StatusCode(response.StatusCode, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPut("payment-request/edit/{id}")]
|
[HttpPut("payment-request/edit/{id}")]
|
||||||
public async Task<IActionResult> EditPaymentRequest(Guid id, [FromBody] PaymentRequestDto model)
|
public async Task<IActionResult> EditPaymentRequest(Guid id, [FromBody] PaymentRequestDto model)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1836,6 +1836,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
.Include(pr => pr.ExpenseCategory)
|
.Include(pr => pr.ExpenseCategory)
|
||||||
.Include(pr => pr.ExpenseStatus)
|
.Include(pr => pr.ExpenseStatus)
|
||||||
.Include(pr => pr.CreatedBy).ThenInclude(e => e!.JobRole)
|
.Include(pr => pr.CreatedBy).ThenInclude(e => e!.JobRole)
|
||||||
|
.Include(pr => pr.UpdatedBy).ThenInclude(e => e!.JobRole)
|
||||||
.FirstOrDefaultAsync(pr =>
|
.FirstOrDefaultAsync(pr =>
|
||||||
pr.Id == model.PaymentRequestId &&
|
pr.Id == model.PaymentRequestId &&
|
||||||
pr.ExpenseStatusId != model.StatusId &&
|
pr.ExpenseStatusId != model.StatusId &&
|
||||||
@ -1920,7 +1921,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
paymentRequest.ExpenseStatus = statusTransition.NextStatus;
|
paymentRequest.ExpenseStatus = statusTransition.NextStatus;
|
||||||
|
|
||||||
|
|
||||||
// 7. Add Reimbursement if applicable
|
// 7. Add Payment details if applicable
|
||||||
if (model.StatusId == Processed)
|
if (model.StatusId == Processed)
|
||||||
{
|
{
|
||||||
var totalAmount = model.BaseAmount + model.TaxAmount;
|
var totalAmount = model.BaseAmount + model.TaxAmount;
|
||||||
@ -1967,6 +1968,38 @@ namespace Marco.Pms.Services.Service
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
_logger.LogInfo("ChangeStatus: Status updated successfully. PaymentRequestId={PaymentRequestId} NewStatus={NewStatusId}", paymentRequest.Id, paymentRequest.ExpenseStatusId);
|
||||||
|
}
|
||||||
|
catch (DbUpdateConcurrencyException ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "ChangeStatus: Concurrency error. PaymentRequestId={PaymentRequestId}", paymentRequest.Id);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Payment Request was modified by another user. Please refresh and try again.", "Concurrency Error", 409);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.StatusId == Done)
|
||||||
|
{
|
||||||
|
if (!model.PaymentModeId.HasValue)
|
||||||
|
{
|
||||||
|
return ApiResponse<object>.ErrorResponse("Payment mode Id is missing from payload", "Payment mode Id is missing from payload", 400);
|
||||||
|
}
|
||||||
|
var expenseConversion = new ExpenseConversionDto
|
||||||
|
{
|
||||||
|
PaymentModeId = model.PaymentModeId.Value,
|
||||||
|
PaymentRequestId = model.PaymentRequestId,
|
||||||
|
Location = model.Location,
|
||||||
|
GSTNumber = model.GSTNumber,
|
||||||
|
BillAttachments = model.BillAttachments
|
||||||
|
};
|
||||||
|
var response = await ChangeToExpanseFromPaymentRequestAsync(expenseConversion, paymentRequest, loggedInEmployee, tenantId);
|
||||||
|
if (!response.Success)
|
||||||
|
{
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 8. Add paymentRequest Log Entry
|
// 8. Add paymentRequest Log Entry
|
||||||
_context.StatusUpdateLogs.Add(new StatusUpdateLog
|
_context.StatusUpdateLogs.Add(new StatusUpdateLog
|
||||||
{
|
{
|
||||||
@ -2027,7 +2060,7 @@ namespace Marco.Pms.Services.Service
|
|||||||
return ApiResponse<object>.SuccessResponse(responseDto, "Status updated, but audit logging or cache update failed.");
|
return ApiResponse<object>.SuccessResponse(responseDto, "Status updated, but audit logging or cache update failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task<ApiResponse<object>> ChangeToExpanseFromPaymentRequestAsync(ExpenseConversionDto model, Employee loggedInEmployee, Guid tenantId)
|
public async Task<ApiResponse<object>> ChangeToExpanseFromPaymentRequestAsync(ExpenseConversionDto model, PaymentRequest paymentRequest, Employee loggedInEmployee, Guid tenantId)
|
||||||
{
|
{
|
||||||
_logger.LogInfo("Start ChangeToExpanseFromPaymentRequestAsync called by EmployeeId: {EmployeeId} for TenantId: {TenantId} PaymentRequestId: {PaymentRequestId}",
|
_logger.LogInfo("Start ChangeToExpanseFromPaymentRequestAsync called by EmployeeId: {EmployeeId} for TenantId: {TenantId} PaymentRequestId: {PaymentRequestId}",
|
||||||
loggedInEmployee.Id, tenantId, model.PaymentRequestId);
|
loggedInEmployee.Id, tenantId, model.PaymentRequestId);
|
||||||
@ -2036,28 +2069,24 @@ namespace Marco.Pms.Services.Service
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Retrieve payment request with required navigation property and validation
|
var ispaymentRequestApplicable = (paymentRequest.Id == model.PaymentRequestId &&
|
||||||
var paymentRequest = await _context.PaymentRequests
|
!paymentRequest.IsAdvancePayment &&
|
||||||
.Include(pr => pr.ExpenseCategory)
|
paymentRequest.ProjectId.HasValue &&
|
||||||
.FirstOrDefaultAsync(pr =>
|
paymentRequest.ExpenseCategoryId.HasValue &&
|
||||||
pr.Id == model.PaymentRequestId &&
|
paymentRequest.PaidById.HasValue &&
|
||||||
!pr.IsAdvancePayment &&
|
paymentRequest.PaidAt.HasValue &&
|
||||||
pr.ProjectId.HasValue &&
|
paymentRequest.ExpenseCategory != null &&
|
||||||
pr.ExpenseCategoryId.HasValue &&
|
paymentRequest.TenantId == tenantId &&
|
||||||
pr.PaidById.HasValue &&
|
paymentRequest.IsActive);
|
||||||
pr.PaidAt.HasValue &&
|
|
||||||
pr.ExpenseCategory != null &&
|
|
||||||
pr.TenantId == tenantId &&
|
|
||||||
pr.IsActive);
|
|
||||||
|
|
||||||
if (paymentRequest == null)
|
if (!ispaymentRequestApplicable)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Payment request not found for Id: {PaymentRequestId}, TenantId: {TenantId}", model.PaymentRequestId, tenantId);
|
_logger.LogWarning("Payment request not found for Id: {PaymentRequestId}, TenantId: {TenantId}", model.PaymentRequestId, tenantId);
|
||||||
return ApiResponse<object>.ErrorResponse("Payment request not found.", "Payment request not found.", 404);
|
return ApiResponse<object>.ErrorResponse("Payment request not found.", "Payment request not found.", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check payment request status for eligibility to convert
|
// Check payment request status for eligibility to convert
|
||||||
if (paymentRequest.ExpenseStatusId != Processed)
|
if (paymentRequest.ExpenseStatusId != Done)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Payment request {PaymentRequestId} status is not processed. Current status: {StatusId}", paymentRequest.Id, paymentRequest.ExpenseStatusId);
|
_logger.LogWarning("Payment request {PaymentRequestId} status is not processed. Current status: {StatusId}", paymentRequest.Id, paymentRequest.ExpenseStatusId);
|
||||||
return ApiResponse<object>.ErrorResponse("Payment is not processed.", "Payment is not processed.", 400);
|
return ApiResponse<object>.ErrorResponse("Payment is not processed.", "Payment is not processed.", 400);
|
||||||
|
|||||||
@ -24,7 +24,6 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
Task<ApiResponse<object>> GetPaymentRequestFilterObjectAsync(Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> GetPaymentRequestFilterObjectAsync(Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> CreatePaymentRequestAsync(PaymentRequestDto model, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> CreatePaymentRequestAsync(PaymentRequestDto model, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> ChangePaymentRequestStatusAsync(PaymentRequestRecordDto model, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> ChangePaymentRequestStatusAsync(PaymentRequestRecordDto model, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> ChangeToExpanseFromPaymentRequestAsync(ExpenseConversionDto model, Employee loggedInEmployee, Guid tenantId);
|
|
||||||
Task<ApiResponse<object>> EditPaymentRequestAsync(Guid id, PaymentRequestDto model, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> EditPaymentRequestAsync(Guid id, PaymentRequestDto model, Employee loggedInEmployee, Guid tenantId);
|
||||||
Task<ApiResponse<object>> DeletePaymentRequestAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
|
Task<ApiResponse<object>> DeletePaymentRequestAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user