This commit is contained in:
Zeeshaun
2026-03-17 09:53:09 -05:00
parent cdcba54aa4
commit 1a0702a79a
590 changed files with 62058 additions and 0 deletions
@@ -0,0 +1,122 @@
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;
}
}
@@ -0,0 +1,103 @@
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;
}
}
@@ -0,0 +1,12 @@
using LCU.Library.Internal.IncentiveApiModels.Entities;
using LCU.API.Internal.Operations.IncentiveApi.Models.Payout;
using LCU.Library.Internal.IncentiveApiModels.Common;
namespace LCU.API.Internal.Operations.IncentiveApi.Services.Payout;
public interface IPayoutCalculateService
{
Task<DepartmentPayout> BuildDepartmentPayoutView(AppUser employee, UserDepartment userDepartment, MonthRange monthRange);
List<PayoutLineItem> CalculateGoalLineItems(DepartmentPayout payoutPlan, UserDepartment userDepartment);
List<PayoutLineItem> CalculateCommissionLineItems(DepartmentPayout payoutPlan, UserDepartment userDepartment);
}
@@ -0,0 +1,22 @@
using LCU.Library.Internal.IncentiveApiModels.Entities;
using LCU.API.Internal.Operations.IncentiveApi.Models.Dayforce;
using LCU.API.Internal.Operations.IncentiveApi.Models.Payout;
using LCU.Library.Internal.IncentiveApiModels.Common;
using LCU.Library.Internal.IncentiveApiModels.Requests;
namespace LCU.API.Internal.Operations.IncentiveApi.Services.Payout
{
public interface IPayoutService
{
Task<IReadOnlyCollection<DepartmentPayout>> BuildUserDepartmentsPayoutView(AppUser employee, MonthRange range);
Task RunMonthlyIncentivePayouts(PayoutIncentiveRequest request);
Task<IReadOnlyCollection<PayoutLineItem>> CreateMonthlyIncentivePayouts(PayoutIncentiveRequest request);
Task<IReadOnlyCollection<PayoutEntry>> RetrieveMonthlyIncentivePayouts(DateTime period);
Task<PayoutEntry> RetrieveUserMonthlyIncentivePayout(AppUser appUser, DateTime period);
Task<IReadOnlyCollection<PayoutLineItem>> RetrieveCombinedDepartmentPayouts(AppUser incentiveAppUser, MonthRange range);
Task<IReadOnlyCollection<PayoutLineItem>> CreateCombinedDepartmentPayouts(AppUser incentiveAppUser, MonthRange range);
Task<TerminatedEmployeeReceipt> CreateTerminatedEmployeePayouts(AppUser appUser, AppUser manager);
Task<AccountingSummary> CreateMonthlyAccountingPayouts(MonthRange range);
Task<AccountingSummary> RetrieveMonthlyAccountingPayouts(MonthRange range);
}
}
@@ -0,0 +1,17 @@
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 interface IPayoutStrategy
{
bool CanPayoutProduct(Product product);
IReadOnlyCollection<PayoutLineItem> CalculateLineItems(
DepartmentPayout payoutPlan,
UserDepartment userDepartment,
List<PayoutProfile> departmentPayouts,
ProductDetail product
);
}
@@ -0,0 +1,138 @@
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;
}
}
@@ -0,0 +1,243 @@
using LCU.API.Internal.Operations.IncentiveApi.Models.Dayforce;
using LCU.API.Internal.Operations.IncentiveApi.Models.Payout;
using LCU.API.Internal.Operations.IncentiveApiLib.Repositories;
using LCU.Library.Internal.IncentiveApiModels.Entities;
using LCU.Library.Internal.IncentiveApiModels.Common;
using LCU.Library.Internal.IncentiveApiModels.Requests;
using LCU.Library.Internal.ApiResponse.Services;
using LCU.Library.Internal.Exceptions;
using ProcessResult = LCU.Library.Internal.IncentiveApiModels.Results.ProcessResult;
namespace LCU.API.Internal.Operations.IncentiveApi.Services.Payout;
public class PayoutService : IPayoutService
{
private readonly IUserRepository _userRepository;
private readonly IPayoutRepository _payoutRepository;
private readonly IAccountingRepository _accountingRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly IPayoutCalculateService _payoutCalculateService;
private readonly IActivityService _activityService;
private readonly ProcessResult _payoutIncentiveProcessResult;
private const int MonthsBack = -2;
public PayoutService(IUserRepository userRepository, IPayoutRepository payoutRepository, IUnitOfWork unitOfWork, IPayoutCalculateService payoutCalculateService,
IAccountingRepository accountingRepository, IActivityService activityService)
{
_userRepository = userRepository;
_payoutRepository = payoutRepository;
_unitOfWork = unitOfWork;
_payoutCalculateService = payoutCalculateService;
_accountingRepository = accountingRepository;
_activityService = activityService;
_payoutIncentiveProcessResult = new ProcessResult();
}
public async Task RunMonthlyIncentivePayouts(PayoutIncentiveRequest request)
{
try
{
Log.Information("Running Monthly Incentive Payout Process");
var result = await CreateMonthlyIncentivePayouts(request);
Log.Information("Successfully Processed Monthly Incentive Payouts.");
await QueueReturnResponse.QueueResponse(request, _payoutIncentiveProcessResult.Success, _payoutIncentiveProcessResult.MessageStack);
}
catch (Exception exception)
{
Log.Fatal(exception, "There was an Unhandled error with Monthly Incentive Payout Process");
var message = $"There was an Unhandled error with Monthly Incentive Payout Process from {request.MonthsBack} months back from today's date. Exception Message: {exception.Message}.";
_payoutIncentiveProcessResult.MessageStack.Add(message);
_payoutIncentiveProcessResult.Success = false;
await QueueReturnResponse.QueueResponse(request, _payoutIncentiveProcessResult.Success, _payoutIncentiveProcessResult.MessageStack);
throw new ServiceException(message);
}
}
public async Task<IReadOnlyCollection<PayoutLineItem>> CreateMonthlyIncentivePayouts(PayoutIncentiveRequest request)
{
var period = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
period = request.MonthsBack == 0 ? period.AddMonths(MonthsBack) : period.AddMonths(request.MonthsBack);
var range = new MonthRange(period);
_activityService.CancelPendingTransfersBetween(range).GetAwaiter().GetResult();
var users = await _userRepository.GetAllUsersToPayoutAsync(range);
var allNewPayouts = new List<PayoutLineItem>();
IReadOnlyCollection<PayoutLineItem> combinedPayouts;
foreach (var incentiveUser in users)
{
try
{
combinedPayouts = await CreateCombinedDepartmentPayouts(incentiveUser, range);
if (!combinedPayouts.Any()) continue;
await _payoutRepository.SavePayoutLineItemRangeAsync(combinedPayouts);
allNewPayouts.AddRange(combinedPayouts);
}
catch (Exception ex)
{
Log.Fatal(ex, $"Employee {incentiveUser.EmployeeId} - {incentiveUser.FullName} experienced a failed payout calculation!");
}
}
await _unitOfWork.CompleteAsync();
return allNewPayouts;
}
public async Task<AccountingSummary> CreateMonthlyAccountingPayouts(MonthRange range)
{
var existing = await RetrieveMonthlyAccountingPayouts(range);
if (existing != null)
{
return existing;
}
var users = await _userRepository.GetAllUsersToPayoutAsync(range);
var allNewPayouts = new List<PayoutLineItem>();
var deptNames = new Dictionary<int, string>();
foreach (var incentiveUser in users)
{
try
{
var departments = incentiveUser.ActiveDepartmentsForRange(range);
foreach (var userDepartment in departments)
{
if (!deptNames.ContainsKey(userDepartment.Department.Id.Value))
{
deptNames.Add(userDepartment.Department.Id.Value, userDepartment.Department.DepartmentName);
}
var newPlan =
await _payoutCalculateService.BuildDepartmentPayoutView(incentiveUser, userDepartment,
range);
allNewPayouts.AddRange(newPlan.CommissionPayouts);
allNewPayouts.AddRange(newPlan.GoalPayouts);
}
}
catch (Exception ex)
{
Log.Fatal(ex, $"Employee {incentiveUser.EmployeeId} - {incentiveUser.FullName} experienced a failed accounting calculation!");
}
}
var summary = new AccountingSummary(range.StartTime.Date);
summary.Apply(allNewPayouts, deptNames);
await _accountingRepository.SaveAccountingSummaryAsync(summary);
await _unitOfWork.CompleteAsync();
return summary;
}
public async Task<AccountingSummary> RetrieveMonthlyAccountingPayouts(MonthRange range)
{
return await _accountingRepository.GetAccountingSummaryAsync(range.StartTime);
}
public async Task<IReadOnlyCollection<DepartmentPayout>> BuildUserDepartmentsPayoutView(AppUser employee,
MonthRange range)
{
var list = new List<DepartmentPayout>();
var departments = employee.ActiveDepartmentsForRange(range);
foreach (var userDepartment in departments)
{
var newPlan = await _payoutCalculateService.BuildDepartmentPayoutView(employee, userDepartment, range);
list.Add(newPlan);
}
return list;
}
public async Task<IReadOnlyCollection<PayoutEntry>> RetrieveMonthlyIncentivePayouts(DateTime period)
{
var payoutsRaw = await _payoutRepository.GetPayoutLineItemsForPeriodAsync(period);
var payouts = new Dictionary<string, PayoutEntry>();
foreach (var lineItem in payoutsRaw)
{
if (payouts.ContainsKey(lineItem.EmployeeId))
{
payouts[lineItem.EmployeeId].PayoutTotal += lineItem.PayoutTotal;
}
else
{
var employee = await _userRepository.FindUserByEmployeeIdAsync(lineItem.EmployeeId);
payouts[lineItem.EmployeeId] = new PayoutEntry()
{
Code = "Incentive",
EmployeeId = lineItem.EmployeeId,
PayoutTotal = lineItem.PayoutTotal,
EmployeeName = employee.FullName
};
}
}
return payouts.Values;
}
public async Task<IReadOnlyCollection<PayoutLineItem>> CreateCombinedDepartmentPayouts(AppUser incentiveAppUser, MonthRange range)
{
var combinedPayouts = new List<PayoutLineItem>();
var existing = await _payoutRepository.GetEmployeePayoutsForPeriod(incentiveAppUser, range.StartTime);
if (existing.Any()) return combinedPayouts;
var payouts = await BuildUserDepartmentsPayoutView(incentiveAppUser, range);
foreach (var departmentPayout in payouts)
{
combinedPayouts.AddRange(departmentPayout.CommissionPayouts);
combinedPayouts.AddRange(departmentPayout.GoalPayouts);
}
return combinedPayouts;
}
public async Task<IReadOnlyCollection<PayoutLineItem>> RetrieveCombinedDepartmentPayouts(AppUser incentiveAppUser, MonthRange range)
{
var existing = await _payoutRepository.GetEmployeePayoutsForPeriod(incentiveAppUser, range.StartTime);
if (existing.Any()) return existing;
return await CreateCombinedDepartmentPayouts(incentiveAppUser, range);
}
public async Task<PayoutEntry> RetrieveUserMonthlyIncentivePayout(AppUser appUser, DateTime period)
{
var payoutsRaw = await _payoutRepository.GetEmployeePayoutsForPeriod(appUser, period);
var payout = new PayoutEntry()
{
Code = "Incentive",
EmployeeId = appUser.EmployeeId,
PayoutTotal = 0,
EmployeeName = appUser.FullName
};
foreach (var lineItem in payoutsRaw)
{
payout.PayoutTotal += lineItem.PayoutTotal;
}
return payout;
}
public async Task<TerminatedEmployeeReceipt> CreateTerminatedEmployeePayouts(AppUser appUser, AppUser manager)
{
var firstOfThisMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
var rangeThisMonth = new MonthRange(firstOfThisMonth);
var rangeLastMonth = new MonthRange(firstOfThisMonth.AddMonths(-1));
var payouts = await CreateCombinedDepartmentPayouts(appUser, rangeThisMonth);
if (payouts.Any())
{
await _payoutRepository.SavePayoutLineItemRangeAsync(payouts);
}
payouts = await CreateCombinedDepartmentPayouts(appUser, rangeLastMonth);
if (payouts.Any())
{
await _payoutRepository.SavePayoutLineItemRangeAsync(payouts);
}
await _unitOfWork.CompleteAsync();
var payoutThisMonth = await RetrieveUserMonthlyIncentivePayout(appUser, rangeThisMonth.StartTime);
var payoutLastMonth = await RetrieveUserMonthlyIncentivePayout(appUser, rangeLastMonth.StartTime);
return new TerminatedEmployeeReceipt(appUser, payoutLastMonth, payoutThisMonth, manager);
}
}