Files
monorepo/LCU.API.Operations.IncentiveAPI/LCU.API.Internal.Operations.IncentiveApi/Services/Payout/PayoutCalculateService.cs
T
2026-03-17 09:53:09 -05:00

139 lines
5.3 KiB
C#

using LCU.Library.Internal.IncentiveApiModels.Entities;
using LCU.Library.Internal.IncentiveApiModels.Enums;
using LCU.API.Internal.Operations.IncentiveApi.Services.Rules;
using LCU.API.Internal.Operations.IncentiveApi.Models.Payout;
using LCU.API.Internal.Operations.IncentiveApiLib.Repositories;
using LCU.Library.Internal.IncentiveApiModels.Common;
namespace LCU.API.Internal.Operations.IncentiveApi.Services.Payout;
public class PayoutCalculateService : IPayoutCalculateService
{
private readonly IActivityRepository _activityRepository;
private readonly IGoalRepository _goalRepository;
private readonly ICommissionRepository _commissionRepository;
private readonly IEnumerable<IPayoutStrategy> _payoutStrategies;
private readonly IBusinessRuleService _businessRuleService;
public PayoutCalculateService(
IActivityRepository activityRepository,
IGoalRepository goalRepository,
ICommissionRepository commissionRepository,
IEnumerable<IPayoutStrategy> payoutStrategies,
IBusinessRuleService businessRuleService
)
{
_activityRepository = activityRepository;
_goalRepository = goalRepository;
_commissionRepository = commissionRepository;
_payoutStrategies = payoutStrategies;
_businessRuleService = businessRuleService;
}
public async Task<DepartmentPayout> BuildDepartmentPayoutView(
AppUser employee,
UserDepartment userDepartment,
MonthRange monthRange
)
{
var payoutPlan = new DepartmentPayout(employee, userDepartment, monthRange,
_businessRuleService.GetRules(PayoutType.Department),
_businessRuleService.GetRules(PayoutType.Personal))
{
EligibleCommissions = await _commissionRepository.FindProductCommissions(userDepartment.Role)
};
if (!payoutPlan.HasEligibleIncentives())
{
return payoutPlan;
}
payoutPlan.PersonalActivity =
await _activityRepository.FindEmployeeActivityByMonthRange(payoutPlan.Employee, payoutPlan.MonthRange);
payoutPlan.DepartmentActivity =
await _activityRepository.FindDepartmentActivityByMonthRange(userDepartment.DepartmentId,
payoutPlan.MonthRange);
if (!payoutPlan.HasEligibleActivity())
{
return payoutPlan;
}
var users = new List<AppUser>()
{
payoutPlan.Employee
};
payoutPlan.PersonalGoals = await _goalRepository.FindPersonnelGoalsByMonthRange(userDepartment.DepartmentId,
users, payoutPlan.MonthRange);
payoutPlan.DepartmentGoals = await _goalRepository.FindDepartmentGoalsByMonthRange(
userDepartment.DepartmentId,
payoutPlan.MonthRange);
if (payoutPlan.HasEligibleCommissions())
{
payoutPlan.CommissionPayouts = CalculateCommissionLineItems(payoutPlan, userDepartment);
}
payoutPlan.GoalPayouts = CalculateGoalLineItems(payoutPlan, userDepartment);
return payoutPlan;
}
public List<PayoutLineItem> CalculateCommissionLineItems(DepartmentPayout payoutPlan, UserDepartment userDepartment)
{
var lineItems = new List<PayoutLineItem>();
var departmentCommissions = payoutPlan.EligibleCommissions;
if (departmentCommissions == null || !departmentCommissions.Any()) return lineItems;
foreach (var product in departmentCommissions.Select(x => x.Product).Distinct().ToList())
{
var eligibleCommission = departmentCommissions.FirstOrDefault(c => c.Product == product);
if (eligibleCommission == null) continue;
var eligibleActivity = payoutPlan.PersonalActivity
.Where(a => a.DepartmentId == userDepartment.DepartmentId &&
a.Product == product &&
a.Type != ActivityType.Other
&& a.State == ActivityState.Accepted
&& !payoutPlan.PersonalRules.Any(x => x.RestrictedByPayoutRule(a, product)))
.ToList();
var lineItem = new PayoutLineItem(product, eligibleCommission, eligibleActivity)
{
ActivityPeriod = payoutPlan.MonthRange.StartTime,
AppUserId = userDepartment.Employee.Id,
EmployeeId = userDepartment.Employee.EmployeeId,
DepartmentId = userDepartment.DepartmentId,
Role = userDepartment.Role
};
if (lineItem.PayoutTotal > 0)
{
lineItems.Add(lineItem);
}
}
return lineItems;
}
public List<PayoutLineItem> CalculateGoalLineItems(DepartmentPayout payoutPlan, UserDepartment userDepartment)
{
var lineItems = new List<PayoutLineItem>();
var departmentPayouts = payoutPlan.EligiblePayouts.ToList();
if (!departmentPayouts.Any()) return lineItems;
foreach (var product in ProductDetail.ProductDetails)
{
var strategy = _payoutStrategies.FirstOrDefault(x => x.CanPayoutProduct(product.Product));
if (strategy == null) continue;
var items = strategy.CalculateLineItems(payoutPlan, userDepartment, departmentPayouts, product);
lineItems.AddRange(items);
}
return lineItems;
}
}