Added an API to update expenses status to master table for that tenant

This commit is contained in:
ashutosh.nehete 2025-07-25 12:28:06 +05:30
parent 2ad0638d4f
commit e31e19ed74
3 changed files with 107 additions and 0 deletions

View File

@ -908,6 +908,13 @@ namespace Marco.Pms.Services.Controllers
var response = await _masterService.CreateExpensesStatusAsync(dto, loggedInEmployee, tenantId); var response = await _masterService.CreateExpensesStatusAsync(dto, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response); return StatusCode(response.StatusCode, response);
} }
[HttpPut("expenses-status/edit/{id}")]
public async Task<IActionResult> 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 #endregion

View File

@ -12,12 +12,14 @@ using Marco.Pms.Model.ViewModels.Master;
using Marco.Pms.Services.Helpers; using Marco.Pms.Services.Helpers;
using Marco.Pms.Services.Service.ServiceInterfaces; using Marco.Pms.Services.Service.ServiceInterfaces;
using MarcoBMS.Services.Service; using MarcoBMS.Services.Service;
using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Marco.Pms.Services.Service namespace Marco.Pms.Services.Service
{ {
public class MasterService : IMasterService public class MasterService : IMasterService
{ {
private readonly IDbContextFactory<ApplicationDbContext> _dbContextFactory;
private readonly ApplicationDbContext _context; private readonly ApplicationDbContext _context;
private readonly ILoggingService _logger; private readonly ILoggingService _logger;
private readonly PermissionServices _permission; private readonly PermissionServices _permission;
@ -26,6 +28,7 @@ namespace Marco.Pms.Services.Service
private readonly CacheUpdateHelper _cache; private readonly CacheUpdateHelper _cache;
public MasterService( public MasterService(
IDbContextFactory<ApplicationDbContext> dbContextFactory,
ApplicationDbContext context, ApplicationDbContext context,
ILoggingService logger, ILoggingService logger,
PermissionServices permission, PermissionServices permission,
@ -33,6 +36,7 @@ namespace Marco.Pms.Services.Service
UtilityMongoDBHelper updateLogHelper, UtilityMongoDBHelper updateLogHelper,
CacheUpdateHelper cache) CacheUpdateHelper cache)
{ {
_dbContextFactory = dbContextFactory;
_context = context; _context = context;
_logger = logger; _logger = logger;
_permission = permission; _permission = permission;
@ -275,6 +279,101 @@ namespace Marco.Pms.Services.Service
return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500); return ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
} }
} }
public async Task<ApiResponse<object>> 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<object>.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<object>.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<object>.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<object>.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<ExpensesStatusMasterVM>(expensesStatus);
return ApiResponse<object>.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<object>.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<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500);
}
}
#endregion #endregion

View File

@ -15,6 +15,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
#region =================================================================== Expenses Status APIs =================================================================== #region =================================================================== Expenses Status APIs ===================================================================
Task<ApiResponse<object>> GetExpensesStatusListAsync(Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> GetExpensesStatusListAsync(Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateExpensesStatusAsync(ExpensesStatusMasterDto model, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> CreateExpensesStatusAsync(ExpensesStatusMasterDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateExpensesStatusAsync(Guid id, ExpensesStatusMasterDto model, Employee loggedInEmployee, Guid tenantId);
#endregion #endregion
#region =================================================================== Payment mode APIs =================================================================== #region =================================================================== Payment mode APIs ===================================================================