// Computing default value on the basis of the previous values protected virtual void ARDunningSetup_DueDays_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e) { ARDunningSetup row = e.Row as ARDunningSetup; if (row != null) { int llevel = row.DunningLetterLevel.Value; if (llevel == 1) { e.NewValue = 30; } else { int PrevValue = 0; foreach (PXResult <ARDunningSetup> ii in PXSelect <ARDunningSetup> .Select(this)) { ARDunningSetup v = ii; if (v.DunningLetterLevel.Value == llevel - 1) { PrevValue += v.DueDays.Value; } if (v.DunningLetterLevel.Value == 1 && llevel > 1) { PrevValue += v.DueDays.Value; } } e.NewValue = PrevValue; } } }
protected virtual void ARDunningSetup_RowSelected(PXCache sender, PXRowSelectedEventArgs e) { ARDunningSetup row = e.Row as ARDunningSetup; if (row != null) { int llevel = row.DunningLetterLevel.Value; ARDunningSetup nextDL = PXSelect <ARDunningSetup, Where <ARDunningSetup.dunningLetterLevel, Greater <Required <ARDunningSetup.dunningLetterLevel> > > > .Select(this, row.DunningLetterLevel); bool clear = true; if (nextDL != null && nextDL.DueDays.HasValue) { if (row.DueDays.HasValue && row.DaysToSettle.HasValue) { int delay = row.DueDays.Value + row.DaysToSettle.Value; if (delay > nextDL.DueDays) { string dueDaysLabel = PXUIFieldAttribute.GetDisplayName <ARDunningSetup.dueDays>(sender); string daysToSettleLabel = PXUIFieldAttribute.GetDisplayName <ARDunningSetup.daysToSettle>(sender); sender.RaiseExceptionHandling <ARDunningSetup.daysToSettle>(row, row.DaysToSettle, new PXSetPropertyException(Messages.DateToSettleCrossDunningLetterOfNextLevel, PXErrorLevel.Warning, dueDaysLabel, daysToSettleLabel)); //PXUIFieldAttribute.SetWarning<ARDunningSetup.daysToSettle>(sender, row, Messages.DateToSettleCrossDunningLetterOfNextLevel); clear = false; } } } if (clear) { //PXUIFieldAttribute.SetWarning<ARDunningSetup.daysToSettle>(sender, row, null); sender.RaiseExceptionHandling <ARDunningSetup.daysToSettle>(row, row.DaysToSettle, null); } } }
// Deleting order control. Prevents break of consecutive enumeration. protected virtual void ARDunningSetup_RowDeleting(PXCache sender, PXRowDeletingEventArgs e) { int MaxRN = 0; foreach (PXResult <ARDunningSetup> ii in PXSelect <ARDunningSetup> .Select(this)) { ARDunningSetup v = ii; int MaxR = v.DunningLetterLevel.Value; MaxRN = MaxRN < MaxR ? MaxR : MaxRN; } ARDunningSetup row = e.Row as ARDunningSetup; if (row != null) { if (row.DunningLetterLevel.Value < MaxRN) { throw new PXException(Messages.OnlyLastRowCanBeDeleted); } } }
// Prevents break of monotonically increasing values protected virtual void ARDunningSetup_DueDays_FieldVerifying(PXCache sender, PXFieldVerifyingEventArgs e) { ARDunningSetup row = e.Row as ARDunningSetup; if (row != null) { int llevel = row.DunningLetterLevel.Value; int nv = Convert.ToInt32(e.NewValue); if (llevel == 1 && nv <= 0) { throw new PXSetPropertyException(Messages.ThisValueMUSTExceed, 0); } else { int NextValue = 0; int PrevValue = 0; foreach (PXResult <ARDunningSetup> ii in PXSelect <ARDunningSetup> .Select(this)) { ARDunningSetup v = ii; if (v.DunningLetterLevel.Value == llevel - 1) { PrevValue = v.DueDays.Value; } if (v.DunningLetterLevel.Value == llevel + 1) { NextValue = v.DueDays.Value; } } if (nv <= PrevValue) { throw new PXSetPropertyException(Messages.ThisValueMUSTExceed, PrevValue); } if (nv >= NextValue && NextValue > 0) { throw new PXSetPropertyException(Messages.ThisValueCanNotExceed, NextValue); } } } }
public static void ReleaseProcess(ARDunningLetterMaint graph, ARDunningLetter doc) { if (doc != null && doc.Released != true && doc.Voided != true) { graph.Document.Current = doc; doc.DunningLetterLevel = 0; foreach (ARDunningLetterDetail detail in graph.Details.Select()) { doc.DunningLetterLevel = Math.Max(doc.DunningLetterLevel ?? 0, detail.DunningLetterLevel ?? 0); } if (doc.DunningLetterLevel == 0) { throw new PXException(Messages.DunningLetterZeroLevel); } ARDunningSetup dunningSetup = PXSelect <ARDunningSetup, Where <ARDunningSetup.dunningLetterLevel, Equal <Required <ARDunningLetter.dunningLetterLevel> > > > .Select(graph, doc.DunningLetterLevel); if (dunningSetup.DunningFee.HasValue && dunningSetup.DunningFee != 0m) { ARInvoice feeInvoice = InsertFeeInvoice(doc, dunningSetup.DunningFee ?? 0m); doc.FeeRefNbr = feeInvoice.RefNbr; doc.FeeDocType = feeInvoice.DocType; } foreach (ARDunningLetterDetail detail in graph.Details.Select()) { detail.Released = true; graph.Details.Update(detail); } doc.Released = true; graph.Document.Update(doc); graph.Save.Press(); } }
public static void ReleaseProcess(ARDunningLetterMaint graph, ARDunningLetter doc) { if (doc != null && doc.Released != true && doc.Voided != true) { graph.Document.Current = doc; doc.DunningLetterLevel = 0; foreach (ARDunningLetterDetail detail in graph.Details.Select()) { doc.DunningLetterLevel = Math.Max(doc.DunningLetterLevel ?? 0, detail.DunningLetterLevel ?? 0); } if (doc.DunningLetterLevel == 0) { throw new PXException(Messages.DunningLetterZeroLevel); } ARSetup setup = PXSelect <ARSetup> .Select(graph); ARDunningSetup dunningSetup = PXSelect <ARDunningSetup, Where <ARDunningSetup.dunningLetterLevel, Equal <Required <ARDunningLetter.dunningLetterLevel> > > > .Select(graph, doc.DunningLetterLevel); ARInvoiceEntry invGraph = PXGraph.CreateInstance <ARInvoiceEntry>(); if (dunningSetup.DunningFee.HasValue && dunningSetup.DunningFee != 0m) { if (setup.DunningFeeInventoryID == null) { throw new PXException(Messages.DunningLetterEmptyInventory); } Customer customer = graph.CurrentCustomer.Select(); ARInvoice feeInvoice = new ARInvoice { Released = false, Hold = false, Voided = false, BranchID = doc.BranchID, DocDate = doc.DunningLetterDate, CustomerID = doc.BAccountID }; invGraph.Document.Current = feeInvoice; feeInvoice.CustomerLocationID = customer.DefLocationID; invGraph.Document.Update(feeInvoice); feeInvoice.CuryID = customer.AllowOverrideCury == false && customer.CuryID != null ? customer.CuryID : ((GL.Company)PXSelect <GL.Company> .Select(invGraph)).BaseCuryID; invGraph.Document.SetValueExt <ARInvoice.curyID>(invGraph.Document.Current, feeInvoice.CuryID); invGraph.Document.Update(feeInvoice); feeInvoice.DocDesc = Messages.DunningLetterFee; feeInvoice.Hold = false; invGraph.Document.Update(feeInvoice); decimal curyVal; var curyInfo = invGraph.currencyinfo.Select(); PXCurrencyAttribute.PXCurrencyHelper.CuryConvCury(invGraph.Caches[typeof(CurrencyInfo)], curyInfo, dunningSetup.DunningFee ?? 0m, out curyVal); IN.InventoryItem item = PXSelect <IN.InventoryItem, Where <IN.InventoryItem.inventoryID, Equal <Required <ARSetup.dunningFeeInventoryID> > > > .Select(graph, setup.DunningFeeInventoryID); if (item == null) { throw new PXException(Messages.DunningLetterEmptyInventory); } if (item.SalesAcctID == null) { throw new PXException(Messages.DunningProcessFeeEmptySalesAccount); } ARTran detail = new ARTran { BranchID = doc.BranchID, Qty = 1, CuryUnitPrice = curyVal, InventoryID = setup.DunningFeeInventoryID, AccountID = item.SalesAcctID, SubID = item.SalesSubID }; invGraph.Transactions.Insert(detail); feeInvoice = PXCache <ARInvoice> .CreateCopy(invGraph.Document.Current); feeInvoice.OrigDocAmt = feeInvoice.DocBal; feeInvoice.CuryOrigDocAmt = feeInvoice.CuryDocBal; invGraph.Document.Update(feeInvoice); invGraph.Save.Press(); if (setup.AutoReleaseDunningFee == true) { invGraph.release.Press(); } doc.FeeRefNbr = invGraph.Document.Current.RefNbr; doc.FeeDocType = invGraph.Document.Current.DocType; } graph.Details.AllowUpdate = true; foreach (ARDunningLetterDetail detail in graph.Details.Select()) { detail.Released = true; graph.Details.Update(detail); } doc.Released = true; graph.Document.Update(doc); graph.Save.Press(); } }
protected virtual IEnumerable dunningLetterList() { this.DunningLetterList.Cache.Clear(); ARDunningLetterRecordsParameters header = Filter.Current; if (header == null || header.DocDate == null) { yield break; } bool Cons = false; int? DBranch = null; bool canAccessToBranch = false; try { ARSetup SetupV = PXSelect <ARSetup, Where <MatchWithBranch <ARSetup.dunningLetterBranchID> > > .Select(this); if (SetupV != null) { Cons = SetupV.ConsolidatedDunningLetter ?? false; DBranch = SetupV.DunningLetterBranchID; canAccessToBranch = true; } } catch {} if (!canAccessToBranch) { yield break; } //Select due customers. (ARInvoice.dueDate < "current date") int?OldBAccount = null; int?OldBranch = null; foreach (PXResult <Customer, ARInvoice> item in PXSelectJoinGroupBy <Customer, InnerJoin <ARInvoice, On <ARInvoice.customerID, Equal <Customer.bAccountID> > >, Where <ARInvoice.released, Equal <boolTrue>, And <ARInvoice.openDoc, Equal <boolTrue>, And <ARInvoice.voided, Equal <boolFalse>, And <Where <ARInvoice.docType, Equal <ARDocType.invoice>, Or <ARInvoice.docType, Equal <ARDocType.finCharge>, And <ARInvoice.dueDate, Less <Required <ARDunningLetterRecordsParameters.docDate> > > > > > > > >, Aggregate <GroupBy <Customer.bAccountID, GroupBy <ARInvoice.branchID> > > > .Select(this, header.DocDate)) { Customer cust = item; ARInvoice br = item; if (header.CustomerClassID != null) { if (cust.CustomerClassID != header.CustomerClassID) { continue; // CustomerClassID filter } } int?BranchID = (Cons ? DBranch : br.BranchID); if ((BranchID == OldBranch) && (OldBAccount == cust.BAccountID)) { continue; // Group by BranchID } if (OldBAccount != cust.BAccountID) { OldBranch = null; OldBAccount = cust.BAccountID; } OldBranch = BranchID; ARDunningLetterList rec = new ARDunningLetterList(); rec.CustomerClassID = cust.CustomerClassID; rec.BAccountID = cust.BAccountID; rec.BranchID = BranchID; rec.DocDate = header.DocDate; bool Show = true; DateTime maxRD = DateTime.MinValue; int rlevel = 0; //Find last active (not closed) Dunning Letter for each Customer foreach (PXResult <ARDunningLetter> ii in PXSelectJoinGroupBy <ARDunningLetter, InnerJoin <ARDunningLetterDetail, On <ARDunningLetterDetail.dunningLetterID, Equal <ARDunningLetter.dunningLetterID>, And <ARDunningLetterDetail.overdue, Equal <boolTrue> > >, InnerJoin <ARInvoice, On <ARInvoice.docType, Equal <ARDunningLetterDetail.docType>, And <ARInvoice.refNbr, Equal <ARDunningLetterDetail.refNbr>, And <ARInvoice.released, Equal <boolTrue>, And <ARInvoice.openDoc, Equal <boolTrue>, And <ARInvoice.voided, Equal <boolFalse> > > > > > > >, Where <ARDunningLetter.bAccountID, Equal <Required <ARDunningLetter.bAccountID> >, And <ARDunningLetter.branchID, Equal <Required <ARDunningLetter.branchID> > > >, Aggregate <GroupBy <ARDunningLetter.dunningLetterLevel, GroupBy <ARDunningLetter.dunningLetterDate> > > > .Select(this, cust.BAccountID, BranchID)) { ARDunningLetter RR = ii; if (maxRD < RR.DunningLetterDate.Value) { maxRD = RR.DunningLetterDate.Value; rlevel = RR.DunningLetterLevel.Value; } } if (rlevel >= D_MaxLevel) { Show = false; // Dunning Letter max level is exceeded } else if (rlevel > 0) // has active Dunning Letter { if (maxRD.AddDays(D_DueDays[rlevel]) > header.DocDate.Value) { Show = false; //Letter is not overdue, not process } } if (Show) // need to process { rec.NumberOfDocuments = 0; rec.NumberOfOverdueDocuments = 0; rec.OrigDocAmt = 0; rec.DocBal = 0; DateTime minD = DateTime.Today; // Selecl all invoices foreach (PXResult <ARInvoice> ix in PXSelect <ARInvoice, Where <ARInvoice.customerID, Equal <Required <ARInvoice.customerID> >, And <ARInvoice.released, Equal <boolTrue>, And <ARInvoice.openDoc, Equal <boolTrue>, And <ARInvoice.voided, Equal <boolFalse>, And <Where <ARInvoice.docType, Equal <ARDocType.invoice>, Or <ARInvoice.docType, Equal <ARDocType.finCharge>, And <ARInvoice.docDate, Less <Required <ARInvoice.docDate> > > > > > > > > > > .Select(this, cust.BAccountID, header.DocDate)) { ARInvoice dl = ix; if (!Cons && dl.BranchID != BranchID) { continue; // alien branch } minD = minD < dl.DueDate.Value ? minD : dl.DueDate.Value; rec.NumberOfDocuments++; rec.NumberOfOverdueDocuments += (dl.DueDate > header.DocDate ? 0 : 1); rec.OrigDocAmt += dl.DocBal; rec.DocBal += (dl.DueDate > header.DocDate ? 0 : dl.DocBal); } rec.DunningLetterLevel = rlevel + 1; rec.DueDate = minD; ARDunningSetup settings = this.DunningSetupList[rlevel]; rec.DueDays = (settings.DaysToSettle ?? 0); //rec.DueDays = D_DueDays[rlevel]; if (rlevel > 0) { rec.LastDunningLetterDate = maxRD; } else { rec.LastDunningLetterDate = null; } if (minD.AddDays(D_DueDays[rlevel]) < header.DocDate) //Has at least one overdue invoice { try { this.DunningLetterList.Insert(rec); } catch {} } } } this.DunningLetterList.Cache.IsDirty = false; foreach (ARDunningLetterList ret in this.DunningLetterList.Cache.Inserted) { yield return(ret); } }