/// <summary> /// If applicable, creates a single related transaction for all original posted transactions /// whose recognition date is earlier than (or equal to) the current document date. /// Does not set any amounts. /// </summary> /// <param name="transactionList"> /// Transaction list where the new transaction will be put (if created). /// </param> /// <param name="lineCounter"> /// Transaction line counter. Will be incremented if any transactions are created by this procedure. /// </param> private void AddRelatedTransactionForPostedBeforeDocumentDate( IList <DRScheduleTran> transactionList, DRScheduleDetail relatedScheduleDetail, IEnumerable <DRScheduleTran> originalPostedTransactions, int?branchID, ref short lineCounter) { IEnumerable <DRScheduleTran> originalTransactionsPostedBeforeDocumentDate = originalPostedTransactions.Where(transaction => transaction.RecDate <= relatedScheduleDetail.DocDate); if (originalTransactionsPostedBeforeDocumentDate.Any()) { ++lineCounter; DRScheduleTran relatedTransaction = new DRScheduleTran { BranchID = branchID, AccountID = relatedScheduleDetail.AccountID, SubID = relatedScheduleDetail.SubID, RecDate = relatedScheduleDetail.DocDate, FinPeriodID = relatedScheduleDetail.FinPeriodID, LineNbr = lineCounter, ScheduleID = relatedScheduleDetail.ScheduleID, ComponentID = relatedScheduleDetail.ComponentID, Status = DRScheduleTranStatus.Open }; transactionList.Add(relatedTransaction); } }
protected virtual void DRScheduleTran_RowDeleted(PXCache sender, PXRowDeletedEventArgs e) { DRScheduleTran row = e.Row as DRScheduleTran; if (row != null && Components.Current != null && Components.Current.Status == DRScheduleStatus.Open) { Subtract(row); } }
protected virtual void DRScheduleTran_RecDate_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e) { DRScheduleTran row = e.Row as DRScheduleTran; if (row != null) { row.FinPeriodID = FinPeriodIDAttribute.PeriodFromDate(this, row.RecDate); } }
/// <summary> /// Tries to perform a redirect to the original AR or AP document referenced by /// the <see cref="DRSchedule"/> that owns the given <see cref="DRScheduleTran"/>. /// </summary> /// <param name="sourceGraph"> /// A graph through which the redirect will be processed. /// </param> /// <param name="scheduleTransaction"> /// The <see cref="DRScheduleDetail"/> object from which the corresponding schedule /// will be selected. /// </param> public static void NavigateToOriginalDocument( PXGraph sourceGraph, DRScheduleTran scheduleTransaction) { DRSchedule correspondingSchedule = PXSelect < DRSchedule, Where <DRSchedule.scheduleID, Equal <Required <DRScheduleTran.scheduleID> > > > .Select(sourceGraph, scheduleTransaction.ScheduleID); NavigateToOriginalDocument(sourceGraph, correspondingSchedule); }
protected virtual void DRScheduleTran_RowSelected(PXCache sender, PXRowSelectedEventArgs e) { DRScheduleTran row = e.Row as DRScheduleTran; if (row != null) { PXUIFieldAttribute.SetEnabled <DRScheduleTran.recDate>(sender, row, row.Status == DRScheduleTranStatus.Open || row.Status == DRScheduleTranStatus.Projected); PXUIFieldAttribute.SetEnabled <DRScheduleTran.amount>(sender, row, row.Status == DRScheduleTranStatus.Open || row.Status == DRScheduleTranStatus.Projected); PXUIFieldAttribute.SetEnabled <DRScheduleTran.accountID>(sender, row, row.Status == DRScheduleTranStatus.Open || row.Status == DRScheduleTranStatus.Projected); PXUIFieldAttribute.SetEnabled <DRScheduleTran.subID>(sender, row, row.Status == DRScheduleTranStatus.Open || row.Status == DRScheduleTranStatus.Projected); } }
protected virtual void DRScheduleTran_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e) { DRScheduleTran row = e.Row as DRScheduleTran; if (!sender.ObjectsEqual <DRScheduleTran.finPeriodID, DRScheduleTran.accountID, DRScheduleTran.subID, DRScheduleTran.amount>(e.Row, e.OldRow)) { if (Components.Current != null && Components.Current.Status == DRScheduleStatus.Open) { DRScheduleTran oldRow = (DRScheduleTran)e.OldRow; Subtract(oldRow); Add(row); } } }
/// <summary> /// Updates the transaction amount and performs the callback to /// <see cref="IDREntityStorage"/>, notifying about the update. /// </summary> private void UpdateTransactionAmount( DRScheduleDetail scheduleDetail, DRDeferredCode detailDeferralCode, DRScheduleTran transaction, decimal?newAmount) { DRScheduleTran oldTransaction = _drEntityStorage.CreateCopy(transaction); transaction.Amount = newAmount; _drEntityStorage.ScheduleTransactionModified( scheduleDetail, detailDeferralCode, oldTransaction, transaction); }
private void Add(DRScheduleTran tran) { Debug.Print("Add FinPeriod={0} Status={1} Amount={2}", tran.FinPeriodID, tran.Status, tran.Amount); DRDeferredCode code = DeferredCode.Select(); if (code.AccountType == DeferredAccountType.Expense) { AddExpenseToProjection(tran); AddExpenseToBalance(tran); } else { AddRevenueToProjection(tran); AddRevenueToBalance(tran); } }
private void Subtract(DRScheduleTran tran) { Debug.Print("Subtract FinPeriod={0} Status={1} Amount={2}", tran.FinPeriodID, tran.Status, tran.Amount); DRDeferredCode code = DeferredCode.Select(); if (code.AccountType == DeferredAccountType.Expense) { SubtractExpenseFromProjection(tran); SubtractExpenseFromBalance(tran); } else { SubtractRevenueFromProjection(tran); SubtractRevenueFromBalance(tran); } }
private void AddExpenseToProjection(DRScheduleTran tran) { if (tran.FinPeriodID == null) { return; } DRExpenseProjectionAccum hist = new DRExpenseProjectionAccum(); hist.FinPeriodID = tran.FinPeriodID; hist.AcctID = Components.Current.AccountID; hist.SubID = Components.Current.SubID; hist.ComponentID = Components.Current.ComponentID ?? 0; hist.ProjectID = Components.Current.ProjectID ?? 0; hist.VendorID = Components.Current.BAccountID ?? 0; hist = ExpenseProjection.Insert(hist); hist.PTDProjected += tran.Amount; }
private void SubtractRevenueFromProjection(DRScheduleTran tran) { if (tran.FinPeriodID == null) { return; } DRRevenueProjectionAccum hist = new DRRevenueProjectionAccum(); hist.FinPeriodID = tran.FinPeriodID; hist.AcctID = Components.Current.AccountID; hist.SubID = Components.Current.SubID; hist.ComponentID = Components.Current.ComponentID ?? 0; hist.ProjectID = Components.Current.ProjectID ?? 0; hist.CustomerID = Components.Current.BAccountID ?? 0; hist = RevenueProjection.Insert(hist); hist.PTDProjected -= tran.Amount; }
/// <summary> /// Adds a related transaction for every original transaction /// in <paramref name="originalTransactions"/> using information /// from the provided related <see cref="DRScheduleDetail"/>. /// Does not set any transaction amounts. /// </summary> /// <param name="transactionList"> /// Transaction list where the new transaction will be put (if created). /// </param> /// <param name="lineCounter"> /// Transaction line counter. Will be incremented if any transactions are created by this procedure. /// </param> private void AddRelatedTransactions( IList <DRScheduleTran> transactionList, DRScheduleDetail relatedScheduleDetail, IEnumerable <DRScheduleTran> originalTransactions, int?branchID, ref short lineCounter) { int?organizationID = PXAccess.GetParentOrganizationID(branchID); foreach (DRScheduleTran originalTransaction in originalTransactions) { ++lineCounter; DRScheduleTran relatedTransaction = new DRScheduleTran { BranchID = branchID, AccountID = relatedScheduleDetail.AccountID, SubID = relatedScheduleDetail.SubID, LineNbr = lineCounter, DetailLineNbr = relatedScheduleDetail.DetailLineNbr, ScheduleID = relatedScheduleDetail.ScheduleID, ComponentID = relatedScheduleDetail.ComponentID, Status = DRScheduleTranStatus.Open }; var maxDate = originalTransaction.RecDate.Value < relatedScheduleDetail.DocDate.Value ? relatedScheduleDetail.DocDate : originalTransaction.RecDate; relatedTransaction.RecDate = maxDate; var maxPeriod = string.CompareOrdinal(originalTransaction.FinPeriodID, relatedScheduleDetail.FinPeriodID) < 0 ? relatedScheduleDetail.FinPeriodID : originalTransaction.FinPeriodID; FinPeriod maxFinPeriod = _finPeriodRepository.GetByID(maxPeriod, organizationID); relatedTransaction.FinPeriodID = maxFinPeriod.FinPeriodID; relatedTransaction.TranPeriodID = maxFinPeriod.MasterFinPeriodID; transactionList.Add(relatedTransaction); } }
private void AddExpenseToBalance(DRScheduleTran tran) { if (tran.FinPeriodID == null) { return; } DRExpenseBalance hist = new DRExpenseBalance(); hist.FinPeriodID = tran.FinPeriodID; hist.AcctID = Components.Current.DefAcctID; hist.SubID = Components.Current.DefSubID; hist.ComponentID = Components.Current.ComponentID ?? 0; hist.ProjectID = Components.Current.ProjectID ?? 0; hist.VendorID = Components.Current.BAccountID ?? 0; hist = ExpenseBalance.Insert(hist); hist.PTDProjected += tran.Amount; hist.EndProjected -= tran.Amount; }
private void SubtractRevenueFromBalance(DRScheduleTran tran) { if (tran.FinPeriodID == null) { return; } DRRevenueBalance hist = new DRRevenueBalance(); hist.FinPeriodID = tran.FinPeriodID; hist.AcctID = Components.Current.DefAcctID; hist.SubID = Components.Current.DefSubID; hist.ComponentID = Components.Current.ComponentID ?? 0; hist.ProjectID = Components.Current.ProjectID ?? 0; hist.CustomerID = Components.Current.BAccountID ?? 0; hist = RevenueBalance.Insert(hist); hist.PTDProjected -= tran.Amount; hist.EndProjected += tran.Amount; }
/// <summary> /// Adds a related transaction for every original transaction /// in <paramref name="originalTransactions"/> using information /// from the provided related <see cref="DRScheduleDetail"/>. /// Does not set any transaction amounts. /// </summary> /// <param name="transactionList"> /// Transaction list where the new transaction will be put (if created). /// </param> /// <param name="lineCounter"> /// Transaction line counter. Will be incremented if any transactions are created by this procedure. /// </param> private void AddRelatedTransactions( IList <DRScheduleTran> transactionList, DRScheduleDetail relatedScheduleDetail, IEnumerable <DRScheduleTran> originalTransactions, int?branchID, ref short lineCounter) { foreach (DRScheduleTran originalTransaction in originalTransactions) { ++lineCounter; DRScheduleTran relatedTransaction = new DRScheduleTran { BranchID = branchID, AccountID = relatedScheduleDetail.AccountID, SubID = relatedScheduleDetail.SubID, LineNbr = lineCounter, ScheduleID = relatedScheduleDetail.ScheduleID, ComponentID = relatedScheduleDetail.ComponentID, Status = DRScheduleTranStatus.Open }; var maxDate = originalTransaction.RecDate.Value < relatedScheduleDetail.DocDate.Value ? relatedScheduleDetail.DocDate : originalTransaction.RecDate; relatedTransaction.RecDate = maxDate; var maxPeriod = string.CompareOrdinal(originalTransaction.FinPeriodID, relatedScheduleDetail.FinPeriodID) < 0 ? relatedScheduleDetail.FinPeriodID : originalTransaction.FinPeriodID; relatedTransaction.FinPeriodID = maxPeriod; transactionList.Add(relatedTransaction); } }
public static void RunRecognition(List <ScheduledTran> trans, DateTime?filterDate) { ScheduleMaint scheduleMaint = PXGraph.CreateInstance <ScheduleMaint>(); scheduleMaint.Clear(); bool failed = false; List <ScheduledTran> items = GetValidatedItems(trans, scheduleMaint); failed = items.Count() < trans.Count(); // Save virtual records: // - foreach (ScheduledTran tr in items) { PXProcessing <ScheduledTran> .SetCurrentItem(tr); if (tr.IsVirtual == true) { try { scheduleMaint.Document.Current = PXSelect <DRScheduleDetail, Where <DRScheduleDetail.scheduleID, Equal <Required <DRScheduleDetail.scheduleID> >, And <DRScheduleDetail.componentID, Equal <Required <DRScheduleDetail.componentID> > > > > .Select(scheduleMaint, tr.ScheduleID, tr.ComponentID ?? DRScheduleDetail.EmptyComponentID); DRScheduleTran tran = new DRScheduleTran(); tran.BranchID = tr.BranchID; tran.AccountID = tr.AccountID; tran.SubID = tr.SubID; tran.AdjgDocType = tr.AdjgDocType; tran.AdjgRefNbr = tr.AdjgRefNbr; tran.AdjNbr = tr.AdjNbr; tran.Amount = tr.Amount; tran.ComponentID = tr.ComponentID ?? DRScheduleDetail.EmptyComponentID; tran.FinPeriodID = tr.FinPeriodID; tran.ScheduleID = tr.ScheduleID; tran.RecDate = tr.RecDate; tran.Status = DRScheduleTranStatus.Open; tran = scheduleMaint.OpenTransactions.Insert(tran); tr.LineNbr = tran.LineNbr; scheduleMaint.RebuildProjections(); scheduleMaint.Save.Press(); byte[] ts = scheduleMaint.TimeStamp; scheduleMaint.Clear(); scheduleMaint.TimeStamp = ts; PXProcessing <ScheduledTran> .SetProcessed(); } catch (Exception ex) { failed = true; PXProcessing <ScheduledTran> .SetError(ex.Message); } } else { PXProcessing <ScheduledTran> .SetProcessed(); } } PXProcessing <ScheduledTran> .SetCurrentItem(null); List <DRBatch> list = SplitByFinPeriod(items); DRProcess process = CreateInstance <DRProcess>(); process.Clear(); process.TimeStamp = scheduleMaint.TimeStamp; List <Batch> batchlist = process.RunRecognition(list, filterDate); PostGraph pg = PXGraph.CreateInstance <PostGraph>(); //Post Batches if AutoPost bool postFailed = false; if (pg.AutoPost) { foreach (Batch batch in batchlist) { try { pg.Clear(); pg.TimeStamp = batch.tstamp; pg.PostBatchProc(batch); } catch (Exception) { postFailed = true; } } if (postFailed) { throw new PXException(Messages.AutoPostFailed); } } if (failed) { throw new PXException(GL.Messages.DocumentsNotReleased); } }
protected virtual IEnumerable items() { ScheduleRecognitionFilter filter = Filter.Current; if (filter == null) { yield break; } bool found = false; foreach (ScheduledTran item in Items.Cache.Inserted) { found = true; yield return(item); } if (found) { yield break; } PXSelectBase <DRScheduleTran> select = new PXSelectJoin <DRScheduleTran, InnerJoin <DRScheduleDetail, On <DRScheduleTran.scheduleID, Equal <DRScheduleDetail.scheduleID>, And <DRScheduleTran.componentID, Equal <DRScheduleDetail.componentID> > >, InnerJoin <DRSchedule, On <DRScheduleTran.scheduleID, Equal <DRSchedule.scheduleID> >, LeftJoin <InventoryItem, On <DRScheduleTran.componentID, Equal <InventoryItem.inventoryID> > > > >, Where <DRScheduleTran.recDate, LessEqual <Current <ScheduleRecognitionFilter.recDate> >, And <DRScheduleTran.status, Equal <DRScheduleTranStatus.OpenStatus>, And <DRScheduleDetail.status, NotEqual <DRScheduleStatus.DraftStatus> > > >, OrderBy <Asc <DRScheduleTran.scheduleID, Asc <DRScheduleTran.componentID, Asc <DRScheduleTran.recDate, Asc <DRScheduleTran.lineNbr> > > > > >(this); if (!string.IsNullOrEmpty(filter.DeferredCode)) { select.WhereAnd <Where <DRScheduleDetail.defCode, Equal <Current <ScheduleRecognitionFilter.deferredCode> > > >(); } if (filter.BranchID != null) { select.WhereAnd <Where <DRScheduleDetail.branchID, Equal <Current <ScheduleRecognitionFilter.branchID> > > >(); } Dictionary <string, string> added = new Dictionary <string, string>(); foreach (PXResult <DRScheduleTran, DRScheduleDetail, DRSchedule, InventoryItem> resultSet in select.Select()) { DRScheduleTran tran = (DRScheduleTran)resultSet; DRSchedule schedule = (DRSchedule)resultSet; DRScheduleDetail scheduleDetail = (DRScheduleDetail)resultSet; InventoryItem item = (InventoryItem)resultSet; string key = string.Format("{0}.{1}", tran.ScheduleID, tran.ComponentID); bool doInsert = false; if (added.ContainsKey(key)) { string addedFinPeriod = added[key]; if (tran.FinPeriodID == addedFinPeriod) { doInsert = true; } } else { doInsert = true; added.Add(key, tran.FinPeriodID); } if (doInsert) { ScheduledTran result = new ScheduledTran(); result.BranchID = tran.BranchID; result.AccountID = tran.AccountID; result.Amount = tran.Amount; result.ComponentID = tran.ComponentID; result.DefCode = scheduleDetail.DefCode; result.FinPeriodID = tran.FinPeriodID; result.LineNbr = tran.LineNbr; result.RecDate = tran.RecDate; result.ScheduleID = tran.ScheduleID; result.ScheduleNbr = schedule.ScheduleNbr; result.SubID = tran.SubID; result.ComponentCD = item.InventoryCD; result.DocType = DRScheduleDocumentType.BuildDocumentType(scheduleDetail.Module, scheduleDetail.DocType); Items.Cache.SetStatus(result, PXEntryStatus.Inserted); yield return(result); // Items.Insert(result); } } //Virtual Records (CashReceipt): PXSelectBase <ARInvoice> s = null; if (!string.IsNullOrEmpty(filter.DeferredCode)) { s = new PXSelectJoinGroupBy <ARInvoice, InnerJoin <ARTran, On <ARTran.tranType, Equal <ARInvoice.docType>, And <ARTran.refNbr, Equal <ARInvoice.refNbr> > >, InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>, And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt>, And <DRDeferredCode.deferredCodeID, Equal <Current <ScheduleRecognitionFilter.deferredCode> > > > >, InnerJoin <DRSchedule, On <ARTran.tranType, Equal <DRSchedule.docType>, And <ARTran.refNbr, Equal <DRSchedule.refNbr>, And <ARTran.lineNbr, Equal <DRSchedule.lineNbr> > > >, InnerJoin <DRScheduleDetail, On <DRSchedule.scheduleID, Equal <DRScheduleDetail.scheduleID> > > > > >, Where <ARInvoice.released, Equal <True>, And <DRScheduleDetail.isOpen, Equal <True> > >, Aggregate <GroupBy <ARInvoice.docType, GroupBy <ARInvoice.refNbr> > > >(this); } else { s = new PXSelectJoinGroupBy <ARInvoice, InnerJoin <ARTran, On <ARTran.tranType, Equal <ARInvoice.docType>, And <ARTran.refNbr, Equal <ARInvoice.refNbr> > >, InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>, And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt> > >, InnerJoin <DRSchedule, On <ARTran.tranType, Equal <DRSchedule.docType>, And <ARTran.refNbr, Equal <DRSchedule.refNbr>, And <ARTran.lineNbr, Equal <DRSchedule.lineNbr> > > >, InnerJoin <DRScheduleDetail, On <DRSchedule.scheduleID, Equal <DRScheduleDetail.scheduleID> > > > > >, Where <ARInvoice.released, Equal <True>, And <DRScheduleDetail.isOpen, Equal <True> > >, Aggregate <GroupBy <ARInvoice.docType, GroupBy <ARInvoice.refNbr> > > >(this); } foreach (ARInvoice inv in s.Select()) { PXSelectBase <ARTran> trs = new PXSelectJoin <ARTran, InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>, And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt> > > >, Where <ARTran.tranType, Equal <Required <ARTran.tranType> >, And <ARTran.refNbr, Equal <Required <ARTran.refNbr> > > > >(this); foreach (PXResult <ARTran, DRDeferredCode> res in trs.Select(inv.DocType, inv.RefNbr)) { List <ScheduledTran> virtualRecords = new List <ScheduledTran>(); List <ScheduledTran> virtualVoidedRecords = new List <ScheduledTran>(); ARTran tr = (ARTran)res; DRDeferredCode dc = (DRDeferredCode)res; decimal trPart = 0; if (inv.LineTotal.Value != 0) { trPart = tr.TranAmt.Value / inv.LineTotal.Value; } decimal trPartRest = tr.TranAmt.Value; InventoryItem invItem = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, tr.InventoryID); //NOTE: Multiple Components are not supported in CashReceipt Deferred Revenue Recognition. DRSchedule schedule = GetScheduleByFID(BatchModule.AR, inv.DocType, inv.RefNbr, tr.LineNbr); DRScheduleDetail scheduleDetail = GetScheduleDetailbyID(schedule.ScheduleID, tr.InventoryID != null ? tr.InventoryID : DRScheduleDetail.EmptyComponentID); int lineNbr = scheduleDetail.LineCntr ?? 0; PXSelectBase <ARAdjust> ads = new PXSelectJoin <ARAdjust, LeftJoin <DRScheduleTran, On <ARAdjust.adjgDocType, Equal <DRScheduleTran.adjgDocType>, And <ARAdjust.adjgRefNbr, Equal <DRScheduleTran.adjgRefNbr> > > >, Where <ARAdjust.adjdDocType, Equal <Required <ARAdjust.adjdDocType> >, And <ARAdjust.adjdRefNbr, Equal <Required <ARAdjust.adjdRefNbr> >, And <DRScheduleTran.scheduleID, IsNull, And <ARAdjust.adjgDocType, NotEqual <ARDocType.creditMemo> > > > >, OrderBy <Asc <ARAdjust.adjgDocDate> > >(this); foreach (ARAdjust ad in ads.Select(inv.DocType, inv.RefNbr)) { lineNbr++; decimal amtRaw = Math.Min(trPart * ad.AdjAmt.Value, trPartRest); trPartRest -= amtRaw; decimal amt = PXDBCurrencyAttribute.BaseRound(this, amtRaw); ScheduledTran result = new ScheduledTran(); result.BranchID = ad.AdjgBranchID; result.Amount = amt; result.ComponentID = tr.InventoryID; result.DefCode = tr.DeferredCode; result.FinPeriodID = FinPeriodRepository.GetPeriodIDFromDate(ad.AdjgDocDate, PXAccess.GetParentOrganizationID(ad.AdjgBranchID)); result.LineNbr = lineNbr; result.Module = schedule.Module; result.RecDate = ad.AdjgDocDate; result.ScheduleID = schedule.ScheduleID; result.ScheduleNbr = schedule.ScheduleNbr; result.DocType = schedule.DocType; result.AdjgDocType = ad.AdjgDocType; result.AdjgRefNbr = ad.AdjgRefNbr; result.AdjNbr = ad.AdjNbr; result.IsVirtual = true; result.AccountID = scheduleDetail.AccountID; result.SubID = scheduleDetail.SubID; result.ComponentCD = invItem == null ? "" : invItem.InventoryCD; if (ad.Voided == true) { if (ad.AdjgDocType == ARDocType.VoidPayment && virtualVoidedRecords.Count > 0) { ScheduledTran tran = virtualVoidedRecords.Where <ScheduledTran>(v => (v.AdjgDocType == ARDocType.Payment && v.AdjgRefNbr == ad.AdjgRefNbr && v.AdjNbr == ad.AdjNbr)).First <ScheduledTran>(); if (tran != null) { virtualVoidedRecords.Remove(tran); } } else { virtualVoidedRecords.Add(result); } } else { virtualRecords.Add(result); } } foreach (ScheduledTran v in virtualRecords) { Items.Cache.SetStatus(v, PXEntryStatus.Inserted); yield return(v); // Items.Insert(v); } foreach (ScheduledTran v in virtualVoidedRecords) { Items.Cache.SetStatus(v, PXEntryStatus.Inserted); yield return(v); // Items.Insert(v); } } } Items.Cache.IsDirty = false; }
public virtual IList <DRScheduleTran> GenerateTransactions( DRSchedule deferralSchedule, DRScheduleDetail scheduleDetail, int?branchID) { if (deferralSchedule == null) { throw new ArgumentNullException(nameof(deferralSchedule)); } if (scheduleDetail == null) { throw new ArgumentNullException(nameof(scheduleDetail)); } ValidateTerms(deferralSchedule); decimal defAmount = scheduleDetail.TotalAmt.Value; List <DRScheduleTran> list = new List <DRScheduleTran>(); short lineCounter = 0; if (_code.ReconNowPct.Value > 0) { decimal recNowRaw = defAmount * _code.ReconNowPct.Value * 0.01m; decimal recNow = _roundingFunction(recNowRaw); defAmount -= recNow; lineCounter++; DRScheduleTran nowTran = new DRScheduleTran { BranchID = branchID, AccountID = scheduleDetail.AccountID, SubID = scheduleDetail.SubID, Amount = recNow, RecDate = deferralSchedule.DocDate, FinPeriodID = scheduleDetail.FinPeriodID, LineNbr = lineCounter, ScheduleID = scheduleDetail.ScheduleID, ComponentID = scheduleDetail.ComponentID, Status = _code.Method == DeferredMethodType.CashReceipt ? DRScheduleTranStatus.Projected : DRScheduleTranStatus.Open, }; list.Add(nowTran); } bool isFlexibleDeferralCode = DeferredMethodType.RequiresTerms(_code.Method); DateTime documentDate = deferralSchedule.DocDate.Value; string documentFinPeriod = _financialPeriodProvider.FindFinPeriodByDate(_graph, documentDate)?.FinPeriodID; int occurrences = isFlexibleDeferralCode ? CalcOccurrences(deferralSchedule.TermStartDate.Value, deferralSchedule.TermEndDate.Value) : _code.Occurrences.Value; List <DRScheduleTran> deferredList = new List <DRScheduleTran>(_code.Occurrences.Value); string deferredPeriod = null; for (int i = 0; i < occurrences; i++) { try { if (deferredPeriod == null) { deferredPeriod = isFlexibleDeferralCode ? _financialPeriodProvider.FindFinPeriodByDate(_graph, deferralSchedule.TermStartDate.Value)?.FinPeriodID : _financialPeriodProvider.PeriodPlusPeriod(_graph, scheduleDetail.FinPeriodID, _code.StartOffset.Value); } else { deferredPeriod = _financialPeriodProvider.PeriodPlusPeriod(_graph, deferredPeriod, _code.Frequency.Value); } } catch (PXFinPeriodException ex) { throw new PXException(ex, Messages.NoFinPeriod, _code.DeferredCodeID); } lineCounter++; DateTime recognitionDate = GetRecognitionDate( deferredPeriod, minimumDate: isFlexibleDeferralCode ? deferralSchedule.TermStartDate.Value : documentDate, maximumDate: isFlexibleDeferralCode ? deferralSchedule.TermEndDate : null); DRScheduleTran deferralTransaction = new DRScheduleTran { BranchID = branchID, AccountID = scheduleDetail.AccountID, SubID = scheduleDetail.SubID, RecDate = recognitionDate, FinPeriodID = _financialPeriodProvider.FindFinPeriodByDate(_graph, recognitionDate)?.FinPeriodID, LineNbr = lineCounter, ScheduleID = scheduleDetail.ScheduleID, ComponentID = scheduleDetail.ComponentID, Status = _code.Method == DeferredMethodType.CashReceipt ? DRScheduleTranStatus.Projected : DRScheduleTranStatus.Open }; deferredList.Add(deferralTransaction); } SetAmounts(deferredList, defAmount, deferralSchedule); if (DeferredMethodType.RequiresTerms(_code) && _code.RecognizeInPastPeriods != true) { // Adjust recognition dates and financial periods // that are in the past relative to the document date. // - foreach (DRScheduleTran transaction in deferredList .Where(transaction => transaction.RecDate < documentDate)) { transaction.RecDate = documentDate; transaction.FinPeriodID = documentFinPeriod; } } list.AddRange(deferredList); return(list); }
/// <summary> /// Generates the related transactions given the list of original /// </summary> /// <param name="relatedScheduleDetail"> /// The schedule detail /// to which the related transactions will pertain. /// </param> /// <param name="originalOpenTransactions"> /// Original transactions in the Open (or Projected) status. /// </param> /// <param name="originalPostedTransactions"> /// Original transactions in the Posted status. /// </param> /// <param name="amountToDistributeForUnposted"> /// Amount to distribute among the related transactions that are /// created for original Open transactions. /// </param> /// <param name="amountToDistributeForPosted"> /// Amount to distribute among the related transactions that are /// created for original Posted transactions. /// </param> /// <param name="branchID"> /// Branch ID for the related transactions. /// </param> /// <returns></returns> public virtual IList <DRScheduleTran> GenerateRelatedTransactions( DRScheduleDetail relatedScheduleDetail, IEnumerable <DRScheduleTran> originalOpenTransactions, IEnumerable <DRScheduleTran> originalPostedTransactions, decimal amountToDistributeForUnposted, decimal amountToDistributeForPosted, int?branchID) { ValidateOpenTransactions(originalOpenTransactions); ValidatePostedTransactions(originalPostedTransactions); List <DRScheduleTran> transactionList = new List <DRScheduleTran>(); short lineCounter = 0; int transactionsAddedDuringPreviousStep; // Handle posted transactions // - if (originalPostedTransactions != null && originalPostedTransactions.Any()) { decimal originalPostedTransactionsTotal = originalPostedTransactions.Sum(transaction => transaction.Amount ?? 0); AddRelatedTransactionForPostedBeforeDocumentDate( transactionList, relatedScheduleDetail, originalPostedTransactions, branchID, ref lineCounter); transactionsAddedDuringPreviousStep = lineCounter; decimal originalPostedBeforeDocumentDateSum = originalPostedTransactions .Where(transaction => transaction.RecDate <= relatedScheduleDetail.DocDate) .Sum(transaction => transaction.Amount ?? 0); decimal multiplier = amountToDistributeForPosted / originalPostedTransactionsTotal; // Amount to be distributed across other transactions that // are related to the original posted transactions. // - decimal residualPostedAmount = amountToDistributeForPosted; if (transactionList.Any()) { transactionList[0].Amount = multiplier * originalPostedBeforeDocumentDateSum; residualPostedAmount -= transactionList[0].Amount ?? 0; } IEnumerable <DRScheduleTran> originalPostedAfterDocumentDate = originalPostedTransactions.Where(transaction => transaction.RecDate > relatedScheduleDetail.DocDate); AddRelatedTransactions( transactionList, relatedScheduleDetail, originalPostedAfterDocumentDate, branchID, ref lineCounter); // Set amounts for related transactions // - decimal relatedTransactionTotal = 0; if (originalPostedAfterDocumentDate.Any()) { originalPostedAfterDocumentDate.SkipLast(1).ForEach((originalTransaction, i) => { decimal rawTransactionAmount = multiplier * originalTransaction.Amount ?? 0; transactionList[transactionsAddedDuringPreviousStep + i].Amount = _roundingFunction(rawTransactionAmount); relatedTransactionTotal += transactionList[transactionsAddedDuringPreviousStep + i].Amount ?? 0; }); transactionList[transactionList.Count - 1].Amount = residualPostedAmount - relatedTransactionTotal; } } transactionsAddedDuringPreviousStep = lineCounter; // Handle open transactions // - if (originalOpenTransactions != null && originalOpenTransactions.Any()) { decimal originalOpenTransactionsTotal = originalOpenTransactions.Sum(transaction => transaction.Amount ?? 0); AddRelatedTransactions( transactionList, relatedScheduleDetail, originalOpenTransactions, branchID, ref lineCounter); // Set amounts for related transactions // - decimal multiplier = amountToDistributeForUnposted / originalOpenTransactionsTotal; decimal relatedTransactionTotal = 0; originalOpenTransactions.SkipLast(1).ForEach((originalTransaction, i) => { decimal rawTransactionAmount = multiplier * originalTransaction.Amount.Value; transactionList[transactionsAddedDuringPreviousStep + i].Amount = _roundingFunction(rawTransactionAmount); relatedTransactionTotal += transactionList[transactionsAddedDuringPreviousStep + i].Amount ?? 0; }); transactionList[transactionList.Count - 1].Amount = amountToDistributeForUnposted - relatedTransactionTotal; } else if (amountToDistributeForUnposted > 0) { ++lineCounter; DRScheduleTran deferralTransaction = new DRScheduleTran { Amount = amountToDistributeForUnposted, BranchID = branchID, AccountID = relatedScheduleDetail.AccountID, SubID = relatedScheduleDetail.SubID, RecDate = relatedScheduleDetail.DocDate, FinPeriodID = relatedScheduleDetail.FinPeriodID, LineNbr = lineCounter, ScheduleID = relatedScheduleDetail.ScheduleID, ComponentID = relatedScheduleDetail.ComponentID, Status = DRScheduleTranStatus.Open }; transactionList.Add(deferralTransaction); } return(transactionList); }
public virtual IList <DRScheduleTran> GenerateTransactions( DRSchedule deferralSchedule, DRScheduleDetail scheduleDetail) { if (deferralSchedule == null) { throw new ArgumentNullException(nameof(deferralSchedule)); } if (scheduleDetail == null) { throw new ArgumentNullException(nameof(scheduleDetail)); } if (PXAccess.FeatureInstalled <CS.FeaturesSet.aSC606>()) { ValidateTerms(scheduleDetail); } else { ValidateTerms(deferralSchedule); } int? organizationID = PXAccess.GetParentOrganizationID(scheduleDetail.BranchID); decimal defAmount = scheduleDetail.TotalAmt.Value; List <DRScheduleTran> list = new List <DRScheduleTran>(); short lineCounter = 0; if (_code.ReconNowPct.Value > 0) { decimal recNowRaw = defAmount * _code.ReconNowPct.Value * 0.01m; decimal recNow = _roundingFunction(recNowRaw); defAmount -= recNow; lineCounter++; DRScheduleTran nowTran = new DRScheduleTran { BranchID = scheduleDetail.BranchID, AccountID = scheduleDetail.AccountID, SubID = scheduleDetail.SubID, Amount = recNow, RecDate = deferralSchedule.DocDate, FinPeriodID = scheduleDetail.FinPeriodID, TranPeriodID = scheduleDetail.TranPeriodID, LineNbr = lineCounter, DetailLineNbr = scheduleDetail.DetailLineNbr, ScheduleID = scheduleDetail.ScheduleID, ComponentID = scheduleDetail.ComponentID, Status = GetStatus(), }; list.Add(nowTran); } bool isFlexibleDeferralCode = DeferredMethodType.RequiresTerms(_code.Method); DateTime?termStartDate = null; DateTime?termEndDate = null; if (isFlexibleDeferralCode) { bool isASC606 = PXAccess.FeatureInstalled <CS.FeaturesSet.aSC606>(); termStartDate = isASC606 ? scheduleDetail.TermStartDate.Value : deferralSchedule.TermStartDate.Value; termEndDate = isASC606 ? scheduleDetail.TermEndDate.Value : deferralSchedule.TermEndDate.Value; } DateTime documentDate = deferralSchedule.DocDate.Value; FinPeriod documentFinPeriod = _finPeriodRepository.FindFinPeriodByDate(documentDate, organizationID); int occurrences = isFlexibleDeferralCode ? CalcOccurrences(termStartDate.Value, termEndDate.Value, organizationID) : _code.Occurrences.Value; List <DRScheduleTran> deferredList = new List <DRScheduleTran>(_code.Occurrences.Value); FinPeriod deferredPeriod = null; for (int i = 0; i < occurrences; i++) { try { if (deferredPeriod == null) { deferredPeriod = isFlexibleDeferralCode ? _finPeriodRepository.FindFinPeriodByDate(termStartDate, organizationID): _finPeriodRepository.GetOffsetPeriod(scheduleDetail.FinPeriodID, _code.StartOffset.Value, organizationID); } else { deferredPeriod = _finPeriodRepository.GetOffsetPeriod(deferredPeriod.FinPeriodID, _code.Frequency.Value, organizationID); } } catch (PXFinPeriodException ex) { throw new PXException(ex, Messages.NoFinPeriod, _code.DeferredCodeID); } lineCounter++; DateTime recognitionDate = GetRecognitionDate( deferredPeriod.FinPeriodID, minimumDate: isFlexibleDeferralCode ? termStartDate.Value : documentDate, maximumDate: isFlexibleDeferralCode ? termEndDate : null, organizationID: organizationID); FinPeriod finPeriod = _finPeriodRepository.FindFinPeriodByDate(recognitionDate, organizationID); DRScheduleTran deferralTransaction = new DRScheduleTran { BranchID = scheduleDetail.BranchID, AccountID = scheduleDetail.AccountID, SubID = scheduleDetail.SubID, RecDate = recognitionDate, FinPeriodID = finPeriod?.FinPeriodID, TranPeriodID = finPeriod?.MasterFinPeriodID, LineNbr = lineCounter, DetailLineNbr = scheduleDetail.DetailLineNbr, ScheduleID = scheduleDetail.ScheduleID, ComponentID = scheduleDetail.ComponentID, Status = GetStatus(), }; deferredList.Add(deferralTransaction); } SetAmounts(deferredList, defAmount, deferralSchedule.DocDate, termStartDate, termEndDate, organizationID); if (DeferredMethodType.RequiresTerms(_code) && _code.RecognizeInPastPeriods != true) { // Adjust recognition dates and financial periods // that are in the past relative to the document date. // - foreach (DRScheduleTran transaction in deferredList .Where(transaction => transaction.RecDate < documentDate)) { transaction.RecDate = documentDate; transaction.FinPeriodID = documentFinPeriod?.FinPeriodID; transaction.TranPeriodID = documentFinPeriod?.MasterFinPeriodID; } } list.AddRange(deferredList); return(list); }