private async Task <FundsResponseResult> DigestResponseItemAsync( FundsResponseFile file, FundsResponseFileItem item, FundsTransferRequest fundsTransferRequest, FundsTransferBatchMessage responseBatchMessage, SO statefulObject, State stateAfterRequest) { if (file == null) { throw new ArgumentNullException(nameof(file)); } if (item == null) { throw new ArgumentNullException(nameof(item)); } if (fundsTransferRequest == null) { throw new ArgumentNullException(nameof(fundsTransferRequest)); } var line = new FundsResponseLine(file, item, responseBatchMessage.ID); return(await DigestResponseLineAsync(fundsTransferRequest, line, statefulObject, stateAfterRequest)); }
/// <summary> /// Digest a funds response file by feeding it to all <see cref="FundsTransferManagers"/> /// for digestion and combining results. /// The existence of the credit system and /// the collation specified in <paramref name="file"/> is assumed. /// </summary> /// <param name="file">The file to digest.</param> /// <param name="responseBatchMessage">The batch message where the generated funds transfer events will be assigned.</param> /// <returns> /// Returns a collection of results describing the execution outcome of the /// contents of the <paramref name="file"/> or an empty collection if the file is not relevant to this manager. /// </returns> protected internal override async Task <IReadOnlyCollection <FundsResponseResult> > DigestResponseFileAsync( FundsResponseFile file, FundsTransferBatchMessage responseBatchMessage) { if (file == null) { throw new ArgumentNullException(nameof(file)); } if (responseBatchMessage == null) { throw new ArgumentNullException(nameof(responseBatchMessage)); } var fundsResponseResults = Enumerable.Empty <FundsResponseResult>(); foreach (var manager in this.FundsTransferManagers) { var managerResults = await manager.DigestResponseFileAsync(file, responseBatchMessage); await manager.PostProcessLinesAsync(file.BatchID, managerResults, responseBatchMessage.ID); fundsResponseResults = fundsResponseResults.Concat(managerResults); } return(fundsResponseResults.ToArray()); }
/// <summary> /// Digest a funds transfer response file from a credit system /// and execute the appropriate state paths /// as specified by the <see cref="TrySpecifyNextStatePath(SO, State, FundsResponseLine)"/> method /// on the corresponding stateful objects. /// The existence of the credit system and /// the collation specified in <paramref name="file"/> is assumed. /// </summary> /// <param name="file">The file to digest.</param> /// <param name="responseBatchMessage">The batch message where the generated funds transfer events will be assigned.</param> /// <returns> /// Returns a collection of results describing the execution outcome of the /// contents of the <paramref name="file"/> or an empty collection if the file is not relevant to this manager. /// </returns> /// <remarks> /// Each action in paths being executed will receive an arguments dictionary /// containing at least the key <see cref="StandardArgumentKeys.BillingItem"/> set with value /// of type <see cref="FundsResponseLine"/>. /// </remarks> protected internal override async Task <IReadOnlyCollection <FundsResponseResult> > DigestResponseFileAsync( FundsResponseFile file, FundsTransferBatchMessage responseBatchMessage) { if (file == null) { throw new ArgumentNullException(nameof(file)); } long[] lineIDs = file.Items.Select(i => i.LineID).ToArray(); var fundsTransferEventAssociations = this.FundsTransferEventAssociations; var stateHolders = from a in fundsTransferEventAssociations where a != null select a.StateHolder; await EagerFetchStateHoldersAsync(stateHolders); var associationsQuery = from a in fundsTransferEventAssociations where a.Event.Type == FundsTransferEventType.Pending let ftr = a.Event.Request where lineIDs.Contains(ftr.GroupID) && ftr.BatchID == file.BatchID select new { Request = ftr, ftr.Events, ftr.MainAccount, ftr.TransferAccount, a.StateHolder, a.CurrentState, StateAfterRequest = a.StateTransition != null ? a.StateTransition.Path.NextState : null }; var associations = await associationsQuery.ToArrayAsync(); if (associations.Length == 0) { return(emptyFundsResponseResults); } var responseResults = new List <FundsResponseResult>(associations.Length); var itemsByLineID = file.Items .OrderBy(i => i.Time) .ToSequentialReadOnlyMultiDictionary(i => i.LineID); foreach (var association in associations) { foreach (var item in itemsByLineID[association.Request.GroupID]) { var statefulObject = GetStatefulObject(association.StateHolder); var fundsResponseResult = await DigestResponseItemAsync( file, item, association.Request, responseBatchMessage, statefulObject, association.StateAfterRequest); responseResults.Add(fundsResponseResult); } } return(responseResults); }