Example #1
0
		private static IEnumerable<Customer> GetCustomersForAutoApplication(PXGraph graph, ARStatementCycle cycle, ARAutoApplyParameters filter)
		{
			var result = new List<Customer> { };

			if (filter.LoadChildDocuments != LoadChildDocumentsOptions.None)
			{
				var childrenOfParentsWithCycle = PXSelectJoin<Customer,
					InnerJoin<CustomerMaster,
						On<Customer.parentBAccountID, Equal<CustomerMaster.bAccountID>,
						And<Customer.consolidateToParent, Equal<True>>>>,
					Where<CustomerMaster.statementCycleId, Equal<Required<Customer.statementCycleId>>,
						And<Match<Current<AccessInfo.userName>>>>>
						.Select(graph, cycle.StatementCycleId);

				result.AddRange(childrenOfParentsWithCycle.RowCast<Customer>());
			}

			var nonChildrenWithCycle = PXSelectJoin<Customer,
				LeftJoin<CustomerMaster,
					On<Customer.parentBAccountID, Equal<CustomerMaster.bAccountID>,
					And<Customer.consolidateToParent, Equal<True>>>>,
				Where<Customer.statementCycleId, Equal<Required<Customer.statementCycleId>>,
					And2<Match<Current<AccessInfo.userName>>,
					And<Where<CustomerMaster.bAccountID, IsNull,
						Or<CustomerMaster.statementCycleId, NotEqual<Required<CustomerMaster.statementCycleId>>>>>>>>
					.Select(graph, cycle.StatementCycleId, cycle.StatementCycleId);

			var toAdd = nonChildrenWithCycle.RowCast<Customer>()
				.Where(c => result.FirstOrDefault(alreadyPresent => alreadyPresent.BAccountID == c.BAccountID) == null).ToList();
			result.AddRange(toAdd);
			return result;
		}
        protected static void Accumulate(ARStatement aDest, ARRegister aSrc1, ARStatementCycle aSrc2, bool isNewDoc, bool aAgeCredits)
        {
            ARInvoice inv = aSrc1 as ARInvoice;

            Copy(aDest, aSrc2);
            if (isNewDoc)
            {
                aDest.EndBalance     = (aDest.EndBalance ?? Decimal.Zero) + ((aSrc1.Payable ?? false) ? aSrc1.OrigDocAmt : (-aSrc1.OrigDocAmt));
                aDest.CuryEndBalance = (aDest.CuryEndBalance ?? Decimal.Zero) + ((aSrc1.Payable ?? false) ? aSrc1.CuryOrigDocAmt : (-aSrc1.CuryOrigDocAmt));
            }
            //ARDocType.SmallCreditWO - is an invoice, but it must be processed as payment
            int days = 0;

            if (inv != null && inv.DocType != ARDocType.SmallCreditWO)
            {
                TimeSpan diff = (aDest.StatementDate.Value.Subtract(inv.DueDate.Value));
                days = diff.Days;
            }
            else
            {
                TimeSpan diff = (aDest.StatementDate.Value.Subtract(aSrc1.DocDate.Value));
                days = diff.Days;
            }
            if ((inv != null && inv.DocType != ARDocType.SmallCreditWO) || aAgeCredits)
            {
                Decimal docBal     = ((bool)aSrc1.Paying) ? -aSrc1.DocBal.Value : aSrc1.DocBal.Value;
                Decimal curyDocBal = ((bool)aSrc1.Paying) ? -aSrc1.CuryDocBal.Value : aSrc1.CuryDocBal.Value;
                if (days <= 0)
                {
                    aDest.AgeBalance00     = (aDest.AgeBalance00 ?? Decimal.Zero) + docBal;
                    aDest.CuryAgeBalance00 = (aDest.CuryAgeBalance00 ?? Decimal.Zero) + curyDocBal;
                }
                else if (!aSrc2.AgeDays00.HasValue || days <= aSrc2.AgeDays00)
                {
                    aDest.AgeBalance01     = (aDest.AgeBalance01 ?? Decimal.Zero) + docBal;
                    aDest.CuryAgeBalance01 = (aDest.CuryAgeBalance01 ?? Decimal.Zero) + curyDocBal;
                }
                else if (!aSrc2.AgeDays01.HasValue || days <= aSrc2.AgeDays01)
                {
                    aDest.AgeBalance02     = (aDest.AgeBalance02 ?? Decimal.Zero) + docBal;
                    aDest.CuryAgeBalance02 = (aDest.CuryAgeBalance02 ?? Decimal.Zero) + curyDocBal;
                }
                else if (!aSrc2.AgeDays02.HasValue || days <= aSrc2.AgeDays02)
                {
                    aDest.AgeBalance03     = (aDest.AgeBalance03 ?? Decimal.Zero) + docBal;
                    aDest.CuryAgeBalance03 = (aDest.CuryAgeBalance03 ?? Decimal.Zero) + curyDocBal;
                }
                else
                {
                    aDest.AgeBalance04     = (aDest.AgeBalance04 ?? Decimal.Zero) + docBal;
                    aDest.CuryAgeBalance04 = (aDest.CuryAgeBalance04 ?? Decimal.Zero) + curyDocBal;
                }
            }
            else
            {
                //Payments, when credits are not aged
                aDest.AgeBalance04     = aDest.AgeBalance04 - aSrc1.DocBal;             //After completion we must apply resedual payments to previous buckets
                aDest.CuryAgeBalance04 = aDest.CuryAgeBalance04 - aSrc1.CuryDocBal;
            }
        }
Example #3
0
		protected virtual void ARStatementCycle_RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
		{
			if (e.Row != null)
			{
				ARStatementCycle row = e.Row as ARStatementCycle;

				row.NextStmtDate = ARStatementProcess.CalcStatementDateBefore(
					sender.Graph,
					this.Accessinfo.BusinessDate.Value, 
					row.PrepareOn, 
					row.Day00, 
					row.Day01,
					row.DayOfWeek);

				if (row.LastStmtDate.HasValue && row.NextStmtDate <= row.LastStmtDate)
				{
					row.NextStmtDate = ARStatementProcess.CalcNextStatementDate(
						sender.Graph,
						row.LastStmtDate.Value, 
						row.PrepareOn, 
						row.Day00, 
						row.Day01,
						row.DayOfWeek);
				}
			}
		}
        public virtual void CustomerClass_StatementCycleId_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
        {
            CustomerClass row = (CustomerClass)e.Row;

            if (row == null)
            {
                return;
            }
            if ((row.StatementCycleId != null))
            {
                ARSetup setup = (ARSetup)PXSelect <ARSetup> .Select(this);

                if (setup != null && (setup.DefFinChargeFromCycle == true))
                {
                    ARStatementCycle arSC = PXSelect <ARStatementCycle,
                                                      Where <ARStatementCycle.statementCycleId, Equal <Required <ARStatementCycle.statementCycleId> > > > .
                                            Select(this, row.StatementCycleId);

                    if ((arSC != null) && (arSC.FinChargeID != null))
                    {
                        row.FinChargeID = arSC.FinChargeID;
                        this.CustomerClassRecord.Cache.RaiseFieldUpdated <CustomerClass.finChargeID>(row, null);
                    }
                }
            }
        }
        protected virtual void GenerateStatement(ARStatementCycle aCycle, DateTime aStatementDate)
        {
            PXSelectBase <Customer>   selectCustomer = new PXSelect <Customer, Where <Customer.statementCycleId, Equal <Required <Customer.statementCycleId> > > >(this);
            PXSelectBase <ARRegister> selectOpenDocs = new PXSelectJoin <ARRegister, LeftJoin <ARInvoice, On <ARInvoice.docType, Equal <ARRegister.docType>,
                                                                                                              And <ARInvoice.refNbr, Equal <ARRegister.refNbr> > > >,
                                                                         Where <ARRegister.customerID, Equal <Required <ARRegister.customerID> >,
                                                                                And <ARRegister.released, Equal <BQLConstants.BitOn>,
                                                                                     And <ARRegister.docDate, LessEqual <Required <ARRegister.docDate> >,
                                                                                          And <Where <ARRegister.openDoc, Equal <BQLConstants.BitOn>,
                                                                                                      Or <ARRegister.statementDate, IsNull> > >
                                                                                          > > > >(this);
            PXSelectBase <ARStatementDetail> selectDocsStmDetail = new PXSelect <ARStatementDetail, Where <ARStatementDetail.customerID,
                                                                                                           Equal <Required <ARStatementDetail.customerID> >,
                                                                                                           And <ARStatementDetail.docType, Equal <Required <ARStatementDetail.docType> >,
                                                                                                                And <ARStatementDetail.refNbr, Equal <Required <ARStatementDetail.refNbr> > > > >, OrderBy <Asc <ARStatementDetail.statementDate> > >(this);

            PXSelectBase <ARStatement> selectAllPreviousByCustomer = new PXSelect <ARStatement,
                                                                                   Where <ARStatement.customerID, Equal <Required <ARStatement.customerID> > >,
                                                                                   OrderBy <Asc <ARStatement.curyID, Desc <ARStatement.statementDate> > > >(this);
            PXSelectBase <ARStatement> selectPreviousStatement = new PXSelect <ARStatement,
                                                                               Where <ARStatement.branchID, Equal <Required <ARStatement.branchID> >,
                                                                                      And <ARStatement.customerID, Equal <Required <ARStatement.customerID> >,
                                                                                           And <ARStatement.curyID, Equal <Required <ARStatement.curyID> > > > >,
                                                                               OrderBy <Desc <ARStatement.statementDate> > >(this);
            bool ageCredits = (this.ARSetup.Current.AgeCredits ?? false);

            foreach (Customer iCst in selectCustomer.Select(aCycle.StatementCycleId))
            {
                GenerateCustomerStatement(aCycle, iCst, aStatementDate, new Dictionary <Tuple <int, string, int, DateTime>, ARStatement>());
            }
            aCycle.LastStmtDate = aStatementDate;
        }
 protected static void Copy(ARStatement aDest, ARStatementCycle aSrc)
 {
     aDest.StatementCycleId = aSrc.StatementCycleId;
     aDest.AgeDays00        = 0;
     aDest.AgeDays01        = aSrc.AgeDays00;
     aDest.AgeDays02        = aSrc.AgeDays01;
     aDest.AgeDays03        = aSrc.AgeDays02;
 }
Example #7
0
        public static void ProcessCycles(StatementCycleProcessBO graph, ARStatementCycle aCycle)
        {
            graph.Clear();
            ARStatementCycle cycle         = graph.CyclesList.Select(aCycle.StatementCycleId);
            DateTime         statementDate = aCycle.NextStmtDate ?? graph.Accessinfo.BusinessDate.Value;

            graph.GenerateStatement(cycle, statementDate, false);
        }
        public static DateTime FindNextStatementDate(DateTime aBusinessDate, ARStatementCycle aCycle)
        {
            DateTime?result = CalcStatementDateBefore(aBusinessDate, aCycle.PrepareOn, aCycle.Day00, aCycle.Day01);

            if (aCycle.LastStmtDate.HasValue && result <= aCycle.LastStmtDate)
            {
                result = CalcNextStatementDate(aCycle.LastStmtDate.Value, aCycle.PrepareOn, aCycle.Day00, aCycle.Day01);
            }
            return(result.HasValue ? result.Value : aBusinessDate);
        }
Example #9
0
        private void SetStatementDateFromCycle(PrintParameters filter)
        {
            if (!string.IsNullOrEmpty(filter.StatementCycleId))
            {
                ARStatementCycle cycle = PXSelect <ARStatementCycle,
                                                   Where <ARStatementCycle.statementCycleId,
                                                          Equal <Required <ARStatementCycle.statementCycleId> > > > .Select(this, filter.StatementCycleId);

                filter.StatementDate = cycle.LastStmtDate;
            }
        }
Example #10
0
        public static void RegenerateLastStatement(StatementCycleProcessBO graph, ARStatementCycle aCycle)
        {
            graph.Clear();
            ARStatementCycle cycle = graph.CyclesList.Select(aCycle.StatementCycleId);

            if (cycle.LastStmtDate != null)
            {
                DateTime stmtDate = (DateTime)cycle.LastStmtDate;
                graph.GenerateStatement(cycle, stmtDate, true);
            }
        }
        protected virtual void ARStatementDetailsParameters_StatementCycleId_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
        {
            ARStatementDetailsParameters row = (ARStatementDetailsParameters)e.Row;

            if (!string.IsNullOrEmpty(row.StatementCycleId))
            {
                ARStatementCycle cycle = PXSelect <ARStatementCycle,
                                                   Where <ARStatementCycle.statementCycleId,
                                                          Equal <Required <ARStatementCycle.statementCycleId> > > > .Select(this, row.StatementCycleId);

                row.StatementDate = cycle.LastStmtDate;
            }
        }
        protected static void DeleteStatement(ARStatementCycle aStatementCycle, DateTime aStmtDate)
        {
            StatementCreateBO statementBO = PXGraph.CreateInstance <StatementCreateBO>();

            foreach (ARStatement iStm in statementBO.Statement.Select(aStatementCycle.StatementCycleId, aStmtDate))
            {
                statementBO.Statement.Delete(iStm);
            }
            statementBO.Actions.PressSave();
            if (aStatementCycle.LastStmtDate == aStmtDate)
            {
                aStatementCycle.LastStmtDate = statementBO.FindLastCycleStatementDate(aStatementCycle.StatementCycleId, aStmtDate);
            }
        }
Example #13
0
        protected virtual void GenerateStatement(ARStatementCycle cycle, DateTime statementDate, bool clearExisting)
        {
            PXSelectBase <Customer> selectCustomer = new PXSelectJoin <Customer,
                                                                       InnerJoin <CustomerMaster, On <CustomerMaster.bAccountID, Equal <Customer.statementCustomerID> > >,
                                                                       Where <CustomerMaster.statementCycleId, Equal <Required <Customer.statementCycleId> > >,
                                                                       OrderBy <Asc <Customer.statementCustomerID> > >(this);

            var statementGraph = CreateInstance <StatementCreateBO>();

            var family = new List <Customer> {
            };

            foreach (Customer customer in selectCustomer.Select(cycle.StatementCycleId))
            {
                if (family.Any() == false || family.First().StatementCustomerID == customer.StatementCustomerID)
                {
                    family.Add(customer);
                }
                else
                {
                    GenerateStatementForCustomerFamily(statementGraph, cycle, family, statementDate, clearExisting);
                    family = new List <Customer> {
                        customer
                    };
                }
            }

            if (family.Any())
            {
                GenerateStatementForCustomerFamily(statementGraph, cycle, family, statementDate, clearExisting);
            }

            Customer leftToProcess = PXSelectReadonly2 <Customer,
                                                        InnerJoin <CustomerMaster, On <CustomerMaster.bAccountID, Equal <Customer.statementCustomerID> > >,
                                                        Where <CustomerMaster.statementCycleId, Equal <Required <Customer.statementCycleId> >,
                                                               And <Where <Customer.statementLastDate, IsNull,
                                                                           Or <Customer.statementLastDate, Less <Required <Customer.statementLastDate> > > > > > > .SelectWindowed(this, 0, 1, cycle.StatementCycleId, statementDate);

            if (leftToProcess == null)
            {
                cycle.LastStmtDate = statementDate;
                this.CyclesList.Update(cycle);
                this.Actions.PressSave();
            }
        }
        protected static IEnumerable <ARStatement> DeleteStatements(ARStatementCycle aStatementCycle, IEnumerable <Customer> customers, DateTime aStmtDate)
        {
            var trace = new List <ARStatement>();

            StatementCreateBO statementBO = PXGraph.CreateInstance <StatementCreateBO>();

            foreach (var customer in customers)
            {
                foreach (ARStatement iStm in statementBO.CustomerStatement.Select(aStatementCycle.StatementCycleId, customer.BAccountID, aStmtDate))
                {
                    trace.Add(StatementTrace(iStm));
                    statementBO.CustomerStatement.Delete(iStm);
                }
            }
            statementBO.Actions.PressSave();

            return(trace);
        }
        public static void RegenerateLastStatement(StatementCycleProcessBO graph, ARStatementCycle aCycle)
        {
            graph.Clear();
            ARStatementCycle cycle = graph.CyclesList.Select(aCycle.StatementCycleId);

            if (cycle.LastStmtDate != null)
            {
                DateTime stmtDate = (DateTime)cycle.LastStmtDate;
                using (PXTransactionScope ts = new PXTransactionScope())
                {
                    DeleteStatement(cycle, stmtDate);
                    graph.GenerateStatement(cycle, stmtDate);
                    PXCache cache = graph.CyclesList.Cache;
                    cache.Update(cycle);
                    cache.Persist(PXDBOperation.Update);
                    ts.Complete();
                }
            }
        }
Example #16
0
        public static void RegenerateStatements(StatementCycleProcessBO graph, ARStatementCycle aCycle, IEnumerable <Customer> customers)
        {
            graph.Clear();
            ARStatementCycle cycle = graph.CyclesList.Select(aCycle.StatementCycleId);

            if (cycle.LastStmtDate != null)
            {
                DateTime stmtDate = (DateTime)cycle.LastStmtDate;

                var statementGraph = CreateInstance <StatementCreateBO>();

                var customerFamilies = GetStatementCustomers(graph, customers).GroupBy(c => c.StatementCustomerID);

                foreach (var family in customerFamilies)
                {
                    graph.GenerateStatementForCustomerFamily(statementGraph, aCycle, family, stmtDate, true);
                }
            }
        }
        public static DateTime FindNextStatementDateAfter(DateTime aBusinessDate, ARStatementCycle aCycle)
        {
            DateTime?result = null;

            if (aCycle.LastStmtDate.HasValue)
            {
                result = CalcNextStatementDate(aCycle.LastStmtDate.Value, aCycle.PrepareOn, aCycle.Day00, aCycle.Day01);
                if (result >= aBusinessDate)
                {
                    return(result.Value);
                }
            }
            result = CalcStatementDateBefore(aBusinessDate, aCycle.PrepareOn, aCycle.Day00, aCycle.Day01);
            do
            {
                result = CalcNextStatementDate(result.Value, aCycle.PrepareOn, aCycle.Day00, aCycle.Day01);
            }while ((result != null) && (result < aBusinessDate));
            return(result.Value);
        }
Example #18
0
        protected virtual ARStatement AddARStatement(Dictionary <StatementKey, ARStatement> statements, StatementKey key,
                                                     ARStatementCycle cycle, Customer customer, DateTime statementDate)
        {
            ARStatement statement;

            if (!statements.TryGetValue(key, out statement))
            {
                statement = new ARStatement();
                Clear(statement);
                Copy(statement, customer);
                Copy(statement, cycle);
                Copy(statement, key);
                statement.StatementDate = statementDate;

                statements[key] = statement;
            }

            return(statement);
        }
Example #19
0
        protected virtual IEnumerable <ARStatement> DeleteCustomerStatement(ARStatementCycle aCycle, Customer customer, DateTime aStatementDate)
        {
            StatementCreateBO statementBO = PXGraph.CreateInstance <StatementCreateBO>();
            var trace        = new List <ARStatement>();
            int deletedCount = 0;

            foreach (ARStatement iStm in statementBO.CustomerStatement.Select(customer.BAccountID, aStatementDate))
            {
                trace.Add(StatementTrace(iStm));
                statementBO.CustomerStatement.Delete(iStm);
                deletedCount++;
            }
            if (deletedCount == 0)
            {
                customer.StatementLastDate = statementBO.FindLastCstmStatementDate(customer.BAccountID, aStatementDate);
                statementBO.Customer.Update(customer);
            }
            statementBO.Actions.PressSave();
            return(trace);
        }
        public static void ProcessCycles(StatementCycleProcessBO graph, ARStatementCycle aCycle)
        {
            graph.Clear();
            ARStatementCycle cycle         = graph.CyclesList.Select(aCycle.StatementCycleId);
            DateTime?        statementDate = aCycle.NextStmtDate;

            using (PXTransactionScope ts = new PXTransactionScope())
            {
                if (statementDate.HasValue)
                {
                    graph.GenerateStatement(cycle, statementDate.Value);
                }
                else
                {
                    graph.GenerateStatement(cycle, graph.Accessinfo.BusinessDate.Value);
                }
                graph.CyclesList.Update(cycle);
                graph.CyclesList.Cache.Persist(PXDBOperation.Update);
                ts.Complete();
            }
        }
        public static void RegenerateStatements(StatementCycleProcessBO graph, ARStatementCycle aCycle, IEnumerable <Customer> customers)
        {
            graph.Clear();
            ARStatementCycle cycle = graph.CyclesList.Select(aCycle.StatementCycleId);

            if (cycle.LastStmtDate != null)
            {
                DateTime stmtDate = (DateTime)cycle.LastStmtDate;
                using (PXTransactionScope ts = new PXTransactionScope())
                {
                    //why don't we pass the graph to the DeleteStatements?
                    var trace = DeleteStatements(cycle, customers, stmtDate);
                    //don't we want graph.Accessinfo.BusinessDate.Value here???
                    foreach (var c in customers.GroupBy(cs => cs.BAccountID).Select(g => g.First()))
                    {
                        graph.GenerateCustomerStatement(cycle, c, stmtDate, TraceToDict(trace));
                    }

                    ts.Complete();
                }
            }
        }
Example #22
0
        public virtual void ARStatementCycle_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            if (e.Row == null)
            {
                return;
            }

            ARStatementCycle row = (ARStatementCycle)e.Row;

            if (row.NextStmtDate.HasValue == false)
            {
                DateTime basisDate = row.LastStmtDate.HasValue? row.LastStmtDate.Value: Accessinfo.BusinessDate.HasValue? Accessinfo.BusinessDate.Value: DateTime.Now;
                row.NextStmtDate = CalcNextStatementDate(basisDate, row.PrepareOn, row.Day00, row.Day01);
            }
            ARSetup setup = this.ARSetup.Select();

            PXCache.TryDispose(cache.GetAttributes(e.Row, null));

            if (CheckForUnprocessedPPD(this, row.StatementCycleId, row.NextStmtDate, null))
            {
                PXUIFieldAttribute.SetEnabled(cache, row, false);
                cache.RaiseExceptionHandling <FinPeriod.selected>(row, false,
                                                                  new PXSetPropertyException(Messages.UnprocessedPPDExists, PXErrorLevel.RowError));

                return;
            }

            bool?hasOverdueInvoices    = null;
            bool hasUnAppliedPayments  = false;
            bool hasChargeableInvoices = false;

            if (row.RequirePaymentApplication ?? false)
            {
                hasOverdueInvoices = CheckForOverdueInvoices(this, row.StatementCycleId, row.NextStmtDate.Value);
                if (hasOverdueInvoices.Value)
                {
                    if (CheckForOpenPayments(this, row.StatementCycleId))
                    {
                        hasUnAppliedPayments = true;
                    }
                }
            }

            // The third condition below conveys the 'hidden' meaning of
            // DefFinChargeFromCycle, i.e. 'attaching' overdue charges calculation
            // to statement cycles.
            //
            // If DefFinChargeFromCycle is false, it is assumed that the users take
            // care of overdue charges themselves and need not be warned.
            // -
            if ((row.FinChargeApply ?? false) &&
                (row.RequireFinChargeProcessing ?? false) &&
                (setup.DefFinChargeFromCycle ?? false))
            {
                if (!hasOverdueInvoices.HasValue)
                {
                    hasOverdueInvoices = CheckForOverdueInvoices(this, row.StatementCycleId, row.NextStmtDate.Value);
                }
                if (hasOverdueInvoices.Value &&
                    (!row.LastFinChrgDate.HasValue || row.LastFinChrgDate.Value < row.NextStmtDate.Value))
                {
                    hasChargeableInvoices = true;
                }
            }

            if (hasChargeableInvoices && hasUnAppliedPayments)
            {
                this.CyclesList.Cache.RaiseExceptionHandling <ARStatementCycle.statementCycleId>(row, row.StatementCycleId,
                                                                                                 new PXSetPropertyException(Messages.WRN_ProcessStatementDetectsOverdueInvoicesAndUnappliedPayments, PXErrorLevel.RowWarning));
            }
            else if (hasChargeableInvoices)
            {
                this.CyclesList.Cache.RaiseExceptionHandling <ARStatementCycle.statementCycleId>(row, row.StatementCycleId,
                                                                                                 new PXSetPropertyException(Messages.WRN_ProcessStatementDetectsOverdueInvoices, PXErrorLevel.RowWarning));
            }
            else if (hasUnAppliedPayments)
            {
                this.CyclesList.Cache.RaiseExceptionHandling <ARStatementCycle.statementCycleId>(row, row.StatementCycleId,
                                                                                                 new PXSetPropertyException(Messages.WRN_ProcessStatementDetectsUnappliedPayments, PXErrorLevel.RowWarning));
            }
        }
Example #23
0
        protected virtual void GenerateStatementForCustomerFamily(StatementCreateBO statementGraph, ARStatementCycle cycle, IEnumerable <Customer> customers, DateTime statementDate, bool clearExisting)
        {
            var documentsList = new List <PXResult <ARRegister, ARInvoice> > {
            };

            foreach (var customer in customers.OrderByDescending(c => c.ParentBAccountID))
            {
                using (PXTransactionScope ts = new PXTransactionScope())
                {
                    Dictionary <Tuple <int, string, int, DateTime>, ARStatement> trace = new Dictionary <Tuple <int, string, int, DateTime>, ARStatement>();
                    if (clearExisting || customer.StatementLastDate == statementDate)
                    {
                        //Need to pass Prints and E-mail counts to the regenerated statement - for this reason we need to copy
                        IEnumerable <ARStatement> deleted = this.DeleteCustomerStatement(cycle, customer, statementDate);
                        trace = TraceToDict(deleted);
                    }

                    GenerateCustomerStatement(statementGraph, cycle, customer, statementDate, trace, documentsList);
                    ts.Complete();
                }
            }
        }
Example #24
0
        protected virtual void GenerateCustomerStatement(StatementCreateBO statementGraph, ARStatementCycle aCycle, Customer customer, DateTime aStatementDate,
                                                         Dictionary <Tuple <int, string, int, DateTime>, ARStatement> statementsTrace, IList <PXResult <ARRegister, ARInvoice> > familyDocuments)
        {
            PXSelectBase <ARRegister> selectOpenDocs = new PXSelectJoin <ARRegister, LeftJoin <ARInvoice, On <ARInvoice.docType, Equal <ARRegister.docType>,
                                                                                                              And <ARInvoice.refNbr, Equal <ARRegister.refNbr> > > >,
                                                                         Where <ARRegister.customerID, Equal <Required <ARRegister.customerID> >,
                                                                                And <ARRegister.released, Equal <BQLConstants.BitOn>,
                                                                                     And <ARRegister.docDate, LessEqual <Required <ARRegister.docDate> >,
                                                                                          And <Where <ARRegister.openDoc, Equal <BQLConstants.BitOn>,
                                                                                                      Or <ARRegister.statementDate, IsNull> > > > > > >(this);

            PXSelectBase <ARStatementDetail> selectDocsStmDetail = new PXSelect <ARStatementDetail, Where <ARStatementDetail.customerID,
                                                                                                           Equal <Required <ARStatementDetail.customerID> >,
                                                                                                           And <ARStatementDetail.docType, Equal <Required <ARStatementDetail.docType> >,
                                                                                                                And <ARStatementDetail.refNbr, Equal <Required <ARStatementDetail.refNbr> > > > >, OrderBy <Asc <ARStatementDetail.statementDate> > >(this);

            PXSelectBase <ARStatement> selectAllPreviousByCustomer = new PXSelect <ARStatement,
                                                                                   Where <ARStatement.customerID, Equal <Required <ARStatement.customerID> > >,
                                                                                   OrderBy <Asc <ARStatement.curyID, Desc <ARStatement.statementDate> > > >(this);

            PXSelectBase <ARStatement> selectPreviousStatement = new PXSelect <ARStatement,
                                                                               Where <ARStatement.branchID, Equal <Required <ARStatement.branchID> >,
                                                                                      And <ARStatement.customerID, Equal <Required <ARStatement.customerID> >,
                                                                                           And <ARStatement.curyID, Equal <Required <ARStatement.curyID> > > > >,
                                                                               OrderBy <Desc <ARStatement.statementDate> > >(this);

            bool ageCredits = (this.ARSetup.Current.AgeCredits ?? false);
            bool isParent   = customer.StatementCustomerID == customer.BAccountID;

            Dictionary <StatementKey, ARStatement> statements = new Dictionary <StatementKey, ARStatement>();

            if (isParent)
            {
                foreach (PXResult <ARRegister, ARInvoice> res in familyDocuments)
                {
                    ARRegister   doc = res;
                    StatementKey key = new StatementKey(doc.BranchID.Value, doc.CuryID);
                    AddARStatement(statements, key, aCycle, customer, aStatementDate);
                }
            }

            List <ARStatementDetail> details = new List <ARStatementDetail>();

            foreach (PXResult <ARRegister, ARInvoice> iDoc in selectOpenDocs.Select(customer.BAccountID, aStatementDate))
            {
                ARRegister        doc             = iDoc;
                ARInvoice         inv             = iDoc;
                ARStatementDetail statementDetail = selectDocsStmDetail.Select(doc.CustomerID, doc.DocType, doc.RefNbr);
                bool         isNewDoc             = statementDetail == null;
                StatementKey key = new StatementKey(doc.BranchID.Value, doc.CuryID);

                familyDocuments.Add(iDoc);

                if (IsMultipleInstallmentMaster(inv))
                {
                    continue;                     //Skip invoice, which is the first in multiple installments sequence (master)
                }
                ARStatement header = AddARStatement(statements, key, aCycle, customer, aStatementDate);
                if (header.Processed != true)
                {
                    ARStatement prevStatement = selectPreviousStatement.Select(header.BranchID, header.CustomerID, header.CuryID);
                    if (prevStatement != null)
                    {
                        header.PrevStatementDate = prevStatement.StatementDate;
                    }

                    ARStatement trace;
                    if (statementsTrace.TryGetValue(new Tuple <int, string, int, DateTime>(header.BranchID.Value,
                                                                                           header.CuryID, header.CustomerID.Value, header.StatementDate.Value), out trace))
                    {
                        header.PrevPrintedCnt = trace.PrevPrintedCnt;
                        header.PrevEmailedCnt = trace.PrevEmailedCnt;
                    }

                    header.Processed = true;
                }

                ARStatementDetail det = new ARStatementDetail();
                Copy(det, header);
                Copy(det, doc);

                if (doc.DocType != AR.ARDocType.CashSale && doc.DocType != AR.ARDocType.CashReturn)
                {
                    var document = (doc.Payable == true ? inv : doc);

                    if (header.StatementType == StatementTypes.CS_BALANCE_BROUGHT_FORWARD && isNewDoc)
                    {
                        header.EndBalance     = (header.EndBalance ?? 0m) + document.SignBalance * document.OrigDocAmt;
                        header.CuryEndBalance = (header.CuryEndBalance ?? 0m) + document.SignBalance * document.CuryOrigDocAmt;
                    }
                    else if (header.StatementType == StatementTypes.CS_OPEN_ITEM)
                    {
                        header.EndBalance     = (header.EndBalance ?? 0m) + document.SignBalance * document.DocBal;
                        header.CuryEndBalance = (header.CuryEndBalance ?? 0m) + document.SignBalance * document.CuryDocBal;
                    }
                }

                details.Add(det);
            }

            if (isParent)
            {
                AccumulateAgeBalancesIntoStatements(familyDocuments, statements, ageCredits);
            }

            //Merge with previous statements - is needed for Balance Brought Forward
            Dictionary <StatementKey, DateTime> lastCuryStatement = new Dictionary <StatementKey, DateTime>();

            foreach (ARStatement iPrev in selectAllPreviousByCustomer.Select(customer.BAccountID))
            {
                StatementKey key = new StatementKey(iPrev.BranchID.Value, iPrev.CuryID);
                if (lastCuryStatement.ContainsKey(key) && lastCuryStatement[key] > iPrev.StatementDate)
                {
                    continue;
                }

                ARStatement header = AddARStatement(statements, key, aCycle, customer, aStatementDate);

                header.BegBalance     = iPrev.EndBalance;
                header.CuryBegBalance = iPrev.CuryEndBalance;
                Recalculate(header);
                lastCuryStatement[key] = iPrev.StatementDate.Value;
            }

            foreach (ARStatement iH in statements.Values)
            {
                ARStatement prev = selectPreviousStatement.Select(iH.CustomerID, iH.BranchID, iH.CuryID);
                if (prev != null)
                {
                    iH.BegBalance     = prev.EndBalance;
                    iH.CuryBegBalance = prev.CuryEndBalance;
                }

                ApplyFIFORule(iH, ageCredits);
            }

            PersistStatement(statementGraph, customer.BAccountID, aStatementDate, statements.Values, details);
        }
        protected virtual IEnumerable history()
        {
            this.History.Cache.Clear();

            ARStatementHistoryParameters header = Filter.Current;

            if (header == null)
            {
                yield break;
            }

            int?          prevCustomerID = null;
            string        prevCuryID     = null;
            HistoryResult prevRec        = null;

            PXResultset <ARStatement> res;
            List <object>             stored = new List <object>();

            PXSelectBase <ARStatement> select = new PXSelectJoin <ARStatement,
                                                                  LeftJoin <ARStatementCycle, On <ARStatementCycle.statementCycleId, Equal <ARStatement.statementCycleId> >,
                                                                            LeftJoin <Customer, On <Customer.bAccountID, Equal <ARStatement.statementCustomerID> > > >,
                                                                  Where <ARStatement.statementCustomerID, Equal <ARStatement.customerID>,
                                                                         And <ARStatement.statementDate, GreaterEqual <Required <ARStatement.statementDate> >,
                                                                              And <ARStatement.statementDate, LessEqual <Required <ARStatement.statementDate> >,
                                                                                   And <Where <ARStatement.statementCycleId, Equal <Required <ARStatement.statementCycleId> >,
                                                                                               Or <Required <ARStatement.statementCycleId>, IsNull> > > > > >,
                                                                  OrderBy <Asc <ARStatement.statementCycleId,
                                                                                Asc <ARStatement.statementDate,
                                                                                     Asc <ARStatement.customerID,
                                                                                          Asc <ARStatement.curyID> > > > > >(this);

            using (new PXFieldScope(select.View,
                                    typeof(ARStatement.branchID),
                                    typeof(ARStatement.statementCycleId),
                                    typeof(ARStatement.statementDate),
                                    typeof(ARStatement.customerID),
                                    typeof(ARStatement.statementCustomerID),
                                    typeof(ARStatement.curyID),
                                    typeof(ARStatement.dontPrint),
                                    typeof(ARStatement.dontEmail),
                                    typeof(ARStatement.printed),
                                    typeof(ARStatement.emailed),

                                    typeof(ARStatementCycle.descr),
                                    typeof(Customer.printCuryStatements)))
            {
                res = select.Select(header.StartDate, header.EndDate, header.StatementCycleId, header.StatementCycleId);
            }

            foreach (PXResult <ARStatement, ARStatementCycle, Customer> item in res)
            {
                stored.Add(item);

                ARStatement      st    = item;
                ARStatementCycle cycle = item;
                Customer         cust  = item;
                HistoryResult    rec   = new HistoryResult
                {
                    StatementCycleId = st.StatementCycleId,
                    StatementDate    = st.StatementDate,
                    Descr            = cycle.Descr,
                    DontPrintCount   = 0,
                    DontEmailCount   = 0,
                    PrintedCount     = 0,
                    EmailedCount     = 0,
                    NoActionCount    = 0
                };

                rec = (HistoryResult)this.History.Cache.Locate(rec) ?? this.History.Insert(rec);
                if (rec != null)
                {
                    if (prevRec != rec)
                    {
                        prevCustomerID = null; prevCuryID = null;
                    }
                    if (prevCustomerID != st.CustomerID || (cust.PrintCuryStatements == true && prevCuryID != st.CuryID))
                    {
                        rec.NumberOfDocuments += 1;
                        rec.DontPrintCount    += st.DontPrint == true ? 1 : 0;
                        rec.DontEmailCount    += st.DontEmail == true ? 1 : 0;
                        rec.NoActionCount     += st.DontEmail == true && st.DontPrint == true ? 1 : 0;
                        rec.PrintedCount      += st.Printed == true ? 1 : 0;
                        rec.EmailedCount      += st.Emailed == true ? 1 : 0;
                    }

                    prevRec        = rec;
                    prevCustomerID = st.CustomerID;
                    prevCuryID     = st.CuryID;
                }
            }

            select.StoreCached(new PXCommandKey(new object[] { header.StartDate, header.EndDate, header.StatementCycleId, header.StatementCycleId }), stored);

            this.History.Cache.IsDirty = false;
            foreach (HistoryResult ret in this.History.Cache.Inserted)
            {
                yield return(ret);
            }
        }
Example #26
0
        public static void ProcessDoc(ARPaymentEntry graph, ARStatementCycle cycle, ARAutoApplyParameters filter)
        {
            List <ARRegister> toRelease = new List <ARRegister>();

            // Build Invoices List
            foreach (Customer customer in
                     PXSelect <Customer,
                               Where <Customer.statementCycleId, Equal <Required <Customer.statementCycleId> >,
                                      And <Match <Required <AccessInfo.userName> > > > >
                     .Select(graph, cycle.StatementCycleId, graph.Accessinfo.UserName))
            {
                List <ARInvoice> arInvoiceList = new List <ARInvoice>();

                foreach (ARInvoice invoice in
                         PXSelect <ARInvoice, Where <ARInvoice.customerID, Equal <Required <ARInvoice.customerID> >,
                                                     And <ARInvoice.released, Equal <boolTrue>,
                                                          And <ARInvoice.openDoc, Equal <boolTrue>,
                                                               And <Where <ARInvoice.docType, Equal <Required <ARInvoice.docType> >,
                                                                           Or <ARInvoice.docType, Equal <Required <ARInvoice.docType> >,
                                                                               Or <ARInvoice.docType, Equal <Required <ARInvoice.docType> > > > > > > > >,
                                   OrderBy <Asc <ARInvoice.dueDate> > >
                         .Select(graph,
                                 customer.BAccountID,
                                 ARDocType.Invoice,
                                 ARDocType.FinCharge,
                                 filter.ApplyCreditMemos == true ? ARDocType.DebitMemo : ARDocType.Invoice))
                {
                    arInvoiceList.Add(invoice);
                }

                arInvoiceList.Sort(new Comparison <ARInvoice>(delegate(ARInvoice a, ARInvoice b)
                {
                    if ((bool)graph.arsetup.Current.FinChargeFirst)
                    {
                        int aSortOrder = (a.DocType == ARDocType.FinCharge ? 0 : 1);
                        int bSortOrder = (b.DocType == ARDocType.FinCharge ? 0 : 1);
                        int ret        = ((IComparable)aSortOrder).CompareTo(bSortOrder);
                        if (ret != 0)
                        {
                            return(ret);
                        }
                    }

                    {
                        object aDueDate = a.DueDate;
                        object bDueDate = b.DueDate;
                        int ret         = ((IComparable)aDueDate).CompareTo(bDueDate);

                        return(ret);
                    }
                }
                                                              ));


                if (arInvoiceList.Count > 0)
                {
                    int invoiceIndex = 0;

                    // this foreach gets all payments [and CreditMemos if applyCreditMemos = true] sorted by docDate
                    foreach (ARPayment payment in
                             PXSelect <ARPayment,
                                       Where <ARPayment.customerID, Equal <Required <ARPayment.customerID> >,
                                              And <ARPayment.released, Equal <boolTrue>,
                                                   And <ARPayment.openDoc, Equal <boolTrue>,
                                                        And <Where <ARPayment.docType, Equal <Required <ARPayment.docType> >,
                                                                    Or <ARPayment.docType, Equal <Required <ARPayment.docType> > > > > > > >,
                                       OrderBy <Asc <ARPayment.docDate> > >
                             .Select(graph,
                                     customer.BAccountID,
                                     ARDocType.Payment,
                                     filter.ApplyCreditMemos == true ? ARDocType.CreditMemo : ARDocType.Payment))
                    {
                        graph.Clear();
                        graph.Document.Current = payment;

                        if (graph.Adjustments.Select().Count == 0)
                        {
                            bool adjustmentAdded = false;
                            while (graph.Document.Current.CuryUnappliedBal > 0)
                            {
                                if (graph.Document.Current.CuryApplAmt == null)
                                {
                                    object curyapplamt = graph.Document.Cache.GetValueExt <ARPayment.curyApplAmt>(graph.Document.Current);
                                    if (curyapplamt is PXFieldState)
                                    {
                                        curyapplamt = ((PXFieldState)curyapplamt).Value;
                                    }
                                    graph.Document.Current.CuryApplAmt = (decimal?)curyapplamt;
                                }
                                graph.Document.Current.AdjDate        = filter.ApplicationDate;
                                graph.Document.Current.AdjFinPeriodID = filter.FinPeriodID;
                                graph.Document.Cache.Update(graph.Document.Current);

                                ARInvoice invoice = arInvoiceList[invoiceIndex];

                                ARAdjust adj = new ARAdjust();
                                adj.AdjdDocType = invoice.DocType;
                                adj.AdjdRefNbr  = invoice.RefNbr;

                                graph.AutoPaymentApp = true;
                                adj = graph.Adjustments.Insert(adj);
                                if (adj == null)
                                {
                                    throw new PXException(PXMessages.LocalizeFormat(Messages.ErrorAutoApply, invoice.DocType, invoice.RefNbr, payment.DocType, payment.RefNbr));
                                }
                                adjustmentAdded = true;
                                if (adj.CuryDocBal <= 0m)
                                {
                                    invoiceIndex++;
                                }
                                if (invoiceIndex >= arInvoiceList.Count)
                                {
                                    break;
                                }
                            }
                            if (adjustmentAdded)
                            {
                                graph.Save.Press();
                                if (filter.ReleaseBatchWhenFinished == true)
                                {
                                    toRelease.Add(graph.Document.Current);
                                }
                            }
                        }
                        if (invoiceIndex >= arInvoiceList.Count)
                        {
                            break;
                        }
                    }
                }
            }

            if (toRelease.Count > 0)
            {
                ARDocumentRelease.ReleaseDoc(toRelease, false);
            }
        }
        protected virtual void GenerateCustomerStatement(ARStatementCycle aCycle, Customer customer, DateTime aStatementDate,
                                                         Dictionary <Tuple <int, string, int, DateTime>, ARStatement> statementsTrace)
        {
            PXSelectBase <Customer>   selectCustomer = new PXSelect <Customer, Where <Customer.statementCycleId, Equal <Required <Customer.statementCycleId> > > >(this);
            PXSelectBase <ARRegister> selectOpenDocs = new PXSelectJoin <ARRegister, LeftJoin <ARInvoice, On <ARInvoice.docType, Equal <ARRegister.docType>,
                                                                                                              And <ARInvoice.refNbr, Equal <ARRegister.refNbr> > > >,
                                                                         Where <ARRegister.customerID, Equal <Required <ARRegister.customerID> >,
                                                                                And <ARRegister.released, Equal <BQLConstants.BitOn>,
                                                                                     And <ARRegister.docDate, LessEqual <Required <ARRegister.docDate> >,
                                                                                          And <Where <ARRegister.openDoc, Equal <BQLConstants.BitOn>,
                                                                                                      Or <ARRegister.statementDate, IsNull> > > > > > >(this);

            PXSelectBase <ARStatementDetail> selectDocsStmDetail = new PXSelect <ARStatementDetail, Where <ARStatementDetail.customerID,
                                                                                                           Equal <Required <ARStatementDetail.customerID> >,
                                                                                                           And <ARStatementDetail.docType, Equal <Required <ARStatementDetail.docType> >,
                                                                                                                And <ARStatementDetail.refNbr, Equal <Required <ARStatementDetail.refNbr> > > > >, OrderBy <Asc <ARStatementDetail.statementDate> > >(this);

            PXSelectBase <ARStatement> selectAllPreviousByCustomer = new PXSelect <ARStatement,
                                                                                   Where <ARStatement.customerID, Equal <Required <ARStatement.customerID> > >,
                                                                                   OrderBy <Asc <ARStatement.curyID, Desc <ARStatement.statementDate> > > >(this);

            PXSelectBase <ARStatement> selectPreviousStatement = new PXSelect <ARStatement,
                                                                               Where <ARStatement.branchID, Equal <Required <ARStatement.branchID> >,
                                                                                      And <ARStatement.customerID, Equal <Required <ARStatement.customerID> >,
                                                                                           And <ARStatement.curyID, Equal <Required <ARStatement.curyID> > > > >,
                                                                               OrderBy <Desc <ARStatement.statementDate> > >(this);

            bool ageCredits = (this.ARSetup.Current.AgeCredits ?? false);

            Dictionary <StatementKey, ARStatement> statements = new Dictionary <StatementKey, ARStatement>();
            List <ARStatementDetail> details = new List <ARStatementDetail>();

            foreach (PXResult <ARRegister, ARInvoice> iDoc in selectOpenDocs.Select(customer.BAccountID, aStatementDate))
            {
                ARStatement       header          = null;
                ARRegister        doc             = (ARRegister)iDoc;
                ARInvoice         inv             = (ARInvoice)iDoc;
                ARStatementDetail statementDetail = (ARStatementDetail)selectDocsStmDetail.Select(doc.CustomerID, doc.DocType, doc.RefNbr);
                bool         isNewDoc             = (statementDetail == null);
                StatementKey key = new StatementKey(doc.BranchID.Value, doc.CuryID);

                if (IsMultipleInstallmentMaster(inv))
                {
                    continue; //Skip invoice, which is the first in multiple installments sequence (master)
                }
                if (!statements.ContainsKey(key))
                {
                    header = new ARStatement();
                    Clear(header);
                    Copy(header, customer);
                    Copy(header, aCycle);
                    Copy(header, doc);
                    header.StatementDate = aStatementDate;

                    ARStatement trace    = null;
                    bool        gotTrace = statementsTrace.TryGetValue(new Tuple <int, string, int, DateTime>(header.BranchID.Value, header.CuryID, header.CustomerID.Value, header.StatementDate.Value), out trace);
                    if (gotTrace)
                    {
                        header.PrevPrintedCnt = trace.PrevPrintedCnt;
                        header.PrevEmailedCnt = trace.PrevEmailedCnt;
                    }
                    statements[key] = header;
                }
                else
                {
                    header = statements[key];
                }

                ARStatementDetail det = new ARStatementDetail();
                Copy(det, header);
                Copy(det, doc);

                if (doc.DocType != AR.ARDocType.CashSale && doc.DocType != AR.ARDocType.CashReturn)
                {
                    Accumulate(header, (doc.Payable == true ? inv : doc), aCycle, isNewDoc, ageCredits);
                }

                details.Add(det);
            }

            //Merge with previous statements - is needed for Balance Brought Forward
            Dictionary <StatementKey, DateTime> lastCuryStatement = new Dictionary <StatementKey, DateTime>();

            foreach (ARStatement iPrev in selectAllPreviousByCustomer.Select(customer.BAccountID))
            {
                ARStatement  header = null;
                StatementKey key    = new StatementKey(iPrev.BranchID.Value, iPrev.CuryID);
                if (lastCuryStatement.ContainsKey(key) && lastCuryStatement[key] > iPrev.StatementDate)
                {
                    continue;
                }

                if (!statements.ContainsKey(key))
                {
                    header = new ARStatement();
                    Clear(header);
                    header.BranchID      = iPrev.BranchID;
                    header.CuryID        = iPrev.CuryID;
                    header.CustomerID    = iPrev.CustomerID;
                    header.StatementDate = aStatementDate;
                    Copy(header, customer);
                    Copy(header, aCycle);
                    statements[key] = header;
                }
                else
                {
                    header = statements[key];
                }

                header.BegBalance     = iPrev.EndBalance;
                header.CuryBegBalance = iPrev.CuryEndBalance;
                Recalculate(header);
                lastCuryStatement[key] = iPrev.StatementDate.Value;
            }

            foreach (ARStatement iH in statements.Values)
            {
                ARStatement prev = selectPreviousStatement.Select(iH.CustomerID, iH.BranchID, iH.CuryID);
                if (prev != null)
                {
                    iH.BegBalance     = prev.EndBalance;
                    iH.CuryBegBalance = prev.CuryEndBalance;
                }

                ApplyFIFORule(iH, ageCredits);
            }

            PersistStatement(customer.BAccountID, aStatementDate, statements.Values, details);
        }
Example #28
0
		public static void ProcessDoc(ARPaymentEntry graph, ARStatementCycle cycle, ARAutoApplyParameters filter)
		{
			List<ARRegister> toRelease = new List<ARRegister>();

			HashSet<string> trace = new HashSet<string>();
			string warningRefNbr = String.Empty;

			int?[] branches = PXAccess.GetBranchIDs().Select(i => (int?)i).ToArray<int?>();

			foreach (Customer customer in GetCustomersForAutoApplication(graph, cycle, filter))
			{
				List<ARInvoice> arInvoiceList = new List<ARInvoice>();

				var invoiceQuery = new PXSelectJoin<ARInvoice,
					InnerJoin<Customer, On<ARInvoice.customerID, Equal<Customer.bAccountID>>>,
					Where<ARInvoice.released, Equal<True>,
						And<ARInvoice.openDoc, Equal<True>,
						And<ARInvoice.pendingPPD, NotEqual<True>, 
						And<Where<ARInvoice.docType, Equal<ARDocType.invoice>,
							Or<ARInvoice.docType, Equal<ARDocType.finCharge>,
							Or<ARInvoice.docType, Equal<ARDocType.debitMemo>>>>>>>>,
					OrderBy<Asc<ARInvoice.dueDate>>>(graph);

				if(filter.LoadChildDocuments == LoadChildDocumentsOptions.None || customer.ParentBAccountID != null)
				{
					invoiceQuery.WhereAnd<Where<Customer.bAccountID, Equal<Required<ARInvoice.customerID>>>>();
				}
				else
				{
					invoiceQuery.WhereAnd<Where<Customer.consolidatingBAccountID, Equal<Required<ARInvoice.customerID>>>>();
				}

				PXResultset<ARInvoice> invoices;
				using (new PXReadBranchRestrictedScope(null, branches, true, false))
				{
					invoices = invoiceQuery.Select(customer.BAccountID);
				}

				foreach (ARInvoice invoice in invoices)
				{
					arInvoiceList.Add(invoice);
				}

				arInvoiceList.Sort(new Comparison<ARInvoice>(delegate(ARInvoice a, ARInvoice b)
					{
						if ((bool)graph.arsetup.Current.FinChargeFirst)
						{
							int aSortOrder = (a.DocType == ARDocType.FinCharge ? 0 : 1);
							int bSortOrder = (b.DocType == ARDocType.FinCharge ? 0 : 1);
							int ret = ((IComparable)aSortOrder).CompareTo(bSortOrder);
							if (ret != 0)
							{
								return ret;
							}
						}

						{
							object aDueDate = a.DueDate;
							object bDueDate = b.DueDate;
							int ret = ((IComparable)aDueDate).CompareTo(bDueDate);

							return ret;
						}
					}
				));

				if (arInvoiceList.Count > 0)
				{
					PXSelectBase<ARPayment> getPaymentsQuery =
						new PXSelectJoin<ARPayment,
								InnerJoin<Branch,
									On<ARPayment.branchID, Equal<Branch.branchID>>,
								InnerJoin<OrganizationFinPeriod,
									On<Branch.organizationID, Equal<OrganizationFinPeriod.organizationID>,
										And<OrganizationFinPeriod.finPeriodID, Equal<Required<OrganizationFinPeriod.finPeriodID>>>>>>,
								Where<
									OrganizationFinPeriod.status, NotEqual<FinPeriod.status.locked>,
									And<OrganizationFinPeriod.status, NotEqual<FinPeriod.status.inactive>,
									And<ARPayment.released, Equal<True>,
									And<ARPayment.openDoc, Equal<True>,
									And<ARPayment.customerID, Equal<Required<ARPayment.customerID>>,
									And2<Not<HasUnreleasedVoidPayment<ARPayment.docType, ARPayment.refNbr>>,
									And<Where<
											ARPayment.docType, Equal<ARDocType.payment>,
											Or<ARPayment.docType, Equal<ARDocType.prepayment>,
											Or<ARPayment.docType, Equal<Required<ARPayment.docType>>>>>>>>>>>>,
								OrderBy<
									Asc<ARPayment.docDate>>>(graph);

					if (!graph.FinPeriodUtils.CanPostToClosedPeriod())
					{
						getPaymentsQuery.WhereAnd<Where<OrganizationFinPeriod.status, NotEqual<FinPeriod.status.closed>>>();
					}

					foreach (ARPayment payment in 
						getPaymentsQuery.Select(filter.FinPeriodID,
												customer.BAccountID,
												filter.ApplyCreditMemos == true ? ARDocType.CreditMemo : ARDocType.Payment))
					{
						ApplyPayment(graph, filter, payment, arInvoiceList, toRelease, out warningRefNbr);
						trace.Add(warningRefNbr);
					}
				}

				var remainingParentInvoices = arInvoiceList.Where(inv => inv.CustomerID == customer.BAccountID).ToList();

				if (remainingParentInvoices.Count > 0
					&& filter.ApplyCreditMemos == true 
					&& filter.LoadChildDocuments == LoadChildDocumentsOptions.IncludeCRM)
				{
					PXSelectBase<ARPayment> getCreditMemosQuery =
						new PXSelectJoin<ARPayment,
							InnerJoin<Customer, 
								On<ARPayment.customerID, Equal<Customer.bAccountID>>,
							InnerJoin<Branch,
								On<ARPayment.branchID, Equal<Branch.branchID>>,
							InnerJoin<OrganizationFinPeriod,
								On<Branch.organizationID, Equal<OrganizationFinPeriod.organizationID>,
									And<OrganizationFinPeriod.finPeriodID, Equal<Required<OrganizationFinPeriod.finPeriodID>>>>>>>,
							Where<
								OrganizationFinPeriod.status, NotEqual<FinPeriod.status.locked>,
								And<OrganizationFinPeriod.status, NotEqual<FinPeriod.status.inactive>,
								And<ARPayment.released, Equal<True>,
								And<ARPayment.openDoc, Equal<True>,
								And<Customer.consolidatingBAccountID, Equal<Required<Customer.consolidatingBAccountID>>,
								And<ARPayment.docType, Equal<ARDocType.creditMemo>,
								And<Not<HasUnreleasedVoidPayment<ARPayment.docType, ARPayment.refNbr>>>>>>>>>,
							OrderBy<
								Asc<ARPayment.docDate>>>(graph);

					if (!graph.FinPeriodUtils.CanPostToClosedPeriod())
					{
						getCreditMemosQuery.WhereAnd<Where<OrganizationFinPeriod.status, NotEqual<FinPeriod.status.closed>>>();
					}

					foreach (ARPayment payment in 
						getCreditMemosQuery.Select(filter.FinPeriodID, customer.BAccountID))
					{
						ApplyPayment(graph, filter, payment, remainingParentInvoices, toRelease, out warningRefNbr);
						trace.Add(warningRefNbr);
					}
				}
			}

			if (trace != null && trace.Count != 0)
			{
				PXTrace.WriteWarning(String.Format(Messages.FuturePayments, trace.Where(x => !x.IsNullOrEmpty()).JoinToString("; ")));
				trace.Clear();
			}

			if (toRelease.Count > 0)
			{
				ARDocumentRelease.ReleaseDoc(toRelease, false);
			}
		}
        public virtual void ARStatementCycle_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            if (e.Row == null)
            {
                return;
            }

            ARStatementCycle row = (ARStatementCycle)e.Row;

            if (row.NextStmtDate.HasValue == false)
            {
                DateTime basisDate = row.LastStmtDate.HasValue? row.LastStmtDate.Value: Accessinfo.BusinessDate.HasValue? Accessinfo.BusinessDate.Value: DateTime.Now;
                row.NextStmtDate = CalcNextStatementDate(basisDate, row.PrepareOn, row.Day00, row.Day01);
            }
            ARSetup setup = this.ARSetup.Select();

            cache.GetAttributes(e.Row, null);
            if (setup.DefFinChargeFromCycle ?? false)
            {
                bool?hasOverdueInvoices    = null;
                bool hasUnAppliedPayments  = false;
                bool hasChargeableInvoices = false;
                if (row.RequirePaymentApplication ?? false)
                {
                    hasOverdueInvoices = CheckForOverdueInvoices(this, row.StatementCycleId, row.NextStmtDate.Value);
                    if (hasOverdueInvoices.Value)
                    {
                        if (CheckForOpenPayments(this, row.StatementCycleId))
                        {
                            hasUnAppliedPayments = true;
                        }
                    }
                }

                if ((row.FinChargeApply ?? false) && (row.RequireFinChargeProcessing ?? false))
                {
                    if (!hasOverdueInvoices.HasValue)
                    {
                        hasOverdueInvoices = CheckForOverdueInvoices(this, row.StatementCycleId, row.NextStmtDate.Value);
                    }
                    if (hasOverdueInvoices.Value &&
                        (!row.LastFinChrgDate.HasValue || row.LastFinChrgDate.Value < row.NextStmtDate.Value))
                    {
                        hasChargeableInvoices = true;
                    }
                }
                if (hasChargeableInvoices && hasUnAppliedPayments)
                {
                    this.CyclesList.Cache.RaiseExceptionHandling <ARStatementCycle.statementCycleId>(row, row.StatementCycleId,
                                                                                                     new PXSetPropertyException(Messages.WRN_ProcessStatementDetectsOverdueInvoicesAndUnappliedPayments, PXErrorLevel.RowWarning));
                }
                else
                {
                    if (hasChargeableInvoices)
                    {
                        this.CyclesList.Cache.RaiseExceptionHandling <ARStatementCycle.statementCycleId>(row, row.StatementCycleId,
                                                                                                         new PXSetPropertyException(Messages.WRN_ProcessStatementDetectsOverdueInvoices, PXErrorLevel.RowWarning));
                    }

                    if (hasUnAppliedPayments)
                    {
                        this.CyclesList.Cache.RaiseExceptionHandling <ARStatementCycle.statementCycleId>(row, row.StatementCycleId,
                                                                                                         new PXSetPropertyException(Messages.WRN_ProcessStatementDetectsUnappliedPayments, PXErrorLevel.RowWarning));
                    }
                }
            }
        }
        public static void ProcessDoc(ARPaymentEntry graph, ARStatementCycle cycle, ARAutoApplyParameters filter)
        {
            List <ARRegister> toRelease = new List <ARRegister>();

            foreach (Customer customer in GetCustomersForAutoApplication(graph, cycle, filter))
            {
                List <ARInvoice> arInvoiceList = new List <ARInvoice>();

                var invoiceQuery = new PXSelectJoin <ARInvoice,
                                                     InnerJoin <Customer, On <ARInvoice.customerID, Equal <Customer.bAccountID> > >,
                                                     Where <ARInvoice.released, Equal <True>,
                                                            And <ARInvoice.openDoc, Equal <True>,
                                                                 And <ARInvoice.pendingPPD, NotEqual <True>,
                                                                      And <Where <ARInvoice.docType, Equal <ARDocType.invoice>,
                                                                                  Or <ARInvoice.docType, Equal <ARDocType.finCharge>,
                                                                                      Or <ARInvoice.docType, Equal <ARDocType.debitMemo> > > > > > > >,
                                                     OrderBy <Asc <ARInvoice.dueDate> > >(graph);

                if (filter.LoadChildDocuments == LoadChildDocumentsOptions.None || customer.ParentBAccountID != null)
                {
                    invoiceQuery.WhereAnd <Where <Customer.bAccountID, Equal <Required <ARInvoice.customerID> > > >();
                }
                else
                {
                    invoiceQuery.WhereAnd <Where <Customer.consolidatingBAccountID, Equal <Required <ARInvoice.customerID> > > >();
                }

                foreach (ARInvoice invoice in invoiceQuery.Select(
                             customer.BAccountID))
                {
                    arInvoiceList.Add(invoice);
                }

                arInvoiceList.Sort(new Comparison <ARInvoice>(delegate(ARInvoice a, ARInvoice b)
                {
                    if ((bool)graph.arsetup.Current.FinChargeFirst)
                    {
                        int aSortOrder = (a.DocType == ARDocType.FinCharge ? 0 : 1);
                        int bSortOrder = (b.DocType == ARDocType.FinCharge ? 0 : 1);
                        int ret        = ((IComparable)aSortOrder).CompareTo(bSortOrder);
                        if (ret != 0)
                        {
                            return(ret);
                        }
                    }

                    {
                        object aDueDate = a.DueDate;
                        object bDueDate = b.DueDate;
                        int ret         = ((IComparable)aDueDate).CompareTo(bDueDate);

                        return(ret);
                    }
                }
                                                              ));


                if (arInvoiceList.Count > 0)
                {
                    foreach (ARPayment payment in PXSelect <ARPayment,
                                                            Where <ARPayment.released, Equal <True>,
                                                                   And <ARPayment.openDoc, Equal <True>,
                                                                        And <ARPayment.customerID, Equal <Required <ARPayment.customerID> >,
                                                                             And <Where <ARPayment.docType, Equal <ARDocType.payment>,
                                                                                         Or <ARPayment.docType, Equal <ARDocType.prepayment>,
                                                                                             Or <ARPayment.docType, Equal <Required <ARPayment.docType> > > > > > > > >,
                                                            OrderBy <Asc <ARPayment.docDate> > > .Select(graph,
                                                                                                         customer.BAccountID,
                                                                                                         filter.ApplyCreditMemos == true ? ARDocType.CreditMemo : ARDocType.Payment))
                    {
                        ApplyPayment(graph, filter, payment, arInvoiceList, toRelease);
                    }
                }

                var remainingParentInvoices = arInvoiceList.Where(inv => inv.CustomerID == customer.BAccountID).ToList();

                if (remainingParentInvoices.Count > 0 &&
                    filter.ApplyCreditMemos == true && filter.LoadChildDocuments == LoadChildDocumentsOptions.IncludeCRM)
                {
                    foreach (ARPayment payment in PXSelectJoin <ARPayment,
                                                                InnerJoin <Customer, On <ARPayment.customerID, Equal <Customer.bAccountID> > >,
                                                                Where <ARPayment.released, Equal <True>,
                                                                       And <ARPayment.openDoc, Equal <True>,
                                                                            And <Customer.consolidatingBAccountID, Equal <Required <Customer.consolidatingBAccountID> >,
                                                                                 And <ARPayment.docType, Equal <ARDocType.creditMemo> > > > >,
                                                                OrderBy <Asc <ARPayment.docDate> > > .Select(graph, customer.BAccountID))
                    {
                        ApplyPayment(graph, filter, payment, remainingParentInvoices, toRelease);
                    }
                }
            }

            if (toRelease.Count > 0)
            {
                ARDocumentRelease.ReleaseDoc(toRelease, false);
            }
        }