From 0c1cb98f5b81b74a2223c95bded5500468f2ac2a Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Tue, 29 Jul 2025 18:11:33 +0530 Subject: [PATCH] Added the code to save reimbursement in database --- .../Dtos/Expenses/ExpenseRecordDto.cs | 3 ++ .../ViewModels/Expenses/ExpenseDetailsVM.cs | 1 + .../Expenses/ExpensesReimburseVM.cs | 13 ++++++ .../MappingProfiles/MappingProfile.cs | 2 + Marco.Pms.Services/Service/ExpensesService.cs | 41 ++++++++++++++++++- 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 Marco.Pms.Model/ViewModels/Expenses/ExpensesReimburseVM.cs diff --git a/Marco.Pms.Model/Dtos/Expenses/ExpenseRecordDto.cs b/Marco.Pms.Model/Dtos/Expenses/ExpenseRecordDto.cs index 3731f3b..d59c90e 100644 --- a/Marco.Pms.Model/Dtos/Expenses/ExpenseRecordDto.cs +++ b/Marco.Pms.Model/Dtos/Expenses/ExpenseRecordDto.cs @@ -5,5 +5,8 @@ public Guid ExpenseId { get; set; } public Guid StatusId { get; set; } public string? Comment { get; set; } + public string? ReimburseTransactionId { get; set; } + public DateTime? ReimburseDate { get; set; } + public Guid? ReimburseById { get; set; } } } diff --git a/Marco.Pms.Model/ViewModels/Expenses/ExpenseDetailsVM.cs b/Marco.Pms.Model/ViewModels/Expenses/ExpenseDetailsVM.cs index 34ecc24..b59bd59 100644 --- a/Marco.Pms.Model/ViewModels/Expenses/ExpenseDetailsVM.cs +++ b/Marco.Pms.Model/ViewModels/Expenses/ExpenseDetailsVM.cs @@ -27,5 +27,6 @@ namespace Marco.Pms.Model.ViewModels.Expenses public string? GSTNumber { get; set; } public int? NoOfPersons { get; set; } public bool IsActive { get; set; } = true; + public List ExpensesReimburse { get; set; } = new List(); } } diff --git a/Marco.Pms.Model/ViewModels/Expenses/ExpensesReimburseVM.cs b/Marco.Pms.Model/ViewModels/Expenses/ExpensesReimburseVM.cs new file mode 100644 index 0000000..75e04ba --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Expenses/ExpensesReimburseVM.cs @@ -0,0 +1,13 @@ +using Marco.Pms.Model.ViewModels.Activities; + +namespace Marco.Pms.Model.ViewModels.Expenses +{ + public class ExpensesReimburseVM + { + public Guid Id { get; set; } + public string ReimburseTransactionId { get; set; } = string.Empty; + public DateTime ReimburseDate { get; set; } + public BasicEmployeeVM? ReimburseBy { get; set; } + public string ReimburseNote { get; set; } = string.Empty; + } +} diff --git a/Marco.Pms.Services/MappingProfiles/MappingProfile.cs b/Marco.Pms.Services/MappingProfiles/MappingProfile.cs index 2a99028..793e94a 100644 --- a/Marco.Pms.Services/MappingProfiles/MappingProfile.cs +++ b/Marco.Pms.Services/MappingProfiles/MappingProfile.cs @@ -123,6 +123,8 @@ namespace Marco.Pms.Services.MappingProfiles CreateMap(); CreateMap(); CreateMap(); + + CreateMap(); CreateMap() .ForMember( dest => dest.Id, diff --git a/Marco.Pms.Services/Service/ExpensesService.cs b/Marco.Pms.Services/Service/ExpensesService.cs index 7d30672..2ae8c20 100644 --- a/Marco.Pms.Services/Service/ExpensesService.cs +++ b/Marco.Pms.Services/Service/ExpensesService.cs @@ -35,6 +35,7 @@ namespace Marco.Pms.Services.Service private readonly IMapper _mapper; private static readonly Guid Draft = Guid.Parse("297e0d8f-f668-41b5-bfea-e03b354251c8"); private static readonly Guid Rejected = Guid.Parse("d1ee5eec-24b6-4364-8673-a8f859c60729"); + private static readonly Guid PaidStatus = Guid.Parse("61578360-3a49-4c34-8604-7b35a3787b95"); private static readonly string Collection = "ExpensesModificationLog"; public ExpensesService( IDbContextFactory dbContextFactory, @@ -490,6 +491,17 @@ namespace Marco.Pms.Services.Service return ApiResponse.ErrorResponse("This status change is not allowed.", "Invalid Transition", 400); } + if (statusMapping.NextStatusId == PaidStatus && + (string.IsNullOrWhiteSpace(model.ReimburseTransactionId) || + !model.ReimburseDate.HasValue || + model.ReimburseById == null || + model.ReimburseById == Guid.Empty)) + { + _logger.LogWarning("Invalid status transition attempted for ExpenseId: {ExpenseId}. From StatusId: {FromStatusId} to {ToStatusId}", + existingExpense.Id, existingExpense.StatusId, model.StatusId); + return ApiResponse.ErrorResponse("This status change is not allowed.", "Invalid Transition", 400); + } + // Check permissions. The logic is: // 1. If the target status has specific permissions defined, the user must have at least one of them. // 2. If no permissions are defined for the target status, only the original creator of the expense can change it. @@ -527,6 +539,23 @@ namespace Marco.Pms.Services.Service existingExpense.StatusId = statusMapping.NextStatusId; existingExpense.Status = statusMapping.NextStatus; // Assigning the included entity for the response mapping. + var expensesRemburse = new ExpensesReimburse + { + ReimburseTransactionId = model.ReimburseTransactionId!, + ReimburseDate = model.ReimburseDate!.Value, + ReimburseById = model.ReimburseById!.Value, + ReimburseNote = model.Comment ?? string.Empty, + TenantId = tenantId + }; + _context.ExpensesReimburse.Add(expensesRemburse); + + _context.ExpensesReimburseMapping.Add(new ExpensesReimburseMapping + { + ExpensesId = existingExpense.Id, + ExpensesReimburseId = expensesRemburse.Id, + TenantId = tenantId + }); + _context.ExpenseLogs.Add(new ExpenseLog { ExpenseId = existingExpense.Id, @@ -1064,9 +1093,17 @@ namespace Marco.Pms.Services.Service PermissionIds = g.Select(ps => ps.PermissionId).ToList() }).ToListAsync(); }); + var expenseReimburseTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesReimburseMapping + .Include(er => er.ExpensesReimburse) + .Where(er => er.TenantId == tenantId && er.ExpensesId == Guid.Parse(model.Id)) + .Select(er => er.ExpensesReimburse).ToListAsync(); + }); // Await all prerequisite checks at once. - await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, statusTask, permissionStatusMappingTask); + await Task.WhenAll(projectTask, expenseTypeTask, paymentModeTask, statusMappingTask, paidByTask, createdByTask, statusTask, permissionStatusMappingTask, expenseReimburseTask); var project = projectTask.Result; var expenseType = expenseTypeTask.Result; @@ -1075,6 +1112,7 @@ namespace Marco.Pms.Services.Service var permissionStatusMappings = permissionStatusMappingTask.Result; var paidBy = paidByTask.Result; var createdBy = createdByTask.Result; + var expensesReimburse = expenseReimburseTask.Result; var response = _mapper.Map(model); @@ -1083,6 +1121,7 @@ namespace Marco.Pms.Services.Service response.CreatedBy = _mapper.Map(createdBy); response.PaymentMode = _mapper.Map(paymentMode); response.ExpensesType = _mapper.Map(expenseType); + response.ExpensesReimburse = _mapper.Map>(expensesReimburse); if (statusMapping != null) { response.Status = _mapper.Map(statusMapping.Status);