forked from slavaxom9k/PIBD-23_Fomichev_V.S._MagicCarpet
125 lines
5.5 KiB
C#
125 lines
5.5 KiB
C#
using MagicCarpetContracts.BuisnessLogicContracts;
|
||
using MagicCarpetContracts.DataModels;
|
||
using MagicCarpetContracts.Exceptions;
|
||
using MagicCarpetContracts.Extensions;
|
||
using MagicCarpetContracts.Infrastructure;
|
||
using MagicCarpetContracts.Infrastructure.PostConfigurations;
|
||
using MagicCarpetContracts.StoragesContracts;
|
||
using Microsoft.Extensions.Logging;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace MagicCarpetBusinessLogic.Implementations;
|
||
public class SalaryBusinessLogicContract(ISalaryStorageContract salaryStorageContract,ISaleStorageContract saleStorageContract,
|
||
IPostStorageContract postStorageContract, IEmployeeStorageContract employeeStorageContract, 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 IEmployeeStorageContract _employeeStorageContract = employeeStorageContract;
|
||
private readonly IConfigurationSalary _salaryConfiguration = сonfiguration;
|
||
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);
|
||
}
|
||
return _salaryStorageContract.GetList(fromDate, toDate) ?? throw new NullListException();
|
||
}
|
||
|
||
public List<SalaryDataModel> GetAllSalariesByPeriodByEmployee(DateTime fromDate, DateTime toDate, string employeeId)
|
||
{
|
||
if (fromDate.IsDateNotOlder(toDate))
|
||
{
|
||
throw new IncorrectDatesException(fromDate, toDate);
|
||
}
|
||
if (employeeId.IsEmpty())
|
||
{
|
||
throw new ArgumentNullException(nameof(employeeId));
|
||
}
|
||
if (!employeeId.IsGuid())
|
||
{
|
||
throw new ValidationException("The value in the field employeeId is not a unique identifier.");
|
||
}
|
||
_logger.LogInformation("GetAllSalaries params: {fromDate}, {toDate}, {employeeId}", fromDate, toDate, employeeId);
|
||
return _salaryStorageContract.GetList(fromDate, toDate, employeeId) ?? throw new NullListException();
|
||
}
|
||
|
||
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 employees = _employeeStorageContract.GetList() ?? throw new NullListException();
|
||
foreach (var employee in employees)
|
||
{
|
||
var sales = _saleStorageContract.GetList(startDate, finishDate, employeeId: employee.Id) ?? throw new NullListException();
|
||
var post = _postStorageContract.GetElementById(employee.PostId) ?? throw new NullListException();
|
||
var salary = post.ConfigurationModel switch
|
||
{
|
||
null => 0,
|
||
TravelAgentPostConfiguration cpc => CalculateSalaryForTravelAgent(sales, startDate, finishDate, cpc),
|
||
ChiefPostConfiguration spc => CalculateSalaryForChief(startDate, finishDate, spc),
|
||
PostConfiguration pc => pc.Rate,
|
||
};
|
||
_logger.LogDebug("The employee {employeeId} was paid a salary of {salary}", employee.Id, salary);
|
||
_salaryStorageContract.AddElement(new SalaryDataModel(employee.Id, finishDate, salary));
|
||
}
|
||
}
|
||
private double CalculateSalaryForTravelAgent(List<SaleDataModel> sales, DateTime startDate, DateTime finishDate, TravelAgentPostConfiguration config)
|
||
{
|
||
var calcPercent = 0.0;
|
||
var dates = new List<DateTime>();
|
||
for (var date = startDate; date < finishDate; date = date.AddDays(1))
|
||
{
|
||
dates.Add(date);
|
||
}
|
||
|
||
var parallelOptions = new ParallelOptions
|
||
{
|
||
MaxDegreeOfParallelism = _salaryConfiguration.MaxConcurrentThreads
|
||
};
|
||
|
||
Parallel.ForEach(dates, parallelOptions, date =>
|
||
{
|
||
var salesInDay = sales.Where(x => x.SaleDate.Date == date.Date).ToArray();
|
||
if (salesInDay.Length > 0)
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
calcPercent += (salesInDay.Sum(x => x.Sum) / salesInDay.Length) * config.SalePercent;
|
||
}
|
||
}
|
||
});
|
||
|
||
double calcBonusTask = 0;
|
||
try
|
||
{
|
||
calcBonusTask = sales.Where(x => x.Sum > _salaryConfiguration.ExtraSaleSum).Sum(x => x.Sum) * config.BonusForExtraSales;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Error in bonus calculation");
|
||
}
|
||
return config.Rate + calcPercent + calcBonusTask;
|
||
}
|
||
private double CalculateSalaryForChief(DateTime startDate, DateTime finishDate, ChiefPostConfiguration config)
|
||
{
|
||
try
|
||
{
|
||
return config.Rate + config.PersonalCountTrendPremium * _employeeStorageContract.GetEmployeeTrend(startDate, finishDate);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Error in the chief payroll process");
|
||
return 0;
|
||
}
|
||
}
|
||
}
|