private async Task AddRefundPaymentToCache(CalculatedRequiredLevyAmount paymentEvent) { var keysValue = await refundSortKeysCache.TryGet(CacheKeys.RefundPaymentsKeyListKey).ConfigureAwait(false); var refundKeysList = keysValue.HasValue ? keysValue.Value : new List <string>(); refundKeysList.Add(paymentEvent.EventId.ToString()); await requiredPaymentsCache.AddOrReplace(paymentEvent.EventId.ToString(), paymentEvent).ConfigureAwait(false); await refundSortKeysCache.AddOrReplace(CacheKeys.RefundPaymentsKeyListKey, refundKeysList).ConfigureAwait(false); }
public async Task <ReadOnlyCollection <FundingSourcePaymentEvent> > ProcessReceiverTransferPayment(ProcessUnableToFundTransferFundingSourcePayment message) { if (!message.AccountId.HasValue) { throw new InvalidOperationException($"Invalid ProcessUnableToFundTransferFundingSourcePayment event. No account id populated on message. Event id: {message.EventId}"); } paymentLogger.LogDebug($"Converting the unable to fund transfer payment to a levy payment. Event id: {message.EventId}, account id: {message.AccountId}, job id: {message.JobId}"); var requiredPayment = mapper.Map <CalculatedRequiredLevyAmount>(message); paymentLogger.LogVerbose("Mapped ProcessUnableToFundTransferFundingSourcePayment to CalculatedRequiredLevyAmount"); var payments = new List <FundingSourcePaymentEvent>(); var monthEndStartedCacheItem = await monthEndCache.TryGet(CacheKeys.MonthEndCacheKey); if (!monthEndStartedCacheItem.HasValue || !monthEndStartedCacheItem.Value) { paymentLogger.LogDebug("Month end has not been started yet so adding the payment to the cache."); await AddRequiredPayment(requiredPayment); } else { var levyAccountCacheItem = await levyAccountCache.TryGet(CacheKeys.LevyBalanceKey, CancellationToken.None) .ConfigureAwait(false); if (!levyAccountCacheItem.HasValue) { throw new InvalidOperationException($"The last levy account balance has not been stored in the reliable for account: {message.AccountId}"); } levyBalanceService.Initialise(levyAccountCacheItem.Value.Balance, levyAccountCacheItem.Value.TransferAllowance); paymentLogger.LogDebug("Service has finished month end processing so now generating the payments for the ProcessUnableToFundTransferFundingSourcePayment event."); payments.AddRange(CreateFundingSourcePaymentsForRequiredPayment(requiredPayment, message.AccountId.Value, message.JobId)); var remainingBalance = mapper.Map <LevyAccountModel>(levyAccountCacheItem.Value); remainingBalance.Balance = levyBalanceService.RemainingBalance; remainingBalance.TransferAllowance = levyBalanceService.RemainingTransferAllowance; await levyAccountCache.AddOrReplace(CacheKeys.LevyBalanceKey, remainingBalance); } paymentLogger.LogInfo($"Finished processing the ProcessUnableToFundTransferFundingSourcePayment. Event id: {message.EventId}, account id: {message.AccountId}, job id: {message.JobId}"); return(payments.AsReadOnly()); }
private async Task AddRequiredPaymentToCache(CalculatedRequiredLevyAmount paymentEvent) { var keysValue = await requiredPaymentSortKeysCache.TryGet(CacheKeys.RequiredPaymentKeyListKey).ConfigureAwait(false); var requiredPaymentKeysList = keysValue.HasValue ? keysValue.Value : new List <RequiredPaymentSortKeyModel>(); var newRequiredPaymentSortKey = new RequiredPaymentSortKeyModel { Id = paymentEvent.EventId.ToString(), Uln = paymentEvent.Learner.Uln, Ukprn = paymentEvent.Ukprn, AgreedOnDate = paymentEvent.AgreedOnDate ?? DateTime.MinValue }; requiredPaymentKeysList.Add(newRequiredPaymentSortKey); await requiredPaymentsCache.AddOrReplace(newRequiredPaymentSortKey.Id, paymentEvent).ConfigureAwait(false); await requiredPaymentSortKeysCache.AddOrReplace(CacheKeys.RequiredPaymentKeyListKey, requiredPaymentKeysList).ConfigureAwait(false); }
public async Task <ReadOnlyCollection <FundingSourcePaymentEvent> > HandleMonthEnd(long employerAccountId, long jobId) { var fundingSourceEvents = new List <FundingSourcePaymentEvent>(); var keys = await generateSortedPaymentKeys.GeyKeys().ConfigureAwait(false); var levyAccount = await levyFundingSourceRepository.GetLevyAccount(employerAccountId); levyBalanceService.Initialise(levyAccount.Balance, levyAccount.TransferAllowance); paymentLogger.LogDebug($"Processing {keys.Count} required payments, levy balance {levyAccount.Balance}, account {employerAccountId}, job id {jobId}"); foreach (var key in keys) { var requiredPaymentEvent = await requiredPaymentsCache.TryGet(key).ConfigureAwait(false); if (!requiredPaymentEvent.HasValue) { continue; } fundingSourceEvents.AddRange(CreateFundingSourcePaymentsForRequiredPayment(requiredPaymentEvent.Value, employerAccountId, jobId)); await requiredPaymentsCache.Clear(key).ConfigureAwait(false); } paymentLogger.LogDebug($"Created {fundingSourceEvents.Count} payments - {GetFundsDebugString(fundingSourceEvents)}, account {employerAccountId}, job id {jobId}"); levyAccount.Balance = levyBalanceService.RemainingBalance; levyAccount.TransferAllowance = levyBalanceService.RemainingTransferAllowance; await levyAccountCache.AddOrReplace(CacheKeys.LevyBalanceKey, levyAccount); await refundSortKeysCache.Clear(CacheKeys.RefundPaymentsKeyListKey).ConfigureAwait(false); await transferPaymentSortKeysCache.Clear(CacheKeys.SenderTransferKeyListKey).ConfigureAwait(false); await requiredPaymentSortKeysCache.Clear(CacheKeys.RequiredPaymentKeyListKey).ConfigureAwait(false); await monthEndCache.AddOrReplace(CacheKeys.MonthEndCacheKey, true, CancellationToken.None); paymentLogger.LogInfo($"Finished generating levy and/or co-invested payments for the account: {employerAccountId}, number of payments: {fundingSourceEvents.Count}."); return(fundingSourceEvents.AsReadOnly()); }
public async Task StoreEmployerProviderPriority(EmployerChangedProviderPriority providerPriorityEvent) { try { int order = 1; var paymentPriorities = new List <EmployerProviderPriorityModel>(); foreach (var providerUkprn in providerPriorityEvent.OrderedProviders) { paymentPriorities.Add(new EmployerProviderPriorityModel { Ukprn = providerUkprn, EmployerAccountId = providerPriorityEvent.EmployerAccountId, Order = order }); order++; } using (var scope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled)) { paymentLogger.LogDebug($"Replacing Previous EmployerProviderPriority for Account Id {providerPriorityEvent.EmployerAccountId}"); await levyFundingSourceRepository.ReplaceEmployerProviderPriorities(providerPriorityEvent.EmployerAccountId, paymentPriorities).ConfigureAwait(false); paymentLogger.LogDebug($"Successfully Replaced Previous EmployerProviderPriority for Account Id {providerPriorityEvent.EmployerAccountId}"); paymentLogger.LogDebug($"Adding EmployerProviderPriority to Cache for Account Id {providerPriorityEvent.EmployerAccountId}"); await employerProviderPriorities.AddOrReplace(CacheKeys.EmployerPaymentPriorities, paymentPriorities).ConfigureAwait(false); paymentLogger.LogInfo($"Successfully Add EmployerProviderPriority to Cache for Account Id {providerPriorityEvent.EmployerAccountId}"); scope.Complete(); } } catch (Exception e) { paymentLogger.LogError($"Error while updating EmployerProviderPriority for Account Id {providerPriorityEvent.EmployerAccountId}", e); throw; } }
public async Task <ReadOnlyCollection <FundingSourcePaymentEvent> > HandleMonthEnd( ProcessLevyPaymentsOnMonthEndCommand command) { paymentLogger.LogVerbose( $"Handling ProcessLevyPaymentsOnMonthEndCommand for {Id}, Job: {command.JobId}, Account: {command.AccountId}"); try { using (var operation = telemetry.StartOperation("LevyFundedService.HandleMonthEnd", command.CommandId.ToString())) { var stopwatch = Stopwatch.StartNew(); var fundingSourceEvents = await fundingSourceEventGenerationService.HandleMonthEnd(command.AccountId, command.JobId, command.CollectionPeriod); await monthEndCache.AddOrReplace(CacheKeys.MonthEndStartedForThisAccountCacheKey, true, CancellationToken.None); telemetry.TrackDurationWithMetrics("LevyFundedService.HandleMonthEnd", stopwatch, command, command.AccountId, new Dictionary <string, double> { { TelemetryKeys.Count, fundingSourceEvents.Count } }); telemetry.StopOperation(operation); return(fundingSourceEvents); } } catch (Exception ex) { paymentLogger.LogError($"Failed to get levy or co-invested month end payments. Error: {ex.Message}", ex); throw; } }
private async Task Initialise() { if (await actorCache.IsInitialiseFlagIsSet().ConfigureAwait(false)) { paymentLogger.LogVerbose($"Actor already initialised for employer {Id}"); return; } var stopwatch = Stopwatch.StartNew(); paymentLogger.LogInfo($"Initialising actor for employer {Id.GetLongId()}"); var paymentPriorities = await levyFundingSourceRepository.GetPaymentPriorities(Id.GetLongId()).ConfigureAwait(false); await employerProviderPriorities .AddOrReplace(CacheKeys.EmployerPaymentPriorities, paymentPriorities, default(CancellationToken)) .ConfigureAwait(false); await actorCache.SetInitialiseFlag().ConfigureAwait(false); paymentLogger.LogInfo($"Initialised actor for employer {Id.GetLongId()}"); TrackInfrastructureEvent("LevyFundedService.Initialise", stopwatch); }
public async Task <ReadOnlyCollection <FundingSourcePaymentEvent> > HandleMonthEnd(long employerAccountId, long jobId, CollectionPeriod collectionPeriod) { var levyAccount = await levyFundingSourceRepository.GetLevyAccount(employerAccountId); levyBalanceService.Initialise(levyAccount.Balance, levyAccount.TransferAllowance); var orderedRequiredLevyPayments = await GetOrderedCalculatedRequiredLevyAmounts(employerAccountId, collectionPeriod).ConfigureAwait(false); logger.LogDebug($"Processing {orderedRequiredLevyPayments.Count} required payments, levy balance {levyAccount.Balance}, account {employerAccountId}, job id {jobId}"); var fundingSourceEvents = new List <FundingSourcePaymentEvent>(); fundingSourceEvents.AddRange(orderedRequiredLevyPayments.SelectMany(payment => fundingSourcePaymentEventBuilder.BuildFundingSourcePaymentsForRequiredPayment(payment, employerAccountId, jobId))); logger.LogDebug($"Created {fundingSourceEvents.Count} payments - {GetFundsDebugString(fundingSourceEvents)}, account {employerAccountId}, job id {jobId}"); levyAccount.Balance = levyBalanceService.RemainingBalance; levyAccount.TransferAllowance = levyBalanceService.RemainingTransferAllowance; await levyAccountCache.AddOrReplace(CacheKeys.LevyBalanceKey, levyAccount); logger.LogInfo($"Finished generating levy and/or co-invested payments for the account: {employerAccountId}, number of payments: {fundingSourceEvents.Count}."); return(fundingSourceEvents.AsReadOnly()); }