Tax amount override in free text invoices

Introduction

One of the common issues we encounter when importing free text invoices into Dynamics AX is overriding the tax. Usually AX calculates the tax when sales invoice lines are inserted into the free text invoice. On some occasions, such as when integrating AX with external systems, users will want the tax calculated by AX to be overridden with the value form the external system so that the tax in  both system matches to the penny.

Override the tax manually

To override tax manually in free text invoices, go to Sales ledger/Common/Free text invoices/All free text invoices. Choose one of the free text invoices that has not been posted yet (e.g. no invoice Id was assigned). Then from the action pane, click on VAT under Details group. This will open a form that will look like this…

B1

Click on the Adjustment tab and you will see the following:

B2

In the form above, you can tick the “Override calculated VAT” field and then set the new tax value in the “Actual VAT amount” text box. Before you close the form, click apply.

Override the tax in x++

We will do the same exercise but from x++ code. There are many blogs and articles on how to do this but in order not to jump into different websites to get the code, I copied the code from a random website here below and then added my code afterwards.

So, the original code will look something like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void FreeTextTaxAdjust(Args _args)  
{  
  CustInvoiceTable    custInvoiceTable;  
  CustInvoiceCalcTax  custInvoiceCalcTax;  
  TaxFreeInvoice      taxFreeInvoice;  
  TaxRegulation       taxRegulation;  
  ;  
 
  ttsbegin;  
 
  select firstonly custInvoiceTable  
  where custInvoiceTable.RecId == 54371652769;  
 
  custInvoiceCalcTax = new CustInvoiceCalcTax_Table(custInvoiceTable);  
  taxFreeInvoice     = new TaxFreeInvoice(custInvoiceCalcTax);  
  taxFreeInvoice.calc();  
  taxRegulation = TaxRegulation::newTaxRegulation(taxFreeInvoice);  
  taxRegulation.allocateAmount(2.01);  
  taxRegulation.saveTaxRegulation();  
 
  ttscommit;  
}

As shown in the code above, this will override the total tax amount of the free text invoice from the automatically calculated £2 to £2.01. The issue with this is that AX will merge the taxes by the VAT code. So, if in the form above we had two tax codes (STD and RED) instead of only one tax code (STD), then the code above will not handle it. The code above will only allow inserting the total tax amount for both tax codes. It will not allow splitting the values for each tax code.

I managed to fix the issue by splitting the above into two steps:

  1. A method to get the tax code. In my case, I cross reference the Tax Group with the Tax Item Group to get the tax code. This can be done by using the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static TaxCode CWFGetCrossRefTaxCode(TaxGroup _taxGroup, 
                                            TaxItemGroup _taxItemGroup)
{
    TaxOnItem           taxOnItem;
    TaxGroupData        taxGroupData;
    TaxTable            taxTable;
    ;
 
    select firstonly TaxCode from taxTable
    join firstonly TaxGroup, TaxCode from taxGroupData
    where taxGroupData.TaxCode == taxTable.TaxCode
       && taxGroupData.TaxGroup == _taxGroup
    join firstonly TaxItemGroup, TaxCode from taxOnItem
    where taxOnItem.TaxCode == taxTable.TaxCode
       && taxOnItem.TaxItemGroup == _taxItemGroup;
 
    return taxTable.TaxCode;
}
  1. Use the tax code from the method above and pass it to the method below along with the new tax amount:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public static void CWFCalculateTax(TaxCode _taxCode, 
                                   TaxAmount _taxAmount, 
                                   CustInvoiceTable _custInvoiceTable)
{
    CustInvoiceCalcTax          custInvoiceCalcTax;
    TaxFreeInvoice              taxFreeInvoice;
    TaxRegulation               taxRegulation;
    TmpTaxWorkTrans             tmpTaxWorkTrans;
    TmpTaxRegulation            tmpTaxRegulation;
    ;
 
    ttsbegin;
 
    custInvoiceCalcTax = new CustInvoiceCalcTax_Table(_custInvoiceTable);
    taxFreeInvoice     = new TaxFreeInvoice(custInvoiceCalcTax, true, true, true);
    taxFreeInvoice.calcTax();
 
    taxRegulation = TaxRegulation::newTaxRegulation(taxFreeInvoice);
    tmpTaxRegulation = taxRegulation.tmpTaxRegulation();
    tmpTaxWorkTrans = taxRegulation.tmpTaxWorkTrans();
 
    while select tmpTaxRegulation
    where tmpTaxRegulation.TaxCode == _taxCode
    {
        tmpTaxRegulation.SourceRegulateAmountCur = _taxAmount;
        tmpTaxRegulation.OverrideCalculatedTax = NoYes::Yes;
        tmpTaxRegulation.update();
    }
 
    while select tmpTaxWorkTrans
        where tmpTaxWorkTrans.TaxCode == _taxCode
    {
        tmpTaxWorkTrans.SourceRegulateAmountCur = _taxAmount;
        tmpTaxWorkTrans.update();
    }
 
    taxRegulation.setTmpTaxWorkTransTmpData(tmpTaxWorkTrans);
    taxRegulation.saveTaxRegulation();
    ttscommit;
}

With the code above, I managed to override the tax amount for multiple tax codes only when I’ve updated the table TmpTaxWorkTrans.

Happy DAXing!

“The Art Of Debugging” – Tip 4 – Intercept a query

It has been a while since my last post on debugging. I haven’t run out of tips though – just been incredibly busy.

Sometimes when you are debugging the software in Ax you will be interested in seeing what records are being returned by a query. That can be easy when the records are displayed in a form and you can immediately see for yourself the returned data but when the query is running in X++ and not displayed directly on a screen it isn’t so easy to track.

One approach to make things easy is to override the PostLoad method at table level.

Take for example a list of Vendors. If we override the method PostLoad on table VendTable we can then set a breakpoint on this method. The breakpoint will be hit for each VendTable record returned by any query on that table. This applies to records returned by a form data source, by a query object or even by a direct X++ select statement.

This technique can prove to be a very good way to trace all of the reads on a particular table but don’t leave the method behind when you’re finished debugging as it will negatively impact performance of reads on that table.

Keep on debugging!

Changing label text on the POS

Sometimes you’ll want to customise the text that appears on the POS forms to meet the needs of the client.

Did you know that each string of text that appears on a POS form has a unique label ID?  Well, by finding out the POS label ID it is possible to centrally override the standard POS text linked to that ID and apply the text you want to display instead.

This is how you do it…

1.  Change the POS shortcut target = ‘-tr’

Change the target

Change the target

2.  Now open the POS using the amended shortcut.  Every label on the POS will now display a unique label ID.

2

3.  Identify the text on the POS that you want to change and make a note of the POS label ID – in this case lets change label 110 which currently says “Search or enter quantity”

4.  Login to Dynamics AX

5.  Access the AOT > Tables – find the table named ‘RetailLanguageText’ and select open

5

6.  This table contains a list of POS override text.  Any text linked to labels here will override the standard POS labels.

6

7.  Create a new row in the table and specify:

  • The language ID
  • The replacement label text
  • And in Text ID ensure this is the label number – e.g. 110
  • Tick the Active checkbox

8.  In this example I have changed the text for label 110 to be “Enter SKU or product name”.

9.  Now you will need to synchronise this label update down to the POS.  To do this run the Registers job under Retail > Periodic > Data Distribution – Distribution Schedule.  The actual sub job that applies the change is ‘ADDP-PLT’ which updates the RetailLanguageText table on the POS Database.

7

10.  Logon to the POS.  You should see that the relevant POS label has now been changed.

8

11.  Don’t forget to remove –tr from your POS shortcut so that the label ID’s stop showing

If this didn’t work – ensure you entered the label language ID in AX correctly for the User who is logging onto the POS.