public async Task <List <DataLockStatusChanged> > ProcessPayableEarning(DataLockEvent payableEarningEvent) { using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { var result = new List <DataLockStatusChanged>(); var changedToPassed = new DataLockStatusChangedToPassed { TransactionTypesAndPeriods = new Dictionary <TransactionType, List <EarningPeriod> >() }; var failuresToDelete = new List <long>(); var newPassesGroupedByTypeAndPeriod = GetPassesGroupedByTypeAndPeriod(payableEarningEvent); var oldFailures = await dataLockFailureRepository.GetFailures( payableEarningEvent.Ukprn, payableEarningEvent.Learner.ReferenceNumber, payableEarningEvent.LearningAim.FrameworkCode, payableEarningEvent.LearningAim.PathwayCode, payableEarningEvent.LearningAim.ProgrammeType, payableEarningEvent.LearningAim.StandardCode, payableEarningEvent.LearningAim.Reference, payableEarningEvent.CollectionYear ).ConfigureAwait(false); foreach (var oldFailure in oldFailures) { if (newPassesGroupedByTypeAndPeriod.TryGetValue( (oldFailure.TransactionType, oldFailure.DeliveryPeriod), out var newPass)) { AddTypeAndPeriodToEvent(changedToPassed, oldFailure.TransactionType, newPass, payableEarningEvent); failuresToDelete.Add(oldFailure.Id); } } if (changedToPassed.TransactionTypesAndPeriods.Count > 0) { result.Add(changedToPassed); } foreach (var dataLockStatusChanged in result) { mapper.Map(payableEarningEvent, dataLockStatusChanged); } await dataLockFailureRepository.ReplaceFailures(failuresToDelete, new List <DataLockFailureEntity>(), payableEarningEvent.EarningEventId, payableEarningEvent.EventId).ConfigureAwait(false); scope.Complete(); paymentLogger.LogDebug( $"Deleted {failuresToDelete.Count} old DL failures for UKPRN {payableEarningEvent.Ukprn} Learner Ref {payableEarningEvent.Learner.ReferenceNumber} on R{payableEarningEvent.CollectionPeriod.Period:00}"); return(result); } }
public async Task <List <DataLockStatusChanged> > ProcessDataLockFailure(DataLockEvent dataLockEvent) { var result = new List <DataLockStatusChanged>(); var changedToFailed = new DataLockStatusChangedToFailed { TransactionTypesAndPeriods = new Dictionary <TransactionType, List <EarningPeriod> >() }; var changedToPassed = new DataLockStatusChangedToPassed { TransactionTypesAndPeriods = new Dictionary <TransactionType, List <EarningPeriod> >() }; var failureChanged = new DataLockFailureChanged { TransactionTypesAndPeriods = new Dictionary <TransactionType, List <EarningPeriod> >() }; var failuresToDelete = new List <long>(); var failuresToRecord = new List <DataLockFailureEntity>(); var newFailuresGroupedByTypeAndPeriod = GetFailuresGroupedByTypeAndPeriod(dataLockEvent); using (var scope = TransactionScopeFactory.CreateSerialisableTransaction()) { var oldFailures = await dataLockFailureRepository.GetFailures( dataLockEvent.Ukprn, dataLockEvent.Learner.ReferenceNumber, dataLockEvent.LearningAim.FrameworkCode, dataLockEvent.LearningAim.PathwayCode, dataLockEvent.LearningAim.ProgrammeType, dataLockEvent.LearningAim.StandardCode, dataLockEvent.LearningAim.Reference, dataLockEvent.CollectionYear ).ConfigureAwait(false); var fullListOfKeys = newFailuresGroupedByTypeAndPeriod.Keys .Concat(oldFailures.Select(f => (f.TransactionType, f.DeliveryPeriod))) .Distinct() .ToList(); foreach (var key in fullListOfKeys) { var transactionType = key.Item1; var period = key.Item2; if (!newFailuresGroupedByTypeAndPeriod.TryGetValue(key, out var newPeriod)) { paymentLogger.LogWarning( $"Earning does not have transaction type {transactionType} for period {period} which is present in DataLockFailure. UKPRN {dataLockEvent.Ukprn}, LearnRefNumber: {dataLockEvent.Learner.ReferenceNumber}"); continue; } var oldFailureEntity = oldFailures.FirstOrDefault(f => f.TransactionType == transactionType && f.DeliveryPeriod == period); var oldFailure = oldFailureEntity?.EarningPeriod.DataLockFailures; var newFailure = newPeriod?.DataLockFailures; var statusChange = dataLockStatusService.GetStatusChange(oldFailure, newFailure); switch (statusChange) { case DataLockStatusChange.ChangedToFailed: AddTypeAndPeriodToEvent(changedToFailed, transactionType, newPeriod, dataLockEvent); failuresToRecord.Add(CreateEntity(dataLockEvent, transactionType, period, newPeriod)); break; case DataLockStatusChange.ChangedToPassed: AddTypeAndPeriodToEvent(changedToPassed, transactionType, newPeriod, dataLockEvent); failuresToDelete.Add(oldFailureEntity.Id); break; case DataLockStatusChange.FailureChanged: AddTypeAndPeriodToEvent(failureChanged, transactionType, newPeriod, dataLockEvent); failuresToRecord.Add(CreateEntity(dataLockEvent, transactionType, period, newPeriod)); failuresToDelete.Add(oldFailureEntity.Id); break; } } if (changedToFailed.TransactionTypesAndPeriods.Count > 0) { result.Add(changedToFailed); } if (changedToPassed.TransactionTypesAndPeriods.Count > 0) { result.Add(changedToPassed); } if (failureChanged.TransactionTypesAndPeriods.Count > 0) { result.Add(failureChanged); } foreach (var dataLockStatusChanged in result) { mapper.Map(dataLockEvent, dataLockStatusChanged); } await dataLockFailureRepository.ReplaceFailures(failuresToDelete, failuresToRecord, dataLockEvent.EarningEventId, dataLockEvent.EventId).ConfigureAwait(false); scope.Complete(); paymentLogger.LogDebug( $"Deleted {failuresToDelete.Count} old DL failures, created {failuresToRecord.Count} new for UKPRN {dataLockEvent.Ukprn} Learner Ref {dataLockEvent.Learner.ReferenceNumber} on R{dataLockEvent.CollectionPeriod.Period:00}"); return(result); } }