Files
monorepo/LCU.API.Operations.IncentiveAPI/LCU.API.Internal.Operations.IncentiveApi/Services/GoalDispersalService.cs
T
2026-04-23 16:27:51 +00:00

217 lines
9.9 KiB
C#

using LCU.API.Internal.Operations.IncentiveApi.Services.DispersalStrategy;
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.Requests;
using LCU.API.Internal.Operations.IncentiveApi.Services.MicroApiServices;
using LCU.Library.Internal.ApiResponse.Services;
using LCU.Library.Internal.IncentiveApiModels.Results;
namespace LCU.API.Internal.Operations.IncentiveApi.Services;
public class GoalDispersalService : IGoalDispersalService
{
private readonly IUserService _userService;
private readonly IGoalService _goalService;
private readonly IDepartmentRepository _departmentRepository;
private readonly INotificationApiService _notificationService;
private readonly IDispersalStrategyService _dispersalStrategyService;
private readonly ProcessResult _goalDispersalProcessResult;
public GoalDispersalService(
IUserService userService,
IGoalService goalService,
IDepartmentRepository departmentRepository,
INotificationApiService notificationService,
IDispersalStrategyService dispersalStrategyService
)
{
_userService = userService;
_goalService = goalService;
_departmentRepository = departmentRepository;
_notificationService = notificationService;
_dispersalStrategyService = dispersalStrategyService;
_goalDispersalProcessResult = new ProcessResult();
}
public async Task<GoalDispersalReceipt> DisperseGoalsByExtrapolatingLastMonth(int departmentId, int dispersalMonth, int dispersalYear)
{
try
{
var lastMonth = dispersalMonth == 1 ? 12 : dispersalMonth - 1;
var lastMonthCorrectedYear = dispersalMonth == 1 ? dispersalYear - 1 : dispersalYear;
var dispersalMonthStartDateTime = DateTime.Parse($"{dispersalYear}-{dispersalMonth}-01");
var departmentGoals = await _goalService.GetAnnualDepartmentGoalsAsync(departmentId, dispersalYear);
var dispersalMonthDepartmentGoals = departmentGoals.MonthlyGoals[dispersalMonth - 1];
var dispersalMonthPersonnel = await _userService.FindDepartmentAssignments(
new DepartmentPersonnelSearchRequest()
{
DepartmentId = departmentId,
Month = dispersalMonth,
Year = dispersalYear,
IncludeAllPersonnel = true
}
);
var dispersalMonthPersonnelGoals = await _goalService.GetMonthlyPersonnelGoalsAsync(
new DepartmentPersonnelSearchRequest()
{
DepartmentId = departmentId,
Month = dispersalMonth,
Year = dispersalYear,
IncludeAllPersonnel = true
}
);
var modelMonthPersonnelGoals = await _goalService.GetMonthlyPersonnelGoalsAsync(
new DepartmentPersonnelSearchRequest()
{
DepartmentId = departmentId,
Month = lastMonth,
Year = lastMonthCorrectedYear,
IncludeAllPersonnel = true
}
);
if (modelMonthPersonnelGoals.GoalAudit.All(x => x.Value < 1))
{
var weightedDispersalRequest = new DefaultWeightedGoalDispersalData()
{
DepartmentId = departmentId,
DispersalMonthStartDate = dispersalMonthStartDateTime,
DispersalMonthPersonnel = dispersalMonthPersonnel,
DispersalMonthDepartmentGoals = dispersalMonthDepartmentGoals
};
var weightedReceipt = _dispersalStrategyService.DefaultWeightedDispersal(weightedDispersalRequest);
await _goalService.SaveGoalRangeAsync(weightedReceipt.GoalChanges);
return weightedReceipt;
}
departmentGoals = await _goalService.GetAnnualDepartmentGoalsAsync(departmentId, lastMonthCorrectedYear);
var lastMonthDepartmentGoals = departmentGoals.MonthlyGoals[lastMonth - 1];
var extrapolateGoalsDispersalRequest = new ExtrapolationGoalDispersalData()
{
DepartmentId = departmentId,
DispersalMonthStartDate = dispersalMonthStartDateTime,
DispersalMonthDepartmentGoals = dispersalMonthDepartmentGoals,
DispersalMonthPersonnelGoals = dispersalMonthPersonnelGoals,
ModelDepartmentGoals = lastMonthDepartmentGoals,
ModelPersonnelGoals = modelMonthPersonnelGoals,
DispersalMonthPersonnel = dispersalMonthPersonnel
};
var receipt = _dispersalStrategyService.ExtrapolateFromExistingGoals(extrapolateGoalsDispersalRequest);
await _goalService.SaveGoalRangeAsync(receipt.GoalChanges);
return receipt;
}
catch (Exception ex)
{
Log.Error(ex, $"Failed to DisperseGoalsForNextMonth for dept:{departmentId} month:{dispersalMonth} dispersalYear: {dispersalYear}");
throw new Exceptions.ServerErrorException();
}
}
public async Task<Dictionary<string, GoalDispersalReceipt>> DisperseAllDepartmentGoalsForMonth(int month, int year)
{
var results = new Dictionary<string, GoalDispersalReceipt>();
var departments = await _departmentRepository.GetAllDepartmentsAsync();
foreach (var department in departments)
{
try
{
if (department.Id == null)
{
throw new Exception($"Department Has No Id. Skipping Dispersal: {department.DepartmentName}");
}
var departmentKey = $"{department.Id} - {department.DepartmentName}";
Log.Debug($"Dispersing Goals for Department: {departmentKey}");
var receipt = await DisperseGoalsByExtrapolatingLastMonth((int)department.Id, month, year);
results.Add(departmentKey, receipt);
Log.Debug($"Completed Dispersal for: {departmentKey}");
}
catch (Exception ex)
{
var departmentKey = $"{department.Id} - {department.DepartmentName}";
Log.Error(ex, $"Failed Month Start Auto-Disperse of Personnel Goals for Department: {departmentKey}");
results.Add(departmentKey, null);
}
}
return results;
}
public async Task ExecuteMonthStartDispersal(GoalDispersalRequest request)
{
try
{
Log.Information("Executing Monthly Goal Dispersal");
var result = await DisperseAllDepartmentGoalsForMonth(request.StartDate.Month, request.StartDate.Year);
Log.Information("Finished Monthly Goal Dispersal. Sending Report Email.");
await _notificationService.SendMonthStartGoalDispersalReceipt(result, request.GoalDispersalNotification);
_goalDispersalProcessResult.MessageStack.Add($"Goal Dispersal Service Processed for {request.StartDate.Month}{request.StartDate.Year} records.");
Log.Information("Successfully Sent Report Email.");
await QueueReturnResponse.QueueResponse(request, _goalDispersalProcessResult.Success, _goalDispersalProcessResult.MessageStack);
}
catch (Exception exception)
{
Log.Fatal(exception, "There was an Unhandled error Executing Month Start Dispersal");
var processLabel = request == null
? "unknown"
: $"{request.StartDate.Month}{request.StartDate.Year}";
var message = $"There was an issue with handling the Goal Dispersal Service Process {processLabel}. Exception Message: {exception.Message}.";
_goalDispersalProcessResult.MessageStack.Add(message);
_goalDispersalProcessResult.Success = false;
await QueueReturnResponse.QueueResponse(request, _goalDispersalProcessResult.Success, _goalDispersalProcessResult.MessageStack);
}
}
public async Task<GoalDispersalReceipt> DepartmentGoalChangeReDispersal(DepartmentGoalExtrapolationRequest request)
{
var personnelGoals = await _goalService.GetMonthlyPersonnelGoalsAsync(new DepartmentPersonnelSearchRequest()
{
DepartmentId = request.DepartmentId,
IncludeAllPersonnel = true,
Year = request.DepartmentGoalStartDate.Year,
Month = request.DepartmentGoalStartDate.Month,
});
var receipt = _dispersalStrategyService.ExtrapolateSingleDepartmentProduct(request, personnelGoals);
return receipt;
}
public async Task<GoalDispersalReceipt> CustomWeightedDispersal(CustomWeightedDispersalRequest request)
{
try
{
var departmentGoals = await _goalService.GetAnnualDepartmentGoalsAsync(request.DepartmentId, request.year);
var productDepartmentGoal = departmentGoals.MonthlyGoals[request.month - 1].ProductGoals[request.DispersalProduct];
var departmentPersonnel = await _userService.FindDepartmentAssignments(
new DepartmentPersonnelSearchRequest()
{
DepartmentId = request.DepartmentId,
Month = request.month,
Year = request.year,
IncludeAllPersonnel = true
}
);
var receipt = _dispersalStrategyService.CustomWeightedDispersal(request, departmentPersonnel, productDepartmentGoal);
await _goalService.SaveGoalRangeAsync(receipt.GoalChanges);
return receipt;
}
catch (Exception ex)
{
Log.Error(ex, "Custom Weighted Dispersal Failed");
throw new Exceptions.ServerErrorException();
}
}
}