From e31e19ed74ab1c87295f261ba5025a852215d9ac Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Fri, 25 Jul 2025 12:28:06 +0530 Subject: [PATCH] Added an API to update expenses status to master table for that tenant --- .../Controllers/MasterController.cs | 7 ++ Marco.Pms.Services/Service/MasterService.cs | 99 +++++++++++++++++++ .../ServiceInterfaces/IMasterService.cs | 1 + 3 files changed, 107 insertions(+) diff --git a/Marco.Pms.Services/Controllers/MasterController.cs b/Marco.Pms.Services/Controllers/MasterController.cs index 1571229..013c890 100644 --- a/Marco.Pms.Services/Controllers/MasterController.cs +++ b/Marco.Pms.Services/Controllers/MasterController.cs @@ -908,6 +908,13 @@ namespace Marco.Pms.Services.Controllers var response = await _masterService.CreateExpensesStatusAsync(dto, loggedInEmployee, tenantId); return StatusCode(response.StatusCode, response); } + [HttpPut("expenses-status/edit/{id}")] + public async Task UpdateExpensesStatus(Guid id, ExpensesStatusMasterDto dto) + { + var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); + var response = await _masterService.UpdateExpensesStatusAsync(id, dto, loggedInEmployee, tenantId); + return StatusCode(response.StatusCode, response); + } #endregion diff --git a/Marco.Pms.Services/Service/MasterService.cs b/Marco.Pms.Services/Service/MasterService.cs index 4334370..294b13c 100644 --- a/Marco.Pms.Services/Service/MasterService.cs +++ b/Marco.Pms.Services/Service/MasterService.cs @@ -12,12 +12,14 @@ using Marco.Pms.Model.ViewModels.Master; using Marco.Pms.Services.Helpers; using Marco.Pms.Services.Service.ServiceInterfaces; using MarcoBMS.Services.Service; +using Microsoft.CodeAnalysis; using Microsoft.EntityFrameworkCore; namespace Marco.Pms.Services.Service { public class MasterService : IMasterService { + private readonly IDbContextFactory _dbContextFactory; private readonly ApplicationDbContext _context; private readonly ILoggingService _logger; private readonly PermissionServices _permission; @@ -26,6 +28,7 @@ namespace Marco.Pms.Services.Service private readonly CacheUpdateHelper _cache; public MasterService( + IDbContextFactory dbContextFactory, ApplicationDbContext context, ILoggingService logger, PermissionServices permission, @@ -33,6 +36,7 @@ namespace Marco.Pms.Services.Service UtilityMongoDBHelper updateLogHelper, CacheUpdateHelper cache) { + _dbContextFactory = dbContextFactory; _context = context; _logger = logger; _permission = permission; @@ -275,6 +279,101 @@ namespace Marco.Pms.Services.Service return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); } } + public async Task> UpdateExpensesStatusAsync(Guid id, ExpensesStatusMasterDto model, Employee loggedInEmployee, Guid tenantId) + { + try + { + // Validation if employee is taking action in same tenant + if (tenantId != loggedInEmployee.TenantId) + { + _logger.LogWarning("Employee {EmployeeId} attempted to add new Expense Status in different tenant", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied", "User do not have access for this information", 403); + } + + // Checking permssion for managing masters + var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id); + if (!hasManagePermission) + { + _logger.LogWarning("Access DENIED for employee {EmployeeId} for managing EXPENSE STATUS MASTER.", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Access Denied.", "You do not have permission to Manage masters", 403); + + } + // Validating the prvided data + if (model.Id != id) + { + _logger.LogWarning("Employee {EmployeeId} provide different Ids in payload and path variable", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Invalid Data", "User has send invalid payload", 400); + } + // featching expenses status and permissions parallelly + var expensesStatusTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.ExpensesStatusMaster.AsNoTracking() + .FirstOrDefaultAsync(et => et.Id == model.Id.Value && et.TenantId == tenantId); + }); + + var permissionStatusMappingsTask = Task.Run(async () => + { + await using var dbContext = await _dbContextFactory.CreateDbContextAsync(); + return await dbContext.StatusPermissionMapping + .AsNoTracking() + .Where(ps => ps.StatusId == model.Id.Value && ps.TenantId == tenantId) + .ToListAsync(); + }); + + await Task.WhenAll(expensesStatusTask, permissionStatusMappingsTask); + var expensesStatus = expensesStatusTask.Result; + + // Checking if Expense Status exists + if (expensesStatus == null) + { + _logger.LogWarning("Employee {EmployeeId} tries to update Expense Status, but not found in database", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Expense Status not found", "Expense Status not found", 404); + } + + // Mapping ExpensesStatusMaster to BsonDocument + var existingEntityBson = _updateLogHelper.EntityToBsonDocument(expensesStatus); + + // Mapping ExpensesStatusMasterDto to ExpensesStatusMaster + _mapper.Map(model, expensesStatus); + + _context.ExpensesStatusMaster.Update(expensesStatus); + + var permissionStatusMappings = permissionStatusMappingsTask.Result; + var permissionIds = permissionStatusMappings.Select(ps => ps.PermissionId).ToList(); + if (model.PermissionIds != null) + { + var newPermissionStatusMappings = model.PermissionIds.Where(p => !permissionIds.Contains(p)).Select(p => new StatusPermissionMapping + { + PermissionId = p, + StatusId = expensesStatus.Id, + TenantId = tenantId + }).ToList(); + var deletedPermissionStatusMappings = permissionStatusMappings.Where(ps => !model.PermissionIds.Contains(ps.PermissionId)).ToList(); + + _context.StatusPermissionMapping.AddRange(newPermissionStatusMappings); + _context.StatusPermissionMapping.RemoveRange(deletedPermissionStatusMappings); + + } + await _context.SaveChangesAsync(); + + _logger.LogInfo("New Expense Status {ExpensesStatusId} was added by employee {EmployeeId}", expensesStatus.Id, loggedInEmployee.Id); + + // Mapping the ExpensesStatusMaster Model to View Model + var response = _mapper.Map(expensesStatus); + return ApiResponse.SuccessResponse(response, "Expense Status craeted Successfully", 201); + } + catch (DbUpdateException dbEx) + { + _logger.LogError(dbEx, "Database Exception occured while adding new Expense Status by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500); + } + catch (Exception ex) + { + _logger.LogError(ex, "Exception occured while adding new Expense Status by employee {EmployeeId}", loggedInEmployee.Id); + return ApiResponse.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); + } + } #endregion diff --git a/Marco.Pms.Services/Service/ServiceInterfaces/IMasterService.cs b/Marco.Pms.Services/Service/ServiceInterfaces/IMasterService.cs index e5e869c..24a26bf 100644 --- a/Marco.Pms.Services/Service/ServiceInterfaces/IMasterService.cs +++ b/Marco.Pms.Services/Service/ServiceInterfaces/IMasterService.cs @@ -15,6 +15,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces #region =================================================================== Expenses Status APIs =================================================================== Task> GetExpensesStatusListAsync(Employee loggedInEmployee, Guid tenantId); Task> CreateExpensesStatusAsync(ExpensesStatusMasterDto model, Employee loggedInEmployee, Guid tenantId); + Task> UpdateExpensesStatusAsync(Guid id, ExpensesStatusMasterDto model, Employee loggedInEmployee, Guid tenantId); #endregion #region =================================================================== Payment mode APIs ===================================================================