104 lines
3.7 KiB
C#
104 lines
3.7 KiB
C#
using LCU.Library.Internal.IncentiveApiModels.Entities;
|
|
using LCU.Library.Internal.IncentiveApiModels.Enums;
|
|
using LCU.API.Internal.Operations.IncentiveApi.Models.Payout;
|
|
|
|
namespace LCU.API.Internal.Operations.IncentiveApi.Services.Payout;
|
|
|
|
public class GapPayoutStrategy : IPayoutStrategy
|
|
{
|
|
private const bool IsEnabled = false;
|
|
|
|
public bool CanPayoutProduct(Product product)
|
|
{
|
|
return product == Product.GAPInsurance && IsEnabled;
|
|
}
|
|
|
|
public IReadOnlyCollection<PayoutLineItem> CalculateLineItems(
|
|
DepartmentPayout payoutPlan,
|
|
UserDepartment userDepartment,
|
|
List<PayoutProfile> departmentPayouts,
|
|
ProductDetail product
|
|
)
|
|
{
|
|
var lineItems = new List<PayoutLineItem>();
|
|
|
|
if (!payoutPlan.Department.IsHome) return lineItems;
|
|
|
|
var eligiblePayouts = departmentPayouts.Where(p => p.Product == product.Product);
|
|
|
|
if (eligiblePayouts.Any(x => x.Type == PayoutType.Department))
|
|
{
|
|
throw new Exception("GAP Payouts configured for personal goals only, if you have enable department payouts you must add payout logic.");
|
|
}
|
|
|
|
foreach (var eligiblePayoutProfile in eligiblePayouts.Where(x => x.Type == PayoutType.Personal))
|
|
{
|
|
var eligibleGoal = payoutPlan.PersonalActivity
|
|
.Where(a => a.Detail is { IsDebtProtectionEligible: true } && a.State == ActivityState.Accepted)
|
|
.ToList();
|
|
|
|
if (!eligibleGoal.Any()) continue;
|
|
|
|
var gapActivity = payoutPlan.PersonalActivity
|
|
.Where(a => a.Product == product.Product
|
|
&& a.State == ActivityState.Accepted
|
|
&& !payoutPlan.PersonalRules.Any(x => x.RestrictedByPayoutRule(a, product.Product))
|
|
)
|
|
.ToList();
|
|
|
|
var goalCount = eligibleGoal.Count;
|
|
var actualCount = eligibleGoal.Count(a => a.Detail.DebtProtectionAddDate != null && a.Detail.DebtProtectionRemoveDate == null);
|
|
|
|
gapActivity.AddRange(eligibleGoal);
|
|
var lineItem = new PayoutLineItem(product.Product, eligiblePayoutProfile, eligibleGoal.Count,
|
|
userDepartment.SlidingPayout, gapActivity)
|
|
{
|
|
ActivityPeriod = payoutPlan.MonthRange.StartTime,
|
|
AppUserId = userDepartment.Employee.Id,
|
|
EmployeeId = userDepartment.Employee.EmployeeId,
|
|
DepartmentId = userDepartment.DepartmentId,
|
|
Role = userDepartment.Role
|
|
};
|
|
lineItem.PayoutTotal = CalculateLineItemPayout(eligiblePayoutProfile, goalCount, actualCount, lineItem.ActivityTotal,
|
|
payoutPlan.MonthRange.StartTime, lineItem.SlidingPayout);
|
|
|
|
if (lineItem.PayoutTotal > 0)
|
|
{
|
|
lineItems.Add(lineItem);
|
|
}
|
|
}
|
|
|
|
return lineItems;
|
|
}
|
|
|
|
private decimal CalculateLineItemPayout(PayoutProfile profile, int goal, decimal actual, decimal each, 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 *= each;
|
|
}
|
|
|
|
var payoutPercentage = (double)payoutPercent / 100;
|
|
var finalPayout = (double)payoutAmt * payoutPercentage;
|
|
payoutAmt = (decimal)Math.Round(finalPayout, 2);
|
|
|
|
return payoutAmt;
|
|
}
|
|
}
|