Batch jobs in D365: a Russian roulette

Batch jobs in D365: a Russian roulette

Real world production scenarios include automated batch tasks executed in the background with some cadence: Batch processing overview – Finance & Operations. They apply to sets of documents fetched at the run time, for example to sales orders delivered, but not invoiced yet. Obviously, every day the query with the documents should return a different set with the recently despatched sales orders. It is called Late selection: Late selection in D365FO – D365Tour. So far so known.

As the complexity of the business grows, so does the complexity of the batch jobs. You’ll need jobs consisting of multiple tasks, executed one after another. It is called task dependency, or task Constraints. One of the latest unpleasant discoveries was the fact, that you cannot always rely on the sequence of steps set in the batch job: the most useful tasks, such as the SalesFormLetter_Invoice and its likes (used to update sales and purchase orders with order confirmations, delivery notes and invoices) act as orchestrators and spin off child batch tasks for simultaneous, multi-threaded sales order, purchase order, production order processing. These child tasks are not constrained (!) and get executed at a first come, first served basis. They may still run while the master task SalesFormLetter_Invoice seemingly ends and relays the baton to the next task. This leads to interference and racing conditions. You better evaluate the average execution time of the master controller task as a whole, put these controllers into different batch jobs, schedule them at a safe time distance from one another.

Heterogenous batch jobs as the one shown below pose a different challenge.

Here is the how-to instruction:

  1. Spin off the first task from the main menu (here: Production control > Periodic tasks > Production order status update) and choose Run in the background / Batch processing. This will be your starting point, a template for the batch job.
  2. Locate the batch job in the My batch jobs list, set the status to Withheld and start editing.
  3. Every task within a batch job needs a Class name. Now you know the class name of the first task: ProdMultiCostEstimation. To add the next task, you have to manually specify its Class name. The owners of this framework provided a lookup list, but it is slow and completely dysfunctional: it shows just a fraction of the possible executable RunBase or SysOperation classes, sometimes it crashes if there are some bad customizations in the source code. If you don’t know the class name, repeat the step 1 to reveal it.
  4. Add the next task, type the class name in. The first time it will take the system up to 20-30 seconds to accept and retrieve the Class description.
  5. Most batch tasks need a query. Click Parameters to populate it. Here you experience another nasty trait of the batch framework: the query shown is the last one you used in the system elsewhere. It is not necessarily the one really persisting at the batch task. Another user is not going to see your query criteria at all: only the owner/creator has the control. *1) *2) *3)
  6. On the Batch task details tab, Constraints, choose the predecessor task to build a chain. You many need to change the Expected status to Ended or error if the batch job has to continue with the next task on an error somewhere in the chain.
  7. Check the recurrence, remove the Alerts if needed, and put the Batch job back to Waiting.

1) Lessons learned: take a screenshot of every query and parameter, document it thoroughly to pass the maintenance to the Dynamics system administrator.

2) In certain cases a manually added task does not let edit the execution parameters and/or the query. Sometimes(e.g. on sales order updates) it helps to execute the same periodic task in the normal user session once. This is the reason why it is often hard to pre-configure the batch jobs in a “Golden Config” environment: it may need real transactions to execute against. Sometimes it wishes to be initialised from the main menu and nowhere else because badly programmed. In such a case, start your step 1 – the key task – from this critical periodic task. Should there be 2 such bitchy tasks in one batch job chain, it is over. They must be separated into different batch jobs.  

3) As a really bad surprize came the fact that even the owner has no control over the query: if you use the Late selection, in a chain of nearly identical tasks as the ones below, the QUERY OF THE LAST TASK IS APPLIED TO EVERY TASK of the kind, at least in the case of the production order status updates.

You should let the bloody job run one first time, then put the batch job back on hold and adjust the queries in the tasks once more, then save and re-activate the batch job.

Austrian VAT declaration / Umsatzsteuervoranmeldung 2020

Austrian VAT declaration / Umsatzsteuervoranmeldung 2020

Following up on my latest blog, let me continue with the specific setup for the VAT return in Austria. This electronic VAT declaration called Umsatzsteuervoranmeldung “UVA” must be uploaded monthly or quarterly (depending on the company’s turnover) in a proprietary XML format to the web site FinanzOnline of BMF, the Austrian Ministry of Finance. The interface is well maintained by the DACH support team for Dynamics, but there was nowhere on the Internet a description of the barebone setup. Well, up until now.

The only documentation is the class TaxReport_ReportAT, which is used by the periodic function VAT payment in the Tax module to produce a “UVA” declaration, both printed and the electronic. I reverse engineered it, and it should be noted that

  • It requires a non-continuous number sequence XML VAT package number to form a message ID.
  • The printed PDF version is not accepted by the ministry anymore, but it is quite useful to visualize and check the VAT return prior to the booking. The latest template required by the class can be downloaded here.
  • The printed form expects an exotic address format of the legal entity primary address, one with a separate house number Street number.
  • The tax number (not to mix with the European VAT (UID)-number) MUST be present in the legal entity, Tax registration number field in the format xxx/yyyy-ZZ, where ZZ is the number of the BMF’s local office. The same can be seen without dashes and slashes on FinanzOnline.
  • The class uses a set of hardcoded 4 digit codes to map tax codes to cells on the tax return. There are cells (and the respective XML elements) for a total tax base per tax period per VAT rate, or a tax amount per tax period per VAT rate.

Below are the most relevant VAT return cell codes. For more information on the individual VAT return cells, please refer to the comprehensive description (de-at) on the BMF site.
You should add the 16 codes to the table VAT reporting codes with the Report layout = Austrian report layout.

Reporting codeReport textBrief description
1122Gesamt Umsatzsteuer: 20% NormalsteuersatzTotal sales VAT: full 20%
1022Gesamt Bemessungsgrundlage: 20% NormalsteuersatzTotal sales base: full 20%
1011Bemessungsgrundlage: Ausfuhrlieferungen § 6 Abs. 1 Z 1 iVm § 7Sales base: Export 3rd country tangible
1021Bemessungsgrundlage: Steuerschuldübergang § 19, grenzüberschreitende LeistungenSales base: Reverse charge incl. export of services IC, 3rd
1020Bemessungsgrundlage: übrige steuerfreie Umsätze ohne VorsteuerabzugSales base: Other exempt sales
1017Bemessungsgrundlage: IgL Art. 6 Abs. 1 ohne FahrzSales base: IC delivery
1160Vorsteuer ohne…Total purchase VAT except for…
1157Steuerschuldübergang bei Bezug gemäß § 19 Abs. 1 zweiter Satz, § 19 Abs. 1cIC purchase payable VAT: Reverse charge on service acquis
1166Vorsteuer: Steuerschuldübergang gemäß §19, grenzüberschreitende LeistungenIC purchase receivable VAT: reverse charge on service acquis
1183Vorsteuer: Einfuhrumsatzsteuer geschuldet (§ 12 Abs. 1 Z 2 lit. b)Purchase 3rd country import VAT (payable)
1172IgE Steuerschuld: 20% NormalsteuersatzIC purchase payable VAT: full 20%
1072IgE Bemessungsgrundlage: 20% NormalsteuersatzIC purchase payable base: full 20%
1106Gesamt Umsatzsteuer: 13% ermäßigter SteuersatzTotal sales VAT: reduced 13% (agro B2C)
1006Gesamt Bemessungsgrundlage: 13% ermäßigter SteuersatzTotal sales base: reduced 13% (agro B2C)
1129Gesamt Umsatzsteuer: 10% ermäßigter SteuersatzTotal sales VAT: reduced 10% (foodstuffs, print media)
1029Gesamt Bemessungsgrundlage: 10% ermäßigter SteuersatzTotal sales base: reduced 10% (foodstuffs, print media)

 

Finally, the above 16 reporting cells are assigned to my 12 VAT codes in the VAT codes table:

Report setupexFexSeuFeuAeuReuSNRTFdoFdoAdoHdoR
Taxable sales        1022102210061029
Duty-free sale101110211017101710171021 1020    
VAT payable        1122112211061129
Taxable purchases            
Duty-free purchase            
VAT receivable        1160116011601160
Taxable import  107210721073       
Offset taxable import            
Import VAT/ purchase VAT1183 1172117211731157      
Offset import VAT/ purchase VAT     1166      
(EU sales list excluded)yesyes    yesyesyesyesyesyes
(Country type)3rd3rdEUEUEUEU DomDomDomDomDom

The Report setup – credit note of the VAT code records is identical.

The full list of the Austrian VAT reporting codes can be downloaded here. The not relevant codes are marked “N/A”. My criteria for the relevance for a typical manufacturing or a service business were:

  • Reselling of cars, scrap, gas, electricity, CO2 certificates are ‘exotic’ businesses, as well as seafaring, trucking, taxi services, real estate agencies;
  • Small businesses below the 100 000 EUR turnover threshold would never use Dynamics AX either;
  • The Jungholz and Mittelberg exclave valleys with the German VAT are too small to get noticed;
  • It is not practical to apply a dedicated tax code to goods intended for the self-consumption by the company owner: such goods do not reduce the income/corporate tax base either and should better not appear in the accounting at all, or be simply sold to the owner via a sales order as everything else.

Happy tax paying!