예제 #1
0
        public static bool CalculateDiscountedTaxes(PXCache cache, APTaxTran aptaxTran, decimal cashDiscPercent)
        {
            bool?  result = null;
            object value  = null;

            IBqlCreator whereTaxable = (IBqlCreator)Activator.CreateInstance(typeof(WhereAPPPDTaxable <Required <APTaxTran.taxID> >));

            whereTaxable.Verify(cache, aptaxTran, new List <object> {
                aptaxTran.TaxID
            }, ref result, ref value);

            aptaxTran.CuryDiscountedTaxableAmt = cashDiscPercent == 0m
                                ? aptaxTran.CuryTaxableAmt
                                : PXDBCurrencyAttribute.RoundCury(cache, aptaxTran,
                                                                  (decimal)(aptaxTran.CuryTaxableAmt * (1m - cashDiscPercent)));

            aptaxTran.CuryDiscountedPrice = cashDiscPercent == 0m
                                ? aptaxTran.CuryTaxAmt
                                : PXDBCurrencyAttribute.RoundCury(cache, aptaxTran,
                                                                  (decimal)(aptaxTran.TaxRate / 100m * aptaxTran.CuryDiscountedTaxableAmt));

            return(result == true);
        }
        /// <summary>
        /// For an application of a payment to an invoice, calculates the
        /// payment's document balance in the currency of the target invoice
        /// document.
        /// </summary>
        /// <param name="paymentBalanceInBase">
        /// The balance of the payment document in the base currency.
        /// </param>
        /// <param name="paymentBalanceInCurrency">
        /// The balance of the payment document in the document's currency.
        /// Will be re-used in case when the invoice's currency is the same
        /// as the payment's currency.
        /// </param>
        public static decimal CalculateApplicationDocumentBalance(
            PXCache cache,
            CurrencyInfo paymentCurrencyInfo,
            CurrencyInfo invoiceCurrencyInfo,
            decimal?paymentBalanceInBase,
            decimal?paymentBalanceInCurrency)
        {
            decimal applicationDocumentBalance;

            if (string.Equals(paymentCurrencyInfo.CuryID, invoiceCurrencyInfo.CuryID))
            {
                applicationDocumentBalance = (paymentBalanceInCurrency ?? 0m);
            }
            else
            {
                PXDBCurrencyAttribute.CuryConvCury(
                    cache,
                    invoiceCurrencyInfo,
                    paymentBalanceInBase ?? 0m,
                    out applicationDocumentBalance);
            }

            return(applicationDocumentBalance);
        }
예제 #3
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);
        }
        protected virtual IEnumerable items()
        {
            ScheduleRecognitionFilter filter = Filter.Current;

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

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


            PXSelectBase <DRScheduleTran> select = new PXSelectJoin <DRScheduleTran,
                                                                     InnerJoin <DRScheduleDetail, On <DRScheduleTran.scheduleID, Equal <DRScheduleDetail.scheduleID>, And <DRScheduleTran.componentID, Equal <DRScheduleDetail.componentID> > >,
                                                                                InnerJoin <DRSchedule, On <DRScheduleTran.scheduleID, Equal <DRSchedule.scheduleID> >,
                                                                                           LeftJoin <InventoryItem, On <DRScheduleTran.componentID, Equal <InventoryItem.inventoryID> > > > >,
                                                                     Where <DRScheduleTran.recDate, LessEqual <Current <ScheduleRecognitionFilter.recDate> >,
                                                                            And <DRScheduleTran.status, Equal <DRScheduleTranStatus.OpenStatus>,
                                                                                 And <DRScheduleDetail.status, NotEqual <DRScheduleStatus.DraftStatus> > > >,
                                                                     OrderBy <Asc <DRScheduleTran.scheduleID, Asc <DRScheduleTran.componentID, Asc <DRScheduleTran.recDate, Asc <DRScheduleTran.lineNbr> > > > > >(this);

            if (!string.IsNullOrEmpty(filter.DeferredCode))
            {
                select.WhereAnd <Where <DRScheduleDetail.defCode, Equal <Current <ScheduleRecognitionFilter.deferredCode> > > >();
            }

            if (filter.BranchID != null)
            {
                select.WhereAnd <Where <DRScheduleDetail.branchID, Equal <Current <ScheduleRecognitionFilter.branchID> > > >();
            }

            Dictionary <string, string> added = new Dictionary <string, string>();

            foreach (PXResult <DRScheduleTran, DRScheduleDetail, DRSchedule, InventoryItem> resultSet in select.Select())
            {
                DRScheduleTran   tran           = (DRScheduleTran)resultSet;
                DRSchedule       schedule       = (DRSchedule)resultSet;
                DRScheduleDetail scheduleDetail = (DRScheduleDetail)resultSet;
                InventoryItem    item           = (InventoryItem)resultSet;

                string key = string.Format("{0}.{1}", tran.ScheduleID, tran.ComponentID);

                bool doInsert = false;

                if (added.ContainsKey(key))
                {
                    string addedFinPeriod = added[key];

                    if (tran.FinPeriodID == addedFinPeriod)
                    {
                        doInsert = true;
                    }
                }
                else
                {
                    doInsert = true;
                    added.Add(key, tran.FinPeriodID);
                }

                if (doInsert)
                {
                    ScheduledTran result = new ScheduledTran();
                    result.BranchID    = tran.BranchID;
                    result.AccountID   = tran.AccountID;
                    result.Amount      = tran.Amount;
                    result.ComponentID = tran.ComponentID;
                    result.DefCode     = scheduleDetail.DefCode;
                    result.FinPeriodID = tran.FinPeriodID;
                    result.LineNbr     = tran.LineNbr;
                    result.RecDate     = tran.RecDate;
                    result.ScheduleID  = tran.ScheduleID;
                    result.ScheduleNbr = schedule.ScheduleNbr;
                    result.SubID       = tran.SubID;
                    result.ComponentCD = item.InventoryCD;
                    result.DocType     = DRScheduleDocumentType.BuildDocumentType(scheduleDetail.Module, scheduleDetail.DocType);

                    Items.Cache.SetStatus(result, PXEntryStatus.Inserted);
                    yield return(result);                   // Items.Insert(result);
                }
            }


            //Virtual Records (CashReceipt):

            PXSelectBase <ARInvoice> s = null;

            if (!string.IsNullOrEmpty(filter.DeferredCode))
            {
                s = new PXSelectJoinGroupBy <ARInvoice,
                                             InnerJoin <ARTran, On <ARTran.tranType, Equal <ARInvoice.docType>,
                                                                    And <ARTran.refNbr, Equal <ARInvoice.refNbr> > >,
                                                        InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>,
                                                                                       And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt>,
                                                                                            And <DRDeferredCode.deferredCodeID, Equal <Current <ScheduleRecognitionFilter.deferredCode> > > > >,
                                                                   InnerJoin <DRSchedule, On <ARTran.tranType, Equal <DRSchedule.docType>,
                                                                                              And <ARTran.refNbr, Equal <DRSchedule.refNbr>,
                                                                                                   And <ARTran.lineNbr, Equal <DRSchedule.lineNbr> > > >,
                                                                              InnerJoin <DRScheduleDetail, On <DRSchedule.scheduleID, Equal <DRScheduleDetail.scheduleID> > > > > >,
                                             Where <ARInvoice.released, Equal <True>,
                                                    And <DRScheduleDetail.isOpen, Equal <True> > >,
                                             Aggregate <GroupBy <ARInvoice.docType, GroupBy <ARInvoice.refNbr> > > >(this);
            }
            else
            {
                s = new PXSelectJoinGroupBy <ARInvoice,
                                             InnerJoin <ARTran, On <ARTran.tranType, Equal <ARInvoice.docType>,
                                                                    And <ARTran.refNbr, Equal <ARInvoice.refNbr> > >,
                                                        InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>,
                                                                                       And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt> > >,
                                                                   InnerJoin <DRSchedule, On <ARTran.tranType, Equal <DRSchedule.docType>,
                                                                                              And <ARTran.refNbr, Equal <DRSchedule.refNbr>,
                                                                                                   And <ARTran.lineNbr, Equal <DRSchedule.lineNbr> > > >,
                                                                              InnerJoin <DRScheduleDetail, On <DRSchedule.scheduleID, Equal <DRScheduleDetail.scheduleID> > > > > >,
                                             Where <ARInvoice.released, Equal <True>,
                                                    And <DRScheduleDetail.isOpen, Equal <True> > >,
                                             Aggregate <GroupBy <ARInvoice.docType, GroupBy <ARInvoice.refNbr> > > >(this);
            }


            foreach (ARInvoice inv in s.Select())
            {
                PXSelectBase <ARTran> trs =
                    new PXSelectJoin <ARTran,
                                      InnerJoin <DRDeferredCode, On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID>,
                                                                     And <DRDeferredCode.method, Equal <DeferredMethodType.cashReceipt> > > >,
                                      Where <ARTran.tranType, Equal <Required <ARTran.tranType> >,
                                             And <ARTran.refNbr, Equal <Required <ARTran.refNbr> > > > >(this);

                foreach (PXResult <ARTran, DRDeferredCode> res in trs.Select(inv.DocType, inv.RefNbr))
                {
                    List <ScheduledTran> virtualRecords       = new List <ScheduledTran>();
                    List <ScheduledTran> virtualVoidedRecords = new List <ScheduledTran>();

                    ARTran         tr = (ARTran)res;
                    DRDeferredCode dc = (DRDeferredCode)res;

                    decimal trPart = 0;
                    if (inv.LineTotal.Value != 0)
                    {
                        trPart = tr.TranAmt.Value / inv.LineTotal.Value;
                    }
                    decimal trPartRest = tr.TranAmt.Value;

                    InventoryItem invItem = PXSelect <InventoryItem, Where <InventoryItem.inventoryID, Equal <Required <InventoryItem.inventoryID> > > > .Select(this, tr.InventoryID);

                    //NOTE: Multiple Components are not supported in CashReceipt Deferred Revenue Recognition.
                    DRSchedule       schedule       = GetScheduleByFID(BatchModule.AR, inv.DocType, inv.RefNbr, tr.LineNbr);
                    DRScheduleDetail scheduleDetail = GetScheduleDetailbyID(schedule.ScheduleID, tr.InventoryID != null ? tr.InventoryID : DRScheduleDetail.EmptyComponentID);
                    int lineNbr = scheduleDetail.LineCntr ?? 0;


                    PXSelectBase <ARAdjust> ads =
                        new PXSelectJoin <ARAdjust,
                                          LeftJoin <DRScheduleTran, On <ARAdjust.adjgDocType, Equal <DRScheduleTran.adjgDocType>,
                                                                        And <ARAdjust.adjgRefNbr, Equal <DRScheduleTran.adjgRefNbr> > > >,
                                          Where <ARAdjust.adjdDocType, Equal <Required <ARAdjust.adjdDocType> >,
                                                 And <ARAdjust.adjdRefNbr, Equal <Required <ARAdjust.adjdRefNbr> >,
                                                      And <DRScheduleTran.scheduleID, IsNull,
                                                           And <ARAdjust.adjgDocType, NotEqual <ARDocType.creditMemo> > > > >,
                                          OrderBy <Asc <ARAdjust.adjgDocDate> > >(this);

                    foreach (ARAdjust ad in ads.Select(inv.DocType, inv.RefNbr))
                    {
                        lineNbr++;
                        decimal amtRaw = Math.Min(trPart * ad.AdjAmt.Value, trPartRest);
                        trPartRest -= amtRaw;
                        decimal amt = PXDBCurrencyAttribute.BaseRound(this, amtRaw);

                        ScheduledTran result = new ScheduledTran();

                        result.BranchID    = ad.AdjgBranchID;
                        result.Amount      = amt;
                        result.ComponentID = tr.InventoryID;
                        result.DefCode     = tr.DeferredCode;
                        result.FinPeriodID = FinPeriodRepository.GetPeriodIDFromDate(ad.AdjgDocDate, PXAccess.GetParentOrganizationID(ad.AdjgBranchID));
                        result.LineNbr     = lineNbr;
                        result.Module      = schedule.Module;
                        result.RecDate     = ad.AdjgDocDate;
                        result.ScheduleID  = schedule.ScheduleID;
                        result.ScheduleNbr = schedule.ScheduleNbr;
                        result.DocType     = schedule.DocType;
                        result.AdjgDocType = ad.AdjgDocType;
                        result.AdjgRefNbr  = ad.AdjgRefNbr;
                        result.AdjNbr      = ad.AdjNbr;
                        result.IsVirtual   = true;
                        result.AccountID   = scheduleDetail.AccountID;
                        result.SubID       = scheduleDetail.SubID;
                        result.ComponentCD = invItem == null ? "" : invItem.InventoryCD;

                        if (ad.Voided == true)
                        {
                            if (ad.AdjgDocType == ARDocType.VoidPayment && virtualVoidedRecords.Count > 0)
                            {
                                ScheduledTran tran = virtualVoidedRecords.Where <ScheduledTran>(v => (v.AdjgDocType == ARDocType.Payment && v.AdjgRefNbr == ad.AdjgRefNbr && v.AdjNbr == ad.AdjNbr)).First <ScheduledTran>();
                                if (tran != null)
                                {
                                    virtualVoidedRecords.Remove(tran);
                                }
                            }
                            else
                            {
                                virtualVoidedRecords.Add(result);
                            }
                        }
                        else
                        {
                            virtualRecords.Add(result);
                        }
                    }

                    foreach (ScheduledTran v in virtualRecords)
                    {
                        Items.Cache.SetStatus(v, PXEntryStatus.Inserted);
                        yield return(v);                       // Items.Insert(v);
                    }

                    foreach (ScheduledTran v in virtualVoidedRecords)
                    {
                        Items.Cache.SetStatus(v, PXEntryStatus.Inserted);
                        yield return(v);                       // Items.Insert(v);
                    }
                }
            }


            Items.Cache.IsDirty = false;
        }
            public Decimal CalcTaxableFromTotalAmount(PXCache cache, object row, string aTaxZoneID, string aTaxCategoryID, DateTime aDocDate, Decimal aCuryTotal)
            {
                Decimal           result  = Decimal.Zero;
                PXGraph           graph   = cache.Graph;
                List <TaxZoneDet> taxList = GetApplicableTaxList(graph, aTaxZoneID, aTaxCategoryID, aDocDate);
                Dictionary <string, PXResult <Tax, TaxRev> > taxRates = GetTaxRevisionList(graph, aDocDate);
                List <PXResult <Tax, TaxRev> > orderedTaxList         = new List <PXResult <Tax, TaxRev> >(taxList.Count);

                foreach (TaxZoneDet iDet in taxList)
                {
                    PXResult <Tax, TaxRev> line;
                    if (taxRates.TryGetValue(iDet.TaxID, out line))
                    {
                        int idx;
                        for (idx = orderedTaxList.Count;
                             (idx > 0) &&
                             String.Compare(((Tax)orderedTaxList[idx - 1]).TaxCalcLevel, ((Tax)line).TaxCalcLevel) > 0;
                             idx--)
                        {
                            ;
                        }
                        orderedTaxList.Insert(idx, new PXResult <Tax, TaxRev>(line, line));
                    }
                }
                Decimal rateInclusive = Decimal.Zero;
                Decimal rateLvl1      = Decimal.Zero;
                Decimal rateLvl2      = Decimal.Zero;

                foreach (PXResult <Tax, TaxRev> iRes in orderedTaxList)
                {
                    Tax     tax        = iRes;
                    TaxRev  taxRev     = iRes;
                    Decimal multiplier = tax.ReverseTax == true ? Decimal.MinusOne : Decimal.One;
                    switch (tax.TaxCalcLevel)
                    {
                    case CSTaxCalcLevel.Inclusive:
                        rateInclusive += multiplier * taxRev.TaxRate.Value;
                        break;

                    case CSTaxCalcLevel.CalcOnItemAmt:
                        rateLvl1 += multiplier * taxRev.TaxRate.Value;
                        break;

                    case CSTaxCalcLevel.CalcOnItemAmtPlusTaxAmt:
                        rateLvl2 += multiplier * taxRev.TaxRate.Value;
                        break;
                    }
                }

                decimal baseLvl2      = PXDBCurrencyAttribute.RoundCury(cache, row, aCuryTotal / (1 + rateLvl2 / 100));
                decimal baseLvl1      = PXDBCurrencyAttribute.RoundCury(cache, row, baseLvl2 / (1 + (rateLvl1 + rateInclusive) / 100));
                Decimal curyTaxTotal  = decimal.Zero;
                Decimal curyTax2Total = decimal.Zero;

                foreach (PXResult <Tax, TaxRev> iRes in orderedTaxList)
                {
                    Tax     tax        = iRes;
                    TaxRev  taxRev     = iRes;
                    Decimal multiplier = tax.ReverseTax == true ? Decimal.MinusOne : Decimal.One;
                    switch (tax.TaxCalcLevel)
                    {
                    case CSTaxCalcLevel.Inclusive:
                        break;

                    case CSTaxCalcLevel.CalcOnItemAmt:
                        curyTaxTotal += multiplier * PXDBCurrencyAttribute.RoundCury(cache, row, (baseLvl1 * taxRev.TaxRate / 100m) ?? 0m);
                        break;

                    case CSTaxCalcLevel.CalcOnItemAmtPlusTaxAmt:
                        curyTax2Total += multiplier * PXDBCurrencyAttribute.RoundCury(cache, row, (baseLvl2 * taxRev.TaxRate / 100m) ?? 0m);
                        break;
                    }
                }
                result = aCuryTotal - curyTaxTotal - curyTax2Total;
                return(result);
            }
예제 #6
0
        public decimal AllocateOverRCTLine(List <POReceiptLineAdjustment> result, POReceiptLine aLine, decimal toDistribute, Int32?branchID)
        {
            var aLCCode = new LandedCostCode();

            aLCCode.AllocationMethod = LandedCostAllocationMethod.ByQuantity;
            decimal baseTotal = GetBaseValue(aLCCode, aLine);

            decimal shareAmt      = Decimal.Zero;
            decimal allocatedAmt  = Decimal.Zero;
            decimal allocatedBase = Decimal.Zero;

            List <Type> bql = new List <Type>
            {
                typeof(Select4 <, ,>),
                typeof(POReceiptLineSplit),
                typeof(Where <POReceiptLineSplit.receiptNbr, Equal <Required <POReceiptLine.receiptNbr> >, And <POReceiptLineSplit.lineNbr, Equal <Required <POReceiptLine.lineNbr> > > >),
                typeof(Aggregate <>),
                typeof(GroupBy <,>),
                typeof(POReceiptLineSplit.locationID),
                typeof(GroupBy <,>),
                typeof(POReceiptLineSplit.subItemID),
                typeof(Sum <,>),
                typeof(POReceiptLineSplit.baseQty),
                typeof(GroupBy <>),
                typeof(POReceiptLineSplit.lotSerialNbr)
            };

            InventoryItem ii = (InventoryItem)PXSelectorAttribute.Select <POReceiptLine.inventoryID>(_graph.Caches[typeof(POReceiptLine)], aLine);
            bool          requierelotserial = ii.ValMethod == INValMethod.Specific;

            if (!requierelotserial)
            {
                bql.RemoveAt(bql.Count - 1);
                bql.RemoveAt(bql.Count - 1);
                bql[bql.Count - 2] = typeof(Sum <>);
            }

            PXView splitsView = new PXView(_graph, false, BqlCommand.CreateInstance(bql.ToArray()));

            bool hasSplits = false;

            foreach (POReceiptLineSplit split in splitsView.SelectMulti(aLine.ReceiptNbr, aLine.LineNbr))
            {
                hasSplits = true;
                decimal allocatingBase = split.BaseQty ?? 0m;
                shareAmt = CalcAllocationValue(aLCCode, split, aLine, baseTotal, toDistribute);
                shareAmt = PXDBCurrencyAttribute.BaseRound(_graph, shareAmt);

                //accu rounding
                shareAmt += PXCurrencyAttribute.BaseRound(_graph, (allocatedBase + allocatingBase) * toDistribute / baseTotal - shareAmt - allocatedAmt);

                if (shareAmt != Decimal.Zero)
                {
                    POReceiptLine newPOReceiptLine = (POReceiptLine)_graph.Caches[typeof(POReceiptLine)].CreateCopy(aLine);
                    newPOReceiptLine.LocationID   = split.LocationID;
                    newPOReceiptLine.SiteID       = split.SiteID;
                    newPOReceiptLine.SubItemID    = split.SubItemID;
                    newPOReceiptLine.LotSerialNbr = requierelotserial ? split.LotSerialNbr : null;
                    result.Add(new POReceiptLineAdjustment(newPOReceiptLine, shareAmt, branchID));
                    allocatedAmt  += shareAmt;
                    allocatedBase += allocatingBase;
                }
            }
            if (!hasSplits)
            {
                shareAmt = toDistribute;
                shareAmt = PXDBCurrencyAttribute.BaseRound(_graph, shareAmt);
                if (shareAmt != Decimal.Zero)
                {
                    result.Add(new POReceiptLineAdjustment(aLine, shareAmt, branchID));
                }

                allocatedAmt = shareAmt;
            }
            return(allocatedAmt);
        }
예제 #7
0
        private void CreateSingleSchedule <T>(T originalDocument, Amount lineTotal, int?DefScheduleID, bool isDraft, DRScheduleParameters scheduleParameters)
            where T : ARRegister
        {
            ARSetup arSetup = PXSelect <ARSetup> .Select(this);

            DRSchedule existingSchedule = PXSelect <
                DRSchedule,
                Where <
                    DRSchedule.module, Equal <BatchModule.moduleAR>,
                    And <DRSchedule.docType, Equal <Required <ARRegister.docType> >,
                         And <DRSchedule.refNbr, Equal <Required <ARRegister.refNbr> > > > > >
                                          .SelectSingleBound(this, null, originalDocument.DocType, originalDocument.RefNbr, 1);

            if (existingSchedule?.LineNbr != null)
            {
                throw new PXException(Messages.CantCompleteBecauseASC606FeatureIsEnabled);
            }

            if (DefScheduleID == null)
            {
                Location location = PXSelect <Location, Where <Location.locationID, Equal <Required <DRSchedule.bAccountLocID> > > > .SelectSingleBound(this, null, scheduleParameters.BAccountLocID);

                CurrencyInfo currencyInfo = PXSelect <CurrencyInfo, Where <CurrencyInfo.curyInfoID, Equal <Required <DRSchedule.curyInfoID> > > > .SelectSingleBound(this, null, scheduleParameters.CuryInfoID);

                SingleScheduleCreator scheduleCreator = new SingleScheduleCreator(
                    this, new ARSubaccountProvider(this), this, this, this, this, this, FinPeriodRepository,
                    roundingFunction: x => PXDBCurrencyAttribute.Round(Schedule.Cache, Schedule.Current, x, CMPrecision.TRANCURY),
                    branchID: originalDocument.BranchID, isDraft: isDraft, location: location, currencyInfo: currencyInfo);

                if (existingSchedule == null)
                {
                    scheduleCreator.CreateOriginalSchedule(
                        scheduleParameters,
                        lineTotal);
                }
                else
                {
                    scheduleCreator.ReevaluateSchedule(
                        existingSchedule,
                        scheduleParameters,
                        lineTotal,
                        attachedToOriginalSchedule: false);
                }
            }
            else
            {
                if (originalDocument.DocType == ARDocType.CreditMemo || originalDocument.DocType == ARDocType.DebitMemo)
                {
                    bool accountForPostedTransactions = originalDocument.DocType == ARDocType.CreditMemo;

                    if (existingSchedule == null)
                    {
                        CreateRelatedSingleSchedule(scheduleParameters, DefScheduleID, lineTotal, isDraft, accountForPostedTransactions);
                    }
                    else
                    {
                        Location location = PXSelect <Location, Where <Location.locationID, Equal <Required <DRSchedule.bAccountLocID> > > > .SelectSingleBound(this, null, scheduleParameters.BAccountLocID);

                        CurrencyInfo currencyInfo = PXSelect <CurrencyInfo, Where <CurrencyInfo.curyInfoID, Equal <Required <DRSchedule.curyInfoID> > > > .SelectSingleBound(this, null, scheduleParameters.CuryInfoID);

                        var scheduleCreator = new SingleScheduleCreator(
                            this, new ARSubaccountProvider(this), this, this, this, this, this, FinPeriodRepository,
                            roundingFunction: x => PXCurrencyAttribute.BaseRound(this, x),
                            branchID: originalDocument.BranchID, isDraft: !accountForPostedTransactions,
                            location: location, currencyInfo: currencyInfo);

                        scheduleCreator.ReevaluateSchedule(
                            existingSchedule,
                            scheduleParameters,
                            lineTotal,
                            attachedToOriginalSchedule: true);
                    }
                }
            }
        }
예제 #8
0
        private void CreateRelatedSingleSchedule(DRScheduleParameters scheduleParameters, int?defScheduleID, Amount tranAmt, bool isDraft, bool accountForPostedTransactions)
        {
            DRSchedule relatedSchedule = (this as IDREntityStorage).CreateCopy(scheduleParameters);

            relatedSchedule.IsDraft  = isDraft;
            relatedSchedule.IsCustom = false;

            relatedSchedule = Schedule.Insert(relatedSchedule);

            DRSchedule originalDeferralSchedule = GetDeferralSchedule(defScheduleID);

            DRScheduleDetail originalDetailsTotalDetail = PXSelectGroupBy <
                DRScheduleDetail,
                Where <
                    DRScheduleDetail.scheduleID, Equal <Required <DRScheduleDetail.scheduleID> > >, Aggregate <Sum <DRScheduleDetail.curyTotalAmt> > >
                                                          .Select(this, originalDeferralSchedule.ScheduleID);

            decimal originalDetailsTotal = originalDetailsTotalDetail.CuryTotalAmt ?? 0m;
            decimal adjustmentTotal      = tranAmt.Cury.Value;

            decimal newDetailTotal = 0m;

            var originalDetails = PXSelectJoin <DRScheduleDetail,
                                                LeftJoin <ARTran,
                                                          On <DRScheduleDetail.lineNbr, Equal <ARTran.lineNbr> >,
                                                          InnerJoin <InventoryItem,
                                                                     On <ARTran.inventoryID, Equal <InventoryItem.inventoryID> >,
                                                                     LeftJoin <INComponent,
                                                                               On <DRScheduleDetail.componentID, Equal <INComponent.inventoryID> >,
                                                                               InnerJoin <DRDeferredCode,
                                                                                          On <ARTran.deferredCode, Equal <DRDeferredCode.deferredCodeID> > > > > >,
                                                Where <DRScheduleDetail.scheduleID, Equal <Required <DRSchedule.scheduleID> >,
                                                       And <ARTran.tranType, Equal <Required <DRSchedule.docType> >,
                                                            And <ARTran.refNbr, Equal <Required <DRSchedule.refNbr> > > > > > .Select(this, defScheduleID, scheduleParameters.DocType, scheduleParameters.RefNbr);

            foreach (PXResult <DRScheduleDetail, ARTran, InventoryItem, INComponent, DRDeferredCode> item in originalDetails)
            {
                DRScheduleDetail originalDetail = item;
                ARTran           tran           = item;
                InventoryItem    inventoryItem  = item;
                INComponent      inComponent    = item;
                DRDeferredCode   defCode        = item;


                decimal detailPartRaw = originalDetailsTotal == 0 ? 0 :
                                        originalDetail.CuryTotalAmt.Value * adjustmentTotal / originalDetailsTotal;

                decimal detailPart = PXDBCurrencyAttribute.BaseRound(this, detailPartRaw);

                decimal takeFromPostedRaw = 0;

                if (accountForPostedTransactions && originalDetail.CuryTotalAmt.Value != 0)
                {
                    takeFromPostedRaw =
                        detailPartRaw * (originalDetail.CuryTotalAmt.Value - originalDetail.CuryDefAmt.Value) / originalDetail.CuryTotalAmt.Value;
                }

                decimal takeFromPosted = PXDBCurrencyAttribute.BaseRound(this, takeFromPostedRaw);

                decimal adjustmentDeferredAmountRaw = detailPartRaw - takeFromPosted;
                decimal adjustmentDeferredAmount    = PXDBCurrencyAttribute.BaseRound(this, adjustmentDeferredAmountRaw);

                INComponent    inventoryItemComponent = null;
                DRDeferredCode componentDeferralCode  = null;

                if (inventoryItem != null && inComponent != null)
                {
                    inventoryItemComponent = GetInventoryItemComponent(inventoryItem.InventoryID, originalDetail.ComponentID);

                    if (inventoryItemComponent != null)
                    {
                        componentDeferralCode = PXSelect <
                            DRDeferredCode,
                            Where <
                                DRDeferredCode.deferredCodeID, Equal <Required <DRDeferredCode.deferredCodeID> > > >
                                                .Select(this, inventoryItemComponent.DeferredCode);
                    }
                }

                InventoryItem component = GetInventoryItem(originalDetail.ComponentID);

                DRScheduleDetail relatedScheduleDetail;

                if (componentDeferralCode != null)
                {
                    // Use component's deferral code
                    // -
                    relatedScheduleDetail = InsertScheduleDetail(
                        tran.BranchID,
                        relatedSchedule,
                        inventoryItemComponent,
                        component,
                        componentDeferralCode,
                        detailPart,
                        originalDetail.DefAcctID,
                        originalDetail.DefSubID,
                        isDraft);
                }
                else
                {
                    // Use deferral code and accounts from the document line
                    // -
                    relatedScheduleDetail = InsertScheduleDetail(
                        tran.BranchID,
                        relatedSchedule,
                        component == null ? DRScheduleDetail.EmptyComponentID : component.InventoryID,
                        defCode,
                        detailPart,
                        originalDetail.DefAcctID,
                        originalDetail.DefSubID,
                        tran.AccountID,
                        tran.SubID,
                        isDraft);
                }

                newDetailTotal += detailPart;

                IList <DRScheduleTran> relatedTransactions             = new List <DRScheduleTran>();
                DRDeferredCode         relatedTransactionsDeferralCode = componentDeferralCode ?? defCode;

                IEnumerable <DRScheduleTran> originalPostedTransactions = null;

                if (accountForPostedTransactions)
                {
                    originalPostedTransactions = PXSelect <
                        DRScheduleTran,
                        Where <
                            DRScheduleTran.status, Equal <DRScheduleTranStatus.PostedStatus>,
                            And <DRScheduleTran.scheduleID, Equal <Required <DRScheduleTran.scheduleID> >,
                                 And <DRScheduleTran.componentID, Equal <Required <DRScheduleTran.componentID> >,
                                      And <DRScheduleTran.detailLineNbr, Equal <Required <DRScheduleTran.detailLineNbr> >,
                                           And <DRScheduleTran.lineNbr, NotEqual <Required <DRScheduleTran.lineNbr> > > > > > > >
                                                 .Select(
                        this,
                        originalDetail.ScheduleID,
                        originalDetail.ComponentID,
                        originalDetail.DetailLineNbr,
                        originalDetail.CreditLineNbr)
                                                 .RowCast <DRScheduleTran>();
                }

                if (adjustmentDeferredAmount != 0m ||
                    accountForPostedTransactions && takeFromPosted != 0m)
                {
                    string requiredTransactionStatus =
                        relatedTransactionsDeferralCode.Method == DeferredMethodType.CashReceipt ?
                        DRScheduleTranStatus.Projected :
                        DRScheduleTranStatus.Open;

                    IEnumerable <DRScheduleTran> originalOpenTransactions = PXSelect <
                        DRScheduleTran,
                        Where <
                            DRScheduleTran.status, Equal <Required <DRScheduleTran.status> >,
                            And <DRScheduleTran.scheduleID, Equal <Required <DRScheduleTran.scheduleID> >,
                                 And <DRScheduleTran.componentID, Equal <Required <DRScheduleTran.componentID> >,
                                      And <DRScheduleTran.detailLineNbr, Equal <Required <DRScheduleTran.detailLineNbr> > > > > > >
                                                                            .Select(
                        this,
                        requiredTransactionStatus,
                        originalDetail.ScheduleID,
                        originalDetail.ComponentID,
                        originalDetail.DetailLineNbr)
                                                                            .RowCast <DRScheduleTran>();

                    IList <DRScheduleTran> relatedDeferralTransactions =
                        GetTransactionsGenerator(relatedTransactionsDeferralCode).GenerateRelatedTransactions(
                            relatedScheduleDetail,
                            originalOpenTransactions,
                            originalPostedTransactions,
                            adjustmentDeferredAmount,
                            takeFromPosted,
                            tran.BranchID);

                    foreach (DRScheduleTran deferralTransaction in relatedDeferralTransactions)
                    {
                        Transactions.Insert(deferralTransaction);
                        relatedTransactions.Add(deferralTransaction);
                    }
                }

                UpdateBalanceProjection(relatedTransactions, relatedScheduleDetail, defCode.AccountType);
            }
        }
예제 #9
0
        public virtual void RowInserted(PXCache sender, PXRowInsertedEventArgs e)
        {
            //When a new row is inserted there is 2 possible ways of handling it:
            //1. Sync the Discounts fields DiscAmt and DiscPct and calculate LineAmt as ExtPrice - DiscAmt. If DiscAmt <> 0 then ManualDisc flag is set.
            //2. Add line as is without changing any of the fields.
            //First Mode is typically executed when a user adds a line to Invoice from UI. Moreover the user enters Only Ext.Amt on the UI.
            //Second Mode is when a line from SOOrder is added to SOInvoice - in this case all discounts must be freezed and line must be added as is.

            if (!sender.Graph.IsCopyPasteContext)
            {
                AmountLineFields lineAmountsFields = GetDiscountDocumentLine(sender, e.Row);
                if (lineAmountsFields.FreezeManualDisc == true)
                {
                    lineAmountsFields.FreezeManualDisc = false;
                    return;
                }
                DiscountLineFields lineDiscountFields = GetDiscountedLine(sender, e.Row);
                if (lineDiscountFields.LineType == SOLineType.Discount)
                {
                    return;
                }

                if (lineDiscountFields.CuryDiscAmt != null && lineDiscountFields.CuryDiscAmt != 0 && lineAmountsFields.CuryExtPrice != 0)
                {
                    decimal?revCuryDiscAmt = null;
                    if (lineDiscountFields.DiscPct != null)
                    {
                        revCuryDiscAmt = PXDBCurrencyAttribute.RoundCury(sender, e.Row, (decimal)((lineAmountsFields.CuryExtPrice ?? 0m) / 100 * lineDiscountFields.DiscPct));
                    }
                    if (revCuryDiscAmt != null && revCuryDiscAmt != lineDiscountFields.CuryDiscAmt)
                    {
                        lineDiscountFields.DiscPct = 100 * lineDiscountFields.CuryDiscAmt / lineAmountsFields.CuryExtPrice;
                    }
                    if (sender.Graph.IsContractBasedAPI)
                    {
                        sender.SetValue(e.Row, lineDiscountFields.GetField <DiscountLineFields.manualDisc>().Name, true);
                        sender.SetValueExt(e.Row, lineAmountsFields.GetField <AmountLineFields.curyLineAmount>().Name, lineAmountsFields.CuryExtPrice - lineDiscountFields.CuryDiscAmt);
                    }
                    else
                    {
                        sender.SetValue(e.Row, lineAmountsFields.GetField <AmountLineFields.curyLineAmount>().Name, lineAmountsFields.CuryExtPrice - lineDiscountFields.CuryDiscAmt);
                    }
                }
                else if (lineDiscountFields.DiscPct != null && lineDiscountFields.DiscPct != 0)
                {
                    lineDiscountFields.CuryDiscAmt = (lineAmountsFields.CuryExtPrice ?? 0) * (lineDiscountFields.DiscPct ?? 0) * 0.01m;
                    if (sender.Graph.IsContractBasedAPI)
                    {
                        sender.SetValue(e.Row, lineDiscountFields.GetField <DiscountLineFields.manualDisc>().Name, true);
                        sender.SetValueExt(e.Row, lineAmountsFields.GetField <AmountLineFields.curyLineAmount>().Name, lineAmountsFields.CuryExtPrice - lineDiscountFields.CuryDiscAmt);
                    }
                    else
                    {
                        sender.SetValue(e.Row, lineAmountsFields.GetField <AmountLineFields.curyLineAmount>().Name, lineAmountsFields.CuryExtPrice - lineDiscountFields.CuryDiscAmt);
                    }
                }
                else if (lineAmountsFields.CuryExtPrice != null && lineAmountsFields.CuryExtPrice != 0m && (lineAmountsFields.CuryLineAmount == null || lineAmountsFields.CuryLineAmount == 0m))
                {
                    if (sender.Graph.IsContractBasedAPI)
                    {
                        sender.SetValueExt(e.Row, lineAmountsFields.GetField <AmountLineFields.curyLineAmount>().Name, lineAmountsFields.CuryExtPrice);
                    }
                    else
                    {
                        sender.SetValue(e.Row, lineAmountsFields.GetField <AmountLineFields.curyLineAmount>().Name, lineAmountsFields.CuryExtPrice);
                    }
                }
            }
        }
        protected virtual void TaxAdjustment_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            TaxAdjustment doc = e.Row as TaxAdjustment;

            if (doc == null)
            {
                return;
            }

            bool isAdjustmentReleased = doc.Released == true;

            cache.AllowDelete = !isAdjustmentReleased;
            cache.AllowUpdate = !isAdjustmentReleased;

            Transactions.Cache.SetAllEditPermissions(!isAdjustmentReleased);
            PXUIFieldAttribute.SetEnabled(cache, doc, !isAdjustmentReleased);
            reverseAdjustment.SetEnabled(isAdjustmentReleased);

            if (isAdjustmentReleased)
            {
                release.SetEnabled(false);
            }
            else
            {
                PXDBCurrencyAttribute.SetBaseCalc <TaxAdjustment.curyDocBal>(cache, null, true);

                PXUIFieldAttribute.SetEnabled <TaxAdjustment.status>(cache, doc, false);
                PXUIFieldAttribute.SetEnabled <TaxAdjustment.curyDocBal>(cache, doc, false);
                PXUIFieldAttribute.SetEnabled <TaxAdjustment.batchNbr>(cache, doc, false);

                release.SetEnabled(doc.Hold == false);
                ValidateDocDate(cache, doc);
            }

            PXUIFieldAttribute.SetEnabled <TaxAdjustment.docType>(cache, doc);
            PXUIFieldAttribute.SetEnabled <TaxAdjustment.refNbr>(cache, doc);
            PXUIFieldAttribute.SetEnabled <TaxAdjustment.curyID>(cache, doc, false);
            PXUIFieldAttribute.SetVisible <TaxAdjustment.curyID>(cache, doc, PXAccess.FeatureInstalled <FeaturesSet.multicurrency>());

            editVendor.SetEnabled(vendor.Current != null);
            bool tranExist = (TaxTran)this.Transactions.SelectWindowed(0, 1) != null;

            PXUIFieldAttribute.SetEnabled <TaxAdjustment.vendorID>(cache, doc, !tranExist);

            cache.RaiseExceptionHandling <TaxAdjustment.docDate>(doc, doc.DocDate, null);

            if (doc?.BranchID == null || doc.VendorID == null || doc.DocDate == null)
            {
                return;
            }

            TaxPeriod taxPeriod = GetTaxPeriodForTaxAdjustment(doc);

            if (taxPeriod == null)
            {
                cache.RaiseExceptionHandling <TaxAdjustment.docDate>(doc, doc.DocDate,
                                                                     new PXSetPropertyException(Messages.DateBelongsToNonExistingPeriod, PXErrorLevel.Warning));
            }
            else if (taxPeriod.Status == TaxPeriodStatus.Closed)
            {
                cache.RaiseExceptionHandling <TaxAdjustment.docDate>(doc, doc.DocDate,
                                                                     new PXSetPropertyException(Messages.DateBelongsToClosedPeriod, PXErrorLevel.Warning));
            }
        }
        public virtual void RevalueInventory(INUpdateStdCostRecord itemsite)
        {
            using (new PXConnectionScope())
            {
                using (PXTransactionScope ts = new PXTransactionScope())
                {
                    if (je.adjustment.Current == null)
                    {
                        je.adjustment.Cache.Insert();
                    }

                    foreach (
                        PXResult <INCostStatus, InventoryItem, INSite, INPostClass, INItemSite> res in
                        incoststatus.View.SelectMultiBound(new object[] { itemsite }))
                    {
                        INCostStatus layer = res;
                        INSite       site  = res;
                        INTran       tran  = new INTran();

                        try
                        {
                            ValidateProjectLocation(site, res);
                        }
                        catch (PXException ex)
                        {
                            PXProcessing <INUpdateStdCostRecord> .SetError(ex.Message);

                            continue;
                        }

                        if (((INCostStatus)res).LayerType == INLayerType.Oversold)
                        {
                            tran.TranType = INTranType.NegativeCostAdjustment;
                        }
                        else
                        {
                            tran.TranType = INTranType.StandardCostAdjustment;
                        }
                        tran.BranchID   = site.BranchID;
                        tran.InvtAcctID = layer.AccountID;
                        tran.InvtSubID  = layer.SubID;
                        tran.AcctID     = INReleaseProcess.GetAccountDefaults <INPostClass.stdCstRevAcctID>
                                              (je, (InventoryItem)res, (INSite)res, (INPostClass)res);
                        tran.SubID = INReleaseProcess.GetAccountDefaults <INPostClass.stdCstRevSubID>
                                         (je, (InventoryItem)res, (INSite)res, (INPostClass)res);

                        tran.InventoryID = layer.InventoryID;
                        tran.SubItemID   = layer.CostSubItemID;
                        tran.SiteID      = layer.CostSiteID;
                        tran.Qty         = 0m;
                        tran.TranCost    = PXDBCurrencyAttribute.BaseRound(this, (decimal)(layer.QtyOnHand * itemsite.StdCost)) -
                                           layer.TotalCost;

                        je.transactions.Insert(tran);
                    }

                    if (je.transactions.Select().Count == 0)
                    {
                        je.Clear();
                    }
                    else
                    {
                        je.Save.Press();
                        PXProcessing <INUpdateStdCostRecord> .SetInfo(PXMessages.LocalizeFormatNoPrefixNLA(Messages.AdjstmentCreated, je.adjustment.Current.RefNbr));
                    }

                    ts.Complete();
                }
            }
        }
        public virtual void UpdateStdCost(INUpdateStdCostRecord itemsite)
        {
            using (new PXConnectionScope())
            {
                using (PXTransactionScope ts = new PXTransactionScope())
                {
                    //will be true for non-stock items as well
                    if (itemsite.StdCostOverride == false)
                    {
                        PXDatabase.Update <INItemSite>(
                            new PXDataFieldAssign("StdCost", PXDbType.DirectExpression, "PendingStdCost"),
                            new PXDataFieldAssign("StdCostDate", PXDbType.DateTime, itemsite.PendingStdCostDate),
                            new PXDataFieldAssign("PendingStdCost", PXDbType.Decimal, 0m),
                            new PXDataFieldAssign("PendingStdCostDate", PXDbType.DateTime, null),
                            new PXDataFieldAssign("LastStdCost", PXDbType.DirectExpression, "StdCost"),
                            new PXDataFieldRestrict("InventoryID", PXDbType.Int, itemsite.InventoryID),
                            new PXDataFieldRestrict("StdCostOverride", PXDbType.Bit, false),
                            new PXDataFieldRestrict("PendingStdCostDate", PXDbType.DateTime, 4, itemsite.PendingStdCostDate, PXComp.LE));

                        PXDatabase.Update <InventoryItem>(
                            new PXDataFieldAssign("StdCost", PXDbType.DirectExpression, "PendingStdCost"),
                            new PXDataFieldAssign("StdCostDate", PXDbType.DateTime, itemsite.PendingStdCostDate),
                            new PXDataFieldAssign("PendingStdCost", PXDbType.Decimal, 0m),
                            new PXDataFieldAssign("PendingStdCostDate", PXDbType.DateTime, null),
                            new PXDataFieldAssign("LastStdCost", PXDbType.DirectExpression, "StdCost"),
                            new PXDataFieldRestrict("InventoryID", PXDbType.Int, itemsite.InventoryID),
                            new PXDataFieldRestrict("PendingStdCostDate", PXDbType.DateTime, 4, itemsite.PendingStdCostDate, PXComp.LE));
                    }
                    else
                    {
                        PXDatabase.Update <INItemSite>(
                            new PXDataFieldAssign("StdCost", PXDbType.DirectExpression, "PendingStdCost"),
                            new PXDataFieldAssign("StdCostDate", PXDbType.DateTime, itemsite.PendingStdCostDate),
                            new PXDataFieldAssign("PendingStdCost", PXDbType.Decimal, 0m),
                            new PXDataFieldAssign("PendingStdCostDate", PXDbType.DateTime, null),
                            new PXDataFieldAssign("LastStdCost", PXDbType.DirectExpression, "StdCost"),
                            new PXDataFieldRestrict("InventoryID", PXDbType.Int, itemsite.InventoryID),
                            new PXDataFieldRestrict("SiteID", PXDbType.Int, itemsite.SiteID),
                            new PXDataFieldRestrict("PendingStdCostDate", PXDbType.DateTime, 4, itemsite.PendingStdCostDate, PXComp.LE));
                    }

                    if (je.adjustment.Current == null)
                    {
                        je.adjustment.Cache.Insert();
                    }

                    foreach (
                        PXResult <INCostStatus, InventoryItem, INSite, INPostClass, INItemSite> res in
                        incoststatus.View.SelectMultiBound(new object[] { je.adjustment.Current, itemsite }))
                    {
                        INCostStatus layer = res;
                        INSite       site  = res;
                        INTran       tran  = new INTran();

                        try
                        {
                            ValidateProjectLocation(site, res);
                        }
                        catch (PXException ex)
                        {
                            PXProcessing <INUpdateStdCostRecord> .SetError(ex.Message);

                            continue;
                        }

                        if (((INCostStatus)res).LayerType == INLayerType.Oversold)
                        {
                            tran.TranType = INTranType.NegativeCostAdjustment;
                        }
                        else
                        {
                            tran.TranType = INTranType.StandardCostAdjustment;
                        }
                        tran.BranchID   = site.BranchID;
                        tran.InvtAcctID = layer.AccountID;
                        tran.InvtSubID  = layer.SubID;
                        tran.AcctID     = INReleaseProcess.GetAccountDefaults <INPostClass.stdCstRevAcctID>
                                              (je, (InventoryItem)res, (INSite)res, (INPostClass)res);
                        tran.SubID = INReleaseProcess.GetAccountDefaults <INPostClass.stdCstRevSubID>
                                         (je, (InventoryItem)res, (INSite)res, (INPostClass)res);

                        tran.InventoryID = layer.InventoryID;
                        tran.SubItemID   = layer.CostSubItemID;
                        tran.SiteID      = layer.CostSiteID;
                        tran.Qty         = 0m;
                        tran.TranCost    = PXDBCurrencyAttribute.BaseRound(this, (decimal)(layer.QtyOnHand * itemsite.PendingStdCost)) -
                                           layer.TotalCost;

                        je.transactions.Insert(tran);
                    }

                    if (je.transactions.Select().Count == 0)
                    {
                        je.Clear();
                    }
                    else
                    {
                        je.Save.Press();
                        PXProcessing <INUpdateStdCostRecord> .SetInfo(PXMessages.LocalizeFormatNoPrefixNLA(Messages.AdjstmentCreated, je.adjustment.Current.RefNbr));
                    }
                    ts.Complete();
                }
            }
        }
예제 #13
0
			public Decimal CalcTaxableFromTotalAmount(
				PXCache cache,
				object row,
				HashSet<string> taxList,
				DateTime aDocDate,
				Decimal aCuryTotal)
			{
				IComparer<Tax> taxComparer = GetTaxComparer();
				taxComparer.ThrowOnNull(nameof(taxComparer));

				Decimal result = Decimal.Zero;
				PXGraph graph = cache.Graph;
				Dictionary<string, PXResult<Tax, TaxRev>> taxRates = GetTaxRevisionList(graph, aDocDate);
				List<PXResult<Tax, TaxRev>> orderedTaxList = new List<PXResult<Tax, TaxRev>>(taxList.Count);

				foreach (string taxID in taxList)
				{
					if (taxRates.TryGetValue(taxID, out PXResult<Tax, TaxRev> line))
					{
						int idx;
						for (idx = orderedTaxList.Count;
							(idx > 0) && taxComparer.Compare(orderedTaxList[idx - 1], line) > 0;
							idx--)
							;

						var tax = (Tax)line;
						if (_taxCalcMode != null && tax.TaxCalcLevel != CSTaxCalcLevel.CalcOnItemAmtPlusTaxAmt)
						{
							switch (_taxCalcMode)
							{
								case TaxCalculationMode.Net:
									tax.TaxCalcLevel = CSTaxCalcLevel.CalcOnItemAmt;
									break;

								case TaxCalculationMode.Gross:
									tax.TaxCalcLevel = CSTaxCalcLevel.Inclusive;
									break;
							}
						}
						orderedTaxList.Insert(idx, new PXResult<Tax, TaxRev>(tax, (TaxRev)line));
					}
				}

				Decimal rateInclusive = Decimal.Zero;
				Decimal rateLvl1 = Decimal.Zero;
				Decimal rateLvl2 = Decimal.Zero;

				foreach (PXResult<Tax, TaxRev> iRes in orderedTaxList)
				{
					Tax tax = iRes;
					TaxRev taxRev = iRes;
					Decimal multiplier = tax.ReverseTax == true ? Decimal.MinusOne : Decimal.One;

					if (tax.TaxType == CSTaxType.PerUnit)
					{
						PXTrace.WriteError(Messages.PerUnitTaxesNotSupportedOperation);
						throw new PXException(Messages.PerUnitTaxesNotSupportedOperation);
					}

					switch (tax.TaxCalcLevel)
					{
						case CSTaxCalcLevel.Inclusive:
							rateInclusive += multiplier * taxRev.TaxRate.Value;
							break;
						case CSTaxCalcLevel.CalcOnItemAmt:
							rateLvl1 += multiplier * taxRev.TaxRate.Value;
							break;
						case CSTaxCalcLevel.CalcOnItemAmtPlusTaxAmt:
							rateLvl2 += multiplier * taxRev.TaxRate.Value;
							break;
					}
				}

				decimal baseLvl2 = PXDBCurrencyAttribute.RoundCury(cache, row, aCuryTotal / (1 + rateLvl2 / 100), _precision);
				decimal baseLvl1 = PXDBCurrencyAttribute.RoundCury(cache, row, baseLvl2 / (1 + (rateLvl1 + rateInclusive) / 100), _precision);
				Decimal curyTaxTotal = decimal.Zero;
				Decimal curyTax2Total = decimal.Zero;

				foreach (PXResult<Tax, TaxRev> iRes in orderedTaxList)
				{
					Tax tax = iRes;
					TaxRev taxRev = iRes;
					Decimal multiplier = tax.ReverseTax == true ? Decimal.MinusOne : Decimal.One;
					switch (tax.TaxCalcLevel)
					{
						case CSTaxCalcLevel.Inclusive:
							break;
						case CSTaxCalcLevel.CalcOnItemAmt:
							curyTaxTotal += multiplier * PXDBCurrencyAttribute.RoundCury(cache, row, (baseLvl1 * taxRev.TaxRate / 100m) ?? 0m, _precision);
							break;
						case CSTaxCalcLevel.CalcOnItemAmtPlusTaxAmt:
							curyTax2Total += multiplier * PXDBCurrencyAttribute.RoundCury(cache, row, (baseLvl2 * taxRev.TaxRate / 100m) ?? 0m, _precision);
							break;
					}
				}
				result = aCuryTotal - curyTaxTotal - curyTax2Total;
				return result;
			}
예제 #14
0
        public virtual List <Balance> Run(PMTask task)
        {
            if (task.BillingID == null)
            {
                throw new PXException(Messages.BillingIDIsNotDefined);
            }

            Dictionary <string, Balance> balances = new Dictionary <string, Balance>();

            DateTime?     lastDate;
            List <PMTran> expenseTrans   = CreateExpenseTransactions(task, out lastDate);
            List <long>   expenseTranIds = new List <long>();

            Debug.Print("Created Expense Transactions:");
            Debug.Indent();
            foreach (PMTran tran in expenseTrans)
            {
                expenseTranIds.Add(tran.TranID.Value);
                Debug.Print("TranID:{0} AccountGroup:{1}, InventoryID={2}, Qty={3}, Amt={4}, Allocated={5}, Released={6}, Billed={7}, Date={8}", tran.TranID, AccountGroupFromID(tran.AccountGroupID), InventoryFromID(tran.InventoryID), tran.Qty, tran.Amount, tran.Allocated, tran.Released, tran.Billed, tran.Date);
            }
            Debug.Unindent();

            if (expenseTrans.Count == 0)
            {
                PXTrace.WriteError(Messages.FailedToEmulateExpenses, task.TaskCD);
                return(new List <Balance>());
            }

            PMAllocator ae = PXGraph.CreateInstance <PMAllocator>();

            ae.SourceTransactions = expenseTrans;
            foreach (PMTran tran in expenseTrans)
            {
                ae.Transactions.Insert(tran);
            }
            ae.OverrideAllocationDate = lastDate;
            ae.Execute(task);
            Debug.Print("After Allocation:");
            Debug.Indent();
            foreach (PMTran tran in ae.Transactions.Cache.Inserted)
            {
                tran.Released = true;
                Transactions.Cache.Update(tran);

                if (expenseTranIds.Contains(tran.TranID.Value))
                {
                    continue;
                }

                int    inventoryID = tran.InventoryID ?? PMInventorySelectorAttribute.EmptyInventoryID;
                string key         = string.Format("{0}.{1}", tran.AccountGroupID, inventoryID);

                if (!balances.ContainsKey(key))
                {
                    Balance b = new Balance();
                    b.AccountGroupID = tran.AccountGroupID.Value;
                    b.InventoryID    = inventoryID;

                    balances.Add(key, b);
                }

                Debug.Print("TranID:{0} AccountGroup:{1}, InventoryID={2}, Qty={3}, Amt={4}, Allocated={5}, Released={6}, Billed={7}, Date={8}", tran.TranID, AccountGroupFromID(tran.AccountGroupID), InventoryFromID(tran.InventoryID), tran.Qty, tran.Amount, tran.Allocated, tran.Released, tran.Billed, tran.Date);
            }
            Debug.Unindent();

            DateTime billingDate = lastDate.Value.AddDays(1);

            //Get ARTrans for Bill:
            Debug.Print("Bill using the following Billing date={0}", billingDate);

            PMBillEngine engine = PXGraph.CreateInstance <PMBillEngine>();

            engine.IsEmulation = true;
            engine.FieldVerifying.AddHandler <PMTran.projectID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });
            engine.FieldVerifying.AddHandler <PMTran.taskID>((PXCache sender, PXFieldVerifyingEventArgs e) => { e.Cancel = true; });
            Debug.Print("Transactions passed to BillTask:");
            Debug.Indent();
            foreach (PMTran tran in Transactions.Cache.Cached)
            {
                if (expenseTranIds.Contains(tran.TranID.Value))
                {
                    continue;
                }
                engine.Transactions.Insert(tran);
                Debug.Print("TranID:{0} AccountGroup:{1}, InventoryID={2}, Qty={3}, Amt={4}, Allocated={5}, Released={6}, Billed={7}, Date={8}", tran.TranID, AccountGroupFromID(tran.AccountGroupID), InventoryFromID(tran.InventoryID), tran.Qty, tran.Amount, tran.Allocated, tran.Released, tran.Billed, tran.Date);
            }
            Debug.Unindent();

            List <PMBillEngine.BillingData> arTrans = engine.BillTask(task, billingDate);

            //Create ARInvoice to DEFAULT Accounts and SubAccounts.
            ARInvoiceEntry invoiceEntry = PXGraph.CreateInstance <ARInvoiceEntry>();

            //Project and Task is in Planning State - thus suppress verification:
            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; });
            ARInvoice invoice = new ARInvoice();

            invoice.DocType = ARDocType.Invoice;

            invoice = PXCache <ARInvoice> .CreateCopy(invoiceEntry.Document.Insert(invoice));

            invoice.DocDate            = billingDate;
            invoice.CustomerID         = task.CustomerID;
            invoice.CustomerLocationID = task.LocationID;
            invoice.ProjectID          = task.ProjectID;
            invoice = (ARInvoice)invoiceEntry.Document.Update(invoice);

            CurrencyInfo curyinfo = (CurrencyInfo)invoiceEntry.Caches[typeof(CurrencyInfo)].Current;

            foreach (PMBillEngine.BillingData data in arTrans)
            {
                decimal curyamount;
                PXDBCurrencyAttribute.CuryConvCury(invoiceEntry.Caches[typeof(CurrencyInfo)], curyinfo, (data.Tran.UnitPrice ?? 0), out curyamount);
                data.Tran.CuryUnitPrice = curyamount;
                PXDBCurrencyAttribute.CuryConvCury(invoiceEntry.Caches[typeof(CurrencyInfo)], curyinfo, (data.Tran.ExtPrice ?? 0), out curyamount);
                data.Tran.CuryExtPrice     = curyamount;
                data.Tran.CuryTranAmt      = data.Tran.CuryExtPrice;
                data.Tran.FreezeManualDisc = true;
                ARTran newTran = (ARTran)invoiceEntry.Caches[typeof(ARTran)].Insert(data.Tran);
            }

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

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

            Debug.Print("AR Trans:");
            Debug.Indent();

            foreach (ARTran tran in invoiceEntry.Transactions.Select())
            {
                if (tran.TaskID == task.TaskID)
                {
                    Debug.Print("InventoryID={0}, Qty={1}, Amt={2}", InventoryFromID(tran.InventoryID), tran.Qty, tran.TranAmt);

                    Account acct = PXSelect <Account, Where <Account.accountID, Equal <Required <Account.accountID> > > > .Select(invoiceEntry, tran.AccountID);

                    if (acct.AccountGroupID == null)
                    {
                        throw new PXException("Failed to emulate billing. The Sales Account in the Invoice is not mapped to any Account Group.");
                    }

                    string key = string.Format("{0}.{1}", acct.AccountGroupID, tran.InventoryID ?? PMInventorySelectorAttribute.EmptyInventoryID);

                    if (balances.ContainsKey(key))
                    {
                        balances[key].Amount   += tran.TranAmt ?? 0;
                        balances[key].Quantity += tran.Qty ?? 0;
                    }
                    else
                    {
                        Balance b = new Balance();
                        b.AccountGroupID = acct.AccountGroupID.Value;
                        b.InventoryID    = tran.InventoryID ?? PMInventorySelectorAttribute.EmptyInventoryID;
                        b.Amount         = tran.TranAmt ?? 0;
                        b.Quantity       = tran.Qty ?? 0;

                        balances.Add(key, b);
                    }
                }
            }

            return(new List <Balance>(balances.Values));
        }
        public virtual decimal AllocateOverRCTLine(
            PXGraph graph,
            List <POReceiptLineAdjustment> result,
            AllocationItem allocationItem,
            decimal toDistribute,
            Int32?branchID)
        {
            // the artificial object is used for allocating the landed cost amount between splits (by quantity)
            var nAllocationItem = new AllocationItem()
            {
                LandedCostCode = new LandedCostCode()
                {
                    AllocationMethod = LandedCostAllocationMethod.ByQuantity
                },
                ReceiptLine = allocationItem.ReceiptLine,
            };

            InventoryItem ii = InventoryItem.PK.Find(graph, allocationItem.ReceiptLine.InventoryID.Value);
            bool          requireLotSerial = (ii.ValMethod == INValMethod.Specific);

            List <Type> bql = new List <Type>(16)
            {
                typeof(Select4 <, ,>),
                typeof(POReceiptLineSplit),
                typeof(Where <POReceiptLineSplit.receiptType, Equal <Required <POReceiptLine.receiptType> >, And <POReceiptLineSplit.receiptNbr, Equal <Required <POReceiptLine.receiptNbr> >, And <POReceiptLineSplit.lineNbr, Equal <Required <POReceiptLine.lineNbr> > > > >),
                typeof(Aggregate <>),
                typeof(GroupBy <,>),
                typeof(POReceiptLineSplit.locationID),
                typeof(GroupBy <,>),
                typeof(POReceiptLineSplit.subItemID),
                typeof(Sum <>),
                typeof(POReceiptLineSplit.baseQty),
            };

            if (requireLotSerial)
            {
                bql.Insert(bql.Count - 2, typeof(GroupBy <,>));
                bql.Insert(bql.Count - 2, typeof(POReceiptLineSplit.lotSerialNbr));
            }

            PXView splitsView = new PXView(graph, false, BqlCommand.CreateInstance(bql.ToArray()));
            var    splits     = splitsView.SelectMulti(allocationItem.ReceiptLine.ReceiptType, allocationItem.ReceiptLine.ReceiptNbr,
                                                       allocationItem.ReceiptLine.LineNbr);

            bool               hasSplits      = false;
            decimal            baseTotal      = GetBaseValue(nAllocationItem);
            decimal            allocatedBase  = 0m;
            decimal            allocatingBase = 0m;
            decimal            allocatedAmt   = 0m;
            POReceiptLineSplit maxSplit       = null;

            foreach (POReceiptLineSplit split in splits)
            {
                hasSplits       = true;
                allocatingBase += split.BaseQty ?? 0m;
                decimal handledSplitsAmt = (baseTotal == 0m) ? 0m : (allocatedBase + allocatingBase) * toDistribute / baseTotal;
                handledSplitsAmt = PXDBCurrencyAttribute.BaseRound(graph, handledSplitsAmt);
                decimal shareAmt = handledSplitsAmt - allocatedAmt;

                if (maxSplit == null || maxSplit.BaseQty < split.BaseQty)
                {
                    maxSplit = split;
                }

                if (shareAmt != 0m)
                {
                    POReceiptLine newPOReceiptLine = PXCache <POReceiptLine> .CreateCopy(allocationItem.ReceiptLine);

                    newPOReceiptLine.LocationID   = maxSplit.LocationID;
                    newPOReceiptLine.SiteID       = maxSplit.SiteID;
                    newPOReceiptLine.SubItemID    = maxSplit.SubItemID;
                    newPOReceiptLine.LotSerialNbr = requireLotSerial ? maxSplit.LotSerialNbr : null;

                    var adj = CreateReceiptLineAdjustment(allocationItem, newPOReceiptLine, shareAmt, branchID);

                    result.Add(adj);
                    allocatedAmt  += shareAmt;
                    allocatedBase += allocatingBase;
                    allocatingBase = 0m;
                    maxSplit       = null;
                }
            }
            if (!hasSplits)
            {
                decimal shareAmt = toDistribute;
                shareAmt = PXDBCurrencyAttribute.BaseRound(graph, shareAmt);
                if (shareAmt != 0m)
                {
                    var adj = CreateReceiptLineAdjustment(allocationItem, null, shareAmt, branchID);

                    result.Add(adj);
                }

                allocatedAmt = shareAmt;
            }
            return(allocatedAmt);
        }
예제 #16
0
        public static List <INCostAdjustmentInfo> AllocateOverRCTLines(IEnumerable <POReceiptLine> aLines, PXCache aCache, LandedCostCode aLCCode, LandedCostTran aTran, IEnumerable <LandedCostTranSplit> aSplits)
        {
            List <INCostAdjustmentInfo> result = new List <INCostAdjustmentInfo>();
            Decimal toDistribute    = aTran.LCAmount.Value;
            Decimal baseTotal       = decimal.Zero;
            int     distributeCount = 0;

            foreach (POReceiptLine iDet in aLines)
            {
                if (LandedCostUtils.IsApplicable(aTran, aSplits, aLCCode, iDet))
                {
                    baseTotal += LandedCostUtils.GetBaseValue(aLCCode, iDet);
                    distributeCount++;
                }
            }
            Decimal leftToDistribute  = toDistribute;
            INCostAdjustmentInfo last = null;

            foreach (POReceiptLine iDet in aLines)
            {
                if (LandedCostUtils.IsApplicable(aTran, aSplits, aLCCode, iDet))
                {
                    decimal shareAmt = Decimal.Zero;
                    if (distributeCount > 1)
                    {
                        shareAmt = LandedCostUtils.CalcAllocationValue(aLCCode, iDet, baseTotal, toDistribute);
                        shareAmt = PXDBCurrencyAttribute.BaseRound(aCache.Graph, shareAmt);
                    }
                    else
                    {
                        shareAmt = toDistribute;
                    }
                    if (shareAmt != Decimal.Zero)
                    {
                        leftToDistribute -= shareAmt;
                        INCostAdjustmentInfo newLine = new INCostAdjustmentInfo(iDet);
                        //POReceiptLine newLine = (POReceiptLine)aCache.CreateCopy(iDet);
                        //newLine.CuryExtCost = shareAmt;
                        //newLine.ExtCost = shareAmt;
                        newLine.AdjustmentAmount = shareAmt;
                        if (last == null || Math.Abs(last.AdjustmentAmount) < Math.Abs(newLine.AdjustmentAmount))
                        {
                            last = newLine;
                        }
                        result.Add(newLine);
                    }
                }
            }
            if (leftToDistribute != Decimal.Zero)
            {
                if (last == null)
                {
                    last = new INCostAdjustmentInfo();
                    last.AdjustmentAmount = leftToDistribute;
                    result.Add(last);
                }
                else
                {
                    last.AdjustmentAmount += leftToDistribute;
                }
            }
            return(result);
        }