Wednesday 30 September 2020

Customize Sales Totals form in D365 FO (AX)

Customize Sales Totals form in D365 FO (AX)

Today, I am going to share with you that how to override Sales tax in Sales Totals form based on condition.

Here, my requirement is- If (SalesTable.HSChangedInD365 == NoYes::No) then Sales Totals form should display the tax what we have received through web service (Or, order import through from party API) otherwise it should display the standard calculated tax. So I have overridden the tax value when values are initializing in container.

Here, we go...

/// <summary>
///     this is the extension class of SalesTotals class.
/// </summary>
[ExtensionOf(classStr(SalesTotals))]
final class SalesTotalsLFI_Extension
{
    /// <summary>
    ///     this is the COC of SalesTotals.displayFieldsServer()
    ///     to modify container and initialize Total sales tax and updated Invoice amount based on below condition.
    /// </summary>
    /// <param name = "_orderTable">Caller table to calculate totals for.</param>
    /// <param name = "_specQty">Quantity to calculate totals for.</param>
    /// <param name = "_currencyCode">Currency code to calculate totals for.</param>
    /// <returns>
    /// Container of the field values to be shown on the totals form.
    /// </returns>
    static public container displayFieldsServer(Common _orderTable, SalesUpdate _specQty, CurrencyCode _currencyCode)
    {
        container       resultContainer = conNull();

        resultContainer = next displayFieldsServer(_orderTable, _specQty, _currencyCode);

        if (_orderTable.TableId == tableNum(SalesTable))
        {
            SalesTable  salesTableLoc = _orderTable;
            if (salesTableLoc.HSChangedInD365 == NoYes::No && conPeek(resultContainer, TradeTotals::posTaxTotal()) == 0)
            {
                resultContainer = conPoke(resultContainer, TradeTotals::posTaxTotal(), salesTableLoc.HSTotalWebTaxAmountCur);
                resultContainer = conPoke(resultContainer, TradeTotals::posTotalAmount(), (salesTableLoc.HSTotalWebTaxAmountCur + conpeek(resultContainer, TradeTotals::posTotalAmount())));
            }
        }

        return resultContainer;
    }

Happy DAXING...




Monday 28 September 2020

How to override (adjust) tax through X++ code in D365 FO

 Override the tax in D365 FinOps

Today, I am going to share some activities based on Sales tax on to "Override" and "Remove the adjusted tax amount" too for a particular Sales order. 

Task# 01: To override sales tax amount in a Sales order

Here, I am going to share my experience to override the sales tax (adjust sales tax) in a Sales order.

Scenario# 1.1: To override sales tax in a sales order

Here, you just need SalesTable buffer at runtime which you need to pass to the code. I have a custom field control in the SalesTable where I am storing total actual tax amount (which I am getting from the third-party tool). 

TaxRegulation   taxRegulation;
                    SalesTotals     salesTotals = SalesTotals::construct(salesTableLocal);
        
                    salesTotals.calc();
                    taxRegulation = TaxRegulation::newTaxRegulation(salesTotals.tax());
                    taxRegulation.allocateAmount(salesTableLocal.HSTotalWebTaxAmountCur);
                    taxRegulation.saveTaxRegulation();

Scenario# 1.2: To override sales tax in a sales order

Here, the scenario is to create a Sales order and post Sales invoice along with Tax override activity too.





Task# 02: To reset Actual to Calculated sales tax amount in a Sales order

Here, I am going to share my experience on to remove adjusted sales tax amount in a Sales order.

Scenario# 2.1: To override sales tax in a sales order

Here, you just need SalesTable buffer at runtime which you need to pass to the code.

// reset actual to calculated sales tax amount.
            TaxRegulation   taxRegulation;
            SalesTotals     salesTotals = SalesTotals::construct(salesTableLocal);
            salesTotals.calc();

            taxRegulation = TaxRegulation::newTaxRegulation(salesTotals.tax(), null,salesTableLocal.TableId, salesTableLocal.RecId);
            if (taxRegulation.taxLinesExist())
            {
                taxRegulation.resetTaxRegulation();

                taxRegulation.saveTaxRegulation();
            }



Happy DAXing...


Tuesday 15 September 2020

How to calculate total tax for a order in D365 using X++

 How to calculate total tax for a Sales order using X++

Today, I will show, how to calculate tax in D365 FO (AX) through code

Scenario 1: To find Sales Totals values for Sales order in D365

Here, my requirement is to export Sales Totals component's value through custom data entity. I have applied below logic, hope it will help you...

Accounts receivable/ All sales orders/ select any Sales order/ Sales order button group/ View/ Totals 
public void postLoad()
    {
        SalesLine   salesLineLoc;
        SalesTable  salesTableLoc = SalesTable::find(this.SalesId);
        SalesTotals totals;

        super();

        select sum(LineAmount) from salesLineLoc
            where salesLineLoc.SalesId == salesTableLoc.SalesId;
        this.SubTotalAmount = salesLineLoc.LineAmount;

        // No problem if the total is not negative
        totals = SalesTotals::construct(salesTableLoc, SalesUpdate::All);
        totals.calc();
        this.TotalEndDisc   = conPeek(totals.displayFields(), TradeTotals::posEndDisc());
        this.TotalLineDisc  = conPeek(totals.displayFields(), TradeTotals::posLineDisc());
        this.TotalCharges   = conPeek(totals.displayFields(), TradeTotals::posMarkup());
        this.InvoiceAmount  = conPeek(totals.displayFields(), TradeTotals::posTotalAmount());
        
        salesLineLoc = null;
        salesLineLoc = SalesLine::findInventTransId(this.InventTransId);
        if (salesTableLoc.HSChangedInD365 == NoYes::No)
        {
            this.WebShippingTaxAmount   = salesTableLoc.HSWebChargeTaxAmountCur;
            this.TotalTaxAmount         = salesTableLoc.HSTotalWebTaxAmountCur;
            this.LineTaxAmount          = salesLineLoc.HSWebLineTaxAmountCur;
        }
        else
        {
            this.TotalTaxAmount = conPeek(totals.displayFields(), TradeTotals::posTaxTotal());
            //this.TotalTaxAmount = abs(salesTotals.tax().totalTaxAmountCalculated());   // Total calculated sales tax amount
            //this.TotalTaxAmount = abs(salesTotals.tax().totalTaxAmount());             // Total actual sales tax amount

            totals.tax().sourceSingleLine(true, true);
            this.LineTaxAmount = totals.tax().totalRegulatedTaxAmountSingleLine(salesLineLoc.TableId, salesLineLoc.RecId);  // sales line actual tax amount
            //this.LineTaxAmount = salesTotals.tax().totalTaxAmountSingleLine(salesLineLoc.TableId, salesLineLoc.RecId);    // sales line calculated tax amount
            
            // to get calculated tax for a particular charge line associated with a sales order.
            MarkupTrans markupTransLoc;
            select firstonly markupTransLoc
                where markupTransLoc.MarkupCode == HSIntegrationParameters::find().PaidByCustomer  //'CUSTFRGHT'
                &&    markupTransLoc.TransRecId == salesTableLoc.RecId
                &&    markupTransLoc.TransTableId == tableNum(SalesTable);
            this.WebShippingTaxAmount = abs(totals.tax().taxPrLine(tableNum(MarkupTrans), markupTransLoc.RecId));
        }       
    }

//You have to pass these values to the functions whether it comes from PurchLine or SalesLine or any other table.
//This may not work for Avalara tax engine then follow below scenarios...

Tax::calcTaxAmount(purchLine.TaxGroup, purchLine.TaxItemGroup, Systemdateget(), purchLine.CurrencyCode, purchLine.LineAmount, TaxModuleType::Purch);

Scenario 2.1: To calculate tax for each Sales order line in D365

I have written display method in SalesLine table to show line-wise calculated sales tax. This method can be utilized in multiple places...

public display TaxAmountCur displayLineTaxAmount()
    {
        salesTable      salesTable;
        SalesTotals     salesTotals;
        TaxAmountCur    taxAmountCur;

        salesTable  = SalesTable::find(this.SalesId, false); 
        salesTotals = SalesTotals::construct(salesTable, SalesUpdate::All);
        salesTotals.calc();
        salesTotals.tax().sourceSingleLine(true, true);
        taxAmountCur    = salesTotals.tax().totalTaxAmountSingleLine(this.TableId, this.RecId);

        return TaxAmountCur;

    }

Scenario 2.2: To calculate tax for each Sales order line in D365

I have written display method in SalesLine table to show line-wise calculated sales tax. This method can be utilized in multiple places...


public display TaxAmount displayLineTaxAmount()
    {
        SalesLine       salesLineLoc;
       
select firstonly salesLineLoc
            where salesLineLoc.RecId == this.RecId;

        return Tax::calcTaxAmount(salesLineLoc.TaxGroup,
                                salesLineLoc.TaxItemGroup,
                                Systemdateget(), 
                                salesLineLoc.CurrencyCode,
                                salesLineLoc.LineAmount,
                                TaxModuleType::Sales);
    }

Scenario 3: To calculate tax for Sales order in D365

I have written display method in SalesTable table to show total calculated sales tax. This method can be utilized in multiple places...


public display TaxAmountCur displayTotalTaxAmount()
    {
        salesTable      salesTable;
        SalesTotals     salesTotals;
        TaxAmountCur    taxAmountCur;

        salesTable  = SalesTable::find(this.SalesId, false);
        salesTotals = SalesTotals::construct(salesTable, SalesUpdate::All);
        salesTotals.calc();
        taxAmountCur = abs(salesTotals.tax().totalTaxAmount());

        return TaxAmountCur;
    }

Add display method as a data field in Field groups in a table



ScenariScenario 4: To calculate tax for each Purchase order line in D365.

I have written display method in PurchLine table to show line-wise calculated purch tax. This method can be utilized in multiple places...

public display TaxAmountCur totalTaxAmount(boolean _adjustTaxSign = true, boolean _includeUseTax = false)
{
    PurchTotals     purchTotals;
    TaxAmountCur    taxAmountCur;

    purchTotals     = PurchTotals::newPurchTable(this.purchTable());
    purchTotals.calc();
    purchTotals.tax().sourceSingleLine(true, true);
    taxAmountCur    = purchTotals.tax().totalTaxAmountSingleLine(this.TableId, this.RecId, _adjustTaxSign, _includeUseTax);

    return taxAmountCur;
}

Scenario 5: To calculate tax for Purchase order in D365

I have written display method in PurchTable table to show total calculated purch tax. This method can be utilized in multiple places...

public display TaxAmountCur totalTaxAmount(boolean _adjustTaxSign = true, boolean _includeUseTax = false)
{
    PurchTotals     purchTotals;
    TaxAmountCur    taxAmountCur;

    purchTotals     = PurchTotals::newPurchTable(this.purchTable());
    purchTotals.calc();
    taxAmountCur    = purchTotals.tax().totalTaxAmount();

    return taxAmountCur;
}

Scenario 6: To calculate tax for GL journal in D365

I have written display method in LedgerJournalTrans table to show total calculated tax. This method can be utilized in multiple places...

public display TaxAmountCur totalTaxAmount(boolean _adjustTaxSign = true, boolean _includeUseTax = false)
{
        TaxCalculation taxCalculation;
    LedgerJournalTrans      ledgerJournalTrans;
    TmpTaxWorkTrans         tmpTaxWorkTrans;
    TaxAmountCur            taxAmountCur;

    ledgerJournalTrans = LedgerJournalTrans::findRecId(5637293082, false); 

    // This is from `\Classes\LedgerJournalEngine\getShowTax`
    taxCalculation = LedgerJournalTrans::getTaxInstance(ledgerJournalTrans.JournalNum, 
ledgerJournalTrans.Voucher,
  ledgerJournalTrans.Invoice, 
true, 
null, 
false, 
ledgerJournalTrans.TransDate);
    taxCalculation.sourceSingleLine(true, false);

    // This is from `\Classes\TaxTmpWorkTransForm\initTax`
    tmpTaxWorkTrans.setTmpData(taxCalculation.tmpTaxWorkTrans());

    // This is the temporary table that is populated
    while select tmpTaxWorkTrans
    {
        // This is from `\Classes\TaxTmpWorkTransForm\getSourceBaseAmountCur`
        taxAmountCur = (tmpTaxWorkTrans.SourceTaxAmountCur * tmpTaxWorkTrans.taxChangeDisplaySign(null));

        // This just outputs some data
        info(strFmt("%1: %2", tmpTaxWorkTrans.TaxCode, taxAmountCur));
    }

    return taxAmountCur;
}


--------------------------------
Happy DAXing...