124 lines
4.9 KiB
C#
124 lines
4.9 KiB
C#
using CatHasPawsContratcs.BusinessLogicsContracts;
|
||
using CatHasPawsContratcs.DataModels;
|
||
using CatHasPawsContratcs.Exceptions;
|
||
using CatHasPawsContratcs.Extensions;
|
||
using CatHasPawsContratcs.Infrastructure;
|
||
using CatHasPawsContratcs.Infrastructure.PostConfigurations;
|
||
using CatHasPawsContratcs.Resources;
|
||
using CatHasPawsContratcs.StoragesContracts;
|
||
using Microsoft.Extensions.Localization;
|
||
using Microsoft.Extensions.Logging;
|
||
|
||
namespace CatHasPawsBusinessLogic.Implementations;
|
||
|
||
internal class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageContract, ISaleStorageContract saleStorageContract, IPostStorageContract postStorageContract, IWorkerStorageContract workerStorageContract, IStringLocalizer<Messages> localizer, ILogger logger, IConfigurationSalary сonfiguration) : ISalaryBusinessLogicContract
|
||
{
|
||
private readonly ILogger _logger = logger;
|
||
private readonly ISalaryStorageContract _salaryStorageContract = salaryStorageContract;
|
||
private readonly ISaleStorageContract _saleStorageContract = saleStorageContract;
|
||
private readonly IPostStorageContract _postStorageContract = postStorageContract;
|
||
private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract;
|
||
private readonly IConfigurationSalary _salaryConfiguration = сonfiguration;
|
||
private readonly IStringLocalizer<Messages> _localizer = localizer;
|
||
private readonly Lock _lockObject = new();
|
||
|
||
public List<SalaryDataModel> GetAllSalariesByPeriod(DateTime fromDate, DateTime toDate)
|
||
{
|
||
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}", fromDate, toDate);
|
||
if (fromDate.IsDateNotOlder(toDate))
|
||
{
|
||
throw new IncorrectDatesException(fromDate, toDate, _localizer);
|
||
}
|
||
return _salaryStorageContract.GetList(fromDate, toDate);
|
||
}
|
||
|
||
public List<SalaryDataModel> GetAllSalariesByPeriodByWorker(DateTime fromDate, DateTime toDate, string workerId)
|
||
{
|
||
if (fromDate.IsDateNotOlder(toDate))
|
||
{
|
||
throw new IncorrectDatesException(fromDate, toDate, _localizer);
|
||
}
|
||
if (workerId.IsEmpty())
|
||
{
|
||
throw new ArgumentNullException(nameof(workerId));
|
||
}
|
||
if (!workerId.IsGuid())
|
||
{
|
||
throw new ValidationException(string.Format(_localizer["ValidationExceptionMessageNotAId"], "WorkerId"));
|
||
}
|
||
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}, {workerId}", fromDate, toDate, workerId);
|
||
return _salaryStorageContract.GetList(fromDate, toDate, workerId);
|
||
}
|
||
|
||
public void CalculateSalaryByMounth(DateTime date)
|
||
{
|
||
_logger.LogInformation("CalculateSalaryByMounth: {date}", date);
|
||
var startDate = new DateTime(date.Year, date.Month, 1);
|
||
var finishDate = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
|
||
var workers = _workerStorageContract.GetList();
|
||
foreach (var worker in workers)
|
||
{
|
||
var sales = _saleStorageContract.GetList(startDate, finishDate, workerId: worker.Id);
|
||
var post = _postStorageContract.GetElementById(worker.PostId) ?? throw new ElementNotFoundException(worker.PostId, _localizer);
|
||
var salary = post.ConfigurationModel switch
|
||
{
|
||
null => 0,
|
||
CashierPostConfiguration cpc => CalculateSalaryForCashier(sales, startDate, finishDate, cpc),
|
||
SupervisorPostConfiguration spc => CalculateSalaryForSupervisor(startDate, finishDate, spc),
|
||
PostConfiguration pc => pc.Rate,
|
||
};
|
||
_logger.LogDebug("The employee {workerId} was paid a salary of {salary}", worker.Id, salary);
|
||
_salaryStorageContract.AddElement(new SalaryDataModel(worker.Id, finishDate, salary));
|
||
}
|
||
}
|
||
|
||
private double CalculateSalaryForCashier(List<SaleDataModel> sales, DateTime startDate, DateTime finishDate, CashierPostConfiguration config)
|
||
{
|
||
var tasks = new List<Task>();
|
||
var calcPercent = 0.0;
|
||
for (var date = startDate; date < finishDate; date = date.AddDays(1))
|
||
{
|
||
tasks.Add(Task.Factory.StartNew((object? obj) =>
|
||
{
|
||
var dateInTask = (DateTime)obj!;
|
||
var salesInDay = sales.Where(x => x.SaleDate >= dateInTask && x.SaleDate <= dateInTask.AddDays(1)).ToArray();
|
||
if (salesInDay.Length > 0)
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
calcPercent += (salesInDay.Sum(x => x.Sum) / salesInDay.Length) * config.SalePercent;
|
||
}
|
||
}
|
||
}, date));
|
||
}
|
||
var calcBonusTask = Task.Run(() =>
|
||
{
|
||
return sales.Where(x => x.Sum > _salaryConfiguration.ExtraSaleSum).Sum(x => x.Sum) * config.BonusForExtraSales;
|
||
});
|
||
try
|
||
{
|
||
Task.WaitAll([Task.WhenAll(tasks), calcBonusTask]);
|
||
}
|
||
catch (AggregateException agEx)
|
||
{
|
||
foreach (var ex in agEx.InnerExceptions)
|
||
{
|
||
_logger.LogError(ex, "Error in the cashier payroll process");
|
||
}
|
||
return 0;
|
||
}
|
||
return config.Rate + calcPercent + calcBonusTask.Result;
|
||
}
|
||
private double CalculateSalaryForSupervisor(DateTime startDate, DateTime finishDate, SupervisorPostConfiguration config)
|
||
{
|
||
try
|
||
{
|
||
return config.Rate + config.PersonalCountTrendPremium * _workerStorageContract.GetWorkerTrend(startDate, finishDate);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Error in the supervisor payroll process");
|
||
return 0;
|
||
}
|
||
}
|
||
} |