Added the CRUD API for Payment Adjustment heads
This commit is contained in:
parent
302185808e
commit
8c305872a0
@ -0,0 +1,9 @@
|
||||
namespace Marco.Pms.Model.Dtos.Collection
|
||||
{
|
||||
public class PaymentAdjustmentHeadDto
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
public required string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Dtos.Activities;
|
||||
using Marco.Pms.Model.Dtos.Collection;
|
||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.Master;
|
||||
using Marco.Pms.Model.Forum;
|
||||
@ -984,6 +985,29 @@ namespace Marco.Pms.Services.Controllers
|
||||
var response = await _masterService.GetPaymentAdjustmentHeadListAsync(isActive, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
[HttpPost("payment-adjustment-head")]
|
||||
public async Task<IActionResult> CreatePaymentAdjustmentHead([FromBody] PaymentAdjustmentHeadDto dto)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.CreatePaymentAdjustmentHeadAsync(dto, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpPut("payment-adjustment-head/edit/{id}")]
|
||||
public async Task<IActionResult> UpdatePaymentAdjustmentHead(Guid id, [FromBody] PaymentAdjustmentHeadDto dto)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.UpdatePaymentAdjustmentHeadAsync(id, dto, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpDelete("payment-adjustment-head/delete/{id}")]
|
||||
public async Task<IActionResult> DeletePaymentAdjustmentHead(Guid id, [FromQuery] bool isActive = false)
|
||||
{
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _masterService.DeletePaymentAdjustmentHeadAsync(id, isActive, loggedInEmployee, tenantId);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -269,8 +269,6 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
CreateMap<InvoiceComment, InvoiceCommentVM>();
|
||||
|
||||
CreateMap<InvoiceAttachment, InvoiceAttachmentVM>();
|
||||
|
||||
CreateMap<PaymentAdjustmentHead, PaymentAdjustmentHeadVM>();
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Master =======================================================
|
||||
@ -402,19 +400,27 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
CreateMap<UpdateContactCategoryDto, ContactCategoryMaster>();
|
||||
CreateMap<ContactCategoryMaster, ContactCategoryVM>();
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Contact Tag Master =======================================================
|
||||
CreateMap<CreateContactTagDto, ContactTagMaster>();
|
||||
CreateMap<UpdateContactTagDto, ContactTagMaster>();
|
||||
CreateMap<ContactTagMaster, ContactTagVM>();
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Payment Adjustment Head Master =======================================================
|
||||
CreateMap<PaymentAdjustmentHeadDto, PaymentAdjustmentHead>();
|
||||
CreateMap<PaymentAdjustmentHead, PaymentAdjustmentHeadVM>();
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Expenses Status Master =======================================================
|
||||
#endregion
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
using AutoMapper;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Helpers.Utility;
|
||||
using Marco.Pms.Model.Collection;
|
||||
using Marco.Pms.Model.Directory;
|
||||
using Marco.Pms.Model.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.Activities;
|
||||
using Marco.Pms.Model.Dtos.Collection;
|
||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.Master;
|
||||
using Marco.Pms.Model.Employees;
|
||||
@ -2881,6 +2883,7 @@ namespace Marco.Pms.Services.Service
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Payment Adjustment Head APIs ===================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a list of payment adjustment heads for a specific tenant with optional active status filtering.
|
||||
/// </summary>
|
||||
@ -2920,6 +2923,205 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new payment adjustment head for the specified tenant after permission and uniqueness checks.
|
||||
/// </summary>
|
||||
/// <param name="model">DTO containing payment adjustment head data</param>
|
||||
/// <param name="loggedInEmployee">The employee performing the action</param>
|
||||
/// <param name="tenantId">The tenant identifier</param>
|
||||
/// <returns>API response with status and context</returns>
|
||||
public async Task<ApiResponse<object>> CreatePaymentAdjustmentHeadAsync(PaymentAdjustmentHeadDto model, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Permission validation
|
||||
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasManagePermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied for employee {EmployeeId} attempting to create payment adjustment head for tenant {TenantId}.", loggedInEmployee.Id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to manage masters.", 403);
|
||||
}
|
||||
|
||||
// Uniqueness check for payment adjustment head name
|
||||
var nameExists = await _context.PaymentAdjustmentHeads
|
||||
.AnyAsync(pah => pah.Name == model.Name && pah.TenantId == tenantId);
|
||||
if (nameExists)
|
||||
{
|
||||
_logger.LogInfo("Duplicate payment adjustment head name '{Name}' detected for tenant {TenantId}.", model.Name, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("A payment adjustment head with this name already exists.", "Name of payment adjustment head already exists.", 409);
|
||||
}
|
||||
|
||||
// Create and persist new entity
|
||||
var paymentAdjustmentHead = _mapper.Map<PaymentAdjustmentHead>(model);
|
||||
paymentAdjustmentHead.IsActive = true;
|
||||
paymentAdjustmentHead.TenantId = tenantId;
|
||||
|
||||
_context.PaymentAdjustmentHeads.Add(paymentAdjustmentHead);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var response = _mapper.Map<PaymentAdjustmentHeadVM>(paymentAdjustmentHead);
|
||||
|
||||
_logger.LogInfo("Payment adjustment head '{Name}' created successfully by employee {EmployeeId} for tenant {TenantId}.", paymentAdjustmentHead.Name, loggedInEmployee.Id, tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, "Payment adjustment head created successfully.", 201);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log full context with exception for easier debugging
|
||||
_logger.LogError(ex, "Exception while creating payment adjustment head. Employee: {EmployeeId}, Tenant: {TenantId}, Data: {@Model}", loggedInEmployee.Id, tenantId, model);
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred.", "Unable to create payment adjustment head at this moment.", 500);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing payment adjustment head for a specified tenant after performing
|
||||
/// necessary validation, permission, and uniqueness checks.
|
||||
/// </summary>
|
||||
/// <param name="id">Unique identifier of the payment adjustment head to update</param>
|
||||
/// <param name="model">DTO containing updated payment adjustment head data</param>
|
||||
/// <param name="loggedInEmployee">The employee performing the action</param>
|
||||
/// <param name="tenantId">The tenant identifier</param>
|
||||
/// <returns>API response object with update result and status message</returns>
|
||||
public async Task<ApiResponse<object>> UpdatePaymentAdjustmentHeadAsync(Guid id, PaymentAdjustmentHeadDto model, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// --- Step 1: Validate request payload correctness ---
|
||||
if (!model.Id.HasValue || model.Id != id)
|
||||
{
|
||||
_logger.LogWarning("Invalid ID provided in request. Model ID: {ModelId}, Route ID: {RouteId}, TenantId: {TenantId}", model.Id ?? Guid.Empty, id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Invalid request.", "Provided invalid ID.", 400);
|
||||
}
|
||||
|
||||
// --- Step 2: Validate permissions ---
|
||||
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasManagePermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied for employee {EmployeeId} attempting to update payment adjustment head for tenant {TenantId}.", loggedInEmployee.Id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to manage masters.", 403);
|
||||
}
|
||||
|
||||
// --- Step 3: Validate uniqueness constraint for name ---
|
||||
var nameExists = await _context.PaymentAdjustmentHeads
|
||||
.AnyAsync(pah => pah.Name == model.Name && pah.Id != id && pah.TenantId == tenantId);
|
||||
|
||||
if (nameExists)
|
||||
{
|
||||
_logger.LogInfo("Duplicate payment adjustment head name '{Name}' detected during update for tenant {TenantId}.", model.Name, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Conflict detected.", "A payment adjustment head with this name already exists.", 409);
|
||||
}
|
||||
|
||||
// --- Step 4: Retrieve and validate existing entity ---
|
||||
var paymentAdjustmentHead = await _context.PaymentAdjustmentHeads
|
||||
.FirstOrDefaultAsync(pah => pah.Id == id && pah.TenantId == tenantId);
|
||||
|
||||
if (paymentAdjustmentHead == null)
|
||||
{
|
||||
_logger.LogWarning("Payment adjustment head with ID {Id} not found for tenant {TenantId}.", id, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Not Found.", "Payment adjustment head not found.", 404);
|
||||
}
|
||||
|
||||
// Mapping PaymentAdjustmentHead to BsonDocument
|
||||
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(paymentAdjustmentHead);
|
||||
|
||||
// --- Step 5: Map changes and update entity ---
|
||||
_mapper.Map(model, paymentAdjustmentHead);
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
await _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
|
||||
{
|
||||
EntityId = paymentAdjustmentHead.Id.ToString(),
|
||||
UpdatedById = loggedInEmployee.Id.ToString(),
|
||||
OldObject = existingEntityBson,
|
||||
UpdatedAt = DateTime.UtcNow
|
||||
}, "PaymentAdjustmentHeadModificationLog");
|
||||
|
||||
_logger.LogInfo("Payment adjustment head '{Name}' updated successfully by employee {EmployeeId} for tenant {TenantId}.", paymentAdjustmentHead.Name, loggedInEmployee.Id, tenantId);
|
||||
|
||||
var response = _mapper.Map<PaymentAdjustmentHeadVM>(paymentAdjustmentHead);
|
||||
|
||||
// --- Step 6: Return structured success response ---
|
||||
return ApiResponse<object>.SuccessResponse(response, "Payment adjustment head updated successfully.", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// --- Step 7: Handle and log exceptions with full context ---
|
||||
_logger.LogError(ex, "Exception while updating payment adjustment head. Employee: {EmployeeId}, Tenant: {TenantId}, Model: {@Model}", loggedInEmployee.Id, tenantId, model);
|
||||
|
||||
return ApiResponse<object>.ErrorResponse("An unexpected error occurred.", "Unable to update payment adjustment head at this moment.", 500);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates or deactivates a payment adjustment head (soft delete/restore) for a tenant,
|
||||
/// including audit logging and permission validation.
|
||||
/// </summary>
|
||||
/// <param name="id">Unique identifier of the payment adjustment head</param>
|
||||
/// <param name="isActive">Flag indicating activation (restore) or deactivation (delete)</param>
|
||||
/// <param name="loggedInEmployee">Employee requesting the operation</param>
|
||||
/// <param name="tenantId">The tenant identifier</param>
|
||||
/// <returns>API response object with operation status</returns>
|
||||
public async Task<ApiResponse<object>> DeletePaymentAdjustmentHeadAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId)
|
||||
{
|
||||
// Dynamically select operation word for logs and messages
|
||||
var operation = isActive ? "restore" : "delete";
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: Permission check
|
||||
var hasManagePermission = await _permission.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasManagePermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied: Employee {EmployeeId} attempted to {Operation} payment adjustment head for tenant {TenantId}.",
|
||||
loggedInEmployee.Id, operation, tenantId);
|
||||
return ApiResponse<object>.ErrorResponse("Access Denied.", "You do not have permission to manage masters.", 403);
|
||||
}
|
||||
|
||||
// Step 2: Entity existence check
|
||||
var paymentAdjustmentHead = await _context.PaymentAdjustmentHeads
|
||||
.FirstOrDefaultAsync(pah => pah.Id == id && pah.TenantId == tenantId);
|
||||
|
||||
if (paymentAdjustmentHead == null)
|
||||
{
|
||||
_logger.LogWarning("Payment adjustment head with ID {Id} not found for tenant {TenantId} (attempted {Operation}).",
|
||||
id, tenantId, operation);
|
||||
return ApiResponse<object>.ErrorResponse("Not Found.", "Payment adjustment head not found.", 404);
|
||||
}
|
||||
|
||||
// Step 3: Save pre-update state for audit log
|
||||
var existingEntityBson = _updateLogHelper.EntityToBsonDocument(paymentAdjustmentHead);
|
||||
|
||||
// Step 4: Update IsActive status
|
||||
paymentAdjustmentHead.IsActive = isActive;
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// Step 5: Push update action to audit log
|
||||
await _updateLogHelper.PushToUpdateLogsAsync(new UpdateLogsObject
|
||||
{
|
||||
EntityId = paymentAdjustmentHead.Id.ToString(),
|
||||
UpdatedById = loggedInEmployee.Id.ToString(),
|
||||
OldObject = existingEntityBson,
|
||||
UpdatedAt = DateTime.UtcNow
|
||||
}, "PaymentAdjustmentHeadModificationLog");
|
||||
|
||||
_logger.LogInfo(
|
||||
"Payment adjustment head (ID: {Id}, Name: {Name}) successfully {Operation}d by employee {EmployeeId} for tenant {TenantId}.",
|
||||
paymentAdjustmentHead.Id, paymentAdjustmentHead.Name, operation, loggedInEmployee.Id, tenantId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(new { }, $"Payment adjustment head {operation}d successfully.", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex,
|
||||
"Exception occurred while performing {Operation} on payment adjustment head (ID: {Id}) for tenant {TenantId}.",
|
||||
operation, id, tenantId);
|
||||
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred.", $"Exception occurred while trying to {operation} payment adjustment head.", 500);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Helper Function ===================================================================
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Marco.Pms.Model.Dtos.Activities;
|
||||
using Marco.Pms.Model.Dtos.Collection;
|
||||
using Marco.Pms.Model.Dtos.DocumentManager;
|
||||
using Marco.Pms.Model.Dtos.Master;
|
||||
using Marco.Pms.Model.Employees;
|
||||
@ -108,6 +109,9 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
|
||||
#region =================================================================== Payment Adjustment Head APIs ===================================================================
|
||||
Task<ApiResponse<object>> GetPaymentAdjustmentHeadListAsync(bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> CreatePaymentAdjustmentHeadAsync(PaymentAdjustmentHeadDto model, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> UpdatePaymentAdjustmentHeadAsync(Guid id, PaymentAdjustmentHeadDto model, Employee loggedInEmployee, Guid tenantId);
|
||||
Task<ApiResponse<object>> DeletePaymentAdjustmentHeadAsync(Guid id, bool isActive, Employee loggedInEmployee, Guid tenantId);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user