public async Task <int> CancelAsync(JournalizingOption option, CancellationToken token = default(CancellationToken)) { var count = 0; using (var scope = transactionScopeBuilder.Create()) { option.UpdateAt = await dbSystemDateTimeQueryProcessor.GetAsync(token); count += await updateMatchingJournalizingQueryProcessor.CancelAsync(option, token); count += await updateReceiptMatchingJournalizingQueryProcessor.CancelAsync(option, token); count += await updateAdvanceReceivedBackupJournaliginzQueryProcessor.CancelAsync(option, token); count += await updateReceiptExcludeJournalizingQueryProcessor.CancelAsync(option, token); scope.Complete(); } return(count); }
public async Task <MatchingResult> CancelAsync(IEnumerable <MatchingHeader> headers, int loginUserId, CancellationToken token = default(CancellationToken), IProgressNotifier notifier = null) { var headersArray = headers.ToArray(); var updateAt = await dbSystemDatetimeQueryProcessor.GetAsync(token); List <Matching> details = null; List <Billing> billings = null; List <Receipt> receipts = null; var deleteMatchings = new List <Matching>(); var deleteReceipts = new List <Receipt>(); var companyId = headers.Select(x => x.CompanyId).First(); var appControl = await applicationControlGetByCompanyIdQueryProcessor.GetAsync(companyId, token); var useCashOnDueDates = appControl.UseCashOnDueDates == 1; using (var scope = transactionScopeBuilder.Create()) { foreach (var header in headers) { if (token.IsCancellationRequested) { return new MatchingResult { MatchingErrorType = MatchingErrorType.ProcessCanceled } } ; #region 1.消込データ(Matching)取得 details = (await cancelMatchingQueryProcessor.GetByHeaderIdAsync(header.Id, token)).ToList(); deleteMatchings.AddRange(details); #endregion #region 2.消込済請求データ取得 // billing deleteAt など matching 以外の情報が必要なので、 query で呼び出し必須 billings = (await cancelMatchingQueryProcessor.GetMatchedBillingsForCancelAsync(header.Id, token)).ToList(); #endregion if (billings.Count == 0) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.NotExistBillingData }); } //3.請求データチェック if (billings.Any(e => e.DeleteAt.HasValue)) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.BillingOmitted, ErrorIndex = Array.IndexOf(headersArray, header), }); } if (useCashOnDueDates && await cancelMatchingQueryProcessor.ExistAssignmentScheduledIncomeAsync(details.Select(x => x.Id).ToArray(), token)) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.CashOnDueDateOmitted, ErrorIndex = Array.IndexOf(headersArray, header), }); } #region 4.請求データ消込解除処理 // 期日現金管理用 請求ID -> 消込ID の Dictionary Dictionary <long, long[]> billingIdToMatchingIds = null; if (useCashOnDueDates) { billingIdToMatchingIds = details.GroupBy(x => x.BillingId) .ToDictionary(x => x.Key, x => x.Select(y => y.Id).ToArray()); } foreach (var billing in billings) { var item = billing; var matchingAmount = billing.AssignmentAmount; var bankFee = billing.BankTransferFee; var taxDiff = billing.TaxDifference; var discount = billing.DiscountAmount; var amount = matchingAmount + bankFee + discount - (taxDiff < 0 ? taxDiff : 0M); item.CompanyId = header.CompanyId; item.RemainAmount = amount; item.AssignmentAmount = amount; item.UpdateBy = loginUserId; item.UpdateAt = updateAt; var updatedBilling = await cancelMatchingQueryProcessor.UpdateBillingForCancelMatchingAsync(item, token); if (updatedBilling == null) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.CancelError }); } await cancelMatchingQueryProcessor.UpdatePreviousBillingLogsAsync(header.Id, billing.Id, amount, loginUserId, updateAt, token); if (useCashOnDueDates) { foreach (var matchingId in billingIdToMatchingIds[billing.Id]) { var income = await cancelMatchingQueryProcessor.GetBillingScheduledIncomeAsync(matchingId, token); if (income != null) { await cancelMatchingQueryProcessor.DeleteBillingShceduledIncomeAsync(income.BillingId, token); await deleteBillingByIdQueryProcessor.DeleteAsync(income.BillingId, token); } } } } #endregion #region 5.相殺データ消込解除処理 var nettings = (await nettingQueryProcessor.GetByMatchingHeaderIdAsync(header.Id, token)).ToList(); var nettingReceiptIds = new List <long>(); foreach (var netting in nettings) { nettingReceiptIds.Add((long)netting.ReceiptId); var cancelFlag = 1; await updateNettingQueryProcessor.UpdateMatchingNettingAsync(header.CompanyId, 0, netting.Id, cancelFlag, token); } if (nettings.Any()) { var receiptsForNetting = await receiptGetByIdsQueryProcessor.GetByIdsAsync(nettings.Select(n => (long)n.ReceiptId), token); deleteReceipts.AddRange(receiptsForNetting); } #endregion #region 7.消込済入金データ取得 receipts = (await cancelMatchingQueryProcessor.GetMatchedReceiptsForCancelAsync(header, token)).ToList(); #endregion if (receipts.Count == 0) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.NotExistReceiptData }); } #region 8.入金データチェック if (receipts.Any(e => e.DeleteAt.HasValue)) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.ReceiptOmitted, ErrorIndex = Array.IndexOf(headersArray, header), }); } #endregion #region 9.入金データ消込解除処理 var hasAdvanceReceivedOccured = details.Any(x => (x.AdvanceReceivedOccured == 1)); foreach (var receipt in receipts) { var prepare_receipt_update = receipt; var receiptId = receipt.Id; var amount = prepare_receipt_update.AssignmentAmount; prepare_receipt_update.RemainAmount = amount; prepare_receipt_update.AssignmentAmount = amount; prepare_receipt_update.CompanyId = header.CompanyId; prepare_receipt_update.UpdateBy = loginUserId; prepare_receipt_update.UpdateAt = updateAt; await cancelMatchingQueryProcessor.UpdateReceiptForCancelMatchingAsync(prepare_receipt_update, token); // 入金残ログ洗替え await cancelMatchingQueryProcessor.UpdatePreviousReceiptLogsAsync(header.Id, receiptId, amount, loginUserId, updateAt, token); if (!hasAdvanceReceivedOccured) { continue; } //前受データの削除 var maeuke_receipt_flg = details.Exists(x => ((x.AdvanceReceivedOccured == 1) && (x.ReceiptId == receipt.Id))); if (!maeuke_receipt_flg) { continue; } var originalReceiptId = receipt.Id; //前受のテータ取得 var maeuke_Receipts = (await cancelMatchingQueryProcessor.GetByOriginalIdAsync(originalReceiptId)).ToList(); foreach (var maeuke_receipt in maeuke_Receipts) { int canel_flg = await deleteReceiptQueryProcessor.CancelAdvanceReceivedAsync(maeuke_receipt.Id, token); if (canel_flg != 1) { continue; } // データ同期用 deleteReceipts.Add(maeuke_receipt); var originalReceipt = receipts.Find(x => (x.Id == originalReceiptId)); originalReceipt.RemainAmount = maeuke_receipt.ReceiptAmount; originalReceipt.AssignmentAmount = 0; //消込額から減算は不要なので originalReceipt.UpdateBy = loginUserId; originalReceipt.UpdateAt = updateAt; await cancelMatchingQueryProcessor.UpdateReceiptForCancelMatchingAsync(originalReceipt, token); } } #endregion #region 8.その他処理 #region 消込履歴データ検索・出力済データ(MatchingOutputed)の削除 await cancelMatchingQueryProcessor.DeleteMatchingOutputedAsync(header.Id, token); #endregion #region 消込歩引データ(MatchingBillingDiscount)の削除 foreach (var matching in details) { await deleteMatchingBillingDiscountQueryProcessor.DeleteByMatchingIdAsync(matching.Id, token); } #endregion #region 消込データ(Matching)の削除 var deleteMatchingResult = await cancelMatchingQueryProcessor.DeleteMatchingAsync(header.Id, header.MatchingUpdateAt, token); if (deleteMatchingResult <= 0) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.MatchingHeaderChanged, ErrorIndex = Array.IndexOf(headersArray, header), }); } #endregion #region MatchingHeaderの削除 var deleteResult = await deleteMatchingHeaderQueryProcessor.DeleteAsync(header, token); if (deleteResult <= 0) { notifier?.Abort(); return(new MatchingResult { MatchingErrorType = MatchingErrorType.MatchingHeaderChanged, ErrorIndex = Array.IndexOf(headersArray, header), }); } #endregion #region 相殺データから変換した入金データの削除 foreach (long receiptId in nettingReceiptIds) { await deleteReceiptByIdQueryProcessor.DeleteAsync(receiptId, token); } #endregion #endregion notifier?.UpdateState(); } scope.Complete(); return(new MatchingResult { ProcessResult = new ProcessResult { Result = true }, Matchings = deleteMatchings, DeleteReceipts = deleteReceipts, }); } } }
/// <summary> /// 一つの入金データを 複数に分割 /// </summary> /// <param name="transfer"></param> /// <param name="loginUserId"></param> /// <param name="token"></param> /// <returns></returns> private async Task <ReceiptSectionTransfersResult> DivideAsync(ReceiptSectionTransfer transfer, int loginUserId, CancellationToken token) { var result = new ReceiptSectionTransfersResult(); var receipt = await receiptGetByIdQueryProcessor.GetByIdAsync(transfer.ReceiptId, token); if (receipt == null) { return(result); } receipt.SectionId = transfer.DestinationSectionId; receipt.ReceiptAmount = transfer.DestinationAmount; receipt.RemainAmount = transfer.DestinationAmount; receipt.AssignmentAmount = 0; receipt.AssignmentFlag = 0; receipt.OutputAt = null; receipt.MailedAt = null; receipt.OriginalReceiptId = null; receipt.ExcludeFlag = 0; receipt.ExcludeCategoryId = null; receipt.ExcludeAmount = 0; receipt.DeleteAt = null; receipt.CreateBy = loginUserId; receipt.UpdateBy = loginUserId; var firstResult = await addReceiptQueryProcessor.SaveAsync(receipt, token : token); result.InsertReceipts.Add(firstResult); if (!string.IsNullOrWhiteSpace(transfer.TransferMemo)) { await addReceiptMemoQueryProcessor.SaveAsync(firstResult.Id, transfer.TransferMemo, token); } receipt.SectionId = transfer.SourceSectionId; receipt.ReceiptAmount = transfer.SourceAmount - transfer.DestinationAmount; receipt.RemainAmount = transfer.SourceAmount - transfer.DestinationAmount; var secondResult = await addReceiptQueryProcessor.SaveAsync(receipt, token : token); result.InsertReceipts.Add(secondResult); var receiptMemo = await receiptMemoQueryProcessor.GetAsync(transfer.ReceiptId, token); if (receiptMemo != null) { await addReceiptMemoQueryProcessor.SaveAsync(secondResult.Id, receiptMemo.Memo, token); } var updateAt = await dbSystemDateTimeQueryProcessor.GetAsync(token); result.UpdateReceipts.Add(await updateReceiptQueryProcessor.UpdateOriginalRemainAsync(transfer.ReceiptId, loginUserId, updateAt, token)); var saveItem = new ReceiptSectionTransfer { SourceReceiptId = transfer.ReceiptId, DestinationReceiptId = firstResult.Id, SourceSectionId = transfer.SourceSectionId, DestinationSectionId = transfer.DestinationSectionId, SourceAmount = transfer.SourceAmount, DestinationAmount = transfer.DestinationAmount, PrintFlag = 0, CreateBy = loginUserId, UpdateBy = loginUserId }; result.ReceiptSectionTransfers.Add(await addReceiptSectionTransferQueryProcessor.SaveAsync(saveItem, token)); saveItem.DestinationReceiptId = secondResult.Id; saveItem.DestinationSectionId = transfer.SourceSectionId; saveItem.DestinationAmount = transfer.SourceAmount - transfer.DestinationAmount; result.ReceiptSectionTransfers.Add(await addReceiptSectionTransferQueryProcessor.SaveAsync(saveItem, token)); return(result); }
public async Task <MatchingResult> MatchAsync( MatchingSource source, CancellationToken token = default(CancellationToken), IProgressNotifier notifier = null) { var matchings = source.Matchings; var loginUserId = source.LoginUserId; var companyId = source.CompanyId; var customerId = source.CustomerId ?? 0; var paymentAgencyId = source.PaymentAgencyId ?? 0; var childCustomerIds = source.ChildCustomerIds; var useKanaLearning = source.UseKanaLearning == 1; var useFeeLearning = source.UseFeeLearning == 1; var appControl = await applicationControlQueryProcessor.GetAsync(companyId, token); var updateAt = await dbSystemDateTimeQueryProcessor.GetAsync(token); source.UpdateAt = updateAt; var useAuthorization = appControl?.UseAuthorization == 1; var nettingReceipts = new List <Receipt>(); // DBサーバーから取得する var billings = new List <Billing>(); var receipts = new List <Receipt>(); var matchingBillingDiscounts = new List <MatchingBillingDiscount>(); var billingScheduledIncomes = new List <BillingScheduledIncome>(); var billingDiscounts = new HashSet <long>(); MatchingResult validateResult = null; if (!(await ValidateMatchingDataAsync(source, x => validateResult = x, token))) { return(validateResult); } var currencyId = source.Matchings.First().CurrencyId; using (var scope = transactionScopeBuilder.Create()) { #region 相殺データ変換 nettingReceipts = await PrepareNettingDataAsync(source, loginUserId, updateAt, token); foreach (var r in nettingReceipts) { var item = source.Receipts.First(x => x.Id == r.Id); item.UpdateAt = r.UpdateAt; } #endregion #region matchingHeader var header = source.MatchingHeader; header.MatchingProcessType = 1; header.Approved = useAuthorization ? 0 : 1; header.CreateBy = loginUserId; header.UpdateBy = loginUserId; header.CreateAt = updateAt; header.UpdateAt = updateAt; #endregion #region 手数料学習 var bankFee = header.BankTransferFee; if (useFeeLearning) { await SaveBankTransferFeeAsync(customerId, paymentAgencyId, currencyId, bankFee, updateAt, loginUserId, token); } #endregion #region 債権代表者登録 if (childCustomerIds.Any()) { var isParent = 1; await updateCustomerQueryProcessor.UpdateIsParentAsync(isParent, loginUserId, new[] { customerId }, token); foreach (var childId in childCustomerIds) { var group = new CustomerGroup(); group.ParentCustomerId = customerId; group.ChildCustomerId = childId; group.CreateAt = updateAt; group.CreateBy = loginUserId; group.UpdateAt = updateAt; group.UpdateBy = loginUserId; await addCustomerGroupQueryProcessor.SaveAsync(group, token); } } #endregion #region 学習履歴の登録 if (useKanaLearning) { await SaveKanaLearningAsync(matchings, companyId, customerId, paymentAgencyId, loginUserId, updateAt); } #endregion var matchingResult = await matchingSaveProcessor.SaveAsync(source, appControl, token); if (matchingResult.ProcessResult.Result) { scope.Complete(); } matchingResult.NettingReceipts = nettingReceipts; return(matchingResult); } }
public async Task <int> UpdateAsync(JournalizingOption option, CancellationToken token = default(CancellationToken)) { option.UpdateAt = await dbSystemDateTimeQueryProcessor.GetAsync(token); return(await updateMatchingJournalizingQueryProcessor.UpdateAsync(option, token)); }
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 <DateTime> GetDbDateTimeAsync(CancellationToken token = default(CancellationToken)) => await getNowQueryProcessor.GetAsync(token);