protected virtual void PMProject_RowInserted(PXCache sender, PXRowInsertedEventArgs e)
        {
            PMProject row = e.Row as PMProject;

            if (row == null)
            {
                return;
            }
            ContractBillingSchedule schedule = new ContractBillingSchedule {
                ContractID = row.ContractID
            };

            Billing.Insert(schedule);
            Billing.Cache.IsDirty = false;
        }
Exemplo n.º 2
0
        protected virtual ProjectsList CreateListItem(PXResult item)
        {
            PMProject project = PXResult.Unwrap <PMProject>(item);
            ContractBillingSchedule schedule = PXResult.Unwrap <ContractBillingSchedule>(item);
            Customer customer = PXResult.Unwrap <Customer>(item);

            ProjectsList result = new ProjectsList();

            result.ProjectID   = project.ContractID;
            result.ProjectCD   = project.ContractCD;
            result.Description = project.Description;
            result.CustomerID  = project.CustomerID;
            result.LastDate    = schedule.LastDate;

            DateTime?fromDate = null;

            if (schedule.NextDate != null)
            {
                switch (schedule.Type)
                {
                case BillingType.Annual:
                    fromDate = schedule.NextDate.Value.AddYears(-1);
                    break;

                case BillingType.Monthly:
                    fromDate = schedule.NextDate.Value.AddMonths(-1);
                    break;

                case BillingType.Weekly:
                    fromDate = schedule.NextDate.Value.AddDays(-7);
                    break;

                case BillingType.Quarterly:
                    fromDate = schedule.NextDate.Value.AddMonths(-3);
                    break;
                }
            }

            result.FromDate = fromDate;
            result.NextDate = schedule.NextDate;

            return(result);
        }
Exemplo n.º 3
0
        protected ContractProcessing(int? contractID)
        {
            if (contractID > 0)
            {
                this.graph = PXGraph.CreateInstance<ARInvoiceEntry>();
                graph.FieldVerifying.AddHandler<ARInvoice.projectID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });
                this.contract = PXSelect<Contract, Where<Contract.contractID, Equal<Required<Contract.contractID>>>>.Select(graph, contractID);

                this.insetup = PXSelect<INSetup>.Select(graph);
                this.template = PXSelect<Contract, Where<Contract.contractID, Equal<Required<Contract.contractID>>>>.Select(graph, contract.TemplateID);
                this.schedule = PXSelect<ContractBillingSchedule>.Search<ContractBillingSchedule.contractID>(graph, contract.ContractID);
                if (contract.CustomerID != null)
                {
                    if (schedule != null && schedule.AccountID != null)
                    {
                        customer = PXSelect<Customer, Where<Customer.bAccountID, Equal<Required<ContractBillingSchedule.accountID>>>>.Select(graph, schedule.AccountID);
                        if (schedule.LocationID != null)
                        {
                            location = PXSelect<Location, Where<Location.bAccountID, Equal<Required<ContractBillingSchedule.accountID>>, And<Location.locationID, Equal<Required<ContractBillingSchedule.locationID>>>>>.Select(graph, customer.BAccountID, schedule.LocationID);
                        }
                        else
                        {
                            location = PXSelect<Location, Where<Location.locationID, Equal<Required<Customer.defLocationID>>>>.Select(graph, customer.DefLocationID);
                        }
                    }
                    else
                    {
                        customer = PXSelect<Customer, Where<Customer.bAccountID, Equal<Required<Customer.bAccountID>>>>.Select(graph, contract.CustomerID);
                        if (contract.LocationID != null)
                        {
                            location = PXSelect<Location, Where<Location.bAccountID, Equal<Required<ContractBillingSchedule.accountID>>, And<Location.locationID, Equal<Required<ContractBillingSchedule.locationID>>>>>.Select(graph, customer.BAccountID, contract.LocationID);
                        }
                        else
                        {
                            location = PXSelect<Location, Where<Location.locationID, Equal<Required<Customer.defLocationID>>>>.Select(graph, customer.DefLocationID);
                        }
                    }
                }

                SetupGraph();
            }
        }
Exemplo n.º 4
0
        protected virtual List <PMTran> ReverseWipTask(PMTask task, PMBillingRule rule, DateTime billingDate)
        {
            List <PMTran> list = new List <PMTran>();

            //usage:
            PXSelectBase <PMTran> select = new PXSelect <PMTran,
                                                         Where <PMTran.projectID, Equal <Required <PMTran.projectID> >,
                                                                And <PMTran.taskID, Equal <Required <PMTran.taskID> >,
                                                                     And <PMTran.accountGroupID, Equal <Required <PMTran.accountGroupID> >,
                                                                          And <PMTran.date, Less <Required <PMTran.date> >,
                                                                               And <PMTran.billed, Equal <False>,
                                                                                    And <PMTran.released, Equal <True>,
                                                                                         And <PMTran.reversed, Equal <False> > > > > > > > >(this);

            DateTime cuttofDate = billingDate;            //all transactions  excluding the current day.
            ContractBillingSchedule schedule = PXSelect <ContractBillingSchedule> .Search <ContractBillingSchedule.contractID>(this, task.ProjectID);

            if (schedule != null && schedule.Type == BillingType.OnDemand)
            {
                cuttofDate = billingDate.AddDays(1);                //all transactions including the current day.
            }
            else
            {
                if (IncludeTodaysTransactions)
                {
                    cuttofDate = billingDate.AddDays(1);
                }
            }

            foreach (PMTran tran in select.Select(task.ProjectID, task.TaskID, rule.WipAccountGroupID, cuttofDate))
            {
                list.AddRange(ReverseTran(tran));

                tran.Billed     = true;
                tran.BilledDate = billingDate;

                Transactions.Update(tran);
            }

            return(list);
        }
Exemplo n.º 5
0
        public static DateTime?GetNextBillingDate(PXGraph graph, ContractBillingSchedule schedule, DateTime?date)
        {
            switch (schedule.Type)
            {
            case BillingType.Annual:
                return(date.Value.AddYears(1));

            case BillingType.Monthly:
                return(date.Value.AddMonths(1));

            case BillingType.Weekly:
                return(date.Value.AddDays(7));

            case BillingType.Quarterly:
                return(date.Value.AddMonths(3));

            case BillingType.OnDemand:
                return(null);

            default:
                throw new ArgumentException("Invalid Schedule type", "schedule");
            }
        }
Exemplo n.º 6
0
        public virtual bool Bill(int?projectID, DateTime?invoiceDate)
        {
            PMProject project = PXSelect <PMProject, Where <PMProject.contractID, Equal <Required <PMProject.contractID> > > > .Select(this, projectID);

            ContractBillingSchedule schedule = PXSelect <ContractBillingSchedule> .Search <ContractBillingSchedule.contractID>(this, project.ContractID);

            DateTime billingDate;

            if (invoiceDate == null)
            {
                if (schedule.Type == BillingType.OnDemand)
                {
                    billingDate = Accessinfo.BusinessDate ?? DateTime.Now;
                }
                else
                {
                    billingDate = schedule.NextDate.Value;
                }
            }
            else
            {
                billingDate = invoiceDate.Value;
            }

            Customer customer = null;

            if (project.CustomerID != null)
            {
                customer = PXSelect <Customer, Where <Customer.bAccountID, Equal <Required <Customer.bAccountID> > > > .Select(this, project.CustomerID);
            }

            if (customer == null)
            {
                throw new PXException(Messages.NoCustomer);
            }

            List <BillingData> list          = new List <BillingData>();
            List <PMTran>      reversalTrans = new List <PMTran>();

            PXSelectBase <PMTask> selectTasks = new PXSelect <PMTask,
                                                              Where <PMTask.projectID, Equal <Required <PMTask.projectID> >,
                                                                     And <PMTask.billingID, IsNotNull,
                                                                          And <PMTask.isActive, Equal <True> > > > >(this);

            foreach (PMTask task in selectTasks.Select(project.ContractID))
            {
                if ((task.BillingOption == PMBillingOption.OnTaskCompletion && task.IsCompleted == true) ||
                    (task.BillingOption == PMBillingOption.OnProjectCompetion && project.IsCompleted == true) ||
                    task.BillingOption == PMBillingOption.OnBilling)
                {
                    list.AddRange(BillTask(task, billingDate));
                    reversalTrans.AddRange(ReverseWipTask(task, billingDate));
                }
            }

            //Regroup by Invoices:
            Dictionary <string, List <BillingData> > invoices = new Dictionary <string, List <BillingData> >();
            string emptyInvoiceDescriptionKey = "!@#$%^&";

            foreach (BillingData data in list)
            {
                if (string.IsNullOrEmpty(data.Rule.InvoiceDescription))
                {
                    if (invoices.ContainsKey(emptyInvoiceDescriptionKey))
                    {
                        invoices[emptyInvoiceDescriptionKey].Add(data);
                    }
                    else
                    {
                        invoices.Add(emptyInvoiceDescriptionKey, new List <BillingData>(new BillingData[] { data }));
                    }
                }
                else
                {
                    if (invoices.ContainsKey(data.Rule.InvoiceDescription))
                    {
                        invoices[data.Rule.InvoiceDescription].Add(data);
                    }
                    else
                    {
                        invoices.Add(data.Rule.InvoiceDescription, new List <BillingData>(new BillingData[] { data }));
                    }
                }

                //Reverse On Billing:

                if (data.PMTran != null)
                {
                    bool reverseOnBilling = false;

                    if (data.PMTran.Reverse == PMReverse.OnBilling)
                    {
                        reverseOnBilling = true;
                    }
                    else if (data.PMTran.Reverse != PMReverse.Never && IsNonGL(data.PMTran))
                    {
                        reverseOnBilling = true;
                    }

                    if (reverseOnBilling)
                    {
                        reversalTrans.AddRange(ReverseTran(data.PMTran));
                    }
                }
            }


            //Schedule update:
            schedule.NextDate = GetNextBillingDate(this, schedule, schedule.NextDate);
            schedule.LastDate = this.Accessinfo.BusinessDate;
            BillingSchedule.Update(schedule);


            //ContractDetail update:
            PXSelectBase <ContractDetailExt> cis = new PXSelect <ContractDetailExt, Where <ContractDetailExt.contractID, Equal <Required <ContractDetailExt.contractID> >,
                                                                                           And <ContractDetailExt.resetUsage, Equal <ResetUsageOption.onBilling> > > >(this);

            foreach (ContractDetailExt ci in cis.Select(project.ContractID))
            {
                ci.Used = 0;
                ContractDetail.Update(ci);
            }

            List <ARRegister> doclist     = new List <ARRegister>();
            PMRegister        reversalDoc = null;

            if (invoices.Count > 0)
            {
                using (PXTransactionScope ts = new PXTransactionScope())
                {
                    ARInvoiceEntry invoiceEntry = PXGraph.CreateInstance <ARInvoiceEntry>();
                    invoiceEntry.FieldVerifying.AddHandler <ARInvoice.projectID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });
                    invoiceEntry.FieldVerifying.AddHandler <ARTran.projectID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });
                    invoiceEntry.FieldVerifying.AddHandler <ARTran.taskID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });

                    foreach (KeyValuePair <string, List <BillingData> > kv in invoices)
                    {
                        invoiceEntry.Clear(PXClearOption.ClearAll);

                        string    description = kv.Key == emptyInvoiceDescriptionKey ? null : kv.Key;
                        string    docDesc     = description ?? string.Format(PXMessages.LocalizeNoPrefix(CT.Messages.BillingFor), project.ContractCD, project.Description);
                        ARInvoice invoice     = (ARInvoice)invoiceEntry.Caches[typeof(ARInvoice)].CreateInstance();
                        invoice.DocType = GetDocType(kv.Value);
                        int mult = 1;
                        if (invoice.DocType == ARDocType.CreditMemo)
                        {
                            mult = -1;
                        }

                        invoice = (ARInvoice)invoiceEntry.Caches[typeof(ARInvoice)].Insert(invoice);
                        invoiceEntry.Caches[typeof(ARInvoice)].SetValueExt <ARInvoice.customerID>(invoice, customer.AcctCD);
                        invoiceEntry.Caches[typeof(ARInvoice)].SetValue <ARInvoice.customerLocationID>(invoice, project.LocationID);
                        invoiceEntry.Caches[typeof(ARInvoice)].SetValueExt <ARInvoice.docDate>(invoice, billingDate);
                        invoiceEntry.Caches[typeof(ARInvoice)].SetValue <ARInvoice.docDesc>(invoice, docDesc);
                        invoiceEntry.Caches[typeof(ARInvoice)].SetValue <ARInvoice.projectID>(invoice, project.ContractID);

                        CurrencyInfo curyinfo = (CurrencyInfo)invoiceEntry.Caches[typeof(CurrencyInfo)].Current;
                        foreach (BillingData data in kv.Value)
                        {
                            data.Tran.ExtPrice = data.Tran.ExtPrice.GetValueOrDefault() * mult;
                            data.Tran.Qty      = data.Tran.Qty.GetValueOrDefault() * mult;
                            data.Tran.TranAmt  = data.Tran.TranAmt.GetValueOrDefault() * mult;

                            decimal curyamount;
                            PXDBCurrencyAttribute.CuryConvCury(invoiceEntry.Caches[typeof(CurrencyInfo)], curyinfo, data.Tran.UnitPrice.GetValueOrDefault(), out curyamount);
                            data.Tran.CuryUnitPrice = curyamount;
                            PXDBCurrencyAttribute.CuryConvCury(invoiceEntry.Caches[typeof(CurrencyInfo)], curyinfo, data.Tran.ExtPrice.GetValueOrDefault(), out curyamount);
                            data.Tran.CuryExtPrice     = curyamount;
                            data.Tran.CuryTranAmt      = data.Tran.CuryExtPrice;
                            data.Tran.FreezeManualDisc = true;
                            data.Tran.CuryInfoID       = curyinfo.CuryInfoID;
                            ARTran newTran = (ARTran)invoiceEntry.Caches[typeof(ARTran)].Insert(data.Tran);

                            if (data.Tran.TranAmt > newTran.TranAmt)
                            {
                                newTran.PMDeltaOption = ARTran.pMDeltaOption.CompleteLine;                                //autocomplete when currency descrepency exists.
                            }

                            if (data.Tran.AccountID != null)
                            {
                                ARTran copy = (ARTran)invoiceEntry.Caches[typeof(ARTran)].CreateCopy(newTran);
                                copy.AccountID = data.Tran.AccountID;

                                copy = (ARTran)invoiceEntry.Caches[typeof(ARTran)].Update(copy);

                                if (data.SubCD != null)
                                {
                                    invoiceEntry.Caches[typeof(ARTran)].SetValueExt <ARTran.subID>(copy, data.SubCD);
                                }
                            }

                            if (data.Note != null)
                            {
                                PXNoteAttribute.SetNote(invoiceEntry.Caches[typeof(ARTran)], newTran, data.Note);
                            }
                            if (data.Files != null && data.Files.Length > 0)
                            {
                                PXNoteAttribute.SetFileNotes(invoiceEntry.Caches[typeof(ARTran)], newTran, data.Files);
                            }


                            //item.RefLineNbr = newTran.LineNbr;
                        }

                        ARInvoice oldInvoice = (ARInvoice)invoiceEntry.Caches[typeof(ARInvoice)].CreateCopy(invoice);

                        invoice.CuryOrigDocAmt = invoice.CuryDocBal;
                        invoiceEntry.Caches[typeof(ARInvoice)].RaiseRowUpdated(invoice, oldInvoice);
                        invoiceEntry.Caches[typeof(ARInvoice)].SetValue <ARInvoice.curyOrigDocAmt>(invoice, invoice.CuryDocBal);

                        if (project.AutomaticReleaseAR == true)
                        {
                            invoiceEntry.Caches[typeof(ARInvoice)].SetValueExt <ARInvoice.hold>(invoice, false);
                        }

                        doclist.Add((ARInvoice)invoiceEntry.Caches[typeof(ARInvoice)].Current);
                        invoiceEntry.Save.Press();
                    }

                    Actions.PressSave();

                    if (reversalTrans.Count > 0)
                    {
                        RegisterEntry pmEntry = PXGraph.CreateInstance <RegisterEntry>();
                        pmEntry.FieldVerifying.AddHandler <PMTran.projectID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });                    //Project can be completed.
                        pmEntry.FieldVerifying.AddHandler <PMTran.taskID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });                       //Task can be completed.
                        pmEntry.FieldVerifying.AddHandler <PMTran.inventoryID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });
                        reversalDoc              = (PMRegister)pmEntry.Document.Cache.Insert();
                        reversalDoc.OrigDocType  = PMOrigDocType.AllocationReversal;
                        reversalDoc.Description  = "Allocation Reversal on Billing";
                        pmEntry.Document.Current = reversalDoc;

                        foreach (PMTran tran in reversalTrans)
                        {
                            pmEntry.Transactions.Insert(tran);
                        }
                        pmEntry.Save.Press();
                    }

                    ts.Complete();
                }
            }
            else
            {
                this.Persist(typeof(ContractBillingSchedule), PXDBOperation.Update);
                this.Persist(typeof(Contract), PXDBOperation.Update);
            }

            if (project.AutomaticReleaseAR == true)
            {
                try
                {
                    ARDocumentRelease.ReleaseDoc(doclist, false);
                }
                catch (Exception ex)
                {
                    throw new PXException(Messages.AutoReleaseARFailed, ex);
                }

                if (reversalDoc != null)
                {
                    try
                    {
                        RegisterRelease.Release(reversalDoc);
                    }
                    catch (Exception ex)
                    {
                        throw new PXException(Messages.AutoReleaseOfReversalFailed, ex);
                    }
                }
            }

            return(doclist.Count > 0);
        }
Exemplo n.º 7
0
        protected virtual List <BillingData> BillTask(PMTask task, PMBillingRule rule, DateTime billingDate)
        {
            PMProject project = PXSelect <PMProject, Where <PMProject.contractID, Equal <Required <PMProject.contractID> > > > .Select(this, task.ProjectID);

            Customer customer = PXSelect <Customer, Where <Customer.bAccountID, Equal <Required <Customer.bAccountID> > > > .Select(this, project.CustomerID);

            List <BillingData>               list         = new List <BillingData>();
            Dictionary <int, decimal>        availableQty = new Dictionary <int, decimal>();
            Dictionary <int, ContractDetail> billingItems = new Dictionary <int, ContractDetail>();

            //recurent Billing:
            PXSelectBase <ContractDetail> selectBilling = new PXSelect <ContractDetail,
                                                                        Where <ContractDetail.contractID, Equal <Required <ContractDetail.contractID> >,
                                                                               And <ContractDetail.taskID, Equal <Required <ContractDetail.taskID> > > > >(this);

            foreach (ContractDetail billing in selectBilling.Select(task.ProjectID, task.TaskID))
            {
                billingItems.Add(billing.InventoryID.Value, billing);

                if (billing.Included > 0)
                {
                    if (billing.ResetUsage == ResetUsageOption.OnBilling)
                    {
                        availableQty.Add(billing.InventoryID.Value, billing.Included.Value);
                    }
                    else
                    {
                        decimal qtyLeft = billing.Included.Value - billing.LastBilledQty ?? 0;

                        if (qtyLeft > 0)
                        {
                            availableQty.Add(billing.InventoryID.Value, qtyLeft);
                        }
                    }
                }

                bool bill = false;
                if (billing.ResetUsage == ResetUsageOption.OnBilling)
                {
                    bill = true;
                }
                else
                {
                    if (billing.LastBilledDate == null)
                    {
                        bill = true;
                    }
                }

                if (bill)
                {
                    ARTran arTran = new ARTran();
                    arTran.InventoryID    = billing.InventoryID;
                    arTran.TranDesc       = billing.Description;
                    arTran.Qty            = billing.Included;
                    arTran.UOM            = billing.UOM;
                    arTran.ExtPrice       = billing.ItemFee;
                    arTran.TranAmt        = arTran.ExtPrice;
                    arTran.ProjectID      = task.ProjectID;
                    arTran.TaskID         = task.TaskID;
                    arTran.Commissionable = false;                     //todo

                    string subCD = null;
                    #region Set Account and Subaccount
                    if (billing.AccountSource != PMAccountSource.None)
                    {
                        if (rule.AccountSource == PMAccountSource.RecurringBillingItem)
                        {
                            if (billing.AccountID != null)
                            {
                                arTran.AccountID = billing.AccountID;
                            }
                            else
                            {
                                InventoryItem item = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, billing.InventoryID);

                                throw new PXException(Messages.BillingRuleAccountIsNotConfiguredForBillingRecurent, item.InventoryCD);
                            }
                        }
                        else if (billing.AccountSource == PMAccountSource.Project)
                        {
                            if (project.DefaultAccountID != null)
                            {
                                arTran.AccountID = project.DefaultAccountID;
                            }
                            else
                            {
                                InventoryItem item = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, billing.InventoryID);

                                throw new PXException(Messages.ProjectAccountIsNotConfiguredForBillingRecurent, item.InventoryCD, project.ContractCD);
                            }
                        }
                        else if (billing.AccountSource == PMAccountSource.Task)
                        {
                            if (task.DefaultAccountID != null)
                            {
                                arTran.AccountID = task.DefaultAccountID;
                            }
                            else
                            {
                                InventoryItem item = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, billing.InventoryID);

                                throw new PXException(Messages.TaskAccountIsNotConfiguredForBillingRecurent, item.InventoryCD, project.ContractCD, task.TaskCD);
                            }
                        }
                        else if (billing.AccountSource == PMAccountSource.InventoryItem)
                        {
                            InventoryItem item = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, billing.InventoryID);

                            if (item != null)
                            {
                                if (item.SalesAcctID != null)
                                {
                                    arTran.AccountID = item.SalesAcctID;
                                }
                                else
                                {
                                    throw new PXException(Messages.InventoryAccountIsNotConfiguredForBillingRecurent, item.InventoryCD);
                                }
                            }
                        }
                        else if (billing.AccountSource == PMAccountSource.Customer && customer != null)
                        {
                            CR.Location customerLoc = PXSelect <CR.Location, Where <CR.Location.bAccountID, Equal <Required <CR.Location.bAccountID> >, And <CR.Location.locationID, Equal <Required <CR.Location.locationID> > > > > .Select(this, customer.BAccountID, customer.DefLocationID);

                            if (customerLoc != null)
                            {
                                if (customerLoc.CSalesAcctID != null)
                                {
                                    arTran.AccountID = customerLoc.CSalesAcctID;
                                }
                                else
                                {
                                    InventoryItem item = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, billing.InventoryID);

                                    throw new PXException(Messages.CustomerAccountIsNotConfiguredForBillingRecurent, item.InventoryCD, customer.AcctCD);
                                }
                            }
                        }

                        if (arTran.AccountID == null && !string.IsNullOrEmpty(billing.SubMask))
                        {
                            InventoryItem item = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, billing.InventoryID);

                            throw new PXException(Messages.SubAccountCannotBeComposed, item.InventoryCD);
                        }
                        else if (arTran.AccountID != null && !string.IsNullOrEmpty(billing.SubMask))
                        {
                            subCD = PMRecurentBillSubAccountMaskAttribute.MakeSub <PMBillingRule.subMask>(this, billing.SubMask,
                                                                                                          new object[] { billing.SubID, project.DefaultSubID, task.DefaultSubID },
                                                                                                          new Type[] { typeof(PMBillingRule.subID), typeof(PMProject.defaultSubID), typeof(PMTask.defaultSubID) });
                        }
                    }

                    #endregion

                    list.Add(new BillingData(arTran, rule, null, subCD, null, null));

                    billing.LastBilledDate = billingDate;
                    ContractDetail.Update(billing);
                }
            }



            int            mult = 1;
            PMAccountGroup ag   = PXSelect <PMAccountGroup, Where <PMAccountGroup.groupID, Equal <Required <PMAccountGroup.groupID> > > > .Select(this, rule.AccountGroupID);

            if (ag == null)
            {
                throw new PXException(Messages.AccountGroupInBillingRuleNotFound, rule.BillingID, rule.AccountGroupID);
            }
            if (ag.Type == GL.AccountType.Liability || ag.Type == GL.AccountType.Income)
            {
                mult = -1;
            }

            DateTime cuttofDate = billingDate;            //all transactions  excluding the current day.
            ContractBillingSchedule schedule = PXSelect <ContractBillingSchedule> .Search <ContractBillingSchedule.contractID>(this, task.ProjectID);

            if (schedule != null && schedule.Type == BillingType.OnDemand)
            {
                cuttofDate = billingDate.AddDays(1);                //all transactions including the current day.
            }
            else
            {
                if (IncludeTodaysTransactions)
                {
                    cuttofDate = billingDate.AddDays(1);
                }
            }

            List <PMTran> billingBase = SelectBillingBase(task.ProjectID, task.TaskID, rule.AccountGroupID, cuttofDate,
                                                          rule.IncludeNonBillable == true);

            foreach (PMTran tran in billingBase)
            {
                ARTran arTran = new ARTran();
                arTran.BranchID = tran.BranchID;
                if (tran.InventoryID != PMInventorySelectorAttribute.EmptyInventoryID)
                {
                    arTran.InventoryID = tran.InventoryID;
                }
                arTran.TranDesc = tran.Description;
                arTran.UOM      = tran.UOM;
                arTran.Qty      = tran.BillableQty * mult;
                arTran.ExtPrice = tran.Amount * mult;
                if (arTran.Qty != 0)
                {
                    arTran.UnitPrice = arTran.ExtPrice / arTran.Qty;
                }
                else
                {
                    arTran.UnitPrice = 0;
                }
                arTran.TranAmt        = arTran.ExtPrice;
                arTran.ProjectID      = task.ProjectID;
                arTran.TaskID         = task.TaskID;
                arTran.PMTranID       = tran.TranID;
                arTran.Commissionable = false;                 //todo
                arTran.Date           = tran.Date;

                string subCD = null;
                #region Set Account and Subaccount

                int?employeeSubID = null;

                if (tran.ResourceID != null)
                {
                    EP.EPEmployee emp = PXSelect <EP.EPEmployee, Where <EP.EPEmployee.bAccountID, Equal <Required <EP.EPEmployee.bAccountID> > > > .Select(this, tran.ResourceID);

                    if (emp != null)
                    {
                        employeeSubID = emp.SalesSubID;
                    }
                }

                if (rule.AccountSource != PMAccountSource.None)
                {
                    if (rule.AccountSource == PMAccountSource.BillingRule)
                    {
                        if (rule.AccountID != null)
                        {
                            arTran.AccountID = rule.AccountID;
                        }
                        else
                        {
                            throw new PXException(Messages.BillingRuleAccountIsNotConfiguredForBilling, rule.BillingID);
                        }
                    }
                    else if (rule.AccountSource == PMAccountSource.Project)
                    {
                        if (project.DefaultAccountID != null)
                        {
                            arTran.AccountID = project.DefaultAccountID;
                        }
                        else
                        {
                            throw new PXException(Messages.ProjectAccountIsNotConfiguredForBilling, rule.BillingID, project.ContractCD);
                        }
                    }
                    else if (rule.AccountSource == PMAccountSource.Task)
                    {
                        if (task.DefaultAccountID != null)
                        {
                            arTran.AccountID = task.DefaultAccountID;
                        }
                        else
                        {
                            throw new PXException(Messages.TaskAccountIsNotConfiguredForBilling, rule.BillingID, project.ContractCD, task.TaskCD);
                        }
                    }
                    else if (rule.AccountSource == PMAccountSource.InventoryItem)
                    {
                        InventoryItem item = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, tran.InventoryID);

                        if (item != null)
                        {
                            if (item.SalesAcctID != null)
                            {
                                arTran.AccountID = item.SalesAcctID;
                            }
                            else
                            {
                                throw new PXException(Messages.InventoryAccountIsNotConfiguredForBilling, rule.BillingID, item.InventoryCD);
                            }
                        }
                    }
                    else if (rule.AccountSource == PMAccountSource.Customer && customer != null)
                    {
                        CR.Location customerLoc = PXSelect <CR.Location, Where <CR.Location.bAccountID, Equal <Required <CR.Location.bAccountID> >, And <CR.Location.locationID, Equal <Required <CR.Location.locationID> > > > > .Select(this, customer.BAccountID, customer.DefLocationID);

                        if (customerLoc != null)
                        {
                            if (customerLoc.CSalesAcctID != null)
                            {
                                arTran.AccountID = customerLoc.CSalesAcctID;
                            }
                            else
                            {
                                throw new PXException(Messages.CustomerAccountIsNotConfiguredForBilling, rule.BillingID, customer.AcctCD);
                            }
                        }
                    }
                    else if (rule.AccountSource == PMAccountSource.Resource)
                    {
                        EP.EPEmployee emp = PXSelect <EP.EPEmployee, Where <EP.EPEmployee.bAccountID, Equal <Required <EP.EPEmployee.bAccountID> > > > .Select(this, tran.ResourceID);

                        if (emp != null)
                        {
                            if (emp.SalesAcctID != null)
                            {
                                arTran.AccountID = emp.SalesAcctID;
                            }
                            else
                            {
                                throw new PXException(Messages.EmployeeAccountIsNotConfiguredForBilling, rule.BillingID, emp.AcctCD);
                            }
                        }
                    }

                    if (arTran.AccountID == null && !string.IsNullOrEmpty(rule.SubMask))
                    {
                        throw new PXException(Messages.SubAccountCannotBeComposed, rule.BillingID);
                    }
                    else if (arTran.AccountID != null && !string.IsNullOrEmpty(rule.SubMask))
                    {
                        subCD = PMBillSubAccountMaskAttribute.MakeSub <PMBillingRule.subMask>(this, rule.SubMask,
                                                                                              new object[] { tran.SubID, rule.SubID, project.DefaultSubID, task.DefaultSubID, employeeSubID },
                                                                                              new Type[] { typeof(PMTran.subID), typeof(PMBillingRule.subID), typeof(PMProject.defaultSubID), typeof(PMTask.defaultSubID), typeof(EP.EPEmployee.salesSubID) });
                    }
                }

                #endregion

                string note  = PXNoteAttribute.GetNote(Transactions.Cache, tran);
                Guid[] files = PXNoteAttribute.GetFileNotes(Transactions.Cache, tran);
                list.Add(new BillingData(arTran, rule, tran, subCD, note, files));

                if (billingItems.ContainsKey(tran.InventoryID.Value))
                {
                    if (availableQty.ContainsKey(tran.InventoryID.Value))
                    {
                        decimal available = availableQty[tran.InventoryID.Value];

                        if (tran.BillableQty <= available)
                        {
                            //Transaction is already payed for as a post payment included. Thus it should be free.
                            arTran.TranDesc = PXMessages.LocalizeNoPrefix(CT.Messages.PrefixIncludedUsage) + " " + tran.Description;
                            availableQty[tran.InventoryID.Value] -= arTran.Qty.Value;                            //decrease available qty
                            arTran.UnitPrice = 0;
                            arTran.ExtPrice  = 0;
                            arTran.TranAmt   = 0;
                        }
                        else
                        {
                            arTran.TranDesc = PXMessages.LocalizeNoPrefix(CT.Messages.PrefixOverused) + " " + tran.Description;
                            arTran.Qty      = arTran.Qty - available;
                            availableQty[tran.InventoryID.Value] = 0;                            //all available qty was used.
                        }
                    }
                }

                tran.Billed     = true;
                tran.BilledDate = billingDate;

                Transactions.Update(tran);
            }

            return(list);
        }
Exemplo n.º 8
0
        protected virtual IEnumerable items()
        {
            BillingFilter filter = Filter.Current;

            if (filter == null)
            {
                yield break;
            }
            bool found = false;

            foreach (ProjectsList item in Items.Cache.Inserted)
            {
                found = true;
                yield return(item);
            }
            if (found)
            {
                yield break;
            }

            PXSelectBase <PMProject> select = new PXSelectJoin <PMProject,
                                                                InnerJoin <ContractBillingSchedule, On <PMProject.contractID, Equal <ContractBillingSchedule.contractID> >,
                                                                           InnerJoin <Customer, On <PMProject.customerID, Equal <Customer.bAccountID> > > >,
                                                                Where2 <Where <ContractBillingSchedule.nextDate, LessEqual <Current <BillingFilter.invoiceDate> >, Or <ContractBillingSchedule.type, Equal <BillingType.BillingOnDemand> > >,
                                                                        And <PMProject.baseType, Equal <PMProject.ProjectBaseType>,
                                                                             And <PMProject.nonProject, Equal <False>,
                                                                                  And <PMProject.isTemplate, Equal <False> > > > > >(this);

            if (filter.StatementCycleId != null)
            {
                select.WhereAnd <Where <Customer.statementCycleId, Equal <Current <BillingFilter.statementCycleId> > > >();
            }
            if (filter.CustomerClassID != null)
            {
                select.WhereAnd <Where <Customer.customerClassID, Equal <Current <BillingFilter.customerClassID> > > >();
            }
            if (filter.CustomerID != null)
            {
                select.WhereAnd <Where <Customer.bAccountID, Equal <Current <BillingFilter.customerID> > > >();
            }
            if (filter.TemplateID != null)
            {
                select.WhereAnd <Where <PMProject.templateID, Equal <Current <BillingFilter.templateID> > > >();
            }

            foreach (PXResult <PMProject, ContractBillingSchedule, Customer> item in select.Select())
            {
                PMProject project = (PMProject)item;
                ContractBillingSchedule schedule = (ContractBillingSchedule)item;
                Customer customer = (Customer)item;

                ProjectsList result = new ProjectsList();
                result.ProjectID    = project.ContractID;
                result.ProjectCD    = project.ContractCD;
                result.Description  = project.Description;
                result.CustomerID   = project.CustomerID;
                result.CustomerName = customer.AcctName;
                result.LastDate     = schedule.LastDate;

                DateTime?fromDate = null;

                if (schedule.NextDate != null)
                {
                    switch (schedule.Type)
                    {
                    case BillingType.Annual:
                        fromDate = schedule.NextDate.Value.AddYears(-1);
                        break;

                    case BillingType.Monthly:
                        fromDate = schedule.NextDate.Value.AddMonths(-1);
                        break;

                    case BillingType.Weekly:
                        fromDate = schedule.NextDate.Value.AddDays(-7);
                        break;

                    case BillingType.Quarterly:
                        fromDate = schedule.NextDate.Value.AddMonths(-3);
                        break;
                    }
                }

                result.FromDate = fromDate;
                result.NextDate = schedule.NextDate;

                yield return(Items.Insert(result));
            }

            Items.Cache.IsDirty = false;
        }
        protected virtual IEnumerable items()
        {
            BillingFilter filter = Filter.Current;

            if (filter == null)
            {
                yield break;
            }
            bool found = false;

            foreach (ProjectsList item in Items.Cache.Inserted)
            {
                found = true;
                yield return(item);
            }
            if (found)
            {
                yield break;
            }

            PXSelectBase <PMProject> selectUnbilled = new PXSelectJoinGroupBy <PMProject,
                                                                               InnerJoin <PMUnbilledDailySummary, On <PMUnbilledDailySummary.projectID, Equal <PMProject.contractID> >,
                                                                                          InnerJoin <ContractBillingSchedule, On <PMProject.contractID, Equal <ContractBillingSchedule.contractID> >,
                                                                                                     InnerJoin <Customer, On <PMProject.customerID, Equal <Customer.bAccountID> >,
                                                                                                                InnerJoin <PMTask, On <PMTask.projectID, Equal <PMUnbilledDailySummary.projectID>,
                                                                                                                                       And <PMTask.isActive, Equal <True>,
                                                                                                                                            And <PMTask.taskID, Equal <PMUnbilledDailySummary.taskID>,
                                                                                                                                                 And <Where <PMTask.billingOption, Equal <PMBillingOption.onBilling>,
                                                                                                                                                             Or2 <Where <PMTask.billingOption, Equal <PMBillingOption.onTaskCompletion>, And <PMTask.isCompleted, Equal <True> > >,
                                                                                                                                                                  Or <Where <PMTask.billingOption, Equal <PMBillingOption.onProjectCompetion>, And <PMProject.isCompleted, Equal <True> > > > > > > > > >,
                                                                                                                           InnerJoin <PMBillingRule, On <PMBillingRule.billingID, Equal <PMTask.billingID>,
                                                                                                                                                         And <PMBillingRule.accountGroupID, Equal <PMUnbilledDailySummary.accountGroupID> > > > > > > >,
                                                                               Where2 <Where <ContractBillingSchedule.nextDate, LessEqual <Current <BillingFilter.invoiceDate> >,
                                                                                              Or <ContractBillingSchedule.type, Equal <BillingType.BillingOnDemand> > >,
                                                                                       And2 <Where <PMBillingRule.includeNonBillable, Equal <False>, And <PMUnbilledDailySummary.billable, Greater <int0>,
                                                                                                                                                          Or <Where <PMBillingRule.includeNonBillable, Equal <True>, And <Where <PMUnbilledDailySummary.nonBillable, Greater <int0>, Or <PMUnbilledDailySummary.billable, Greater <int0> > > > > > > >,
                                                                                             And2 <Where <PMUnbilledDailySummary.date, LessEqual <Current <BillingFilter.invoiceDate> > >, And <Match <Current <AccessInfo.userName> > > > > >,
                                                                               Aggregate <GroupBy <PMProject.contractID> > >(this);

            if (Setup.Current.CutoffDate == PMCutOffDate.Excluded)
            {
                selectUnbilled = new PXSelectJoinGroupBy <PMProject,
                                                          InnerJoin <PMUnbilledDailySummary, On <PMUnbilledDailySummary.projectID, Equal <PMProject.contractID> >,
                                                                     InnerJoin <ContractBillingSchedule, On <PMProject.contractID, Equal <ContractBillingSchedule.contractID> >,
                                                                                InnerJoin <Customer, On <PMProject.customerID, Equal <Customer.bAccountID> >,
                                                                                           InnerJoin <PMTask, On <PMTask.projectID, Equal <PMUnbilledDailySummary.projectID>,
                                                                                                                  And <PMTask.isActive, Equal <True>,
                                                                                                                       And <PMTask.taskID, Equal <PMUnbilledDailySummary.taskID>,
                                                                                                                            And <Where <PMTask.billingOption, Equal <PMBillingOption.onBilling>,
                                                                                                                                        Or2 <Where <PMTask.billingOption, Equal <PMBillingOption.onTaskCompletion>, And <PMTask.isCompleted, Equal <True> > >,
                                                                                                                                             Or <Where <PMTask.billingOption, Equal <PMBillingOption.onProjectCompetion>, And <PMProject.isCompleted, Equal <True> > > > > > > > > >,
                                                                                                      InnerJoin <PMBillingRule, On <PMBillingRule.billingID, Equal <PMTask.billingID>,
                                                                                                                                    And <PMBillingRule.accountGroupID, Equal <PMUnbilledDailySummary.accountGroupID> > > > > > > >,
                                                          Where2 <Where <ContractBillingSchedule.nextDate, LessEqual <Current <BillingFilter.invoiceDate> >,
                                                                         Or <ContractBillingSchedule.type, Equal <BillingType.BillingOnDemand> > >,
                                                                  And2 <Where <PMBillingRule.includeNonBillable, Equal <False>, And <PMUnbilledDailySummary.billable, Greater <int0>,
                                                                                                                                     Or <Where <PMBillingRule.includeNonBillable, Equal <True>, And <Where <PMUnbilledDailySummary.nonBillable, Greater <int0>, Or <PMUnbilledDailySummary.billable, Greater <int0> > > > > > > >,
                                                                        And2 <Where <PMUnbilledDailySummary.date, Less <Current <BillingFilter.invoiceDate> > >, And <Match <Current <AccessInfo.userName> > > > > >,
                                                          Aggregate <GroupBy <PMProject.contractID> > >(this);
            }


            PXSelectBase <PMProject> selectRecurring = new PXSelectJoinGroupBy <PMProject,
                                                                                InnerJoin <ContractBillingSchedule, On <PMProject.contractID, Equal <ContractBillingSchedule.contractID> >,
                                                                                           InnerJoin <Customer, On <PMProject.customerID, Equal <Customer.bAccountID> >,
                                                                                                      InnerJoin <PMTask, On <PMTask.projectID, Equal <PMProject.contractID> >,
                                                                                                                 InnerJoin <PMBillingRule, On <PMBillingRule.billingID, Equal <PMTask.billingID> >,
                                                                                                                            InnerJoin <PMRecurringItem, On <PMTask.projectID, Equal <PMRecurringItem.projectID>,
                                                                                                                                                            And <PMTask.taskID, Equal <PMRecurringItem.taskID>,
                                                                                                                                                                 And <PMTask.isCompleted, Equal <False> > > > > > > > >,
                                                                                Where2 <Where <ContractBillingSchedule.nextDate, LessEqual <Current <BillingFilter.invoiceDate> >,
                                                                                               Or <ContractBillingSchedule.type, Equal <BillingType.BillingOnDemand> > >,
                                                                                        And <Match <Current <AccessInfo.userName> > > >,
                                                                                Aggregate <GroupBy <PMProject.contractID> > >(this);

            PXSelectBase <PMProject> selectProgressive = new PXSelectJoinGroupBy <PMProject,
                                                                                  InnerJoin <ContractBillingSchedule, On <PMProject.contractID, Equal <ContractBillingSchedule.contractID> >,
                                                                                             InnerJoin <Customer, On <PMProject.customerID, Equal <Customer.bAccountID> >,
                                                                                                        InnerJoin <PMTask, On <PMTask.projectID, Equal <PMProject.contractID> >,
                                                                                                                   InnerJoin <PMBillingRule, On <PMBillingRule.billingID, Equal <PMTask.billingID> >,
                                                                                                                              InnerJoin <PMBudget, On <PMTask.projectID, Equal <PMBudget.projectID>,
                                                                                                                                                       And <PMTask.taskID, Equal <PMBudget.projectTaskID>,
                                                                                                                                                            And <PMBudget.type, Equal <GL.AccountType.income>,
                                                                                                                                                                 And <PMBudget.amountToInvoice, NotEqual <decimal0> > > > > > > > > >,
                                                                                  Where <Match <Current <AccessInfo.userName> > >,
                                                                                  Aggregate <GroupBy <PMProject.contractID> > >(this);


            if (filter.StatementCycleId != null)
            {
                selectUnbilled.WhereAnd <Where <Customer.statementCycleId, Equal <Current <BillingFilter.statementCycleId> > > >();
                selectRecurring.WhereAnd <Where <Customer.statementCycleId, Equal <Current <BillingFilter.statementCycleId> > > >();
                selectProgressive.WhereAnd <Where <Customer.statementCycleId, Equal <Current <BillingFilter.statementCycleId> > > >();
            }
            if (filter.CustomerClassID != null)
            {
                selectUnbilled.WhereAnd <Where <Customer.customerClassID, Equal <Current <BillingFilter.customerClassID> > > >();
                selectRecurring.WhereAnd <Where <Customer.customerClassID, Equal <Current <BillingFilter.customerClassID> > > >();
                selectProgressive.WhereAnd <Where <Customer.customerClassID, Equal <Current <BillingFilter.customerClassID> > > >();
            }
            if (filter.CustomerID != null)
            {
                selectUnbilled.WhereAnd <Where <Customer.bAccountID, Equal <Current <BillingFilter.customerID> > > >();
                selectRecurring.WhereAnd <Where <Customer.bAccountID, Equal <Current <BillingFilter.customerID> > > >();
                selectProgressive.WhereAnd <Where <Customer.bAccountID, Equal <Current <BillingFilter.customerID> > > >();
            }
            if (filter.TemplateID != null)
            {
                selectUnbilled.WhereAnd <Where <PMProject.templateID, Equal <Current <BillingFilter.templateID> > > >();
                selectRecurring.WhereAnd <Where <PMProject.templateID, Equal <Current <BillingFilter.templateID> > > >();
                selectProgressive.WhereAnd <Where <PMProject.templateID, Equal <Current <BillingFilter.templateID> > > >();
            }

            foreach (PXResult item in selectUnbilled.Select().Union(selectRecurring.Select()).Union(selectProgressive.Select()))
            {
                PMProject project = PXResult.Unwrap <PMProject>(item);
                ContractBillingSchedule schedule = PXResult.Unwrap <ContractBillingSchedule>(item);
                Customer customer = PXResult.Unwrap <Customer>(item);

                ProjectsList result = new ProjectsList();
                result.ProjectID    = project.ContractID;
                result.ProjectCD    = project.ContractCD;
                result.Description  = project.Description;
                result.CustomerID   = project.CustomerID;
                result.CustomerName = customer.AcctName;
                result.LastDate     = schedule.LastDate;

                DateTime?fromDate = null;

                if (schedule.NextDate != null)
                {
                    switch (schedule.Type)
                    {
                    case BillingType.Annual:
                        fromDate = schedule.NextDate.Value.AddYears(-1);
                        break;

                    case BillingType.Monthly:
                        fromDate = schedule.NextDate.Value.AddMonths(-1);
                        break;

                    case BillingType.Weekly:
                        fromDate = schedule.NextDate.Value.AddDays(-7);
                        break;

                    case BillingType.Quarterly:
                        fromDate = schedule.NextDate.Value.AddMonths(-3);
                        break;
                    }
                }

                result.FromDate = fromDate;
                result.NextDate = schedule.NextDate;

                if (Items.Locate(result) == null)
                {
                    yield return(Items.Insert(result));
                }
            }

            Items.Cache.IsDirty = false;
        }