Added the API to Map Requisition Status with child

This commit is contained in:
ashutosh.nehete 2025-10-31 13:21:13 +05:30
parent 28d64c71bd
commit 8a36ffe652
6 changed files with 142 additions and 0 deletions

View File

@ -0,0 +1,9 @@
namespace Marco.Pms.Model.Dtos.Inventory
{
public class RequisitionStatusMappingDto
{
public Guid RequisitionStatusId { get; set; }
public Guid NextRequisitionStatusId { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace Marco.Pms.Model.ViewModels.Inventory
{
public class RequisitionStatusMappingVM
{
public Guid Id { get; set; }
public RequisitionStatusVM? PreviousRequisitionStatus { get; set; }
public RequisitionStatusVM? RequisitionStatus { get; set; }
public RequisitionStatusVM? NextRequisitionStatus { get; set; }
}
}

View File

@ -1064,6 +1064,14 @@ namespace Marco.Pms.Services.Controllers
return StatusCode(response.StatusCode, response); return StatusCode(response.StatusCode, response);
} }
[HttpPost("requisition-status/mapping")]
public async Task<IActionResult> AddRequisitionStatusLink([FromBody] RequisitionStatusMappingDto model)
{
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
var response = await _masterService.AddRequisitionStatusLinkAsync(model, loggedInEmployee, tenantId);
return StatusCode(response.StatusCode, response);
}
[HttpPut("requisition-status/edit/{id}")] [HttpPut("requisition-status/edit/{id}")]
public async Task<IActionResult> UpdateRequisitionStatus(Guid id, [FromBody] RequisitionStatusDto model) public async Task<IActionResult> UpdateRequisitionStatus(Guid id, [FromBody] RequisitionStatusDto model)
{ {

View File

@ -418,6 +418,7 @@ namespace Marco.Pms.Services.MappingProfiles
#region ======================================================= Requisition Status Master ======================================================= #region ======================================================= Requisition Status Master =======================================================
CreateMap<RequisitionStatusDto, RequisitionStatus>(); CreateMap<RequisitionStatusDto, RequisitionStatus>();
CreateMap<RequisitionStatus, RequisitionStatusVM>(); CreateMap<RequisitionStatus, RequisitionStatusVM>();
CreateMap<RequisitionStatusMapping, RequisitionStatusMappingVM>();
#endregion #endregion
#region ======================================================= Purchase Order Status Master ======================================================= #region ======================================================= Purchase Order Status Master =======================================================

View File

@ -3377,6 +3377,119 @@ namespace Marco.Pms.Services.Service
} }
} }
public async Task<ApiResponse<object>> AddRequisitionStatusLinkAsync(RequisitionStatusMappingDto model, Employee loggedInEmployee, Guid tenantId)
{
// Start: API entry log
_logger.LogInfo("AddRequisitionStatusLinkAsync started by Employee: {EmployeeId} for Tenant: {TenantId}", loggedInEmployee.Id, tenantId);
// Validate the Requisition Status existence
var requisitionStatus = await _context.RequisitionStatus
.FirstOrDefaultAsync(rs => rs.Id == model.RequisitionStatusId && rs.TenantId == tenantId && rs.IsActive);
if (requisitionStatus == null)
{
_logger.LogWarning("Requisition Status not found for Id: {Id}, Tenant: {TenantId}", model.RequisitionStatusId, tenantId);
return ApiResponse<object>.ErrorResponse(
"Requisition Status not found", "No active requisition status exists with the provided Id.", 404);
}
// Validate the Next Requisition Status existence
var nextRequisitionStatus = await _context.RequisitionStatus
.FirstOrDefaultAsync(rs => rs.Id == model.NextRequisitionStatusId && rs.TenantId == tenantId && rs.IsActive);
if (nextRequisitionStatus == null)
{
_logger.LogWarning("Next Requisition Status not found for Id: {Id}, Tenant: {TenantId}", model.NextRequisitionStatusId, tenantId);
return ApiResponse<object>.ErrorResponse(
"Next Requisition Status not found", "No active next requisition status exists with the provided Id.", 404);
}
try
{
if (model.IsActive)
{
// Check if mapping already exists
var alreadyExists = await _context.RequisitionStatusMappings
.AnyAsync(rsm => rsm.RequisitionStatusId == model.RequisitionStatusId
&& rsm.NextRequisitionStatusId == model.NextRequisitionStatusId);
if (alreadyExists)
{
_logger.LogWarning("Duplicate mapping attempted between {RequisitionStatusId} and {NextRequisitionStatusId}", model.RequisitionStatusId, model.NextRequisitionStatusId);
return ApiResponse<object>.ErrorResponse(
"Mapping already exists", "A mapping between these statuses already exists.", 409);
}
// Prevent mapping if next status already has a parent
var hasParent = await _context.RequisitionStatusMappings
.AnyAsync(rsm => rsm.NextRequisitionStatusId == model.NextRequisitionStatusId);
if (hasParent)
{
_logger.LogWarning("Next Requisition Status {NextRequisitionStatusId} already has a parent, cannot re-map.", model.NextRequisitionStatusId);
return ApiResponse<object>.ErrorResponse(
$"Requisition \"{nextRequisitionStatus.Name}\" already has a parent and cannot be mapped again.",
$"Requisition \"{nextRequisitionStatus.Name}\" already has a parent and cannot be mapped again.", 409);
}
// Find any previous mapping for ordering/trace
var previousMapping = await _context.RequisitionStatusMappings
.Include(rsm => rsm.RequisitionStatus)
.FirstOrDefaultAsync(rsm => rsm.NextRequisitionStatusId == model.RequisitionStatusId);
// Create a new mapping
var newMapping = new RequisitionStatusMapping
{
Id = Guid.NewGuid(),
PreviousRequisitionStatusId = previousMapping?.RequisitionStatusId,
RequisitionStatusId = requisitionStatus.Id,
NextRequisitionStatusId = nextRequisitionStatus.Id,
TenantId = tenantId
};
_context.RequisitionStatusMappings.Add(newMapping);
await _context.SaveChangesAsync();
_logger.LogInfo("Created mapping: {Id} from {RequisitionStatusId} to {NextRequisitionStatusId} for Tenant {TenantId}", newMapping.Id, requisitionStatus.Id, nextRequisitionStatus.Id, tenantId);
var vm = new RequisitionStatusMappingVM
{
Id = newMapping.Id,
PreviousRequisitionStatus = _mapper.Map<RequisitionStatusVM>(previousMapping?.RequisitionStatus),
RequisitionStatus = _mapper.Map<RequisitionStatusVM>(requisitionStatus),
NextRequisitionStatus = _mapper.Map<RequisitionStatusVM>(nextRequisitionStatus)
};
return ApiResponse<object>.SuccessResponse(vm, "Requisition Status mapping added successfully.", 200);
}
else
{
// Remove mapping
var mapping = await _context.RequisitionStatusMappings
.Include(rsm => rsm.PreviousRequisitionStatus)
.Include(rsm => rsm.RequisitionStatus)
.Include(rsm => rsm.NextRequisitionStatus)
.FirstOrDefaultAsync(rsm => rsm.RequisitionStatusId == model.RequisitionStatusId
&& rsm.NextRequisitionStatusId == model.NextRequisitionStatusId);
if (mapping == null)
{
_logger.LogWarning("No mapping found to remove for {RequisitionStatusId} to {NextRequisitionStatusId}", model.RequisitionStatusId, model.NextRequisitionStatusId);
return ApiResponse<object>.ErrorResponse("Mapping not found", "No mapping exists to remove.", 404);
}
_context.RequisitionStatusMappings.Remove(mapping);
await _context.SaveChangesAsync();
_logger.LogInfo("Mapping removed: {Id} from {RequisitionStatusId} to {NextRequisitionStatusId}", mapping.Id, model.RequisitionStatusId, model.NextRequisitionStatusId);
var vm = _mapper.Map<RequisitionStatusMappingVM>(mapping);
return ApiResponse<object>.SuccessResponse(vm, "Requisition Status mapping removed successfully.", 200);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing AddRequisitionStatusLinkAsync for Tenant: {TenantId}, Employee: {EmployeeId}", tenantId, loggedInEmployee.Id);
return ApiResponse<object>.ErrorResponse("Internal Server Error", "An error occurred while processing your request.", 500);
}
}
public async Task<ApiResponse<object>> UpdateRequisitionStatusAsync(Guid id, RequisitionStatusDto model, Employee loggedInEmployee, Guid tenantId) public async Task<ApiResponse<object>> UpdateRequisitionStatusAsync(Guid id, RequisitionStatusDto model, Employee loggedInEmployee, Guid tenantId)
{ {
try try

View File

@ -139,6 +139,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
Task<ApiResponse<object>> GetRequisitionStatusListAsync(bool isActive, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> GetRequisitionStatusListAsync(bool isActive, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> GetRequisitionStatusDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> GetRequisitionStatusDetailsAsync(Guid id, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> CreateRequisitionStatusAsync(RequisitionStatusDto model, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> CreateRequisitionStatusAsync(RequisitionStatusDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> AddRequisitionStatusLinkAsync(RequisitionStatusMappingDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> UpdateRequisitionStatusAsync(Guid id, RequisitionStatusDto model, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> UpdateRequisitionStatusAsync(Guid id, RequisitionStatusDto model, Employee loggedInEmployee, Guid tenantId);
Task<ApiResponse<object>> DeleteRequisitionStatusAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId); Task<ApiResponse<object>> DeleteRequisitionStatusAsync(Guid id, bool active, Employee loggedInEmployee, Guid tenantId);
#endregion #endregion