Files
Pibd-21_Semin_D.A._SmallSof…/SmallSoftwareProject/SmallSoftwareBusinessLogic/Implementations/SalaryBusinessLogicContract.cs
2025-04-24 00:06:05 +04:00

148 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using SmallSoftwareContracts.BusinessLogicsContracts;
using SmallSoftwareContracts.DataModels;
using SmallSoftwareContracts.Exceptions;
using SmallSoftwareContracts.Extensions;
using SmallSoftwareContracts.Infrastructure;
using SmallSoftwareContracts.Infrastructure.PostConfigurations;
using SmallSoftwareContracts.Resources;
using SmallSoftwareContracts.StoragesContracts;
namespace SmallSoftwareBusinessLogic.Implementations;
internal class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageContract,
IRequestStorageContract requestStorageContract, IPostStorageContract postStorageContract,
IWorkerStorageContract workerStorageContract, IStringLocalizer<Messages> localizer, ILogger logger, IConfigurationSalary сonfiguration) : ISalaryBusinessLogicContract
{
private readonly ILogger _logger = logger;
private readonly ISalaryStorageContract _salaryStorageContract = salaryStorageContract;
private readonly IRequestStorageContract _requestStorageContract = requestStorageContract;
private readonly IPostStorageContract _postStorageContract = postStorageContract;
private readonly IWorkerStorageContract _workerStorageContract = workerStorageContract;
private readonly IConfigurationSalary _salaryConfiguration = сonfiguration;
private readonly Lock _lockObject = new();
private readonly IStringLocalizer<Messages> _localizer = localizer;
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) ?? throw new
NullListException();
}
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) ??
throw new NullListException();
}
public void CalculateSalaryByMonth(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() ?? throw new NullListException();
foreach (var worker in workers)
{
var requests = _requestStorageContract.GetList(startDate, finishDate, workerId: worker.Id) ?? throw new NullListException();
var post = _postStorageContract.GetElementById(worker.PostId) ??
throw new NullListException();
var salary = worker.ConfigurationModel switch
{
null => 0,
CashierPostConfiguration cpc => CalculateSalaryForCashier(requests, 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<RequestDataModel> requests, DateTime startDate, DateTime finishDate, CashierPostConfiguration config)
{
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = _salaryConfiguration.MaxConcurrentThreads
};
double calcPercent = 0.0;
var dates = new List<DateTime>();
for (var date = startDate; date < finishDate; date = date.AddDays(1))
{
dates.Add(date);
}
Parallel.ForEach(dates, parallelOptions, date =>
{
var requestsInDay = requests.Where(x => x.RequestDate >= date && x.RequestDate < date.AddDays(1)).ToArray();
if (requestsInDay.Length > 0)
{
double dailySum = requestsInDay.Sum(x => x.Sum);
double dailyAverage = dailySum / requestsInDay.Length;
double dailyPercent = dailyAverage * config.SalePercent;
lock (_lockObject)
{
calcPercent += dailyPercent;
}
}
});
double bonus = 0;
try
{
bonus = requests
.AsParallel()
.WithDegreeOfParallelism(_salaryConfiguration.MaxConcurrentThreads)
.Where(x => x.Sum > _salaryConfiguration.ExtraSaleSum)
.Sum(x => x.Sum * config.BonusForExtraSales);
}
catch (AggregateException agEx)
{
foreach (var ex in agEx.InnerExceptions)
{
_logger.LogError(ex, "Error calculating bonus in cashier payroll");
}
return 0;
}
return config.Rate + calcPercent + bonus;
}
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;
}
}
}