Beispiel #1
0
        public static bool CalculateDiscountedTaxes(PXCache cache, ARTaxTran artax, decimal cashDiscPercent)
        {
            bool?  result = null;
            object value  = null;

            IBqlCreator whereTaxable = (IBqlCreator)Activator.CreateInstance(typeof(WhereTaxable <Required <ARTaxTran.taxID> >));

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

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

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

            return(result == true);
        }
Beispiel #2
0
        private static void AddTaxesAndApplications(ARInvoiceEntry ie, PendingPPDCreditMemoApp doc, Customer customer, ARInvoice invoice)
        {
            ARTaxTran artaxMax               = null;
            decimal?  TaxTotal               = 0m;
            decimal?  InclusiveTotal         = 0m;
            decimal?  DiscountedTaxableTotal = 0m;
            decimal?  DiscountedPriceTotal   = 0m;
            decimal   CashDiscPercent        = (decimal)(doc.CuryAdjdPPDAmt / doc.InvCuryOrigDocAmt);

            PXResultset <ARTaxTran> taxes = PXSelectJoin <ARTaxTran,
                                                          InnerJoin <Tax, On <Tax.taxID, Equal <ARTaxTran.taxID> > >,
                                                          Where <ARTaxTran.module, Equal <BatchModule.moduleAR>,
                                                                 And <ARTaxTran.tranType, Equal <Required <ARTaxTran.tranType> >,
                                                                      And <ARTaxTran.refNbr, Equal <Required <ARTaxTran.refNbr> > > > > > .Select(ie, doc.AdjdDocType, doc.AdjdRefNbr);

            //add taxes
            foreach (PXResult <ARTaxTran, Tax> res in taxes)
            {
                Tax       tax   = res;
                ARTaxTran artax = PXCache <ARTaxTran> .CreateCopy(res);

                ARTaxTran artaxNew = ie.Taxes.Search <ARTaxTran.taxID>(artax.TaxID);

                if (artaxNew == null)
                {
                    artax.TranType    = null;
                    artax.RefNbr      = null;
                    artax.TaxPeriodID = null;
                    artax.Released    = false;
                    artax.Voided      = false;
                    artax.CuryInfoID  = invoice.CuryInfoID;

                    TaxBaseAttribute.SetTaxCalc <ARTran.taxCategoryID, ARTaxAttribute>(ie.Transactions.Cache, null, TaxCalc.NoCalc);
                    artaxNew = ie.Taxes.Insert(artax);

                    artaxNew.CuryTaxableAmt = 0m;
                    artaxNew.CuryTaxAmt     = 0m;
                    artaxNew.TaxRate        = artax.TaxRate;
                }

                bool isTaxable = CalculateDiscountedTaxes(ie.Taxes.Cache, artax, CashDiscPercent);
                DiscountedPriceTotal += artax.CuryDiscountedPrice;

                decimal?CuryTaxableAmt = artax.CuryTaxableAmt - artax.CuryDiscountedTaxableAmt;
                decimal?CuryTaxAmt     = artax.CuryTaxAmt - artax.CuryDiscountedPrice;

                artaxNew.CuryTaxableAmt += CuryTaxableAmt;
                artaxNew.CuryTaxAmt     += CuryTaxAmt;

                TaxBaseAttribute.SetTaxCalc <ARTran.taxCategoryID, ARTaxAttribute>(ie.Transactions.Cache, null, TaxCalc.ManualCalc);
                ie.Taxes.Update(artaxNew);

                if (isTaxable)
                {
                    DiscountedTaxableTotal += artax.CuryDiscountedTaxableAmt;
                    if (artaxMax == null || artaxNew.CuryTaxableAmt > artaxMax.CuryTaxableAmt)
                    {
                        artaxMax = artaxNew;
                    }
                }

                if (tax.TaxCalcLevel == CSTaxCalcLevel.Inclusive)
                {
                    InclusiveTotal += CuryTaxAmt;
                }
                else
                {
                    TaxTotal += CuryTaxAmt;
                }
            }

            //adjust taxes according to parent ARInvoice
            decimal?DiscountedInvTotal = doc.InvCuryOrigDocAmt - doc.InvCuryOrigDiscAmt;
            decimal?DiscountedDocTotal = DiscountedTaxableTotal + DiscountedPriceTotal;

            if (doc.InvCuryOrigDiscAmt == doc.CuryAdjdPPDAmt &&
                artaxMax != null &&
                doc.InvCuryVatTaxableTotal + doc.InvCuryTaxTotal == doc.InvCuryOrigDocAmt &&
                DiscountedDocTotal != DiscountedInvTotal)
            {
                artaxMax.CuryTaxableAmt += DiscountedDocTotal - DiscountedInvTotal;
                TaxBaseAttribute.SetTaxCalc <ARTran.taxCategoryID, ARTaxAttribute>(ie.Transactions.Cache, null, TaxCalc.ManualCalc);
                ie.Taxes.Update(artaxMax);
            }

            //add document details
            ARTran tranNew = ie.Transactions.Insert();

            tranNew.BranchID = doc.AdjdBranchID;
            using (new PXLocaleScope(customer.LocaleName))
                tranNew.TranDesc = string.Format("{0} {1}, {2} {3}", PXMessages.LocalizeNoPrefix(DocTypes[doc.AdjdDocType]), doc.AdjdRefNbr, PXMessages.LocalizeNoPrefix(Messages.Payment), doc.AdjgRefNbr);
            tranNew.CuryExtPrice         = doc.CuryAdjdPPDAmt - TaxTotal;
            tranNew.CuryTaxableAmt       = tranNew.CuryExtPrice - InclusiveTotal;
            tranNew.CuryTaxAmt           = TaxTotal + InclusiveTotal;
            tranNew.AccountID            = customer.DiscTakenAcctID;
            tranNew.SubID                = customer.DiscTakenSubID;
            tranNew.TaxCategoryID        = null;
            tranNew.IsFree               = true;
            tranNew.ManualDisc           = true;
            tranNew.CuryDiscAmt          = 0m;
            tranNew.DiscPct              = 0m;
            tranNew.GroupDiscountRate    = 1m;
            tranNew.DocumentDiscountRate = 1m;

            if (taxes.Count == 1)
            {
                ARTaxTran artax  = taxes[0];
                ARTran    artran = PXSelectJoin <ARTran,
                                                 InnerJoin <ARTax, On <ARTax.tranType, Equal <ARTran.tranType>,
                                                                       And <ARTax.refNbr, Equal <ARTran.refNbr>,
                                                                            And <ARTax.lineNbr, Equal <ARTran.lineNbr> > > > >,
                                                 Where <ARTax.tranType, Equal <Required <ARTax.tranType> >,
                                                        And <ARTax.refNbr, Equal <Required <ARTax.refNbr> >,
                                                             And <ARTax.taxID, Equal <Required <ARTax.taxID> > > > >,
                                                 OrderBy <Asc <ARTran.lineNbr> > > .SelectSingleBound(ie, null, artax.TranType, artax.RefNbr, artax.TaxID);

                if (artran != null)
                {
                    tranNew.TaxCategoryID = artran.TaxCategoryID;
                }
            }

            ie.Transactions.Update(tranNew);

            //add applications
            ARAdjust adj = new ARAdjust();

            adj.AdjdDocType = doc.AdjdDocType;
            adj.AdjdRefNbr  = doc.AdjdRefNbr;
            adj             = ie.Adjustments_1.Insert(adj);

            adj.CuryAdjgAmt = doc.InvCuryDocBal;
            ie.Adjustments_1.Update(adj);
        }
        protected virtual void ApplyTax(ARCashSale invoice, GetTaxResult result)
        {
            TaxZone taxZone = null;

            AP.Vendor vendor = null;
            if (result.TaxSummary.Length > 0)
            {
                taxZone = (TaxZone)Base.taxzone.View.SelectSingleBound(new object[] { invoice });
                vendor  = PXSelect <AP.Vendor, Where <AP.Vendor.bAccountID, Equal <Required <AP.Vendor.bAccountID> > > > .Select(Base, taxZone.TaxVendorID);

                if (vendor == null)
                {
                    throw new PXException(TX.Messages.ExternalTaxVendorNotFound);
                }

                if (vendor.SalesTaxAcctID == null)
                {
                    throw new PXException(TX.Messages.TaxPayableAccountNotSpecified, vendor.AcctCD);
                }

                if (vendor.SalesTaxSubID == null)
                {
                    throw new PXException(TX.Messages.TaxPayableSubNotSpecified, vendor.AcctCD);
                }
            }
            //Clear all existing Tax transactions:
            foreach (PXResult <ARTaxTran, Tax> res in Base.Taxes.View.SelectMultiBound(new object[] { invoice }))
            {
                ARTaxTran taxTran = (ARTaxTran)res;
                Base.Taxes.Delete(taxTran);
            }

            Base.Views.Caches.Add(typeof(Tax));

            for (int i = 0; i < result.TaxSummary.Length; i++)
            {
                string taxID = result.TaxSummary[i].TaxName;
                if (string.IsNullOrEmpty(taxID))
                {
                    taxID = result.TaxSummary[i].JurisCode;
                }

                if (string.IsNullOrEmpty(taxID))
                {
                    PXTrace.WriteInformation(Messages.EmptyValuesFromExternalTaxProvider);
                    continue;
                }

                CreateTax(Base, taxZone, vendor, result.TaxSummary[i], taxID);

                ARTaxTran tax = new ARTaxTran();
                tax.Module         = BatchModule.AR;
                tax.TranType       = invoice.DocType;
                tax.RefNbr         = invoice.RefNbr;
                tax.TaxID          = taxID;
                tax.CuryTaxAmt     = Math.Abs(result.TaxSummary[i].TaxAmount);
                tax.CuryTaxableAmt = Math.Abs(result.TaxSummary[i].TaxableAmount);
                tax.TaxRate        = Convert.ToDecimal(result.TaxSummary[i].Rate) * 100;
                tax.TaxType        = "S";
                tax.TaxBucketID    = 0;
                tax.AccountID      = vendor.SalesTaxAcctID;
                tax.SubID          = vendor.SalesTaxSubID;
                tax.JurisType      = result.TaxSummary[i].JurisType;
                tax.JurisName      = result.TaxSummary[i].JurisName;

                Base.Taxes.Insert(tax);
            }

            bool requireControlTotal = Base.arsetup.Current.RequireControlTotal == true;

            if (invoice.Hold != true)
            {
                Base.arsetup.Current.RequireControlTotal = false;
            }


            try
            {
                invoice.CuryTaxTotal = Math.Abs(result.TotalTaxAmount);
                Base.Document.Cache.SetValueExt <ARCashSale.isTaxSaved>(invoice, true);
            }
            finally
            {
                Base.arsetup.Current.RequireControlTotal = requireControlTotal;
            }
        }
Beispiel #4
0
        public virtual ARInvoice ReleaseRetainageProc(ARInvoice doc, RetainageOptions retainageOpts, bool isAutoRelease = false)
        {
            Base.Clear(PXClearOption.PreserveTimeStamp);

            if (retainageOpts.CuryRetainageAmt <= 0 || retainageOpts.CuryRetainageAmt > doc.CuryRetainageUnreleasedAmt)
            {
                throw new PXException(AP.Messages.IncorrectRetainageAmount);
            }

            // Magic. We need to prevent rewriting of CurrencyInfo.IsReadOnly
            // by true in CurrencyInfoView
            //
            Base.CurrentDocument.Cache.AllowUpdate = true;

            PXResult <ARInvoice, CurrencyInfo, Terms, Customer> resultDoc =
                ARInvoice_CurrencyInfo_Terms_Customer
                .SelectSingleBound(Base, null, doc.DocType, doc.RefNbr, doc.CustomerID)
                .Cast <PXResult <ARInvoice, CurrencyInfo, Terms, Customer> >()
                .First();

            CurrencyInfo info        = resultDoc;
            ARInvoice    origInvoice = resultDoc;
            Customer     customer    = resultDoc;

            CurrencyInfo new_info = PXCache <CurrencyInfo> .CreateCopy(info);

            new_info.CuryInfoID = null;
            new_info.IsReadOnly = false;
            new_info            = PXCache <CurrencyInfo> .CreateCopy(Base.currencyinfo.Insert(new_info));

            ARInvoice invoice = PXCache <ARInvoice> .CreateCopy(origInvoice);

            invoice.CuryInfoID = new_info.CuryInfoID;
            invoice.DocType    = ARDocType.Invoice;
            invoice.RefNbr     = null;
            invoice.LineCntr   = null;
            invoice.InvoiceNbr = origInvoice.InvoiceNbr;

            // Must be set for _RowSelected event handler
            //
            invoice.OpenDoc  = true;
            invoice.Released = false;

            Base.Document.Cache.SetDefaultExt <ARInvoice.isMigratedRecord>(invoice);
            Base.Document.Cache.SetDefaultExt <ARInvoice.hold>(invoice);
            invoice.BatchNbr   = null;
            invoice.ScheduleID = null;
            invoice.Scheduled  = false;
            invoice.NoteID     = null;

            invoice.DueDate         = null;
            invoice.DiscDate        = null;
            invoice.CuryOrigDiscAmt = 0m;
            invoice.OrigDocType     = origInvoice.DocType;
            invoice.OrigRefNbr      = origInvoice.RefNbr;
            invoice.OrigDocDate     = origInvoice.DocDate;

            invoice.CuryLineTotal       = 0m;
            invoice.IsTaxPosted         = false;
            invoice.IsTaxValid          = false;
            invoice.CuryVatTaxableTotal = 0m;
            invoice.CuryVatExemptTotal  = 0m;

            invoice.CuryDocBal     = 0m;
            invoice.CuryOrigDocAmt = retainageOpts.CuryRetainageAmt;
            invoice.Hold           = !isAutoRelease && Base.ARSetup.Current.HoldEntry == true;

            invoice.DocDate     = retainageOpts.DocDate;
            invoice.FinPeriodID = retainageOpts.FinPeriodID;

            Base.ClearRetainageSummary(invoice);
            invoice.RetainageApply      = false;
            invoice.IsRetainageDocument = true;

            invoice = Base.Document.Insert(invoice);

            if (new_info != null)
            {
                CurrencyInfo b_info = (CurrencyInfo)PXSelect <CurrencyInfo,
                                                              Where <CurrencyInfo.curyInfoID, Equal <Current <ARInvoice.curyInfoID> > > > .Select(Base);

                b_info.CuryID         = new_info.CuryID;
                b_info.CuryEffDate    = new_info.CuryEffDate;
                b_info.CuryRateTypeID = new_info.CuryRateTypeID;
                b_info.CuryRate       = new_info.CuryRate;
                b_info.RecipRate      = new_info.RecipRate;
                b_info.CuryMultDiv    = new_info.CuryMultDiv;
                Base.currencyinfo.Update(b_info);
            }

            decimal retainagePercent = (decimal)(retainageOpts.CuryRetainageAmt / doc.CuryRetainageTotal);

            PXResultset <ARTran> details = PXSelectGroupBy <ARTran,
                                                            Where <ARTran.tranType, Equal <Required <ARTran.tranType> >,
                                                                   And <ARTran.refNbr, Equal <Required <ARTran.refNbr> >,
                                                                        And <ARTran.curyRetainageAmt, NotEqual <decimal0> > > >,
                                                            Aggregate <
                                                                GroupBy <ARTran.taxCategoryID,
                                                                         Sum <ARTran.curyRetainageAmt> > > >
                                           .Select(Base, doc.DocType, doc.RefNbr);

            ARTran  tranNew       = null;
            decimal prevCuryTotal = 0m;

            TaxCalc oldTaxCalc = TaxBaseAttribute.GetTaxCalc <ARTran.taxCategoryID>(Base.Transactions.Cache, null);

            TaxBaseAttribute.SetTaxCalc <ARTran.taxCategoryID>(Base.Transactions.Cache, null, TaxCalc.ManualCalc);

            foreach (ARTran detail in details)
            {
                // Create ARTran record for chosen retainage amount,
                // clear all required fields to prevent tax calculation,
                // discount calculation and retainage calculation.
                // CuryUnitPrice = 0m and CuryExtPrice = 0m here to prevent their
                // FieldDefaulting events, because in our case default value
                // should be equal to zero.
                //
                tranNew = Base.Transactions.Insert(new ARTran
                {
                    CuryUnitPrice = 0m,
                    CuryExtPrice  = 0m
                });

                tranNew.BranchID      = origInvoice.BranchID;
                tranNew.TaxCategoryID = detail.TaxCategoryID;
                tranNew.AccountID     = origInvoice.RetainageAcctID;
                tranNew.SubID         = origInvoice.RetainageSubID;
                tranNew.ProjectID     = ProjectDefaultAttribute.NonProject();

                tranNew.Qty                  = 0m;
                tranNew.ManualDisc           = true;
                tranNew.DiscPct              = 0m;
                tranNew.CuryDiscAmt          = 0m;
                tranNew.RetainagePct         = 0m;
                tranNew.CuryRetainageAmt     = 0m;
                tranNew.CuryTaxableAmt       = 0m;
                tranNew.CuryTaxAmt           = 0;
                tranNew.GroupDiscountRate    = 1m;
                tranNew.DocumentDiscountRate = 1m;

                using (new PXLocaleScope(customer.LocaleName))
                {
                    tranNew.TranDesc = PXMessages.LocalizeFormatNoPrefix(
                        AP.Messages.RetainageForTransactionDescription,
                        ARDocTypeDict[origInvoice.DocType],
                        origInvoice.RefNbr);
                }

                prevCuryTotal        = (retainageOpts.CuryRetainageAmt ?? 0m) - (invoice.CuryDocBal ?? 0m);
                tranNew.CuryExtPrice = PXCurrencyAttribute.RoundCury(Base.Transactions.Cache, tranNew, (detail.CuryRetainageAmt ?? 0m) * retainagePercent);
                tranNew = Base.Transactions.Update(tranNew);
            }

            ClearCurrentDocumentDiscountDetails();

            // We should copy all taxes from the original document
            // because it is possible to add or delete them.
            //
            foreach (ARTaxTran artaxtran in PXSelect <ARTaxTran,
                                                      Where <ARTaxTran.module, Equal <BatchModule.moduleAR>,
                                                             And <ARTaxTran.tranType, Equal <Required <ARTaxTran.tranType> >,
                                                                  And <ARTaxTran.refNbr, Equal <Required <ARTaxTran.refNbr> > > > > >
                     .Select(Base, origInvoice.DocType, origInvoice.RefNbr)
                     .RowCast <ARTaxTran>()
                     .Where(row => row.CuryRetainedTaxAmt != 0m))
            {
                ARTaxTran new_artaxtran = Base.Taxes.Insert(new ARTaxTran
                {
                    TaxID = artaxtran.TaxID
                });

                if (new_artaxtran != null)
                {
                    new_artaxtran = PXCache <ARTaxTran> .CreateCopy(new_artaxtran);

                    new_artaxtran.TaxRate = artaxtran.TaxRate;
                    new_artaxtran         = Base.Taxes.Update(new_artaxtran);
                }
            }

            TaxBaseAttribute.SetTaxCalc <ARTran.taxCategoryID>(Base.Transactions.Cache, null, oldTaxCalc);
            decimal diff = (retainageOpts.CuryRetainageAmt ?? 0m) - (invoice.CuryDocBal ?? 0m);

            if (tranNew != null && diff != 0m)
            {
                HashSet <string> taxList = PXSelectJoin <ARTax,
                                                         InnerJoin <Tax, On <Tax.taxID, Equal <ARTax.taxID> > >,
                                                         Where <ARTax.tranType, Equal <Required <ARTax.tranType> >,
                                                                And <ARTax.refNbr, Equal <Required <ARTax.refNbr> >,
                                                                     And <ARTax.lineNbr, Equal <Required <ARTax.lineNbr> >,
                                                                          And <Tax.taxType, NotEqual <CSTaxType.use> > > > > >
                                           .Select(Base, tranNew.TranType, tranNew.RefNbr, tranNew.LineNbr)
                                           .RowCast <ARTax>()
                                           .Select(row => row.TaxID)
                                           .ToHashSet();

                // To guarantee correct document total amount
                // we should calculate last line total,
                // including its taxes.
                //
                TaxAttribute.CalcTaxable calcClass = new TaxAttribute.CalcTaxable(false, TaxAttribute.TaxCalcLevelEnforcing.None);
                decimal curyExtPrice = calcClass.CalcTaxableFromTotalAmount(
                    Base.Transactions.Cache,
                    tranNew,
                    taxList,
                    invoice.DocDate.Value,
                    prevCuryTotal);

                tranNew.CuryExtPrice = curyExtPrice;
                tranNew = Base.Transactions.Update(tranNew);
            }

            return(invoice);
        }
Beispiel #5
0
        public virtual void GenerateProc(Schedule s, short Times, DateTime runDate)
        {
            List <ScheduleDet> sd = GL.ScheduleProcess.MakeSchedule(this, s, Times, runDate);

            ARInvoiceEntry docgraph = CreateGraph();

            foreach (ScheduleDet sdet in sd)
            {
                foreach (PXResult <ARInvoice, Customer, CurrencyInfo> res in PXSelectJoin <ARInvoice, InnerJoin <Customer, On <Customer.bAccountID, Equal <ARInvoice.customerID> >, InnerJoin <CurrencyInfo, On <CurrencyInfo.curyInfoID, Equal <ARInvoice.curyInfoID> > > >, Where <ARInvoice.scheduleID, Equal <Required <ARInvoice.scheduleID> >, And <ARInvoice.scheduled, Equal <boolTrue> > > > .Select(this, s.ScheduleID))
                {
                    docgraph.Clear();
                    docgraph.customer.Current = (Customer)res;
                    ARInvoice    apdoc = (ARInvoice)res;
                    CurrencyInfo info  = (CurrencyInfo)res;

                    CurrencyInfo new_info = PXCache <CurrencyInfo> .CreateCopy(info);

                    new_info.CuryInfoID = null;
                    new_info            = docgraph.currencyinfo.Insert(new_info);

                    ARInvoice new_ardoc = PXCache <ARInvoice> .CreateCopy(apdoc);

                    new_ardoc.CuryInfoID          = new_info.CuryInfoID;
                    new_ardoc.DocDate             = sdet.ScheduledDate;
                    new_ardoc.FinPeriodID         = sdet.ScheduledPeriod;
                    new_ardoc.TranPeriodID        = null;
                    new_ardoc.DueDate             = null;
                    new_ardoc.DiscDate            = null;
                    new_ardoc.CuryOrigDiscAmt     = null;
                    new_ardoc.OrigDiscAmt         = null;
                    new_ardoc.RefNbr              = null;
                    new_ardoc.Scheduled           = false;
                    new_ardoc.CuryLineTotal       = 0m;
                    new_ardoc.CuryVatTaxableTotal = 0m;
                    new_ardoc.CuryVatExemptTotal  = 0m;
                    new_ardoc.NoteID              = null;
                    bool forceClear = false;
                    bool clearPM    = false;
                    if (new_ardoc.PMInstanceID.HasValue)
                    {
                        PXResult <CustomerPaymentMethod, CA.PaymentMethod> pmiResult = (PXResult <CustomerPaymentMethod, CA.PaymentMethod>) PXSelectJoin <CustomerPaymentMethod, InnerJoin <CA.PaymentMethod, On <CA.PaymentMethod.paymentMethodID, Equal <CustomerPaymentMethod.paymentMethodID> > >, Where <CustomerPaymentMethod.pMInstanceID, Equal <Required <CustomerPaymentMethod.pMInstanceID> > > > .Select(docgraph, new_ardoc.PMInstanceID);

                        if (pmiResult != null)
                        {
                            CustomerPaymentMethod pmInstance    = pmiResult;
                            CA.PaymentMethod      paymentMethod = pmiResult;
                            if (pmInstance == null || pmInstance.IsActive != true || paymentMethod.IsActive != true || paymentMethod.UseForAR != true)
                            {
                                clearPM    = true;
                                forceClear = true;
                            }
                        }
                        else
                        {
                            clearPM    = true;
                            forceClear = true;
                        }
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(new_ardoc.PaymentMethodID) == false)
                        {
                            CA.PaymentMethod pm = PXSelect <CA.PaymentMethod, Where <CA.PaymentMethod.paymentMethodID, Equal <Required <CA.PaymentMethod.paymentMethodID> > > > .Select(docgraph, new_ardoc.PaymentMethodID);

                            if (pm == null || pm.IsActive != true || pm.UseForAR != true)
                            {
                                clearPM    = true;
                                forceClear = true;
                            }
                        }
                    }

                    if (clearPM)
                    {
                        new_ardoc.PMInstanceID    = null;
                        new_ardoc.PaymentMethodID = null;
                        new_ardoc.CashAccountID   = null;
                    }

                    new_ardoc = docgraph.Document.Insert(new_ardoc);

                    //force creditrule back
                    docgraph.customer.Current = (Customer)res;

                    if (forceClear == true)
                    {
                        ARInvoice copy = PXCache <ARInvoice> .CreateCopy(new_ardoc);

                        copy.PMInstanceID    = null;
                        copy.PaymentMethodID = null;
                        copy.CashAccountID   = null;
                        new_ardoc            = docgraph.Document.Update(copy);
                    }
                    AddressAttribute.CopyRecord <ARInvoice.billAddressID>(docgraph.Document.Cache, new_ardoc, apdoc, false);
                    ContactAttribute.CopyRecord <ARInvoice.billContactID>(docgraph.Document.Cache, new_ardoc, apdoc, false);

                    TaxAttribute.SetTaxCalc <ARTran.taxCategoryID, ARTaxAttribute>(docgraph.Transactions.Cache, null, TaxCalc.ManualCalc);
                    PXNoteAttribute.SetNote(docgraph.Document.Cache, new_ardoc, PXNoteAttribute.GetNote(Caches[typeof(ARInvoice)], apdoc));
                    PXNoteAttribute.SetFileNotes(docgraph.Document.Cache, new_ardoc, PXNoteAttribute.GetFileNotes(Caches[typeof(ARInvoice)], apdoc));

                    foreach (ARTran aptran in PXSelect <ARTran, Where <ARTran.tranType, Equal <Required <ARTran.tranType> >, And <ARTran.refNbr, Equal <Required <ARTran.refNbr> > > > > .Select(docgraph, apdoc.DocType, apdoc.RefNbr))
                    {
                        ARTran new_aptran = PXCache <ARTran> .CreateCopy(aptran);

                        new_aptran.RefNbr     = null;
                        new_aptran.CuryInfoID = null;
                        docgraph.Transactions.Insert(new_aptran);
                    }

                    foreach (ARTaxTran tax in PXSelect <ARTaxTran, Where <ARTaxTran.tranType, Equal <Required <ARTaxTran.tranType> >, And <ARTaxTran.refNbr, Equal <Required <ARTaxTran.refNbr> > > > > .Select(docgraph, apdoc.DocType, apdoc.RefNbr))
                    {
                        ARTaxTran new_artax = new ARTaxTran();
                        new_artax.TaxID = tax.TaxID;

                        new_artax = docgraph.Taxes.Insert(new_artax);

                        if (new_artax != null)
                        {
                            new_artax = PXCache <ARTaxTran> .CreateCopy(new_artax);

                            new_artax.TaxRate        = tax.TaxRate;
                            new_artax.CuryTaxableAmt = tax.CuryTaxableAmt;
                            new_artax.CuryTaxAmt     = tax.CuryTaxAmt;
                            new_artax = docgraph.Taxes.Update(new_artax);
                        }
                    }

                    docgraph.Save.Press();
                }
                s.LastRunDate = sdet.ScheduledDate;
                Running_Schedule.Cache.Update(s);
            }

            using (PXTransactionScope ts = new PXTransactionScope())
            {
                Running_Schedule.Cache.Persist(PXDBOperation.Update);
                ts.Complete(this);
            }
            Running_Schedule.Cache.Persisted(false);
        }
        public virtual void ApplyTax(ARInvoice invoice, GetTaxResult result)
        {
            TaxZone taxZone = null;

            AP.Vendor vendor = null;
            if (result.TaxSummary.Length > 0)
            {
                taxZone = (TaxZone)Base.taxzone.View.SelectSingleBound(new object[] { invoice });
                vendor  = PXSelect <AP.Vendor, Where <AP.Vendor.bAccountID, Equal <Required <AP.Vendor.bAccountID> > > > .Select(Base, taxZone.TaxVendorID);

                if (vendor == null)
                {
                    throw new PXException(TX.Messages.ExternalTaxVendorNotFound);
                }

                if (vendor.SalesTaxAcctID == null)
                {
                    throw new PXException(TX.Messages.TaxPayableAccountNotSpecified, vendor.AcctCD);
                }

                if (vendor.SalesTaxSubID == null)
                {
                    throw new PXException(TX.Messages.TaxPayableSubNotSpecified, vendor.AcctCD);
                }
            }
            Sign sign = invoice.DocType == ARDocType.CreditMemo ? Sign.Minus : Sign.Plus;

            //Clear all existing Tax transactions:
            foreach (PXResult <ARTaxTran, Tax> res in Base.Taxes.View.SelectMultiBound(new object[] { invoice }))
            {
                ARTaxTran taxTran = res;
                Base.Taxes.Delete(taxTran);
            }

            Base.Views.Caches.Add(typeof(Tax));

            for (int i = 0; i < result.TaxSummary.Length; i++)
            {
                string taxID = result.TaxSummary[i].TaxName;
                if (string.IsNullOrEmpty(taxID))
                {
                    taxID = result.TaxSummary[i].JurisCode;
                }

                if (string.IsNullOrEmpty(taxID))
                {
                    PXTrace.WriteInformation(Messages.EmptyValuesFromExternalTaxProvider);
                    continue;
                }

                //Insert Tax if not exists - just for the selectors sake
                Tax tx = PXSelect <Tax, Where <Tax.taxID, Equal <Required <Tax.taxID> > > > .Select(Base, taxID);

                if (tx == null)
                {
                    tx = new Tax
                    {
                        TaxID             = taxID,
                        Descr             = PXMessages.LocalizeFormatNoPrefixNLA(TX.Messages.ExternalTaxProviderTaxId, taxID),
                        TaxType           = CSTaxType.Sales,
                        TaxCalcType       = CSTaxCalcType.Doc,
                        TaxCalcLevel      = result.TaxSummary[i].TaxCalculationLevel.ToCSTaxCalcLevel(),
                        TaxApplyTermsDisc = CSTaxTermsDiscount.ToTaxableAmount,
                        SalesTaxAcctID    = vendor.SalesTaxAcctID,
                        SalesTaxSubID     = vendor.SalesTaxSubID,
                        ExpenseAccountID  = vendor.TaxExpenseAcctID,
                        ExpenseSubID      = vendor.TaxExpenseSubID,
                        TaxVendorID       = taxZone.TaxVendorID,
                        IsExternal        = true
                    };

                    Base.Caches[typeof(Tax)].Insert(tx);
                }

                var tax = new ARTaxTran
                {
                    Module         = BatchModule.AR,
                    TranType       = invoice.DocType,
                    RefNbr         = invoice.RefNbr,
                    TaxID          = taxID,
                    CuryTaxAmt     = sign * result.TaxSummary[i].TaxAmount,
                    CuryTaxableAmt = sign * result.TaxSummary[i].TaxableAmount,
                    TaxRate        = Convert.ToDecimal(result.TaxSummary[i].Rate) * 100,
                    JurisType      = result.TaxSummary[i].JurisType,
                    JurisName      = result.TaxSummary[i].JurisName,
                    TaxType        = CSTaxType.Sales,
                    TaxBucketID    = 0,
                    AccountID      = vendor.SalesTaxAcctID,
                    SubID          = vendor.SalesTaxSubID
                };

                Base.Taxes.Insert(tax);
            }

            bool requireControlTotal = Base.ARSetup.Current.RequireControlTotal == true;

            if (invoice.Hold != true)
            {
                Base.ARSetup.Current.RequireControlTotal = false;
            }

            try
            {
                invoice.CuryTaxTotal = sign * result.TotalTaxAmount;
                Base.Document.Cache.SetValueExt <ARInvoice.isTaxSaved>(invoice, true);
            }
            finally
            {
                Base.ARSetup.Current.RequireControlTotal = requireControlTotal;
            }

            if (invoice.ApplyPaymentWhenTaxAvailable == true)
            {
                PXSelectBase <ARAdjust2> select = new PXSelectJoin <ARAdjust2,
                                                                    InnerJoin <ARPayment, On <ARAdjust2.adjgDocType, Equal <ARPayment.docType>,
                                                                                              And <ARAdjust2.adjgRefNbr, Equal <ARPayment.refNbr> > > >,
                                                                    Where <ARAdjust2.adjdDocType, Equal <Required <ARInvoice.docType> >,
                                                                           And <ARAdjust2.adjdRefNbr, Equal <Required <ARInvoice.refNbr> > > > >(Base);

                decimal amountApplied = 0m;
                foreach (PXResult <ARAdjust2, ARPayment> res in select.Select(invoice.DocType, invoice.RefNbr))
                {
                    ARAdjust2 row     = (ARAdjust2)res;
                    ARPayment payment = (ARPayment)res;

                    ARAdjust2 copy = PXCache <ARAdjust2> .CreateCopy(row);

                    amountApplied += (copy.CuryAdjdAmt ?? 0m);

                    if (amountApplied > (invoice.CuryDocBal ?? 0m))
                    {
                        decimal newAdjdAmt = (copy.CuryAdjdAmt ?? 0m) - (amountApplied - (invoice.CuryDocBal ?? 0m));
                        copy.CuryAdjdAmt = newAdjdAmt > 0m ? newAdjdAmt : 0m;
                    }
                    Base.Adjustments.Update(copy);
                }
            }
        }
		protected override void ApplyAvalaraTax(ARInvoice invoice, GetTaxResult result)
		{
			TaxZone taxZone = (TaxZone)taxzone.View.SelectSingleBound(new object[] { invoice });
			AP.Vendor vendor = PXSelect<AP.Vendor, Where<AP.Vendor.bAccountID, Equal<Required<AP.Vendor.bAccountID>>>>.Select(this, taxZone.TaxVendorID);

			if (vendor == null)
				throw new PXException("Tax Vendor is required but not found for the External TaxZone.");

			Dictionary<string, ARTaxTran> existingRows = new Dictionary<string, ARTaxTran>();
			foreach (PXResult<ARTaxTran, Tax> res in Taxes.View.SelectMultiBound(new object[] { invoice }))
			{
				ARTaxTran taxTran = (ARTaxTran)res;
				existingRows.Add(taxTran.TaxID.Trim().ToUpperInvariant(), taxTran);
			}

			this.Views.Caches.Add(typeof(Tax));

			bool requireControlTotal = ARSetup.Current.RequireControlTotal == true;

			if (invoice.Hold != true)
				ARSetup.Current.RequireControlTotal = false;

			try
			{

				for (int i = 0; i < result.TaxSummary.Count; i++)
				{
					string taxID = result.TaxSummary[i].TaxName.ToUpperInvariant();

					//Insert Tax if not exists - just for the selectors sake
					Tax tx = PXSelect<Tax, Where<Tax.taxID, Equal<Required<Tax.taxID>>>>.Select(this, taxID);
					if (tx == null)
					{
						tx = new Tax();
						tx.TaxID = taxID;
						//tx.Descr = string.Format("Avalara {0} {1}%", taxID, Convert.ToDecimal(result.TaxSummary[i].Rate)*100);
						tx.Descr = string.Format("Avalara {0}", taxID);
						tx.TaxType = CSTaxType.Sales;
						tx.TaxCalcType = CSTaxCalcType.Doc;
						tx.TaxCalcLevel = CSTaxCalcLevel.CalcOnItemAmt;
						tx.TaxApplyTermsDisc = CSTaxTermsDiscount.ToTaxableAmount;
						tx.SalesTaxAcctID = vendor.SalesTaxAcctID;
						tx.SalesTaxSubID = vendor.SalesTaxSubID;
						tx.ExpenseAccountID = vendor.TaxExpenseAcctID;
						tx.ExpenseSubID = vendor.TaxExpenseSubID;
						tx.TaxVendorID = taxZone.TaxVendorID;

						this.Caches[typeof(Tax)].Insert(tx);
					}

					ARTaxTran existing = null;
					existingRows.TryGetValue(taxID, out existing);

					if (existing != null)
					{
						existing.TaxAmt = Math.Abs(result.TaxSummary[i].Tax);
						existing.CuryTaxAmt = Math.Abs(result.TaxSummary[i].Tax);
						existing.TaxableAmt = Math.Abs(result.TaxSummary[i].Taxable);
						existing.CuryTaxableAmt = Math.Abs(result.TaxSummary[i].Taxable);
						existing.TaxRate = Convert.ToDecimal(result.TaxSummary[i].Rate);

						Taxes.Update(existing);
						existingRows.Remove(existing.TaxID.Trim().ToUpperInvariant());
					}
					else
					{
						ARTaxTran tax = new ARTaxTran();
						tax.Module = BatchModule.AR;
						tax.TranType = invoice.DocType;
						tax.RefNbr = invoice.RefNbr;
						tax.TaxID = taxID;
						tax.TaxAmt = Math.Abs(result.TaxSummary[i].Tax);
						tax.CuryTaxAmt = Math.Abs(result.TaxSummary[i].Tax);
						tax.TaxableAmt = Math.Abs(result.TaxSummary[i].Taxable);
						tax.CuryTaxableAmt = Math.Abs(result.TaxSummary[i].Taxable);
						tax.TaxRate = Convert.ToDecimal(result.TaxSummary[i].Rate);
						tax.TaxType = "S";
						tax.TaxBucketID = 0;
						tax.AccountID = vendor.SalesTaxAcctID;
						tax.SubID = vendor.SalesTaxSubID;

						Taxes.Insert(tax);
					}
				}

				foreach (ARTaxTran taxTran in existingRows.Values)
				{
					Taxes.Delete(taxTran);
				}

				SOInvoice soInvoice = PXSelect<SOInvoice, Where<SOInvoice.docType, Equal<Required<SOInvoice.docType>>, And<SOInvoice.refNbr, Equal<Required<SOInvoice.refNbr>>>>>.Select(this, invoice.DocType, invoice.RefNbr);

				invoice.CuryTaxTotal = Math.Abs(result.TotalTax);
				Document.Cache.SetValueExt<ARInvoice.isTaxSaved>(invoice, true);
			}
			finally
			{
				ARSetup.Current.RequireControlTotal = requireControlTotal;
			}


			if (invoice.ApplyPaymentWhenTaxAvailable == true)
			{
				PXSelectBase<ARAdjust> select = new PXSelectJoin<ARAdjust,
					InnerJoin<ARPayment, On<ARAdjust.adjgDocType, Equal<ARPayment.docType>, And<ARAdjust.adjgRefNbr, Equal<ARPayment.refNbr>>>>,
					Where<ARAdjust.adjdDocType, Equal<Required<ARInvoice.docType>>,
					And<ARAdjust.adjdRefNbr, Equal<Required<ARInvoice.refNbr>>>>>(this);


				foreach (PXResult<ARAdjust, ARPayment> res in select.Select(invoice.DocType, invoice.RefNbr))
				{
					ARAdjust row = (ARAdjust)res;
					ARPayment payment = (ARPayment)res;

					ARAdjust copy = PXCache<ARAdjust>.CreateCopy(row);
					copy.CuryAdjdAmt = Math.Min(copy.CuryAdjdAmt.GetValueOrDefault(), invoice.CuryDocBal.GetValueOrDefault());
					Adjustments.Update(copy);
				}
			}

		}
		public virtual void InvoiceOrder(DateTime invoiceDate, PXResult<SOOrderShipment, SOOrder, CurrencyInfo, SOAddress, SOContact, SOOrderType> order, PXResultset<SOShipLine, SOLine> details, Customer customer, DocumentList<ARInvoice, SOInvoice> list)
		{
			ARInvoice newdoc;
			SOOrder soOrder = order;
			SOOrderType ordertype = order;

            decimal ApprovedBalance = 0;
            decimal PrevDocBal = 0;

            PXRowUpdated ApprovedBalanceCollector = delegate(PXCache sender, PXRowUpdatedEventArgs e)
            {
                ARInvoice ARDoc = (ARInvoice)e.Row;
                if ((decimal)ARDoc.DocBal > (decimal)ARDoc.ApprovedCreditAmt)
                {
                    if ((bool)((SOOrder)order).ApprovedCredit && (decimal)ARDoc.DocBal > PrevDocBal)
                    {
                        ApprovedBalance += (decimal)ARDoc.DocBal - PrevDocBal;
                        ARDoc.ApprovedCreditAmt = ApprovedBalance;
                    }
                    ARDoc.ApprovedCredit = (ApprovedBalance == (decimal)ARDoc.DocBal ? true : false);
                    PrevDocBal = (decimal)ARDoc.DocBal;
                }
            };

            this.RowUpdated.AddHandler(typeof(ARInvoice), ApprovedBalanceCollector);

			if (list != null)
			{
				bool iscc = false;
				DateTime? orderInvoiceDate = (sosetup.Current.UseShipDateForInvoiceDate == true ? ((SOOrderShipment)order).ShipDate : soOrder.InvoiceDate);

				if (soOrder.BillSeparately == false)
				{
					iscc = PXSelectReadonly<CCProcTran, Where<CCProcTran.origDocType, Equal<Required<CCProcTran.origDocType>>, And<CCProcTran.origRefNbr, Equal<Required<CCProcTran.origRefNbr>>, And<CCProcTran.refNbr, IsNull>>>>.Select(this, soOrder.OrderType, soOrder.OrderNbr).Count > 0;
				}

				if (soOrder.PaymentCntr == 0 && soOrder.BillSeparately == false && iscc == false)
				{
					if(soOrder.PaymentMethodID == null && soOrder.CashAccountID == null)
						newdoc = list.Find<ARInvoice.docType, ARInvoice.docDate, ARInvoice.branchID, ARInvoice.customerID, ARInvoice.customerLocationID, SOInvoice.billAddressID, SOInvoice.billContactID, SOInvoice.extRefNbr, ARInvoice.curyID, ARInvoice.termsID, ARInvoice.hidden>(((SOOrderType)order).ARDocType, orderInvoiceDate ?? invoiceDate, soOrder.BranchID, soOrder.CustomerID, soOrder.CustomerLocationID, soOrder.BillAddressID, soOrder.BillContactID, soOrder.ExtRefNbr, soOrder.CuryID, soOrder.TermsID, false) ?? (ARInvoice)new ARInvoice();
					else if (soOrder.CashAccountID == null)
						newdoc = list.Find<ARInvoice.docType, ARInvoice.docDate, ARInvoice.branchID, ARInvoice.customerID, ARInvoice.customerLocationID, SOInvoice.billAddressID, SOInvoice.billContactID, SOInvoice.pMInstanceID, SOInvoice.extRefNbr, ARInvoice.curyID, ARInvoice.termsID, ARInvoice.hidden>(((SOOrderType)order).ARDocType, orderInvoiceDate ?? invoiceDate, soOrder.BranchID, soOrder.CustomerID, soOrder.CustomerLocationID, soOrder.BillAddressID, soOrder.BillContactID, soOrder.PMInstanceID, soOrder.ExtRefNbr, soOrder.CuryID, soOrder.TermsID, false) ?? (ARInvoice)new ARInvoice();					
					else
						newdoc = list.Find<ARInvoice.docType, ARInvoice.docDate, ARInvoice.branchID, ARInvoice.customerID, ARInvoice.customerLocationID, SOInvoice.billAddressID, SOInvoice.billContactID, SOInvoice.pMInstanceID, SOInvoice.cashAccountID, SOInvoice.extRefNbr, ARInvoice.curyID, ARInvoice.termsID, ARInvoice.hidden>(((SOOrderType)order).ARDocType, orderInvoiceDate ?? invoiceDate, soOrder.BranchID, soOrder.CustomerID, soOrder.CustomerLocationID, soOrder.BillAddressID, soOrder.BillContactID, soOrder.PMInstanceID, soOrder.CashAccountID, soOrder.ExtRefNbr, soOrder.CuryID, soOrder.TermsID, false) ?? (ARInvoice)new ARInvoice();
				}
				else
				{
					newdoc = list.Find<ARInvoice.hidden, ARInvoice.hiddenOrderType, ARInvoice.hiddenOrderNbr>(true, soOrder.OrderType, soOrder.OrderNbr);
					if (newdoc == null)
					{
						newdoc = new ARInvoice();
						newdoc.HiddenOrderType = soOrder.OrderType;
						newdoc.HiddenOrderNbr = soOrder.OrderNbr;
						newdoc.Hidden = true;
					}
				}

				if (newdoc.RefNbr != null)
				{
					Document.Current = this.Document.Search<ARInvoice.refNbr>(newdoc.RefNbr, newdoc.DocType);
				}
				else
				{
					this.Clear();

					string docType = ((SOOrderType)order).ARDocType;
					if (((SOOrderShipment)order).Operation == ((SOOrderType)order).DefaultOperation)
					{
						newdoc.DocType = docType;
					}
					else
					{
						//for RMA switch document type if previous shipment was not invoiced previously in the current run, i.e. list.Find() returned null
 						newdoc.DocType = 
							docType == ARDocType.Invoice ? ARDocType.CreditMemo :
							docType == ARDocType.DebitMemo ? ARDocType.CreditMemo :
							docType == ARDocType.CreditMemo ? ARDocType.Invoice :
							docType == ARDocType.CashSale ? ARDocType.CashReturn :
							docType == ARDocType.CashReturn ? ARDocType.CashSale :
							null;
					}

					newdoc.DocDate = orderInvoiceDate ?? invoiceDate;

					if (string.IsNullOrEmpty(soOrder.FinPeriodID) == false)
					{
						newdoc.FinPeriodID = soOrder.FinPeriodID;
					}

					if (soOrder.InvoiceNbr != null)
					{
						newdoc.RefNbr = soOrder.InvoiceNbr;
						newdoc.RefNoteID = soOrder.NoteID;
					}

					if (((SOOrderType)order).UserInvoiceNumbering == true && string.IsNullOrEmpty(newdoc.RefNbr))
					{
						throw new PXException(ErrorMessages.FieldIsEmpty, PXUIFieldAttribute.GetDisplayName<SOOrder.invoiceNbr>(soorder.Cache));
					}

					AutoNumberAttribute.SetNumberingId<ARInvoice.refNbr>(Document.Cache, ((SOOrderType)order).ARDocType, ((SOOrderType)order).InvoiceNumberingID);

					newdoc = (ARInvoice)Document.Cache.CreateCopy(this.Document.Insert(newdoc));

					newdoc.BranchID = soOrder.BranchID;
					newdoc.CustomerID = ((SOOrder)order).CustomerID;
					newdoc.CustomerLocationID = ((SOOrder)order).CustomerLocationID;
					newdoc.TermsID = ((SOOrder)order).TermsID;
					newdoc.DiscDate = ((SOOrder)order).DiscDate;
					newdoc.DueDate = ((SOOrder)order).DueDate;
					newdoc.TaxZoneID = ((SOOrder)order).TaxZoneID;
					newdoc.AvalaraCustomerUsageType = ((SOOrder)order).AvalaraCustomerUsageType;
					newdoc.SalesPersonID = ((SOOrder)order).SalesPersonID;
					newdoc.DocDesc = ((SOOrder)order).OrderDesc;
					newdoc.InvoiceNbr = ((SOOrder)order).CustomerOrderNbr;
					newdoc.CuryID = ((SOOrder)order).CuryID;
					newdoc.ProjectID = ((SOOrder)order).ProjectID ?? PM.ProjectDefaultAttribute.NonProject(this);
				    newdoc.Hold = ordertype.InvoiceHoldEntry;

					if (((SOOrderType)order).MarkInvoicePrinted == true)
					{
						newdoc.Printed = true;
					}

					if (((SOOrderType)order).MarkInvoiceEmailed == true)
					{
						newdoc.Emailed = true;
					}

					if (soOrder.PMInstanceID != null || string.IsNullOrEmpty(soOrder.PaymentMethodID) == false)
					{
						newdoc.PMInstanceID = soOrder.PMInstanceID;
						newdoc.PaymentMethodID = soOrder.PaymentMethodID;
						newdoc.CashAccountID = soOrder.CashAccountID;
					}

					newdoc = this.Document.Update(newdoc);


					if (soOrder.PMInstanceID != null || string.IsNullOrEmpty(soOrder.PaymentMethodID) == false)
					{
						SODocument.Current.PMInstanceID = soOrder.PMInstanceID;
						SODocument.Current.PaymentMethodID = soOrder.PaymentMethodID;
						SODocument.Current.CashAccountID = soOrder.CashAccountID;						
						if(SODocument.Current.CashAccountID == null)
							SODocument.Cache.SetDefaultExt<SOInvoice.cashAccountID>(SODocument.Current);
						SODocument.Current.ExtRefNbr = soOrder.ExtRefNbr;
						//clear error in case invoice currency different from default cash account for customer
						SODocument.Cache.RaiseExceptionHandling<SOInvoice.cashAccountID>(SODocument.Current, null, null);
					}

					foreach (CurrencyInfo info in this.currencyinfo.Select())
					{
						if (((SOOrder)order).InvoiceDate != null)
						{
							PXCache<CurrencyInfo>.RestoreCopy(info, (CurrencyInfo)order);
							info.CuryInfoID = newdoc.CuryInfoID;
						}
					}
					AddressAttribute.CopyRecord<ARInvoice.billAddressID>(this.Document.Cache, newdoc, (SOAddress)order, true);
					ContactAttribute.CopyRecord<ARInvoice.billContactID>(this.Document.Cache, newdoc, (SOContact)order, true);					
				}
			}
			else
			{
				newdoc = (ARInvoice)Document.Cache.CreateCopy(Document.Current);

                if (Transactions.SelectSingle() == null)
                {
                    newdoc.CustomerID = ((SOOrder)order).CustomerID;
                    newdoc.ProjectID = ((SOOrder)order).ProjectID;
                    newdoc.CustomerLocationID = ((SOOrder)order).CustomerLocationID;
                    newdoc.SalesPersonID = ((SOOrder)order).SalesPersonID;
                    newdoc.TaxZoneID = ((SOOrder)order).TaxZoneID;
                    newdoc.AvalaraCustomerUsageType = ((SOOrder)order).AvalaraCustomerUsageType;
                    newdoc.DocDesc = ((SOOrder)order).OrderDesc;
                    newdoc.InvoiceNbr = ((SOOrder)order).CustomerOrderNbr;
                    newdoc.TermsID = ((SOOrder)order).TermsID;

					foreach (CurrencyInfo info in this.currencyinfo.Select())
					{
						PXCache<CurrencyInfo>.RestoreCopy(info, (CurrencyInfo)order);
						info.CuryInfoID = newdoc.CuryInfoID;
						newdoc.CuryID = info.CuryID;
					}
                }

                newdoc = this.Document.Update(newdoc);

				

				AddressAttribute.CopyRecord<ARInvoice.billAddressID>(this.Document.Cache, newdoc, (SOAddress)order, true);
				ContactAttribute.CopyRecord<ARInvoice.billContactID>(this.Document.Cache, newdoc, (SOContact)order, true);								
			}

			PXSelectBase<SOInvoiceDiscountDetail> selectInvoiceDiscounts = new PXSelect<SOInvoiceDiscountDetail,
			Where<SOInvoiceDiscountDetail.tranType, Equal<Current<SOInvoice.docType>>,
			And<SOInvoiceDiscountDetail.refNbr, Equal<Current<SOInvoice.refNbr>>,
			And<SOInvoiceDiscountDetail.orderType, Equal<Required<SOInvoiceDiscountDetail.orderType>>,
			And<SOInvoiceDiscountDetail.orderNbr, Equal<Required<SOInvoiceDiscountDetail.orderNbr>>>>>>>(this);

			foreach (SOInvoiceDiscountDetail detail in selectInvoiceDiscounts.Select(((SOOrderShipment)order).OrderType, ((SOOrderShipment)order).OrderNbr))
			{
			    DiscountDetails.Delete(detail);
			}

			TaxAttribute.SetTaxCalc<ARTran.taxCategoryID>(this.Transactions.Cache, null, TaxCalc.ManualCalc);

			if (details != null)
			{
				foreach (SOShipLine shipline in details)
				{
					this.Caches[typeof(SOShipLine)].Insert(shipline);
				}
			}

			DateTime? origInvoiceDate = null;
			foreach (PXResult<SOShipLine, SOLine, SOOrderTypeOperation, ARTran> res in PXSelectJoin<SOShipLine, InnerJoin<SOLine, On<SOLine.orderType, Equal<SOShipLine.origOrderType>, And<SOLine.orderNbr, Equal<SOShipLine.origOrderNbr>, And<SOLine.lineNbr, Equal<SOShipLine.origLineNbr>>>>, InnerJoin<SOOrderTypeOperation, On<SOOrderTypeOperation.orderType, Equal<SOLine.orderType>, And<SOOrderTypeOperation.operation, Equal<SOLine.operation>>>, LeftJoin<ARTran, On<ARTran.sOShipmentNbr, Equal<SOShipLine.shipmentNbr>, And<ARTran.sOShipmentType, Equal<SOShipLine.shipmentType>, And<ARTran.sOShipmentLineNbr, Equal<SOShipLine.lineNbr>, And<ARTran.sOOrderType, Equal<SOShipLine.origOrderType>, And<ARTran.sOOrderNbr, Equal<SOShipLine.origOrderNbr>, And<ARTran.sOOrderLineNbr, Equal<SOShipLine.origLineNbr>>>>>>>>>>, Where<SOShipLine.shipmentNbr, Equal<Required<SOShipLine.shipmentNbr>>, And<SOShipLine.origOrderType, Equal<Required<SOShipLine.origOrderType>>, And<SOShipLine.origOrderNbr, Equal<Required<SOShipLine.origOrderNbr>>, And<ARTran.refNbr, IsNull>>>>>.Select(this, ((SOOrderShipment)order).ShipmentNbr, ((SOOrderShipment)order).OrderType, ((SOOrderShipment)order).OrderNbr))
			{
				SOLine orderline = (SOLine)res;
				SOShipLine shipline = (SOShipLine)res;

                if (Math.Abs((decimal)shipline.BaseShippedQty) < 0.0000005m)
                {
                    continue;
                }

				if (origInvoiceDate == null && orderline.InvoiceDate != null)
					origInvoiceDate = orderline.InvoiceDate;

				ARTran newtran = new ARTran();
				newtran.BranchID = orderline.BranchID;
				newtran.AccountID = orderline.SalesAcctID;
				newtran.SubID = orderline.SalesSubID;
				newtran.SOOrderType = shipline.OrigOrderType;
				newtran.SOOrderNbr = shipline.OrigOrderNbr;
				newtran.SOOrderLineNbr = shipline.OrigLineNbr;
				newtran.SOShipmentNbr = shipline.ShipmentNbr;
				newtran.SOShipmentType = shipline.ShipmentType;
				newtran.SOShipmentLineNbr = shipline.LineNbr;

				newtran.LineType = orderline.LineType;
				newtran.InventoryID = shipline.InventoryID;
                newtran.SiteID = orderline.SiteID;
				newtran.UOM = shipline.UOM;

				newtran.Qty = shipline.ShippedQty;
				newtran.BaseQty = shipline.BaseShippedQty;

                newtran.Commissionable = orderline.Commissionable;
                newtran.GroupDiscountRate = orderline.GroupDiscountRate;

				decimal shippedQtyInBaseUnits = INUnitAttribute.ConvertToBase(Transactions.Cache, newtran.InventoryID, shipline.UOM, shipline.ShippedQty.Value, INPrecision.QUANTITY);
				decimal shippedQtyInOrderUnits = INUnitAttribute.ConvertFromBase(Transactions.Cache, newtran.InventoryID, orderline.UOM, shippedQtyInBaseUnits, INPrecision.QUANTITY);

				if (shippedQtyInOrderUnits != orderline.OrderQty || shipline.UOM != orderline.UOM)
				{
					decimal curyUnitPriceInBaseUnits = INUnitAttribute.ConvertFromBase(Transactions.Cache, newtran.InventoryID, orderline.UOM, orderline.CuryUnitPrice.Value, INPrecision.UNITCOST);
					decimal curyUnitPriceInShippedUnits = INUnitAttribute.ConvertToBase(Transactions.Cache, newtran.InventoryID, shipline.UOM, curyUnitPriceInBaseUnits, INPrecision.UNITCOST);

                    if (arsetup.Current.LineDiscountTarget == LineDiscountTargetType.SalesPrice)
					{
						decimal? salesPriceAfterDiscount = curyUnitPriceInShippedUnits * (1m - orderline.DiscPct / 100m);
						newtran.CuryTranAmt = shipline.ShippedQty * PXCurrencyAttribute.Round(Transactions.Cache, newtran, salesPriceAfterDiscount ?? 0, CMPrecision.TRANCURY);
					}
					else
					{
						decimal? curyTranAmt = shipline.ShippedQty * curyUnitPriceInShippedUnits * (1m - orderline.DiscPct / 100m);
						newtran.CuryTranAmt = PXCurrencyAttribute.Round(Transactions.Cache, newtran, curyTranAmt ?? 0, CMPrecision.TRANCURY);
					}

					newtran.CuryUnitPrice = curyUnitPriceInShippedUnits;
					newtran.CuryDiscAmt = (shipline.ShippedQty * curyUnitPriceInShippedUnits) - newtran.CuryTranAmt;
				}
				else
				{
					newtran.CuryUnitPrice = orderline.CuryUnitPrice;
                    newtran.CuryTranAmt = orderline.CuryLineAmt;
					newtran.CuryDiscAmt = orderline.CuryDiscAmt;
				}

				if (newdoc.DocType == ((SOOrderType)order).ARDocType && ((SOOrderType)order).DefaultOperation != ((SOOrderTypeOperation)res).Operation)
				{
					//keep BaseQty positive for PXFormula
					newtran.Qty = -newtran.Qty;
					newtran.CuryDiscAmt = -newtran.CuryDiscAmt;
					newtran.CuryTranAmt = -newtran.CuryTranAmt;
				}

				newtran.ProjectID = orderline.ProjectID;
				newtran.TaskID = orderline.TaskID;
				newtran.TranDesc = orderline.TranDesc;
				newtran.SalesPersonID = orderline.SalesPersonID;
				newtran.TaxCategoryID = orderline.TaxCategoryID;
				newtran.DiscPct = orderline.DiscPct;
				
				newtran.ManualDisc = orderline.ManualDisc == true || orderline.IsFree == true;
				newtran.FreezeManualDisc = true;

                newtran.DiscountID = orderline.DiscountID;
                newtran.DiscountSequenceID = orderline.DiscountSequenceID;

				newtran.DetDiscIDC1 = orderline.DetDiscIDC1;
				newtran.DetDiscIDC2 = orderline.DetDiscIDC2;
				newtran.DetDiscSeqIDC1 = orderline.DetDiscSeqIDC1;
				newtran.DetDiscSeqIDC2 = orderline.DetDiscSeqIDC2;
				newtran.DetDiscApp = orderline.DetDiscApp;
				newtran.DocDiscIDC1 = orderline.DocDiscIDC1;
				newtran.DocDiscIDC2 = orderline.DocDiscIDC2;
				newtran.DocDiscSeqIDC1 = orderline.DocDiscSeqIDC1;
				newtran.DocDiscSeqIDC2 = orderline.DocDiscSeqIDC2;

				foreach (ARTran existing in Transactions.Cache.Inserted)
				{
					if (Transactions.Cache.ObjectsEqual<ARTran.sOShipmentNbr, ARTran.sOShipmentType, ARTran.sOShipmentLineNbr, ARTran.sOOrderType, ARTran.sOOrderNbr, ARTran.sOOrderLineNbr>(newtran, existing))
					{
						Transactions.Cache.RestoreCopy(newtran, existing);
						break;
					}
				}

				if (newtran.LineNbr == null)
				{
					newtran = this.Transactions.Insert(newtran);

					if (((SOOrderType)order).CopyLineNotesToInvoice == true)
					{
						if (((SOOrderType)order).CopyLineNotesToInvoiceOnlyNS == false || orderline.LineType == SOLineType.NonInventory)
						{
							PXNoteAttribute.SetNote(Caches[typeof(ARTran)], newtran, PXNoteAttribute.GetNote(Caches[typeof(SOLine)], orderline));
						}
					}

					if (((SOOrderType)order).CopyLineFilesToInvoice == true)
					{
						if (((SOOrderType)order).CopyLineFilesToInvoiceOnlyNS == false || orderline.LineType == SOLineType.NonInventory)
						{
							PXNoteAttribute.SetFileNotes(Caches[typeof(ARTran)], newtran, PXNoteAttribute.GetFileNotes(Caches[typeof(SOLine)], orderline));
						}
					}
				}
				else
				{
					newtran = this.Transactions.Update(newtran);
					TaxAttribute.Calculate<ARTran.taxCategoryID>(Transactions.Cache, new PXRowUpdatedEventArgs(newtran, null, true));
				}

			}
			
			PXSelectBase<ARTran> cmd = new PXSelect<ARTran, Where<ARTran.tranType, Equal<Current<ARInvoice.docType>>, And<ARTran.refNbr, Equal<Current<ARInvoice.refNbr>>, And<ARTran.sOOrderType, Equal<Current<SOMiscLine2.orderType>>, And<ARTran.sOOrderNbr, Equal<Current<SOMiscLine2.orderNbr>>, And<ARTran.sOOrderLineNbr, Equal<Current<SOMiscLine2.lineNbr>>>>>>>>(this);

			foreach (SOMiscLine2 orderline in PXSelect<SOMiscLine2, Where<SOMiscLine2.orderType, Equal<Required<SOMiscLine2.orderType>>, And<SOMiscLine2.orderNbr, Equal<Required<SOMiscLine2.orderNbr>>, And<Where<SOMiscLine2.curyUnbilledAmt, Greater<decimal0>, Or<SOMiscLine2.curyLineAmt, LessEqual<decimal0>>>>>>>.Select(this, ((SOOrderShipment)order).OrderType, ((SOOrderShipment)order).OrderNbr))
			{
				if (cmd.View.SelectSingleBound(new object[] { Document.Current, orderline }) == null)
				{
					ARTran newtran = new ARTran();
					newtran.BranchID = orderline.BranchID;
					newtran.AccountID = orderline.SalesAcctID;
					newtran.SubID = orderline.SalesSubID;
					newtran.SOOrderType = orderline.OrderType;
					newtran.SOOrderNbr = orderline.OrderNbr;
					newtran.SOOrderLineNbr = orderline.LineNbr;
					newtran.SOShipmentNbr = ((SOOrderShipment)order).ShipmentNbr;
					newtran.SOShipmentType = ((SOOrderShipment)order).ShipmentType; 
					newtran.SOShipmentLineNbr = null;

					newtran.LineType = SOLineType.MiscCharge;
					newtran.InventoryID = orderline.InventoryID;
					newtran.TaskID = orderline.TaskID;
					newtran.SalesPersonID = orderline.SalesPersonID;
                    newtran.Commissionable = orderline.Commissionable;
					newtran.UOM = orderline.UOM;
					newtran.Qty = orderline.UnbilledQty;
					newtran.BaseQty = orderline.BaseUnbilledQty;
					newtran.CuryUnitPrice = orderline.CuryUnitPrice;
                    newtran.CuryDiscAmt = orderline.CuryDiscAmt;
					newtran.CuryTranAmt = orderline.CuryUnbilledAmt;
					newtran.TranDesc = orderline.TranDesc;
					newtran.TaxCategoryID = orderline.TaxCategoryID;
                    newtran.DiscPct = orderline.DiscPct;
					newtran.ManualDisc = orderline.ManualDisc == true || orderline.IsFree == true;
					newtran.FreezeManualDisc = true;

                    newtran.DiscountID = orderline.DiscountID;
                    newtran.DiscountSequenceID = orderline.DiscountSequenceID;

					newtran.DetDiscIDC1 = orderline.DetDiscIDC1;
					newtran.DetDiscIDC2 = orderline.DetDiscIDC2;
					newtran.DetDiscSeqIDC1 = orderline.DetDiscSeqIDC1;
					newtran.DetDiscSeqIDC2 = orderline.DetDiscSeqIDC2;
					newtran.DetDiscApp = orderline.DetDiscApp;
					newtran.DocDiscIDC1 = orderline.DocDiscIDC1;
					newtran.DocDiscIDC2 = orderline.DocDiscIDC2;
					newtran.DocDiscSeqIDC1 = orderline.DocDiscSeqIDC1;
					newtran.DocDiscSeqIDC2 = orderline.DocDiscSeqIDC2;

					newtran = this.Transactions.Insert(newtran);

					if (((SOOrderType)order).CopyLineNotesToInvoice == true)
					{
						PXNoteAttribute.SetNote(Caches[typeof(ARTran)], newtran, PXNoteAttribute.GetNote(Caches[typeof(SOMiscLine2)], orderline));
					}

					if (((SOOrderType)order).CopyLineFilesToInvoice == true)
					{
						PXNoteAttribute.SetFileNotes(Caches[typeof(ARTran)], newtran, PXNoteAttribute.GetFileNotes(Caches[typeof(SOMiscLine2)], orderline));
					}
				}
			}

			SODocument.Current = (SOInvoice)SODocument.Select() ?? (SOInvoice)SODocument.Cache.Insert();
			SODocument.Current.BillAddressID = soOrder.BillAddressID;
			SODocument.Current.BillContactID = soOrder.BillContactID;
			SODocument.Current.ShipAddressID = soOrder.ShipAddressID;
			SODocument.Current.ShipContactID = soOrder.ShipContactID;
			SODocument.Current.IsCCCaptured = soOrder.IsCCCaptured;
			SODocument.Current.IsCCCaptureFailed = soOrder.IsCCCaptureFailed;
			SODocument.Current.PaymentProjectID = PM.ProjectDefaultAttribute.NonProject(this);
			
			if (soOrder.IsCCCaptured == true)
			{
				SODocument.Current.CuryCCCapturedAmt = soOrder.CuryCCCapturedAmt;
				SODocument.Current.CCCapturedAmt = soOrder.CCCapturedAmt;
			}

			SODocument.Current.RefTranExtNbr = soOrder.RefTranExtNbr;

			SOOrderShipment shipment = PXCache<SOOrderShipment>.CreateCopy((SOOrderShipment)order);
			shipment.InvoiceType = SODocument.Current.DocType;
			shipment.InvoiceNbr = SODocument.Current.RefNbr;
			shipmentlist.Cache.Update(shipment);

			FillFreightDetails((SOOrder)order, shipment);

            /*In case Discounts were not recalculated add prorated Doc discounts */
            if (ordertype.RecalculateDiscOnPartialShipment != true)
            {
                //add prorated document discount details from invoice:
                PXSelectBase<SOOrderDiscountDetail> selectOrderDocGroupDiscounts = new PXSelect<SOOrderDiscountDetail,
                Where<SOOrderDiscountDetail.orderType, Equal<Required<SOOrderDiscountDetail.orderType>>,
                And<SOOrderDiscountDetail.orderNbr, Equal<Required<SOOrderDiscountDetail.orderNbr>>>>>(this);

                decimal? rate = 1m;
                if (soOrder.LineTotal > 0m)
                    rate = shipment.LineTotal / soOrder.LineTotal;

                foreach (SOOrderDiscountDetail docGroupDisc in selectOrderDocGroupDiscounts.Select(((SOOrderShipment)order).OrderType, ((SOOrderShipment)order).OrderNbr))
                {
                        SOInvoiceDiscountDetail dd = new SOInvoiceDiscountDetail();
                        dd.Type = docGroupDisc.Type;
                        dd.DiscountID = docGroupDisc.DiscountID;
                        dd.DiscountSequenceID = docGroupDisc.DiscountSequenceID;
                        dd.OrderType = docGroupDisc.OrderType;
                        dd.OrderNbr = docGroupDisc.OrderNbr;
                        dd.TranType = newdoc.DocType;
                        dd.RefNbr = newdoc.RefNbr;
                        dd.DiscountPct = docGroupDisc.DiscountPct;
                        dd.FreeItemID = docGroupDisc.FreeItemID;
                        dd.FreeItemQty = docGroupDisc.FreeItemQty;

                        if (docGroupDisc.Type == DiscountType.Group)
                        {
                            SOOrderEntry soOrderQ = (SOOrderEntry)PXGraph.CreateInstance(typeof(SOOrderEntry));
                            soOrderQ.Document.Current = order;

                            Dictionary<DiscountSequenceKey, DiscountEngine<SOLine>.DiscountDetailToLineCorrelation<SOOrderDiscountDetail>> grLinesOrderCorrelation = DiscountEngine<SOLine>.CollectGroupDiscountToLineCorrelation(soOrderQ.Transactions.Cache, soOrderQ.Transactions, soOrderQ.DiscountDetails, soOrder.CustomerLocationID, (DateTime)soOrder.OrderDate, false);

                            foreach (KeyValuePair<DiscountSequenceKey, DiscountEngine<SOLine>.DiscountDetailToLineCorrelation<SOOrderDiscountDetail>> dsGroup in grLinesOrderCorrelation)
                            {
                                if (dsGroup.Key.DiscountID == docGroupDisc.DiscountID && dsGroup.Key.DiscountSequenceID == docGroupDisc.DiscountSequenceID)
                                {
                                    decimal invoicedGroupAmt = 0m;
                                    foreach (SOLine soLine in dsGroup.Value.listOfApplicableLines)
                                    {
                                        foreach (ARTran tran in Transactions.Select())
                                        {
                                            if (soLine.LineNbr == tran.SOOrderLineNbr)
                                                invoicedGroupAmt += (tran.CuryLineAmt ?? 0m);
                                        }
                                    }
                                    rate = (invoicedGroupAmt / (decimal)dsGroup.Value.discountDetailLine.CuryDiscountableAmt);
                                }
                            }
                        }

                        SOInvoiceDiscountDetail located = DiscountDetails.Locate(dd);
                        if (located != null)
                        {
                            located.DiscountAmt += docGroupDisc.DiscountAmt * rate;
                            located.CuryDiscountAmt += docGroupDisc.CuryDiscountAmt * rate;
                            located.DiscountableAmt += docGroupDisc.DiscountableAmt * rate;
                            located.CuryDiscountableAmt += docGroupDisc.CuryDiscountableAmt * rate;
                            located.DiscountableQty += docGroupDisc.DiscountableQty * rate;

                            DiscountDetails.Update(located);
                        }
                        else
                        {
                            dd.DiscountAmt = docGroupDisc.DiscountAmt * rate;
                            dd.CuryDiscountAmt = docGroupDisc.CuryDiscountAmt * rate;
                            dd.DiscountableAmt = docGroupDisc.DiscountableAmt * rate;
                            dd.CuryDiscountableAmt = docGroupDisc.CuryDiscountableAmt * rate;
                            dd.DiscountableQty = docGroupDisc.DiscountableQty * rate;

                            DiscountDetails.Insert(dd);
                        }

                    }
                }
            else
            {
                //Recalculate all discounts
                foreach (ARTran tran in Transactions.Select())
                {
                    RecalculateDiscounts(this.Transactions.Cache, tran);
                }
            }
			RecalculateTotalDiscount();

			foreach (PXResult<SOTaxTran, Tax> res in PXSelectJoin<SOTaxTran,
				InnerJoin<Tax, On<SOTaxTran.taxID, Equal<Tax.taxID>>>,
				Where<SOTaxTran.orderType, Equal<Required<SOTaxTran.orderType>>, And<SOTaxTran.orderNbr, Equal<Required<SOTaxTran.orderNbr>>>>>.Select(this, ((SOOrderShipment)order).OrderType, ((SOOrderShipment)order).OrderNbr))
			{
				SOTaxTran tax = (SOTaxTran)res;
				ARTaxTran newtax = new ARTaxTran();
				newtax.Module = BatchModule.AR;
                Taxes.Cache.SetDefaultExt<ARTaxTran.origTranType>(newtax);
                Taxes.Cache.SetDefaultExt<ARTaxTran.origRefNbr>(newtax);
				Taxes.Cache.SetDefaultExt<ARTaxTran.lineRefNbr>(newtax);
				newtax.TranType = Document.Current.DocType;
				newtax.RefNbr = Document.Current.RefNbr;
				newtax.TaxID = tax.TaxID;
				newtax.TaxRate = 0m;

				this.Taxes.Delete(newtax);

				newtax = this.Taxes.Insert(newtax);
			}

			decimal? CuryApplAmt = 0m;
			bool Calculated = false;

			

			foreach (SOAdjust soadj in PXSelectJoin<SOAdjust, InnerJoin<AR.ARPayment, On<AR.ARPayment.docType, Equal<SOAdjust.adjgDocType>, And<AR.ARPayment.refNbr, Equal<SOAdjust.adjgRefNbr>>>>, Where<SOAdjust.adjdOrderType, Equal<Required<SOAdjust.adjdOrderType>>, And<SOAdjust.adjdOrderNbr, Equal<Required<SOAdjust.adjdOrderNbr>>, And<AR.ARPayment.openDoc, Equal<True>>>>>.Select(this, ((SOOrderShipment)order).OrderType, ((SOOrderShipment)order).OrderNbr))
			{
				ARAdjust prev_adj = null;
				bool found = false;

				foreach (ARAdjust adj in Adjustments.Select())
				{
					if (Calculated)
					{
						CuryApplAmt -= adj.CuryAdjdAmt;
					}

					if (string.Equals(adj.AdjgDocType, soadj.AdjgDocType) && string.Equals(adj.AdjgRefNbr, soadj.AdjgRefNbr))
					{
						if (soadj.CuryAdjdAmt > 0m)
						{
							ARAdjust copy = PXCache<ARAdjust>.CreateCopy(adj);
							copy.CuryAdjdAmt += (soadj.CuryAdjdAmt > adj.CuryDocBal) ? adj.CuryDocBal : soadj.CuryAdjdAmt;
							copy.AdjdOrderType = soadj.AdjdOrderType;
							copy.AdjdOrderNbr = soadj.AdjdOrderNbr;
							prev_adj = Adjustments.Update(copy);
						}

						found = true;

						if (Calculated)
						{
							CuryApplAmt += adj.CuryAdjdAmt;
							break;
						}
					}

					CuryApplAmt += adj.CuryAdjdAmt;
				}

				//if soadjust is not available in adjustments mark as billed
				if (!found)
				{
				/*
					soadj.Billed = true;
					soadjustments.Cache.SetStatus(soadj, PXEntryStatus.Updated);
				*/
				}

				Calculated = true;

				if (!IsExternalTax)
				{
					if (CuryApplAmt > Document.Current.CuryDocBal - Document.Current.CuryOrigDiscAmt && prev_adj != null)
					{
						prev_adj = PXCache<ARAdjust>.CreateCopy(prev_adj);

						if (prev_adj.CuryAdjdAmt > (CuryApplAmt - (Document.Current.CuryDocBal - Document.Current.CuryOrigDiscAmt)))
						{
							prev_adj.CuryAdjdAmt -= (CuryApplAmt - (Document.Current.CuryDocBal - Document.Current.CuryOrigDiscAmt));
							CuryApplAmt = Document.Current.CuryDocBal - Document.Current.CuryOrigDiscAmt;
						}
						else
						{
							CuryApplAmt -= prev_adj.CuryAdjdAmt;
							prev_adj.CuryAdjdAmt = 0m;
						}

						prev_adj = Adjustments.Update(prev_adj);
					}
				}
			}

			newdoc = (ARInvoice)Document.Cache.CreateCopy(Document.Current);
			newdoc.OrigDocDate = origInvoiceDate;
			SOInvoice socopy = (SOInvoice)SODocument.Cache.CreateCopy(SODocument.Current);

			PXFormulaAttribute.CalcAggregate<ARAdjust.curyAdjdAmt>(Adjustments.Cache, SODocument.Current, false);
			Document.Cache.RaiseFieldUpdated<SOInvoice.curyPaymentTotal>(SODocument.Current, null);
			PXDBCurrencyAttribute.CalcBaseValues<SOInvoice.curyPaymentTotal>(SODocument.Cache, SODocument.Current);

			SODocument.Cache.RaiseRowUpdated(SODocument.Current, socopy);

			List<string> ordersdistinct = new List<string>();
			foreach (SOOrderShipment shipments in PXSelect<SOOrderShipment, Where<SOOrderShipment.invoiceType, Equal<Current<ARInvoice.docType>>, And<SOOrderShipment.invoiceNbr, Equal<Current<ARInvoice.refNbr>>>>>.Select(this))
			{
				string key = string.Format("{0}|{1}", shipments.OrderType, shipments.OrderNbr);
				if (!ordersdistinct.Contains(key))
				{
					ordersdistinct.Add(key);
				}

				if (ordersdistinct.Count > 1)
				{
					newdoc.InvoiceNbr = null;
					newdoc.SalesPersonID = null;
					newdoc.DocDesc = null;
					break;
				}

				#region Update FreeItemQty for DiscountDetails based on shipments
				
				PXSelectBase<SOShipmentDiscountDetail> selectShipmentDiscounts = new PXSelect<SOShipmentDiscountDetail,
						Where<SOShipmentDiscountDetail.orderType, Equal<Required<SOShipmentDiscountDetail.orderType>>,
						And<SOShipmentDiscountDetail.orderNbr, Equal<Required<SOShipmentDiscountDetail.orderNbr>>,
						And<SOShipmentDiscountDetail.shipmentNbr, Equal<Required<SOShipmentDiscountDetail.shipmentNbr>>>>>>(this);

				foreach (SOShipmentDiscountDetail sdd in selectShipmentDiscounts.Select(shipments.OrderType, shipments.OrderNbr, shipments.ShipmentNbr))
				{
					SOInvoiceDiscountDetail idd = PXSelect<SOInvoiceDiscountDetail,
						Where<SOInvoiceDiscountDetail.tranType, Equal<Current<ARInvoice.docType>>,
						And<SOInvoiceDiscountDetail.refNbr, Equal<Current<ARInvoice.refNbr>>,
						And<SOInvoiceDiscountDetail.orderType, Equal<Required<SOInvoiceDiscountDetail.orderType>>,
						And<SOInvoiceDiscountDetail.orderNbr, Equal<Required<SOInvoiceDiscountDetail.orderNbr>>,
						And<SOInvoiceDiscountDetail.discountID, Equal<Required<SOInvoiceDiscountDetail.discountID>>,
						And<SOInvoiceDiscountDetail.discountSequenceID, Equal<Required<SOInvoiceDiscountDetail.discountSequenceID>>>>>>>>>.Select(this, shipments.OrderType, shipments.OrderNbr, sdd.DiscountID, sdd.DiscountSequenceID);

					if (idd != null)
					{
						if (idd.FreeItemID == null)
						{
							idd.FreeItemID = sdd.FreeItemID;
							idd.FreeItemQty = sdd.FreeItemQty;
						}
						else
							idd.FreeItemQty = sdd.FreeItemQty;

						DiscountDetails.Update(idd);
					}
					else
					{
						idd = new SOInvoiceDiscountDetail();
						idd.Type = DiscountType.Line;
						idd.TranType = newdoc.DocType;
						idd.RefNbr = newdoc.RefNbr;
						idd.OrderType = sdd.OrderType;
						idd.OrderNbr = sdd.OrderNbr;
						idd.DiscountID = sdd.DiscountID;
						idd.DiscountSequenceID = sdd.DiscountSequenceID;
						idd.FreeItemID = sdd.FreeItemID;
						idd.FreeItemQty = sdd.FreeItemQty;

						DiscountDetails.Insert(idd);
					}
				} 

				#endregion
			}

            this.Document.Update(newdoc);

			if (list != null)
			{
				if (Transactions.Search<ARTran.sOOrderType, ARTran.sOOrderNbr, ARTran.sOShipmentType, ARTran.sOShipmentNbr>(shipment.OrderType, shipment.OrderNbr, shipment.ShipmentType, shipment.ShipmentNbr).Count > 0)
				{
					try
					{
						this.Document.Current.ApplyPaymentWhenTaxAvailable = true;
						this.Save.Press();
					}
					finally
					{
						this.Document.Current.ApplyPaymentWhenTaxAvailable = false;
					}
					

					if (list.Find(this.Document.Current) == null)
					{
						list.Add(this.Document.Current, this.SODocument.Current);
					}
				}
				else
				{
					this.Clear();
				}
			}
            this.RowUpdated.RemoveHandler(typeof(ARInvoice), ApprovedBalanceCollector);
		}