Files
2026-03-17 09:53:09 -05:00

123 lines
4.7 KiB
C#

using LCU.Library.Internal.IncentiveApiModels.Enums;
using LCU.API.Internal.Operations.IncentiveApi.Models.Payout;
using LCU.Library.Internal.IncentiveApiModels.Entities;
namespace LCU.API.Internal.Operations.IncentiveApi.Services.Payout;
public class DefaultPayoutStrategy : IPayoutStrategy
{
public bool CanPayoutProduct(Product product)
{
return product != Product.GAPInsurance;
}
public IReadOnlyCollection<PayoutLineItem> CalculateLineItems(
DepartmentPayout payoutPlan,
UserDepartment userDepartment,
List<PayoutProfile> departmentPayoutProfiles,
ProductDetail product
)
{
var lineItems = new List<PayoutLineItem>();
var eligiblePayoutProfiles = departmentPayoutProfiles.Where(p => p.Product == product.Product);
foreach (var eligiblePayoutProfile in eligiblePayoutProfiles.Where(x => x.Type == PayoutType.Personal))
{
var eligibleGoal = payoutPlan.PersonalGoals.FirstOrDefault(g => g.Product == product.Product);
if (eligibleGoal == null) continue;
var relatedActivity = payoutPlan.PersonalActivity
.Where(a => a.DepartmentId == userDepartment.DepartmentId &&
a.Product == product.Product)
.ToList();
if (!relatedActivity.Any()) continue;
var eligibleActivity = relatedActivity
.Where(a => a.State == ActivityState.Accepted
&& !payoutPlan.PersonalRules.Any(x => x.RestrictedByPayoutRule(a, product.Product)));
var lineItem = new PayoutLineItem(product.Product, eligiblePayoutProfile, eligibleGoal,
userDepartment.SlidingPayout, eligibleActivity, payoutPlan.MonthRange.StartTime)
{
ActivityPeriod = payoutPlan.MonthRange.StartTime,
AppUserId = userDepartment.Employee.Id,
EmployeeId = userDepartment.Employee.EmployeeId,
DepartmentId = userDepartment.DepartmentId,
Role = userDepartment.Role
};
lineItem.PayoutTotal = CalculateLineItemPayout(eligiblePayoutProfile, lineItem.GoalValue, lineItem.ActivityTotal,
payoutPlan.MonthRange.StartTime, lineItem.SlidingPayout);
if (lineItem.PayoutTotal > 0)
{
lineItems.Add(lineItem);
}
}
foreach (var eligiblePayoutProfile in eligiblePayoutProfiles.Where(x => x.Type == PayoutType.Department))
{
var eligibleGoal = payoutPlan.DepartmentGoals.FirstOrDefault(g => g.Product == product.Product);
if (eligibleGoal == null) continue;
var relatedActivity = payoutPlan.DepartmentActivity
.Where(a => a.Product == product.Product)
.ToList();
var eligibleActivity = relatedActivity
.Where(a => a.State == ActivityState.Accepted
&& !payoutPlan.DepartmentRules.Any(x => x.RestrictedByPayoutRule(a, product.Product)));
var lineItem = new PayoutLineItem(product.Product, eligiblePayoutProfile, eligibleGoal,
userDepartment.SlidingPayout, eligibleActivity, payoutPlan.MonthRange.StartTime)
{
ActivityPeriod = payoutPlan.MonthRange.StartTime,
AppUserId = userDepartment.Employee.Id,
EmployeeId = userDepartment.Employee.EmployeeId,
DepartmentId = userDepartment.DepartmentId,
Role = userDepartment.Role
};
lineItem.PayoutTotal = CalculateLineItemPayout(eligiblePayoutProfile, lineItem.GoalValue, lineItem.ActivityTotal,
payoutPlan.MonthRange.StartTime, lineItem.SlidingPayout);
if (lineItem.PayoutTotal > 0)
{
lineItems.Add(lineItem);
}
}
return lineItems;
}
public decimal CalculateLineItemPayout(PayoutProfile profile, int goal, decimal actual, DateTime runDate, decimal payoutPercent = 100)
{
if (profile == null)
{
throw new Exception("Attempt to calculate payout with null profile");
}
if (goal == 0) return 0;
var goalPercentage = (double)actual / goal;
var payoutRange = profile.FindPayoutRange(goalPercentage, runDate);
if (payoutRange == null)
{
return 0;
}
decimal payoutAmt = payoutRange.Payout;
if (profile.PayEach)
{
payoutAmt *= actual;
}
double payoutPercentage = (double)payoutPercent / (double)100;
double finalPayout = (double)payoutAmt * payoutPercentage;
payoutAmt = (decimal)Math.Round(finalPayout, 2);
return payoutAmt;
}
}