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 _payoutStrategies; private readonly IBusinessRuleService _businessRuleService; public PayoutCalculateService( IActivityRepository activityRepository, IGoalRepository goalRepository, ICommissionRepository commissionRepository, IEnumerable payoutStrategies, IBusinessRuleService businessRuleService ) { _activityRepository = activityRepository; _goalRepository = goalRepository; _commissionRepository = commissionRepository; _payoutStrategies = payoutStrategies; _businessRuleService = businessRuleService; } public async Task 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() { 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 CalculateCommissionLineItems(DepartmentPayout payoutPlan, UserDepartment userDepartment) { var lineItems = new List(); 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 CalculateGoalLineItems(DepartmentPayout payoutPlan, UserDepartment userDepartment) { var lineItems = new List(); 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; } }