This commit is contained in:
2026-09-13 08:30:18 +05:30
parent cb41d503c4
commit 99aa395fb1
41 changed files with 3454 additions and 506 deletions
@@ -127,6 +127,22 @@ public sealed class DepartmentService : IDepartmentService
await _uow.SaveChangesAsync(ct);
}
public async Task DeleteAsync(int departmentId, CancellationToken ct = default)
{
var dept = await _departments.GetByIdAsync(departmentId, ct)
?? throw new NotFoundException($"Department {departmentId} was not found.");
_departments.Remove(dept);
try
{
await _uow.SaveChangesAsync(ct);
}
catch (DbUpdateException)
{
throw new DomainException(ErrorCodes.MasterInUse, "This department is referenced by other records (sub-departments or employees) and cannot be deleted.", 409);
}
}
/// <summary>Walks up from <paramref name="newParentId"/>; throws if it ever reaches <paramref name="departmentId"/>.</summary>
private async Task EnsureNoCycleAsync(int departmentId, int newParentId, CancellationToken ct)
{
@@ -101,5 +101,21 @@ public sealed class DesignationService : IDesignationService
await _uow.SaveChangesAsync(ct);
}
public async Task DeleteAsync(int designationId, CancellationToken ct = default)
{
var designation = await _designations.GetByIdAsync(designationId, ct)
?? throw new NotFoundException($"Designation {designationId} was not found.");
_designations.Remove(designation);
try
{
await _uow.SaveChangesAsync(ct);
}
catch (DbUpdateException)
{
throw new DomainException(ErrorCodes.MasterInUse, "This designation is referenced by other records and cannot be deleted.", 409);
}
}
private static DesignationDto Map(Designation d) => new(d.DesignationId, d.Code, d.Name, d.Status, d.CreatedAt, d.UpdatedAt);
}
@@ -101,5 +101,21 @@ public sealed class EmploymentTypeService : IEmploymentTypeService
await _uow.SaveChangesAsync(ct);
}
public async Task DeleteAsync(int employmentTypeId, CancellationToken ct = default)
{
var et = await _employmentTypes.GetByIdAsync(employmentTypeId, ct)
?? throw new NotFoundException($"Employment type {employmentTypeId} was not found.");
_employmentTypes.Remove(et);
try
{
await _uow.SaveChangesAsync(ct);
}
catch (DbUpdateException)
{
throw new DomainException(ErrorCodes.MasterInUse, "This employment type is referenced by other records and cannot be deleted.", 409);
}
}
private static EmploymentTypeDto Map(EmploymentType e) => new(e.EmploymentTypeId, e.Code, e.Name, e.Status, e.CreatedAt, e.UpdatedAt);
}
@@ -108,6 +108,22 @@ public sealed class HrDocumentTypeService : IHrDocumentTypeService
await _uow.SaveChangesAsync(ct);
}
public async Task DeleteAsync(int hrDocumentTypeId, CancellationToken ct = default)
{
var type = await _types.GetByIdAsync(hrDocumentTypeId, ct)
?? throw new NotFoundException($"Document type {hrDocumentTypeId} was not found.");
_types.Remove(type);
try
{
await _uow.SaveChangesAsync(ct);
}
catch (DbUpdateException)
{
throw new DomainException(ErrorCodes.MasterInUse, "This document type is referenced by other records and cannot be deleted.", 409);
}
}
private static HrDocumentTypeDto Map(HrDocumentType t) => new(
t.HrDocumentTypeId, t.Code, t.Name, t.Category, t.RequiredAtOnboarding, t.ExpiryTracked, t.Status, t.CreatedAt, t.UpdatedAt);
}
@@ -43,6 +43,11 @@ public sealed class LeaveRequestService : ILeaveRequestService
var q = _requests.Query().AsNoTracking().Include(r => r.Employee).Include(r => r.LeaveType).AsQueryable();
if (employeeId is not null) q = q.Where(r => r.EmployeeId == employeeId);
if (status is not null) q = q.Where(r => r.Status == status);
if (!string.IsNullOrWhiteSpace(query.Q))
{
var term = query.Q.Trim();
q = q.Where(r => EF.Functions.ILike(r.DocNo, $"%{term}%") || EF.Functions.ILike(r.Employee!.FullName, $"%{term}%"));
}
var total = await q.CountAsync(ct);
var rows = await q.OrderByDescending(r => r.CreatedAt)
@@ -113,6 +113,22 @@ public sealed class LeaveTypeService : ILeaveTypeService
await _uow.SaveChangesAsync(ct);
}
public async Task DeleteAsync(int leaveTypeId, CancellationToken ct = default)
{
var type = await _types.GetByIdAsync(leaveTypeId, ct)
?? throw new NotFoundException($"Leave type {leaveTypeId} was not found.");
_types.Remove(type);
try
{
await _uow.SaveChangesAsync(ct);
}
catch (DbUpdateException)
{
throw new DomainException(ErrorCodes.MasterInUse, "This leave type is referenced by other records and cannot be deleted.", 409);
}
}
private static LeaveTypeDto Map(LeaveType t) => new(
t.LeaveTypeId, t.Code, t.Name, t.IsPaid, t.CountsAsNoPay, t.AccrualPerYear,
t.CarryForwardAllowed, t.MaxCarryForwardDays, t.RequiresApproval, t.Status, t.CreatedAt, t.UpdatedAt);
@@ -107,6 +107,22 @@ public sealed class SalaryComponentService : ISalaryComponentService
await _uow.SaveChangesAsync(ct);
}
public async Task DeleteAsync(int salaryComponentId, CancellationToken ct = default)
{
var component = await _components.GetByIdAsync(salaryComponentId, ct)
?? throw new NotFoundException($"Salary component {salaryComponentId} was not found.");
_components.Remove(component);
try
{
await _uow.SaveChangesAsync(ct);
}
catch (DbUpdateException)
{
throw new DomainException(ErrorCodes.MasterInUse, "This salary component is referenced by other records and cannot be deleted.", 409);
}
}
private static SalaryComponentDto Map(SalaryComponent c) => new(
c.SalaryComponentId, c.Code, c.Name, c.ComponentType, c.IsTaxable, c.IsEpfEtfApplicable, c.Status, c.CreatedAt, c.UpdatedAt);
}
@@ -120,6 +120,22 @@ public sealed class WorkShiftService : IWorkShiftService
await _uow.SaveChangesAsync(ct);
}
public async Task DeleteAsync(int workShiftId, CancellationToken ct = default)
{
var shift = await _shifts.GetByIdAsync(workShiftId, ct)
?? throw new NotFoundException($"Work shift {workShiftId} was not found.");
_shifts.Remove(shift);
try
{
await _uow.SaveChangesAsync(ct);
}
catch (DbUpdateException)
{
throw new DomainException(ErrorCodes.MasterInUse, "This work shift is referenced by other records and cannot be deleted.", 409);
}
}
private static WorkShiftDto Map(WorkShift w) => new(
w.WorkShiftId, w.Code, w.Name, w.StartTime, w.EndTime, w.IsOvernight,
w.GraceMinutes, w.BreakMinutes, w.StandardWorkingMinutes, w.OtMultiplier, w.WorkingDaysMask,
@@ -13,4 +13,5 @@ public interface IDepartmentService
Task<ETagged<DepartmentDto>> CreateAsync(CreateDepartmentRequest request, CancellationToken ct = default);
Task<ETagged<DepartmentDto>> UpdateAsync(int departmentId, UpdateDepartmentRequest request, uint expectedRowVersion, CancellationToken ct = default);
Task SetStatusAsync(int departmentId, EntityStatus status, CancellationToken ct = default);
Task DeleteAsync(int departmentId, CancellationToken ct = default);
}
@@ -12,4 +12,5 @@ public interface IDesignationService
Task<ETagged<DesignationDto>> CreateAsync(CreateDesignationRequest request, CancellationToken ct = default);
Task<ETagged<DesignationDto>> UpdateAsync(int designationId, UpdateDesignationRequest request, uint expectedRowVersion, CancellationToken ct = default);
Task SetStatusAsync(int designationId, EntityStatus status, CancellationToken ct = default);
Task DeleteAsync(int designationId, CancellationToken ct = default);
}
@@ -12,4 +12,5 @@ public interface IEmploymentTypeService
Task<ETagged<EmploymentTypeDto>> CreateAsync(CreateEmploymentTypeRequest request, CancellationToken ct = default);
Task<ETagged<EmploymentTypeDto>> UpdateAsync(int employmentTypeId, UpdateEmploymentTypeRequest request, uint expectedRowVersion, CancellationToken ct = default);
Task SetStatusAsync(int employmentTypeId, EntityStatus status, CancellationToken ct = default);
Task DeleteAsync(int employmentTypeId, CancellationToken ct = default);
}
@@ -13,4 +13,5 @@ public interface IHrDocumentTypeService
Task<ETagged<HrDocumentTypeDto>> CreateAsync(CreateHrDocumentTypeRequest request, CancellationToken ct = default);
Task<ETagged<HrDocumentTypeDto>> UpdateAsync(int hrDocumentTypeId, UpdateHrDocumentTypeRequest request, uint expectedRowVersion, CancellationToken ct = default);
Task SetStatusAsync(int hrDocumentTypeId, EntityStatus status, CancellationToken ct = default);
Task DeleteAsync(int hrDocumentTypeId, CancellationToken ct = default);
}
@@ -12,4 +12,5 @@ public interface ILeaveTypeService
Task<ETagged<LeaveTypeDto>> CreateAsync(CreateLeaveTypeRequest request, CancellationToken ct = default);
Task<ETagged<LeaveTypeDto>> UpdateAsync(int leaveTypeId, UpdateLeaveTypeRequest request, uint expectedRowVersion, CancellationToken ct = default);
Task SetStatusAsync(int leaveTypeId, EntityStatus status, CancellationToken ct = default);
Task DeleteAsync(int leaveTypeId, CancellationToken ct = default);
}
@@ -12,4 +12,5 @@ public interface ISalaryComponentService
Task<ETagged<SalaryComponentDto>> CreateAsync(CreateSalaryComponentRequest request, CancellationToken ct = default);
Task<ETagged<SalaryComponentDto>> UpdateAsync(int salaryComponentId, UpdateSalaryComponentRequest request, uint expectedRowVersion, CancellationToken ct = default);
Task SetStatusAsync(int salaryComponentId, EntityStatus status, CancellationToken ct = default);
Task DeleteAsync(int salaryComponentId, CancellationToken ct = default);
}
@@ -12,4 +12,5 @@ public interface IWorkShiftService
Task<ETagged<WorkShiftDto>> CreateAsync(CreateWorkShiftRequest request, CancellationToken ct = default);
Task<ETagged<WorkShiftDto>> UpdateAsync(int workShiftId, UpdateWorkShiftRequest request, uint expectedRowVersion, CancellationToken ct = default);
Task SetStatusAsync(int workShiftId, EntityStatus status, CancellationToken ct = default);
Task DeleteAsync(int workShiftId, CancellationToken ct = default);
}