private async Task SaveBankTransferFeeAsync(Collation collation, CollationSearch option, DateTime updateAt, CancellationToken token = default(CancellationToken)) { if (collation.CustomerId > 0) { var fee = new CustomerFee { CustomerId = collation.CustomerId, CurrencyId = collation.CurrencyId, Fee = collation.BankTransferFee, NewFee = collation.BankTransferFee, UpdateAt = updateAt, CreateAt = updateAt, CreateBy = option.LoginUserId, UpdateBy = option.LoginUserId, }; await addCustomerFeeQueryProcessor.SaveAsync(fee, token); } if (collation.PaymentAgencyId > 0) { var fee = new PaymentAgencyFee { PaymentAgencyId = collation.PaymentAgencyId, CurrencyId = collation.CurrencyId, Fee = collation.BankTransferFee, NewFee = collation.BankTransferFee, UpdateAt = updateAt, CreateAt = updateAt, CreateBy = option.LoginUserId, UpdateBy = option.LoginUserId, }; await addPaymentAgencyFeeQueryProcessor.SaveAsync(fee, token); } }
public Task <int> CollateMissingAsync(CollationSearch collationSearch, CancellationToken token = default(CancellationToken)) { var query = @" EXECUTE [dbo].[uspCollationMissing] @ClientKey "; return(dbHelper.ExecuteAsync(query, collationSearch, token)); }
public async Task <IEnumerable <MatchingHeader> > SearchMatchedDataR(CollationSearch option) => await hubContext.DoAsync(option.ConnectionId, async (notifier, token) => { var result = (await matchingProcessor.SearchMatchedDataAsync(option, token)).ToArray(); notifier?.UpdateState(); return(result); });
public async Task <IEnumerable <MatchingHeader> > SearchMatchedDataAsync(CollationSearch CollationSearch, CancellationToken token = default(CancellationToken)) { var collationSetting = (await getCollationSettingQueryProcessor.GetAsync(CollationSearch.CompanyId, token)); CollationSearch.SortOrderDirection = collationSetting.SortOrderDirection; var items = await matchingQueryProcessor.SearchMatchedDataAsync(CollationSearch, token); return(items); }
public async Task< MatchingResult> SequentialMatchingAsync(string SessionKey, Collation[] Collations, CollationSearch CollationSearch, string connectionId) => await authorizationProcessor.DoAuthorizeAsync(SessionKey, async token => { var notifier = hubContext.CreateNotifier(connectionId); try { var result = await matchingSequentialProcessor.MatchAsync(Collations, CollationSearch, token, notifier); return result; } catch (Exception) { notifier?.Abort(); // todo: cancellation throw; } }, logger, connectionId);
public async Task <IEnumerable <Collation> > CollateAsync(CollationSearch collationSearch, CancellationToken token = default(CancellationToken), IProgressNotifier notifier = null) { var orders = (await getCollationOrderQueryProcessor.GetItemsAsync(collationSearch.CompanyId, token)) .Where(x => x.Available == 1) .OrderBy(x => x.ExecutionOrder).ToArray(); using (var scope = transactionScopeBuilder.Create()) { var collationSetting = (await getCollationSettingQueryProcessor.GetAsync(collationSearch.CompanyId, token)); collationSearch.SortOrderDirection = collationSetting.SortOrderDirection; await collationQueryProcessor.InitializeAsync(collationSearch, token); notifier?.UpdateState(); foreach (var order in orders) { switch (order.CollationTypeId) { case 0: await collationQueryProcessor.CollatePayerCodeAsync(collationSearch, token); break; case 1: await collationQueryProcessor.CollateCustomerIdAsync(collationSearch, token); break; case 2: await collationQueryProcessor.CollateHistoryAsync(collationSearch, token); break; case 3: await collationQueryProcessor.CollatePayerNameAsync(collationSearch, token); break; case 4: await collationQueryProcessor.CollateKeyAsync(collationSearch, token); break; } notifier?.UpdateState(); } await collationQueryProcessor.CollateMissingAsync(collationSearch, token); notifier?.UpdateState(); var items = await collationQueryProcessor.GetItemsAsync(collationSearch, token); notifier?.UpdateState(); scope.Complete(); return(items); } }
public async Task<CollationsResult> CollateAsync(string SessionKey, CollationSearch CollationSearch, string connectionId) => await authorizationProcessor.DoAuthorizeAsync(SessionKey, async token => { var notifier = hubContext.CreateNotifier(connectionId); try { var result = (await collationProcessor.CollateAsync(CollationSearch, token, notifier)).ToList(); return new CollationsResult { ProcessResult = new ProcessResult { Result = true }, Collation = result, }; } catch (Exception) // cancellation { notifier?.Abort(); throw; } }, logger, connectionId);
public Task <int> InitializeAsync(CollationSearch collationSearch, CancellationToken token = default(CancellationToken)) { var query = @" EXECUTE [dbo].[uspCollationInitialize] @ClientKey , @CompanyId , @CurrencyId , @RecordedAtFrom , @RecordedAtTo , @DueAtFrom , @DueAtTo , @BillingType , @LimitDateType , @AmountType , @UseDepartmentWork, @UseSectionWork "; return(dbHelper.ExecuteAsync(query, collationSearch, token)); }
public async Task<MatchingSourceResult> SolveAsync(string SessionKey, MatchingSource source, CollationSearch option) => await authorizationProcessor.DoAuthorizeAsync(SessionKey, async token => { var result = await matchingSolveProcessor.SolveAsync(source, option, token: token); return new MatchingSourceResult { MatchingSource = result, ProcessResult = new ProcessResult { Result = true}, }; }, logger);
public async Task<MatchingHeadersResult> SearchMatchedDataAsync(string SessionKey, CollationSearch CollationSearch, string connectionId) => await authorizationProcessor.DoAuthorizeAsync(SessionKey, async token => { var notifier = hubContext.CreateNotifier(connectionId); var result = (await matchingProcessor.SearchMatchedDataAsync(CollationSearch, token)).ToList(); notifier?.UpdateState(); return new MatchingHeadersResult { ProcessResult = new ProcessResult { Result = true }, MatchingHeaders = result, }; }, logger, connectionId);
public async Task <ActionResult <IEnumerable <Collation> > > CollateR(CollationSearch option) => await hubContext.DoAsync(option.ConnectionId, async (notifier, token) => (await collationProcessor.CollateAsync(option, token, notifier)).ToArray());
public async Task <ActionResult <IEnumerable <Collation> > > Collate(CollationSearch option, CancellationToken token) => (await collationProcessor.CollateAsync(option, token, null)).ToArray();
public async Task <ActionResult <IEnumerable <MatchingHeader> > > SearchMatchedData(CollationSearch option, CancellationToken token) { var result = (await matchingProcessor.SearchMatchedDataAsync(option, token)).ToArray(); return(result); }
public Task <IEnumerable <Collation> > GetItemsAsync(CollationSearch option, CancellationToken token = default(CancellationToken)) { var receiptDisplayOrder = ""; switch (option.SortOrderDirection) { case SortOrderColumnType.MinRecordedAt: receiptDisplayOrder = "COALESCE(wc.MinReceiptRecordedAt, '9999/12/31') ASC"; break; case SortOrderColumnType.MaxRecordedAt: receiptDisplayOrder = "COALESCE(wc.MaxReceiptRecordedAt, '9999/12/31') DESC"; break; case SortOrderColumnType.MinReceiptId: receiptDisplayOrder = "wc.MinReceiptId ASC"; break; case SortOrderColumnType.MaxReceiptId: receiptDisplayOrder = "wc.MaxReceiptId DESC"; break; case SortOrderColumnType.PayerNameDesc: receiptDisplayOrder = "wc.PayerName DESC"; break; default: receiptDisplayOrder = "wc.PayerName ASC"; break; } var query = $@" SELECT wc.BillingAmount , wc.BillingCount , wc.ReceiptAmount , wc.ReceiptCount , wc.ParentCustomerId , wc.ParentCustomerId [CustomerId] , wc.PaymentAgencyId , wc.PayerName , wc.CurrencyId , wc.AdvanceReceivedCount , cs.Code [CustomerCode] , cs.Name [CustomerName] , pa.Code [PaymentAgencyCode] , pa.Name [PaymentAgencyName] , cs.IsParent , cy.Code [CurrencyCode] , cy.DisplayOrder [DisplayOrder] , cy.Tolerance [CurrencyTolerance] , COALESCE(pa.ShareTransferFee, cs.ShareTransferFee) [ShareTransferFee] , COALESCE(pa.UseFeeTolerance , cs.UseFeeTolerance) [UseFeeTolerance] , COALESCE(pa.UseFeeLearning , cs.UseFeeLearning ) [UseFeeLearning] , COALESCE(pa.UseKanaLearning , cs.UseKanaLearning) [UseKanaLearning] , COALESCE(pa.Code, cs.Code) [DispCustomerCode] , COALESCE(pa.Name, cs.Name) [DispCustomerName] , COALESCE(pa.Kana, cs.Kana) [DispCustomerKana] , CASE wc.BillingCount WHEN 0 THEN NULL ELSE wc.BillingAmount END [DispBillingAmount] , CASE wc.ReceiptCount WHEN 0 THEN NULL ELSE wc.ReceiptAmount END [DispReceiptAmount] , CASE wc.BillingCount WHEN 0 THEN NULL ELSE wc.BillingCount END [DispBillingCount] , CASE wc.ReceiptCount WHEN 0 THEN NULL ELSE wc.ReceiptCount END [DispReceiptCount] , CASE wc.BillingCount WHEN 0 THEN 1 ELSE 0 END [BillingPriority] , CASE wc.ReceiptCount WHEN 0 THEN 1 ELSE 0 END [ReceiptPriority] , wc.ForceMatchingIndividually , 0 [Checked] , 0 [BankTransferFee] , CASE WHEN dupe.[CurrencyId] IS NULL THEN 0 ELSE 1 END [DupeCheck] , cs.PrioritizeMatchingIndividually , ROW_NUMBER() OVER (ORDER BY COALESCE(pa.Code, cs.Code)) [BillingDisplayOrder] , ROW_NUMBER() OVER (ORDER BY {receiptDisplayOrder} ) [ReceiptDisplayOrder] FROM ( SELECT wc.CurrencyId , wc.ParentCustomerId , wc.PaymentAgencyId , SUM(DISTINCT BillingCount) [BillingCount] , SUM(DISTINCT CASE @AmountType WHEN 0 THEN BillingAmount ELSE BillingRemainAmount END) [BillingAmount] , SUM(ReceiptCount) [ReceiptCount] , SUM(ReceiptRemainAmount) [ReceiptAmount] , CASE SUM(AdvanceReceivedCount) WHEN 0 THEN 0 WHEN SUM(ReceiptCount) THEN 2 ELSE 1 END [AdvanceReceivedCount] , CASE MIN(COALESCE(wc.PayerName, '')) WHEN '' THEN NULL ELSE MIN(COALESCE(wc.PayerName, '')) END [PayerName] , MAX(wc.ForceMatchingIndividually) [ForceMatchingIndividually] , MIN(wc.MinReceiptRecordedAt) [MinReceiptRecordedAt] , MAX(wc.MaxReceiptRecordedAt) [MaxReceiptRecordedAt] , MIN(wc.MinReceiptId) [MinReceiptId] , MAX(wc.MaxReceiptId) [MaxReceiptId] FROM WorkCollation wc WHERE wc.ClientKey = @ClientKey AND wc.CompanyId = @CompanyId GROUP BY wc.CurrencyId , wc.ParentCustomerId , wc.PaymentAgencyId , CASE WHEN wc.ParentCustomerId = 0 AND wc.PaymentAgencyId = 0 THEN wc.PayerName END ) wc LEFT JOIN Customer cs ON cs.Id = wc.ParentCustomerId LEFT JOIN PaymentAgency pa ON pa.Id = wc.PaymentAgencyId LEFT JOIN Currency cy ON cy.Id = wc.CurrencyId LEFT JOIN ( SELECT DISTINCT wc.CurrencyId , wc.ParentCustomerId , wc.PaymentAgencyId FROM ( SELECT wc.PayerName , wc.PayerCode , wc.BankCode , wc.BranchCode , wc.SourceBankName , wc.SourceBranchName , wc.CustomerId , wc.CollationKey , wc.CurrencyId FROM WorkCollation wc WHERE wc.ClientKey = @ClientKey AND wc.CompanyId = @CompanyId AND wc.CurrencyId > 0 AND wc.ParentCustomerId >= 0 AND wc.PaymentAgencyId >= 0 AND wc.CollationType > 0 GROUP BY wc.PayerName , wc.PayerCode , wc.BankCode , wc.BranchCode , wc.SourceBankName , wc.SourceBranchName , wc.CustomerId , wc.CollationKey , wc.CurrencyId HAVING COUNT(1) > 1 ) dupe INNER JOIN WorkCollation wc ON wc.PayerName = dupe.PayerName AND wc.PayerCode = dupe.PayerCode AND wc.BankCode = dupe.BankCode ANd wc.BranchCode = dupe.BranchCode AND wc.SourceBankName = dupe.SourceBankName AND wc.SourceBranchName = dupe.SourceBranchName AND wc.CustomerId = dupe.CustomerId AND wc.CollationKey = dupe.CollationKey AND wc.CurrencyId = dupe.CurrencyId AND wc.ClientKey = @ClientKey AND wc.CompanyId = @CompanyId AND wc.CurrencyId > 0 AND wc.ParentCustomerId >= 0 AND wc.PaymentAgencyId >= 0 AND wc.CollationType > 0 ) dupe ON wc.CurrencyId = dupe.CurrencyId AND wc.ParentCustomerId = dupe.ParentCustomerId AND wc.PaymentAgencyId = dupe.PaymentAgencyId "; return(dbHelper.GetItemsAsync <Collation>(query, option, token)); }
public void SetPageDataSetting(List <Collation> collationList, bool timeSort, int useForeignCurrency, int Precision, CollationSearch cs) { this.useForeignCurrency = useForeignCurrency; if (useForeignCurrency == 1) { SetDisplayFormat(Precision); } DataSource = new BindingSource(collationList.ToArray(), null); txtChecked.DataField = "Checked"; txtCurrency.DataField = "CurrencyCode"; txtCustomerCode.DataField = "DispCustomerCode"; txtCustomerName.DataField = "DispCustomerName"; txtBillingCount.DataField = "DispBillingCount"; txtBillingAmount.DataField = "DispBillingAmount"; txtPayerName.DataField = "PayerName"; txtReceiptCount.DataField = "DispReceiptCount"; txtReceiptAmount.DataField = "DispReceiptAmount"; txtFee.DataField = "ReportDispShareTransferFee"; txtDifference.DataField = "DispDifferent"; }
public async Task <MatchingResult> MatchAsync( IEnumerable <Collation> collations, CollationSearch option, CancellationToken token = default(CancellationToken), IProgressNotifier notifier = null) { var appControl = await applicationControlQueryProcessor.GetAsync(option.CompanyId, token); var nettingReceipts = new List <Receipt>(); var updateAt = await dbSystemDateTimeQueryProcessor.GetAsync(token); var matchingOrders = await matchingOrderQueryProcessor.GetItemsAsync(option.CompanyId, token); var matchingBillingOrder = matchingOrders.Where(x => x.TransactionCategory == 1 && x.Available == 1).ToArray(); var matchingReceiptOrder = matchingOrders.Where(x => x.TransactionCategory == 2 && x.Available == 1).ToArray(); var matchings = new List <Matching>(); var advanceReceiveds = new List <AdvanceReceived>(); List <Billing> billings = null; List <Netting> nettings = null; List <Receipt> receipts = null; var index = 0; using (var scope = transactionScopeBuilder.Create()) { foreach (var collation in collations) { // 請求データ取得 var billingSearchOption = new MatchingBillingSearch { ClientKey = option.ClientKey, ParentCustomerId = collation.CustomerId, PaymentAgencyId = collation.PaymentAgencyId, CurrencyId = collation.CurrencyId, }; billings = (await matchingQueryProcessor.GetBillingsForSequentialMatchingAsync(billingSearchOption, matchingBillingOrder, token)).ToList(); var billingAmount = billings.Sum(item => (item.RemainAmount - item.DiscountAmount - item.OffsetAmount)); var billingCount = billings.Count; // 請求データチェック if (billingAmount != collation.BillingAmount || billingCount != collation.BillingCount) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.BillingRemainChanged, ErrorIndex = index, }); } // 相殺データ取得 nettings = (await matchingQueryProcessor.SearchMatchingNettingAsync(option, collation, token)).ToList(); // 相殺データ登録 var createdReceipstFromNetting = new List <Receipt>(); foreach (var netting in nettings) { var receipt = netting.ConvertToReceiptInput(option.LoginUserId, updateAt); var nettingReceipt = await matchingQueryProcessor.SaveMatchingReceiptAsync(receipt, token); if (!string.IsNullOrEmpty(netting.ReceiptMemo)) { await addReceiptMemoQueryProcessor.SaveAsync(nettingReceipt.Id, netting.ReceiptMemo, token); } netting.ReceiptId = nettingReceipt.Id; createdReceipstFromNetting.Add(nettingReceipt); } // 入金データ取得 var receiptSearch = new MatchingReceiptSearch { ClientKey = option.ClientKey, CompanyId = option.CompanyId, CurrencyId = collation.CurrencyId, ParentCustomerId = collation.CustomerId, PaymentAgencyId = collation.PaymentAgencyId, UseScheduledPayment = appControl.UseScheduledPayment, }; receipts = (await matchingQueryProcessor.GetReceiptsForSequentialMatchingAsync(receiptSearch, matchingReceiptOrder, token)).ToList(); var receiptAmount = receipts.Sum(item => (item.RemainAmount)); var receiptCount = receipts.Count(); var hasAdvanceReceived = receipts.Exists(item => item.UseAdvanceReceived == 1); // 入金データチェック if (receiptAmount != collation.ReceiptAmount || receiptCount != collation.ReceiptCount) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.ReceiptRemainChanged, ErrorIndex = index, }); } foreach (var netting in nettings) { await updateNettingQueryProcessor.UpdateMatchingNettingAsync(netting.CompanyId, netting.ReceiptId.Value, netting.Id, CancelFlg : 0, token : token); foreach (var receipt in receipts .Where(x => x.NettingId.HasValue && x.NettingId == netting.Id)) { receipt.Id = netting.ReceiptId.Value; } } // 前受処理日付取得 var recordedAt = option.GetRecordedAt(hasAdvanceReceived ? billings : null); option.AdvanceReceivedRecordedAt = recordedAt; var requestSource = new MatchingSource { Billings = billings, Receipts = receipts, BankTransferFee = collation.BankTransferFee, TaxDifference = collation.TaxDifference, }; var source = await matchingSolveProcessor.SolveAsync(requestSource, option, appControl, token); foreach (var netting in nettings) { foreach (var matching in source.Matchings.Where(x => x.IsNetting && x.ReceiptId == netting.Id)) { matching.ReceiptId = netting.ReceiptId.Value; } } if (collation.UseFeeLearning == 1 && collation.BankTransferFee != 0M) { await SaveBankTransferFeeAsync(collation, option, updateAt, token); } // データの更新処理 int?customerId = collation.CustomerId; if (customerId == 0) { customerId = null; } int?paymentAgencyId = collation.PaymentAgencyId; if (paymentAgencyId == 0) { paymentAgencyId = null; } source.LoginUserId = option.LoginUserId; source.UpdateAt = updateAt; source.MatchingProcessType = 0; source.CustomerId = customerId; source.PaymentAgencyId = paymentAgencyId; source.AdvanceReceivedCustomerId = option.DoTransferAdvanceReceived ? customerId : null; source.ClientKey = option.ClientKey; foreach (var r in createdReceipstFromNetting) { var item = receipts.First(x => x.Id == r.Id); item.UpdateAt = r.UpdateAt; } var matchingResult = await matchingSaveProcessor.SaveAsync(source, appControl, token); if (!matchingResult.ProcessResult.Result) { notifier?.Abort(); return(matchingResult); } matchings.AddRange(matchingResult.Matchings); advanceReceiveds.AddRange(matchingResult.AdvanceReceiveds); nettingReceipts.AddRange(createdReceipstFromNetting); notifier?.UpdateState(); index++; } scope.Complete(); } return(new MatchingResult { ProcessResult = new ProcessResult { Result = true }, Matchings = matchings, AdvanceReceiveds = advanceReceiveds, NettingReceipts = nettingReceipts }); }
public async Task <MatchingSource> SolveAsync( MatchingSource source, CollationSearch option, ApplicationControl control = null, CancellationToken token = default(CancellationToken)) { if (control == null) { control = await applicationControlQueryProcessor.GetAsync(option.CompanyId, token); } var useCashOnDueDates = control.UseCashOnDueDates; var useScheduledPayment = control.UseScheduledPayment; var useDeclaredAmount = control.UseDeclaredAmount; int?doCreateAdvanceReceived = option.DoTransferAdvanceReceived ? 1 : 0; var taxDifference = source.TaxDifference; var bankTransferFee = source.BankTransferFee; var billingItems = source.Billings; var receiptItems = source.Receipts; if (!(billingItems?.Any() ?? false)) { throw new ArgumentNullException("Billings"); } if (!(receiptItems?.Any() ?? false)) { throw new ArgumentNullException("Receipts"); } int companyId; int currencyId; { var billing = billingItems.First(); companyId = billing.CompanyId; currencyId = billing.CurrencyId; } var isAllMinusBilling = true; var billingTotal = 0M; var billingPair = GetBillingPair(billingItems, useScheduledPayment, useDeclaredAmount, ref doCreateAdvanceReceived, ref billingTotal, ref isAllMinusBilling); var isAllMinusReceipt = true; var receiptTotal = 0M; var receiptPair = GetReceiptPair(receiptItems, ref receiptTotal, ref isAllMinusReceipt); var isAllMinus = isAllMinusBilling && isAllMinusReceipt; var taxDiff = taxDifference; var bankFee = bankTransferFee; var isEqual = (billingTotal == receiptTotal + bankFee - taxDiff); Func <decimal, decimal, decimal> amountSolver = Math.Min; if (isAllMinus) { amountSolver = Math.Max; } var header = new MatchingHeader { Id = 1, CompanyId = companyId, CurrencyId = currencyId, BankTransferFee = bankFee, TaxDifference = taxDiff, }; var recordedAt = option.AdvanceReceivedRecordedAt; var matchings = new List <Matching>(); var billingScheduledIncomes = new List <BillingScheduledIncome>(); var matchingBillingDiscounts = new List <MatchingBillingDiscount>(); var billingDiscounts = new HashSet <long>(); var discountTotal = 0M; var beforBillingRemainTotal = 0M; var beforReceiptRemainTotal = 0M; var bindex = 0; var rindex = 0; var nextBilling = true; var nextReceipt = true; Billing bill = null; Receipt rcpt = null; while (bindex < billingItems.Count && rindex < receiptItems.Count && (nextBilling || nextReceipt)) { if (token.IsCancellationRequested) { throw new OperationCanceledException(); } if (nextBilling) { bill = billingItems[bindex]; } if (nextReceipt) { rcpt = receiptItems[rindex]; } var isLastBill = bindex == billingItems.Count - 1; var isLastRcpt = rindex == receiptItems.Count - 1; var discount = bill.DiscountAmount; var billTaxDiff = (0M < taxDiff) ? taxDiff : 0M; var rcptTaxDiff = (0M < taxDiff) ? 0M : -taxDiff; var matching = new Matching(); matching.Id = matchings.Count; matching.CompanyId = companyId; matching.CurrencyId = currencyId; matching.MatchingHeaderId = header.Id; matching.ReceiptId = rcpt.NettingId ?? rcpt.Id; matching.PayerName = rcpt.PayerName; matching.SourceBankName = rcpt.SourceBankName; matching.SourceBranchName = rcpt.SourceBranchName; matching.IsNetting = rcpt.NettingId.HasValue; matching.RecordedAt = (rcpt.OriginalReceiptId.HasValue ? recordedAt : null) ?? rcpt.RecordedAt; matching.ReceiptHeaderId = rcpt.ReceiptHeaderId; if (useCashOnDueDates == 1 && rcpt.UseCashOnDueDates == 1) { matching.UseCashOnDueDates = 1; } matching.BillingId = bill.Id; if (useScheduledPayment == 1 && useDeclaredAmount == 1) { matching.OffsetAmount = bill.OffsetAmount; } if (discount != 0M) { #region billing discount matching.DiscountAmount1 = bill.DiscountAmount1; matching.DiscountAmount2 = bill.DiscountAmount2; matching.DiscountAmount3 = bill.DiscountAmount3; matching.DiscountAmount4 = bill.DiscountAmount4; matching.DiscountAmount5 = bill.DiscountAmount5; if (!billingDiscounts.Contains(bill.Id)) { billingDiscounts.Add(bill.Id); } matchingBillingDiscounts.AddRange(ConvertBillingToDiscounts(bill, matching.Id)); discountTotal += discount; bill.DiscountAmount = 0M; bill.DiscountAmount1 = 0M; bill.DiscountAmount2 = 0M; bill.DiscountAmount3 = 0M; bill.DiscountAmount4 = 0M; bill.DiscountAmount5 = 0M; #endregion } matching.BankTransferFee = bankFee; matching.TaxDifference = taxDiff; matching.Memo = bill.Memo; var billAmount = billingPair[bindex] - rcptTaxDiff - bankFee - discount; var rcptAmount = receiptPair[rindex] - billTaxDiff; matching.Amount = (isEqual && isLastRcpt && !isLastBill) ? billAmount : (isEqual && !isLastRcpt && isLastBill) ? rcptAmount : amountSolver(billAmount, rcptAmount); header.Amount += matching.Amount; if (matching.Amount == 0M && taxDiff == 0M && bankFee == 0M && discount == 0M) { break; } var billAssignAmount = (matching.Amount + rcptTaxDiff + bankFee + discount); var rcptAssignAmount = (matching.Amount + billTaxDiff); if (nextBilling) { beforBillingRemainTotal += bill.RemainAmount; bill.AssignmentAmount = billAssignAmount; } else { bill.AssignmentAmount += billAssignAmount; } if (nextReceipt) { beforReceiptRemainTotal += rcpt.RemainAmount; rcpt.AssignmentAmount = rcptAssignAmount; } else { rcpt.AssignmentAmount += rcptAssignAmount; } billingPair[bindex] -= billAssignAmount; receiptPair[rindex] -= rcptAssignAmount; nextBilling = billingPair[bindex] == 0M && !isLastBill; nextReceipt = receiptPair[rindex] == 0M && !isLastRcpt; matchings.Add(matching); if (!isEqual) { if (!nextBilling && isLastBill && receiptPair[rindex] > 0M && !rcpt.OriginalReceiptId.HasValue) { matching.AdvanceReceivedOccured = 1; } if (!nextBilling && isLastBill && receiptPair[rindex] != 0M) { foreach (var m in matchings.Where(x => x.ReceiptId == rcpt.Id)) { m.ReceiptRemain = receiptPair[rindex]; } } if (!nextReceipt && isLastRcpt && billingPair[bindex] != 0M) { foreach (var m in matchings.Where(x => x.BillingId == bill.Id)) { m.BillingRemain = billingPair[bindex]; } } if (billingPair[bindex] == 0M && isLastBill || receiptPair[rindex] == 0M && isLastRcpt) { break; } } if (nextBilling) { bindex++; } if (nextReceipt) { rindex++; } taxDiff = 0M; bankFee = 0M; } var remainType = 0; var billingRemainTotal = billingPair.Sum(x => x.Value); var receiptRemainTotal = receiptPair.Sum(x => x.Value); if (billingRemainTotal == 0M && receiptRemainTotal == 0M) { remainType = 0; } else if (billingRemainTotal != 0M) { remainType = 1; } else { if (!rcpt.OriginalReceiptId.HasValue && option.UseAdvanceReceived && receiptPair[rindex] > 0M) { remainType = 3; } else { remainType = 2; } } if (useCashOnDueDates == 1) { billingScheduledIncomes.AddRange(ConvertMatchingToScheduled(matchings)); } billingItems = billingItems.Take(bindex + 1).ToList(); receiptItems = receiptItems.Take(rindex + 1).ToList(); header.BillingCount = billingItems.Count; header.ReceiptCount = receiptItems.Count; if (token.IsCancellationRequested) { throw new OperationCanceledException(); } return(new MatchingSource { RemainType = remainType, Matchings = matchings, Billings = billingItems, Receipts = receiptItems, BillingDiscounts = billingDiscounts, MatchingBillingDiscounts = matchingBillingDiscounts, MatchingHeader = header, BillingScheduledIncomes = billingScheduledIncomes, BillingRemainTotal = beforBillingRemainTotal, ReceiptRemainTotal = beforReceiptRemainTotal, BillingDiscountTotal = discountTotal }); }