initial commit
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using Indotalent.ConfigBackEnd.Exceptions;
|
||||
using Indotalent.ConfigBackEnd.Extensions;
|
||||
using Indotalent.Infrastructure.Database;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Indotalent.Features.Payroll.Payrolls.Cqrs;
|
||||
|
||||
public class CreatePayrollProcessRequest
|
||||
{
|
||||
public string? PeriodName { get; set; }
|
||||
public DateTime? FromDate { get; set; }
|
||||
public DateTime? ToDate { get; set; }
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
|
||||
public class CreatePayrollProcessResponse
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
public string? AutoNumber { get; set; }
|
||||
}
|
||||
|
||||
public record CreatePayrollProcessCommand(CreatePayrollProcessRequest Data) : IRequest<CreatePayrollProcessResponse>;
|
||||
|
||||
public class CreatePayrollProcessHandler : IRequestHandler<CreatePayrollProcessCommand, CreatePayrollProcessResponse>
|
||||
{
|
||||
private readonly AppDbContext _context;
|
||||
|
||||
public CreatePayrollProcessHandler(AppDbContext context) => _context = context;
|
||||
|
||||
public async Task<CreatePayrollProcessResponse> Handle(CreatePayrollProcessCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var isExists = await _context.PayrollProcess
|
||||
.AnyAsync(x => x.PeriodName == request.Data.PeriodName, cancellationToken);
|
||||
|
||||
if (isExists)
|
||||
{
|
||||
throw new AlreadyExistsException("Payroll Period", request.Data.PeriodName ?? string.Empty);
|
||||
}
|
||||
|
||||
var entityName = nameof(Data.Entities.PayrollProcess);
|
||||
|
||||
var autoNo = await _context.GenerateAutoNumberAsync(
|
||||
entityName: entityName,
|
||||
prefixTemplate: $"PAY/{request.Data.FromDate?.ToString("yyyyMM") ?? DateTime.Now.ToString("yyyyMM")}/",
|
||||
ct: cancellationToken
|
||||
);
|
||||
|
||||
var payrollProcess = new Data.Entities.PayrollProcess
|
||||
{
|
||||
AutoNumber = autoNo,
|
||||
PeriodName = request.Data.PeriodName,
|
||||
FromDate = request.Data.FromDate ?? DateTime.Now,
|
||||
ToDate = request.Data.ToDate ?? DateTime.Now,
|
||||
Description = request.Data.Description,
|
||||
Status = "Draft",
|
||||
ProcessedBy = "System Admin",
|
||||
ProcessedAt = DateTime.Now
|
||||
};
|
||||
|
||||
var employees = await _context.Employee
|
||||
.Include(x => x.EmployeeIncome)
|
||||
.Include(x => x.EmployeeDeduction)
|
||||
.Where(x => x.EmployeeStatus == "Active")
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
decimal grandBasicSalary = 0;
|
||||
decimal grandTotalIncome = 0;
|
||||
decimal grandTotalDeduction = 0;
|
||||
|
||||
foreach (var emp in employees)
|
||||
{
|
||||
var totalIncome = emp.EmployeeIncome?.Sum(x => x.Amount) ?? 0m;
|
||||
var totalDeduction = emp.EmployeeDeduction?.Sum(x => x.Amount) ?? 0m;
|
||||
var takeHomePay = emp.BasicSalary + totalIncome - totalDeduction;
|
||||
|
||||
var detail = new Data.Entities.PayrollDetail
|
||||
{
|
||||
PayrollProcess = payrollProcess,
|
||||
EmployeeId = emp.Id,
|
||||
EmployeeCode = emp.Code,
|
||||
EmployeeName = $"{emp.FirstName} {emp.LastName}",
|
||||
BasicSalary = emp.BasicSalary,
|
||||
TotalIncome = totalIncome,
|
||||
TotalDeduction = totalDeduction,
|
||||
TakeHomePay = takeHomePay
|
||||
};
|
||||
|
||||
if (emp.EmployeeIncome != null)
|
||||
{
|
||||
foreach (var inc in emp.EmployeeIncome)
|
||||
{
|
||||
detail.Components.Add(new Data.Entities.PayrollComponent
|
||||
{
|
||||
PayrollDetail = detail,
|
||||
ComponentName = "Income Component",
|
||||
ComponentType = "Income",
|
||||
Amount = inc.Amount,
|
||||
Description = inc.Description
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (emp.EmployeeDeduction != null)
|
||||
{
|
||||
foreach (var ded in emp.EmployeeDeduction)
|
||||
{
|
||||
detail.Components.Add(new Data.Entities.PayrollComponent
|
||||
{
|
||||
PayrollDetail = detail,
|
||||
ComponentName = "Deduction Component",
|
||||
ComponentType = "Deduction",
|
||||
Amount = ded.Amount,
|
||||
Description = ded.Description
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
grandBasicSalary += detail.BasicSalary;
|
||||
grandTotalIncome += totalIncome;
|
||||
grandTotalDeduction += totalDeduction;
|
||||
|
||||
_context.PayrollDetail.Add(detail);
|
||||
}
|
||||
|
||||
payrollProcess.TotalEmployees = employees.Count;
|
||||
payrollProcess.TotalBasicSalary = grandBasicSalary;
|
||||
payrollProcess.TotalIncome = grandTotalIncome;
|
||||
payrollProcess.TotalDeduction = grandTotalDeduction;
|
||||
payrollProcess.TotalGross = grandBasicSalary + grandTotalIncome;
|
||||
payrollProcess.TotalTakeHomePay = payrollProcess.TotalGross - grandTotalDeduction;
|
||||
|
||||
_context.PayrollProcess.Add(payrollProcess);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new CreatePayrollProcessResponse
|
||||
{
|
||||
Id = payrollProcess.Id,
|
||||
AutoNumber = payrollProcess.AutoNumber
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user