Files
monorepo/LCU.API.Operations.IncentiveAPI/LCU.API.Internal.Operations.IncentiveApi/Services/GoalService.cs
T
2026-03-17 09:53:09 -05:00

255 lines
9.7 KiB
C#

using LCU.API.Internal.Operations.IncentiveApi.Extensions;
using LCU.API.Internal.Operations.IncentiveApi.Services.DispersalStrategy;
using LCU.API.Internal.Operations.IncentiveApi.Models;
using LCU.API.Internal.Operations.IncentiveApi.Models.GoalDispersal;
using LCU.API.Internal.Operations.IncentiveApiLib.Services;
using LCU.API.Internal.Operations.IncentiveApiLib.Repositories;
using LCU.Library.Internal.IncentiveApiModels.Entities;
using LCU.Library.Internal.IncentiveApiModels.Common;
using LCU.API.Internal.Operations.IncentiveApiLib.Persistence;
using LCU.Library.Internal.IncentiveApiModels.Requests;
namespace LCU.API.Internal.Operations.IncentiveApi.Services;
public class GoalService : IGoalService
{
private readonly IGoalRepository _goalRepository;
private readonly IGoalChangeRepository _goalChangeRepository;
private readonly ICurrentUserService _currentUserService;
private readonly IDispersalStrategyService _dispersalStrategyService;
private readonly IDepartmentRepository _departmentRepository;
private readonly IUserService _userService;
private readonly IUnitOfWork _unitOfWork;
public GoalService(
IGoalRepository goalRepository,
IGoalChangeRepository goalChangeRepository,
ICurrentUserService currentUserService,
IDispersalStrategyService dispersalStrategyService,
IUnitOfWork unitOfWork,
IUserService userService,
IDepartmentRepository departmentRepository
)
{
_goalRepository = goalRepository;
_goalChangeRepository = goalChangeRepository;
_currentUserService = currentUserService;
_unitOfWork = unitOfWork;
_userService = userService;
_departmentRepository = departmentRepository;
_dispersalStrategyService = dispersalStrategyService;
}
public async Task<List<Goal>> SaveGoalAsync(GoalChange goalChange)
{
return await SaveGoalRangeAsync(new List<GoalChange>() { goalChange });
}
private async Task<GoalChange> ConfirmAppUserIdAndSaveGoalChange(GoalChange goalChange)
{
if (!goalChange.IsDepartmentGoalChange())
{
var appUser = await _userService.GetUserByEmployeeIdAsync(goalChange.PersonId);
goalChange.AppUserId = appUser.Id;
}
await _goalChangeRepository.SaveGoalChangeAsync(goalChange);
return goalChange;
}
public async Task<List<Goal>> SaveGoalRangeAsync(List<GoalChange> goalChanges)
{
var goalsToSave = new List<Goal>();
foreach (var goalChange in goalChanges)
{
await ConfirmAppUserIdAndSaveGoalChange(goalChange);
var goal = await _goalRepository.FindExistingGoal(goalChange);
if (goal != null)
{
var originalGoalValue = goal.Value;
goal.Value = goalChange.Value;
if (goal.IsDepartmentGoal() && originalGoalValue != goal.Value)
{
goalsToSave.AddRange(await CreatePersonnelGoalChangesFromDepartmentGoalChange(goalChange, originalGoalValue));
}
}
else
{
goal = new Goal()
{
AppUserId = goalChange.AppUserId,
Product = goalChange.Product,
EmployeeId = goalChange.PersonId,
DepartmentId = goalChange.DepartmentId,
StartDate = goalChange.StartDate.StartOfMonth(),
EndDate = goalChange.EndDate.EndOfMonth(),
Value = goalChange.Value
};
await _goalRepository.SaveGoalAsync(goal);
}
goalsToSave.Add(goal);
}
await _unitOfWork.CompleteAsync();
return goalsToSave;
}
private async Task<List<Goal>> CreatePersonnelGoalChangesFromDepartmentGoalChange(GoalChange goalChange, int originalGoalValue)
{
if (!goalChange.IsDepartmentGoalChange()) return new List<Goal>();
var personnelGoals = new List<Goal>();
var departmentPersonnelGoals = await GetMonthlyPersonnelGoalsAsync(
new DepartmentPersonnelSearchRequest()
{
DepartmentId = goalChange.DepartmentId,
IncludeAllPersonnel = true,
Year = goalChange.StartDate.Year,
Month = goalChange.StartDate.Month,
});
var receipt = _dispersalStrategyService.ExtrapolateSingleDepartmentProduct(
new DepartmentGoalExtrapolationRequest()
{
DepartmentGoalEndDate = goalChange.EndDate.EndOfMonth(),
DepartmentGoalStartDate = goalChange.StartDate.StartOfMonth(),
DepartmentId = goalChange.DepartmentId,
NewDepartmentGoal = goalChange.Value,
OriginalDepartmentGoal = originalGoalValue,
Product = goalChange.Product
}, departmentPersonnelGoals);
foreach (var reDispersedGoalChange in receipt.GoalChanges)
{
await ConfirmAppUserIdAndSaveGoalChange(reDispersedGoalChange);
var reDispersedGoal = await CreateOrUpdateGoalFromGoalChange(reDispersedGoalChange);
personnelGoals.Add(reDispersedGoal);
}
return personnelGoals;
}
private async Task<Goal> CreateOrUpdateGoalFromGoalChange(GoalChange goalChange)
{
var goal = await _goalRepository.FindExistingGoal(goalChange);
if (goal != null)
{
goal.Value = goalChange.Value;
}
else
{
goal = new Goal()
{
Product = goalChange.Product,
AppUserId = goalChange.AppUserId,
EmployeeId = goalChange.PersonId,
DepartmentId = goalChange.DepartmentId,
StartDate = goalChange.StartDate.StartOfMonth(),
EndDate = goalChange.EndDate.EndOfMonth(),
Value = goalChange.Value
};
await _goalRepository.SaveGoalAsync(goal);
}
return goal;
}
public async Task<DepartmentGoals> GetAnnualDepartmentGoalsAsync(int departmentId, int year)
{
var goals = new DepartmentGoals(departmentId, year);
goals.ApplyAll(await _goalRepository.FindAnnualDepartmentGoals(departmentId, year));
return goals;
}
public async Task<IReadOnlyCollection<DepartmentGoals>> GetAllAnnualDepartmentGoalsAsync(int year)
{
var departments = await _departmentRepository.GetAllDepartmentsAsync();
var departmentGoals = new List<DepartmentGoals>();
foreach (var department in departments)
{
if (department.Id != null)
{
departmentGoals.Add(await GetAnnualDepartmentGoalsAsync(department.Id.Value, year));
}
}
return departmentGoals;
}
public async Task<PersonnelGoals> GetMonthlyPersonnelGoalsAsync(DepartmentPersonnelSearchRequest searchRequest)
{
var users = await _userService.FindDepartmentAssignments(searchRequest);
var goals = new PersonnelGoals(searchRequest.DepartmentId, searchRequest.Year, searchRequest.Month, users);
goals.ApplyAll(await _goalRepository.FindMonthlyPersonnelGoals(searchRequest.DepartmentId, users,
searchRequest.Year, searchRequest.Month));
return goals;
}
public async Task<IReadOnlyCollection<Goal>> GetGoalsAsync(GoalSearchRequest goalSearchRequest)
{
return await _goalRepository.GetGoalsAsync(goalSearchRequest);
}
public async Task<IReadOnlyCollection<GoalChange>> GetGoalChangesAsync()
{
return await _goalChangeRepository.GetGoalChangesAsync();
}
public async Task<EmployeeGoals> GetEmployeeGoalsForMonthRangeAsync(AppUser employee, MonthRange monthRange)
{
var users = new List<AppUser>()
{
employee
};
var goals = new EmployeeGoals(employee, monthRange);
foreach (var dept in goals.Departments)
{
goals.ApplyAll(
await _goalRepository.FindPersonnelGoalsByMonthRange(dept.DepartmentId, users, monthRange));
}
return goals;
}
public async Task<IReadOnlyCollection<DepartmentGoalsForRange>> GetEmployeeDepartmentsGoalsForMonthRangeAsync(AppUser employee, MonthRange monthRange)
{
var allGoals = new List<DepartmentGoalsForRange>();
foreach (var dept in employee.Departments)
{
var isAssignedInMonthRange = dept.StartDate.Date < monthRange.EndTime.Date &&
(dept.EndDate == null ||
monthRange.StartTime.Date < dept.EndDate.Value.Date);
if (isAssignedInMonthRange)
{
var StartDate = dept.StartDate.Date < monthRange.StartTime.Date
? monthRange.StartTime.Date
: dept.StartDate.Date;
var EndDate = dept.EndDate == null ? monthRange.EndTime.Date
: dept.EndDate.Value.Date > monthRange.EndTime.Date ? monthRange.EndTime.Date
: dept.EndDate.Value.Date;
var monthRangeOfAssignment = new MonthRange
(
StartDate.Year,
StartDate.Month,
EndDate.Year,
EndDate.Month
);
var goals = new DepartmentGoalsForRange(dept.DepartmentId, monthRangeOfAssignment);
var deptGoals =
await _goalRepository.FindDepartmentGoalsByMonthRange(goals.DepartmentId, goals.MonthRange);
goals.ApplyAll(deptGoals);
allGoals.Add(goals);
}
}
return allGoals;
}
}