244 lines
10 KiB
C#
244 lines
10 KiB
C#
using LCU.Library.Internal.IncentiveApiModels.Entities;
|
|
using LCU.API.Internal.Operations.IncentiveApiLib.Repositories;
|
|
using LCU.Library.Internal.IncentiveApiModels.Enums;
|
|
using LCU.Library.Internal.IncentiveApiModels.Common;
|
|
|
|
namespace LCU.API.Internal.Operations.IncentiveApi.Services;
|
|
|
|
public class GapInsuranceActivityService : IGapInsuranceActivityService
|
|
{
|
|
private readonly IActivityDetailService _activityDetailService;
|
|
private readonly IActivityRepository _activityRepository;
|
|
private readonly IActivityService _activityService;
|
|
private readonly IUnitOfWork _unitOfWork;
|
|
|
|
public GapInsuranceActivityService(
|
|
IActivityDetailService activityDetailService,
|
|
IActivityRepository activityRepository,
|
|
IActivityService activityService,
|
|
IUnitOfWork unitOfWork
|
|
)
|
|
{
|
|
_activityDetailService = activityDetailService;
|
|
_activityRepository = activityRepository;
|
|
_activityService = activityService;
|
|
_unitOfWork = unitOfWork;
|
|
}
|
|
|
|
public async Task<int> MatchOrRemoveGapAccessories(MonthRange monthRange = null)
|
|
{
|
|
var updateCount = 0;
|
|
monthRange ??= new MonthRange(DateTime.UtcNow.AddMonths(-3), DateTime.UtcNow);
|
|
var gapEligibleActivities = await _activityRepository.FindGapInsuranceEligible(monthRange);
|
|
|
|
if (!gapEligibleActivities.Any())
|
|
{
|
|
return updateCount;
|
|
}
|
|
|
|
var matchedGapEligibleActivities = gapEligibleActivities.Where(x => x.HasActiveGapAccessory()).ToList();
|
|
var matchedGapAccessoryActivities = await GetMatchingGapAccessoryActivities(matchedGapEligibleActivities);
|
|
matchedGapEligibleActivities = await ValidateMatchedActivityAccessories(matchedGapEligibleActivities, matchedGapAccessoryActivities);
|
|
|
|
var unmatchedGapEligibleActivities = gapEligibleActivities.Except(matchedGapEligibleActivities).ToList();
|
|
var gapActivities = await _activityRepository.GetFilteredActivities(monthRange, Product.GAPInsurance, ActivityState.Accepted);
|
|
|
|
foreach (var activity in unmatchedGapEligibleActivities)
|
|
{
|
|
try
|
|
{
|
|
updateCount += await TryMatchGapEligibleActivityWithAccessory(activity, gapActivities) != null ? 2 : 0;
|
|
}
|
|
catch (Exception error)
|
|
{
|
|
Log.Error(error, $"MatchOrRemoveGapAccessories failed processing Activity Id: {activity.Id}");
|
|
}
|
|
}
|
|
|
|
return updateCount;
|
|
}
|
|
|
|
private async Task<Activity?> TryMatchGapEligibleActivityWithAccessory(Activity gapEligibleActivity, List<Activity> gapActivities)
|
|
{
|
|
if (gapActivities.Count <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var matchingGapAccessories = gapActivities
|
|
.Where(x => x.Detail.AccountNumber.Equals(gapEligibleActivity.Detail.AccountNumber, StringComparison.CurrentCultureIgnoreCase))
|
|
.ToList();
|
|
|
|
if (matchingGapAccessories.Count <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (matchingGapAccessories.Count > 1)
|
|
{
|
|
throw new Exception(
|
|
$"Multiple matching GAP Accessory Activities found for Activity Id: {gapEligibleActivity.Id} using AccountNumber: {gapEligibleActivity.Detail.AccountNumber}");
|
|
}
|
|
|
|
var matchedAccessoryActivity = matchingGapAccessories.First();
|
|
return await MatchGapAccessory(gapEligibleActivity, matchedAccessoryActivity);
|
|
}
|
|
|
|
private async Task<Activity> MatchGapAccessory(Activity parentActivity, Activity accessoryActivity)
|
|
{
|
|
var addedDateTime = accessoryActivity.Accepted.Date.AddHours(12);
|
|
|
|
await ApplyMatchedChangeUpdates(parentActivity, accessoryActivity, addedDateTime);
|
|
await ApplyMatchedChangeUpdates(accessoryActivity, parentActivity, addedDateTime);
|
|
await _unitOfWork.CompleteAsync();
|
|
|
|
return parentActivity;
|
|
}
|
|
|
|
private async Task ApplyMatchedChangeUpdates(Activity targetActivity, Activity linkedActivity, DateTime addedDateTime)
|
|
{
|
|
targetActivity.Detail.GapInsuranceAddDate = addedDateTime;
|
|
targetActivity.MatchingGapInsuranceActivityId = linkedActivity.Id;
|
|
await _activityDetailService.SaveActivityDetailUpdate(new ActivityDetailUpdate
|
|
{
|
|
ActivityDetailId = targetActivity.Detail.Id,
|
|
Note = $"GapInsuranceAddDate has changed from NULL to {addedDateTime}"
|
|
});
|
|
|
|
if (targetActivity.Detail.GapInsuranceRemoveDate != null)
|
|
{
|
|
targetActivity.Detail.GapInsuranceRemoveDate = null;
|
|
await _activityDetailService.SaveActivityDetailUpdate(new ActivityDetailUpdate
|
|
{
|
|
ActivityDetailId = targetActivity.Detail.Id,
|
|
Note = $"GapInsuranceRemoveDate has changed from {targetActivity.Detail.GapInsuranceRemoveDate} to NULL"
|
|
});
|
|
}
|
|
|
|
await _activityService.ApplyStateChange(new ActivityStateChange
|
|
{
|
|
ActivityId = targetActivity.Id,
|
|
ActivityMatchId = linkedActivity.Id,
|
|
Note = $"Matched {linkedActivity.Product} Activity Id: {linkedActivity.Id} Added",
|
|
State = targetActivity.State
|
|
}, false);
|
|
}
|
|
|
|
private async Task<List<Activity>> ValidateMatchedActivityAccessories(List<Activity> matchedActivities, List<Activity> accessoryActivities)
|
|
{
|
|
var accessoryRemovedActivities = new List<Activity>();
|
|
foreach (var parentActivity in matchedActivities)
|
|
{
|
|
try
|
|
{
|
|
var accessoryActivity = accessoryActivities.FirstOrDefault(x => x.MatchingGapInsuranceActivityId == parentActivity.Id) == null
|
|
? await _activityRepository.GetActivityById(parentActivity.MatchingGapInsuranceActivityId)
|
|
: accessoryActivities.FirstOrDefault(x => x.MatchingGapInsuranceActivityId == parentActivity.Id);
|
|
|
|
if (accessoryActivity == null && parentActivity.Detail.GapInsuranceRemoveDate == null)
|
|
{
|
|
accessoryRemovedActivities.Add(await RemoveMissingGapAccessory(parentActivity));
|
|
continue;
|
|
}
|
|
|
|
if (parentActivity?.State == ActivityState.Accepted && accessoryActivity?.State == ActivityState.Accepted)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
accessoryRemovedActivities.Add(await RemoveGapAccessory(parentActivity, accessoryActivity));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var parentActivityId = parentActivity != null ? parentActivity.Id.ToString() : "NULL";
|
|
Log.Error(ex, $"Failed to validate matched GAP accessory for Activity Id:{parentActivityId}");
|
|
}
|
|
}
|
|
|
|
Log.Information($"Removed GAP Accessory From {accessoryRemovedActivities.Count} Activities");
|
|
|
|
return matchedActivities.Except(accessoryRemovedActivities).ToList();
|
|
}
|
|
|
|
private async Task<Activity> RemoveGapAccessory(Activity parentActivity, Activity accessoryActivity)
|
|
{
|
|
var removedDate = await DetermineRemovedDate(parentActivity, accessoryActivity);
|
|
|
|
await ApplyRemovalChangeUpdates(parentActivity, accessoryActivity, removedDate);
|
|
await ApplyRemovalChangeUpdates(accessoryActivity, parentActivity, removedDate);
|
|
await _unitOfWork.CompleteAsync();
|
|
return parentActivity.State == ActivityState.Accepted ? parentActivity : null;
|
|
}
|
|
|
|
private async Task ApplyRemovalChangeUpdates(Activity targetActivity, Activity linkedActivity, DateTime removedDateTime)
|
|
{
|
|
targetActivity.Detail.GapInsuranceRemoveDate = removedDateTime;
|
|
targetActivity.MatchingGapInsuranceActivityId = 0;
|
|
await _activityDetailService.SaveActivityDetailUpdate(new ActivityDetailUpdate
|
|
{
|
|
ActivityDetailId = targetActivity.Detail.Id,
|
|
Note = $"GapInsuranceRemoveDate has changed from NULL to {removedDateTime}"
|
|
});
|
|
await _activityService.ApplyStateChange(new ActivityStateChange
|
|
{
|
|
ActivityId = targetActivity.Id,
|
|
ActivityMatchId = linkedActivity.Id,
|
|
Note = $"Matched {linkedActivity.Product} Activity Id: {linkedActivity.Id} Removed",
|
|
State = targetActivity.State
|
|
}, false);
|
|
}
|
|
|
|
private static async Task<DateTime> DetermineRemovedDate(Activity parentActivity, Activity accessoryActivity)
|
|
{
|
|
if (parentActivity.State == ActivityState.Accepted && accessoryActivity.State != ActivityState.Accepted)
|
|
{
|
|
return await Task.FromResult(accessoryActivity.Accepted.Date.AddHours(12));
|
|
}
|
|
|
|
if (parentActivity.State != ActivityState.Accepted && accessoryActivity.State == ActivityState.Accepted)
|
|
{
|
|
return await Task.FromResult(parentActivity.Accepted.Date.AddHours(12));
|
|
}
|
|
|
|
return await Task.FromResult(parentActivity.LastUpdated <= accessoryActivity.LastUpdated
|
|
? parentActivity.Accepted.Date.AddHours(12)
|
|
: accessoryActivity.Accepted.Date.AddHours(12));
|
|
}
|
|
|
|
private async Task<Activity?> RemoveMissingGapAccessory(Activity activity)
|
|
{
|
|
Log.Warning($"Unable To Find GAP Accessory Activity Id: {activity.MatchingGapInsuranceActivityId}, Removing GAP Accessory From Activity Id: {activity.Id}");
|
|
var removeDate = DateTime.Now.Date.AddHours(12);
|
|
activity.MatchingGapInsuranceActivityId = 0;
|
|
activity.Detail.GapInsuranceRemoveDate = removeDate;
|
|
await _activityDetailService.SaveActivityDetailUpdate(new ActivityDetailUpdate
|
|
{
|
|
ActivityDetailId = activity.Detail.Id,
|
|
Note = $"GapInsuranceRemoveDate has changed from NULL to {removeDate}"
|
|
});
|
|
var activityStateChange = new ActivityStateChange
|
|
{
|
|
ActivityId = activity.Id,
|
|
Note = $"{Product.GAPInsurance} Accessory Activity Removed, Accessory Activity Not Found",
|
|
State = activity.State
|
|
};
|
|
|
|
await _activityService.ApplyStateChange(activityStateChange);
|
|
return activity.State == ActivityState.Accepted ? activity : null;
|
|
}
|
|
|
|
private async Task<List<Activity>> GetMatchingGapAccessoryActivities(IReadOnlyCollection<Activity> matchedActivities)
|
|
{
|
|
if (!matchedActivities.Any())
|
|
{
|
|
return new List<Activity>();
|
|
}
|
|
|
|
var ids = matchedActivities
|
|
.Select(activity => activity.MatchingGapInsuranceActivityId)
|
|
.ToList();
|
|
|
|
return await _activityRepository.FindById(ids);
|
|
}
|
|
}
|