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 CalculateLineItems( DepartmentPayout payoutPlan, UserDepartment userDepartment, List departmentPayoutProfiles, ProductDetail product ) { var lineItems = new List(); 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; } }