MICROSOFT DYNAMICS® AX 2009

COURSE 80014 DEVELOPMENT IV

Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Last Revision: November 2008

The information contained in this document represents the current view of Microsoft Corporation on the issues
discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should
not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any
information presented after the date of publication.

This document is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED
OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT.

Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under
copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or
transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any
purpose, without the express written permission of Microsoft Corporation.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights
covering subject matter in this document. Except as expressly provided in any written license agreement from
Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or
other intellectual property.

© 2008 Microsoft Corporation. All rights reserved. Microsoft Dynamics®, Microsoft® PowerPoint® Microsoft® SQL
Server® and Microsoft Dynamics® AX MorphX® are trademarks or registered trademarks of Microsoft
Corporation. The names of actual companies and products mentioned herein may be the trademarks of their
respective owners.

This course content is designed for Microsoft Dynamics® AX 2009.

Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Table of Contents

Introduction to Development IV in Microsoft Dynamics AX 2009 0-1
Welcome ............................................................................................................ 0-1
Microsoft Dynamics Courseware Contents ........................................................ 0-2
Documentation Conventions .............................................................................. 0-3
Student Objectives ............................................................................................. 0-4
Chapter 1: Point-of-Sale Project 1-1
Objectives ........................................................................................................... 1-1
Introduction ......................................................................................................... 1-1
Overview ............................................................................................................ 1-2
Functional Design ............................................................................................... 1-3
Technical Design ................................................................................................ 1-4
Summary ............................................................................................................ 1-7
Quick Interaction: Lessons Learned ................................................................... 1-8
Chapter 2: Number Sequences 2-1
Objectives ........................................................................................................... 2-1
Introduction ......................................................................................................... 2-1
Overview ............................................................................................................ 2-2
Assign a New Number ........................................................................................ 2-4
Continuous Number Sequences......................................................................... 2-5
Format a Number ............................................................................................... 2-5
Number Pre-Allocation ....................................................................................... 2-6
Clean Up Process .............................................................................................. 2-6
Form Handler ..................................................................................................... 2-7
NumberSeqReference ........................................................................................ 2-7
Summary ............................................................................................................ 2-8
Test Your Knowledge ......................................................................................... 2-9
Lab 2.1 - Add Pay Id number sequence ........................................................... 2-10
Lab 2.2 - Use Form Handler ............................................................................. 2-12
Quick Interaction: Lessons Learned ................................................................. 2-13
Solutions ........................................................................................................... 2-14
Chapter 3: PrintJobSettings 3-1
Objectives ........................................................................................................... 3-1
Introduction ......................................................................................................... 3-1
Set Print Options ................................................................................................ 3-2
Retrieve Print Options ........................................................................................ 3-4
Use of Pack and Unpack to Store Settings ........................................................ 3-4
Use of SysPrintOptions ...................................................................................... 3-5
Summary ............................................................................................................ 3-6
Test Your Knowledge ......................................................................................... 3-7
Lab 3.1 - Suppress Scaling Message ................................................................. 3-8
Lab 3.2 - Print Job Settings ................................................................................ 3-9
Lab 3.3: Print the receipt to the correct printer ................................................. 3-10
Lab 3.4 - Bypass Print Options ......................................................................... 3-11
Quick Interaction: Lessons Learned ................................................................. 3-12
Solutions ........................................................................................................... 3-13

Microsoft Official Training Materials for Microsoft Dynamics ® i
Your use of this content is subject to your current services agreement

Development IV in Microsoft Dynamics® AX2009

Chapter 4: Business Connector 4-1
Objectives ........................................................................................................... 4-1
Introduction ......................................................................................................... 4-1
Business Connector Overview ........................................................................... 4-2
Business Connector Setup and Configuration.................................................... 4-3
Business Connector Architecture ....................................................................... 4-7
Summary .......................................................................................................... 4-12
Test Your Knowledge ....................................................................................... 4-13
Lab 4.1 - Business Connector .......................................................................... 4-15
Lab 4.1 - Business Connector (Solution) .......................................................... 4-19
Quick Interaction: Lessons Learned ................................................................. 4-21
Chapter 5: CLR Interoperability 5-1
Objectives ........................................................................................................... 5-1
Introduction ......................................................................................................... 5-1
Reference CLR Assemblies in the AOT ............................................................. 5-2
Adding Assemblies to the Global Assembly Cache or Client ............................. 5-3
Leverage CLR Managed Code Within X++ Code............................................... 5-4
InteropPermission Class .................................................................................... 5-6
Web service references ...................................................................................... 5-6
Implementing a DLL ......................................................................................... 5-12
Summary .......................................................................................................... 5-15
Test Your Knowledge ....................................................................................... 5-16
Lab 5.1 - CLR Interop ....................................................................................... 5-18
Lab 5.1 - CLR Interop (Solution)....................................................................... 5-19
Lab 5.2 - Implementing DLL's........................................................................... 5-21
Lab 5.2 - Implementing DLL's (Solution) .......................................................... 5-22
Quick Interaction: Lessons Learned ................................................................. 5-23
Solutions ........................................................................................................... 5-24
Chapter 6: Ledger 6-1
Objectives ........................................................................................................... 6-1
Introduction ......................................................................................................... 6-1
Scenario ............................................................................................................. 6-2
LedgerVoucher ................................................................................................... 6-2
LedgerJournal .................................................................................................. 6-10
Summary .......................................................................................................... 6-13
Test Your Knowledge ....................................................................................... 6-14
Lab 6.1 – Create and Post a Ledger Journal.................................................... 6-16
Lab 6.2 – POS - End-of-day routine ................................................................. 6-18
Quick Interaction: Lessons Learned ................................................................. 6-20
Solutions ........................................................................................................... 6-21
Chapter 7: Trade 7-1
Objectives ........................................................................................................... 7-1
Introduction ......................................................................................................... 7-1
TableType and LineType .................................................................................... 7-2
Post and Print Document Updates ..................................................................... 7-5
Posting Transactions ........................................................................................ 7-11

ii Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

.................3 (Solution) ... 9-2 ProdStatusType ....... 9-18 Lab 9..........................................................................Production (Solution) .. 8-17 InventMovement . 8-2 Inventory Dimensions ...................... 9-8 Summary ............................................................ 7-21 ab 7................. 8-18 InventUpdate ...........................................................................................................................................2 ............................................................................................ 8-29 Quick Interaction: Lessons Learned ............................................................................................................................................................................................................................ 8-27 Lab 8......................................................................................................................2 ...................................3 – POS .................. 9-1 Introduction ........................................................... 7-14 Summary ............................................ 8-4 InventSum .............. 10-1 Microsoft Official Training Materials for Microsoft Dynamics ® iii Your use of this content is subject to your current services agreement .................................................................................................... 7-16 Test Your Knowledge ............................. 7-17 Lab 7.................................1 ......................................................... 8-1 Introduction ...............................................................................................................................................................................................Trade .......................1 ....................................Production (Solution) ............................................................................................................ 7-25 Solutions ................... 7-19 Lab 7...............................................................................................................................Payment Posting and Invoice Update (Solution) ................................................................................................................................................................ 7-13 Trade Agreement .......... 8-25 Lab 8.......................................................................................................................................................................................................................... 8-10 Lab 8............................................................................................................................... 8-20 Summary .........2 .................................. 9-15 Lab 9........ 9-4 ProdUpd ........................................ 8-24 Test Your Knowledge ...................................................................................................................................2 ..................... 9-1 ProdMulti ... 9-14 Test Your Knowledge ....................................................................................... 7-22 Lab 7. 8-2 Inventory Journals ........1 – On-hand Inventory on Sales Order Form ...................... 8-1 Scenario ................ 9-6 Scheduling .....................Settlement ........................Payment Posting and Invoice Update ...................Display inventory dimensions ...... 9-19 Quick Interaction: Lessons Learned ...... 10-1 Introduction ......................................................................................................................... 7-26 Chapter 8: Inventory 8-1 Objectives ....4 – POS ........................... 9-16 Lab 9.................... 8-28 Lab 8......................................................................................................................... 7-20 Lab 7.............................................................................. 8-31 Chapter 9: Production 9-1 Objectives ............................................................................................................................1 .............2 – Create an ABC allocation ......................................................................................................................................................................... 7-24 Quick Interaction: Lessons Learned .....................................................................................................................................................................Production ...............................Trade (Solution) ................... 9-20 Solutions ............................................... 7-23 Lab 7............... 9-17 Lab 9......... 8-30 Solutions ..1 ........... 9-21 Chapter 10: Project Accounting 10-1 Objectives .....................................................................................................Display on hand inventory ....................................................................3 ........................ Table of Contents Settlement .........................................................................................Production ......................................

.................................................................................................. 10-2 Design ...1 .................... 11-2 Create a Workflow Template .................................... 11-27 Quick Interaction: Lessons Learned .......................................................................... 11-4 Create a Workflow Approval ................................ 10-11 Lab 10................................................................. 11-2 Create a Workflow Category ............................................................................................................. 10-2 Posting Transactions ..... 11-5 Enable Workflow on a Form ................................. 11-1 Introduction ....... 11-22 Lab 11..................... 11-17 Lab 11...........................................................................................................2 ............................................................................. 11-3 Create a Workflow Document ...........................................................Enable Resubmit ............................................................................ 11-2 Workflow Installation .............................................................................................................................................................................................................................2 ...................................................................................................................................................................... 10-4 Invoice Proposal .........Development IV in Microsoft Dynamics® AX2009 Scenario .................................................. 11-8 Create Event Handlers ............................................................................................................................................................................................................. 10-5 Invoice ..............................................................................Add Another Condition to the Submit Action ............................... 11-24 Summary .. 11-1 Scenario .......................1 . 11-29 iv Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement ........................................................................... 10-10 Test Your Knowledge ................................................................Warranty Item ........................................................................ 11-19 Code Walkthrough: Submitting a workflow ......... 11-28 Solutions ........... 11-26 Test Your Knowledge .................................................................................. 10-14 Solutions .. 10-15 Chapter 11: Workflow 11-1 Objectives ......................................... 10-13 Quick Interaction: Lessons Learned ....................................................................................................................................Place Invoice Proposal On Hold.......................................................................... 10-8 Summary ..................... 10-12 Lab 10................................................................................................................................................................................................ 11-20 Code Walkthrough: Workflow Processor ..................................................................................................... 11-12 Configure a Workflow .................................................

Online Training Online Training delivers convenient. interactions and quizzes. It is perfect for the customer who does not have the time or budget to travel. Our newest online training option.com/Dynamics. or Training Materials. combine the efficiency of online training with the in-depth product coverage of classroom training. Choose the training type that best suits you so you can stay ahead of the competition. Regularly scheduled throughout North America.microsoft. Classroom Training. From demonstrations to presentations to classroom activities. Training Materials Training Materials enable you to learn at your own pace. Our quality training from industry experts keeps you up-to-date on your solution and helps you develop the skills necessary for fully maximizing the value of your solution. there is a type of training to meet everyone's needs. in-depth training to you in the comfort of your own home or office. and insights you can refer to again and again: Microsoft Dynamics Courseware The Microsoft Dynamics Courseware consists of detailed training manuals. on your own time with information-packed training manuals. you can be sure you will find a class convenient for you. designed from a training perspective. in-depth learning through hands-on interaction. Look for a complete list of manuals available for purchase on the Microsoft Dynamics website: www. Introduction INTRODUCTION TO DEVELOPMENT IV IN MICROSOFT DYNAMICS AX 2009 Welcome We know training is a vital component of retaining the value of your Microsoft Dynamics® AX 2009 investment. with at least two weeks to complete each course. exercises. eCourses. Classroom Training Classroom Training provides serious. These manuals include advanced topics as well as training objectives. Online training provides immediate access to training 24 hours-a-day. you receive hands-on experience with instruction from our certified staff of experts. Microsoft Official Training Materials for Microsoft Dynamics ® 0-1 Your use of this content is subject to your current services agreement . Our wide variety of training manuals feature an abundance of tips. Whether you choose Online Training. tricks.

Quick Interaction: Lessons Learned At the end of each chapter within the Microsoft Dynamics Training Material. These exercises are designed for the experienced student who requires little instruction to complete the required task. if you need help completing the task look to the information in the level two exercises. Need a Little Help? Level 2 exercises are designed to challenge students. and providing themselves with an excellent resource for reviewing key points after class.Development IV in Microsoft Dynamics® AX2009 Microsoft Dynamics Courseware Contents Test Your Skills Within the Microsoft Dynamics Training Materials you find a variety of different exercises. These exercises do not provide step by step instructions. This interaction is designed to provide the student with a moment to reflect on the material they have learned. If you need further assistance each step of the task is outlined in the level one exercise. you find a Quick Interaction: Lessons Learned page. while providing some assistance. the student is maximizing knowledge retention. do provide you with helpful hints and more information to complete the exercise. We suggest you try the level three exercises first. By outlining three key points from the chapter. Level 1 exercises guide you through the task. These exercises are offered in three levels to accommodate the variety of knowledge and expertise of each student. step by step. Step by Step Level 1 exercises are geared towards new users who require detailed instructions and explanations to complete the exercise. Challenge Yourself! Level 3 exercises are the most challenging. 0-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . including navigation. however.

Hints are used to suggest time-saving features or alternative methods for accomplishing a specific task. Microsoft Official Training Materials for Microsoft Dynamics ® 0-3 Your use of this content is subject to your current services agreement . EXAMPLE: Examples are found throughout the training manual and are preceded by the word EXAMPLE in bold. BEYOND THE BASICS: Advanced information found throughout the training manual is preceded by the words BEYOND THE BASICS in bold. Examples bring to light business scenarios that may better explain how an application can be used to address a business problem. Introduction Documentation Conventions The following conventions and icons are used throughout this documentation to help you quickly and effectively navigate through the information. CAUTION: Cautions are found throughout the training manual and are preceded by the word CAUTION in bold. outside of standard functionality. may be valuable to an end user. Notes are used to provide information which. while not critical. Cautions are used to remind you of a specific result of a specific action which may be undesirable. HINT: Hints are found throughout the training manual and are preceded by the word HINT in bold. that may help you to more optimally use the application. Beyond the Basics provides additional detail. NOTE: Notes are found throughout the training manual and are preceded by the word NOTE in bold.

3. 2.Development IV in Microsoft Dynamics® AX2009 Student Objectives What do you hope to learn by participating in this course? List three main objectives below. 0-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . 1.

This lesson also describes the basic POS design which is built upon during the course. you will develop a POS module which encompasses most of the modules that are discussed. Chapter 1: Point-of-Sale Project CHAPTER 1: POINT-OF-SALE PROJECT Objectives The objectives are: • Create the base functionality for the Point-Of-Sale (POS) module • Review the functional design of the POS project • Review the technical design of the POS project Introduction To practice using the knowledge and skills you learn during this course. This lesson describes functional requirements and technical design suggestions as applied to a fictitious company. Microsoft Official Training Materials for Microsoft Dynamics ® 1-1 Your use of this content is subject to your current services agreement . adding functionality appropriate to the lesson being reviewed.

Development IV in Microsoft Dynamics® AX2009 Overview The following is an example of how the POS form looks when completed. FIGURE 1.2 1-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .1 The process flow of the finished POS module is as follows: FIGURE 1.

Functional Design The POS module in this scenario is for The Light Company used in the standard Microsoft Dynamics AX demo data. The POS form contains the following fields: • Sales Id • Register Id • Item Id • Quantity • Sales Price • Line Amount • Item Name Microsoft Official Training Materials for Microsoft Dynamics ® 1-3 Your use of this content is subject to your current services agreement . There is a basic receipt printed. In this case. Chapter 1: Point-of-Sale Project An end of day process is used to post the actual money counted to a cash account. This increases performance when entering lines. which could include information such as: delivery address. as this is the only order update available. This illuatrates running the Microsoft Dynamics® AX business logic from an external application. do not create a customer account each time. where very little information is displayed. It is not a supermarket-type cash register. Because this POS is for people who walk in and pay for items immediately. use a one-time customer parameter. which enables an end of day routine to be processed. but shows more information. Additionally.NET® front end that would be used at a supermarket-type register. and any difference between the posted amount and the counted amount to a difference account. there is a Microsoft® C# . Sales Order The POS has a Register ID to distinguish each register. and the buyer is also offered the option of having the receipt emailed to them in XML format. quantity on hand and special instructions. but you will use one customer for every sale. Payments can be posted against each register. meaning that inventory transactions only get posted at the time of physical movement. This is normally used as a template for creating a new customer for each sale. the time of physical movement is when an invoice is posted. The sales order type should be Journal. Instead.

RegisterId POSPayId Num Payment Id POSPayTable. Technical Design The POS module sits on top of the standard sales module. it is a pro- forma receipt). and procedures. Include a Payment button that opens the Payment Lines form.PayId Tables Table Name Field Name Field Type Comment POSRegisterTable RegisterId POSRegisterId Description Description 1-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . and uses some of the sales module code. which contains the following fields: • Payment Type • Amount Include the capability to print a receipt from the sales line (for now.Development IV in Microsoft Dynamics® AX2009 Totals and Payment The POS form also includes a total order amount. tables. Create the following elements: Extended Data Types Type Name Extends Label Relation POSRegisterId SysGroup Register Id POSRegisterTable. The receipt should show: • Sales Id • Date • Item Id • Qty • Price • Total • Payment Type The payment form and the pro-forma receipt are called from buttons on the POS form.

Chapter 1: Point-of-Sale Project Table Name Field Name Field Type Comment HoldingAccount LedgerAccount POSRegisterTrans RegisterId POSRegisterId SalesId SalesId PayId POSPayId LineNum LineNum PayMode CustPayMode Amount AmountMST Posted NoYes PostedEOD NoYes POSTable Form Form Name Location Control Comments POSTable Data Sources SalesTable SalesLine Design Header Use Tab SalesTable.LineAmount ItemName Register Id can be either prompted for when the form is opened or the selection is mandatory on an order and remembered for subsequent orders. Microsoft Official Training Materials for Microsoft Dynamics ® 1-5 Your use of this content is subject to your current services agreement .SalesQty SalesLine.SalesId RegisterId OrderTotal Lines Use Tab and Grid SalesLine.SalesPrice SalesLine.ItemId SalesLine.

Reports Element Name Location Control Comments POSReciept Data Sources SalesTable SalesTable SalesLine Inner join to SalesTable POSRegisterTrans Inner join to SalesTable Design Header 1-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . POSRegisterTrans Form The header section contains two buttons . LineNum. and LineAmount are calculated from the item table when an item id is entered. PayDate.one to call the POSRegisterTrans form.Development IV in Microsoft Dynamics® AX2009 SalesQty. SalesPrice and LineAmount are calculated when the quantity is updated. SalesId.PayModeId POSRegisterTrans. and UserId are populated by the system. SalesPrice. Form Name Location Control Comments POSRegisterTrans Data Sources POSRegisterTrans Design Use Tab and Grid POSRegisterTrans. Order Total = total Line Amount of all lines on the order. and one to call the POSReceipt report. LineAmount is calculated when SalesPrice is updated. PayTime.AmountMST RegisterId.

Name SalesLine.AmountMST Payment POSPayTable. Microsoft Official Training Materials for Microsoft Dynamics ® 1-7 Your use of this content is subject to your current services agreement .SalesId Date RegisterId Lines SalesLine. Chapter 1: Point-of-Sale Project Element Name Location Control Comments SalesTable.AmountMST Summary This lesson leads you through creating the base elements for the POS module that will be used throughout the entire Development IV course.PayId POSPayTable.

Development IV in Microsoft Dynamics® AX2009 Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1. 1-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . 2. 3.

and all can be set up so that they have a unique format and numbering range. In some instances you can define a voucher series to follow a number series. Microsoft Official Training Materials for Microsoft Dynamics ® 2-1 Your use of this content is subject to your current services agreement . for example. There are many number sequences needed for the application. vouchers are used by the system for tracking and linking transactions posted at the same time. Chapter 2: Number Sequences CHAPTER 2: NUMBER SEQUENCES Objectives The objectives are: • Use and create number sequences • Assign a new number using a number sequence • Use continuous number sequences • Format a number from a number sequence • Use Number Pre-Allocation • Use the Clean Up Process • Use the Form Handler • Use the NumberSeqReference table and methods Introduction Number sequences handle the automatic allocation of ID numbers. Numbers are seen and referred to by the user. invoice numbers and invoice vouchers. vouchers. and journal numbers.

against the journal names. for example. Tables The tables used for number sequences are: • NumberSequenceTable contains the definitions of each number sequence. • NumberSequenceReference holds which number sequence is used for which function. 2-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The format field controls the length of the number and is used to insert fixed characters when desired. If a number from a continuous number sequence is used and the connection is lost completely (if a machine crashes). and also by using a number sequence group. • NumberSequenceGroupRef contains the number sequence references specific to a group. This clean up job is either called automatically by selecting Clean up on the Clean up tab of the number sequence form. or manually by clicking the Clean up button on the number sequence form. on the customer table. Number sequences are assigned to a specific function using various parameter forms in the application. and also the next number to be used. • NumberSequenceGroup is a list of number sequence groups. such as when a sales order is deleted before it is saved.Development IV in Microsoft Dynamics® AX2009 Overview A number sequence is created under main menu > basic > setup > number sequences > number sequence. Specify the smallest and largest numbers allowed for the particular sequences. • NumberSequenceList holds numbers for continuous number sequences that have not been completed or are currently reserved. The General tab provides the following functions: • Stops the sequence from being used • Specifies that the user should enter the number rather than have the system assign it • Sets the number sequence to be continuous Continuous number sequences ensure that no numbers in the sequence are lost. If a number is not used. that number can be used later. A clean up job is available to set the status appropriately. the status of that number may be unknown.

and calls Clean up when appropriate. • NumberSeqFormHandler is used whenever a number sequence assigns a number in a form. • NumberSeqNumCache contains the method to manipulate the cache of reserved numbers. Microsoft Official Training Materials for Microsoft Dynamics ® 2-3 Your use of this content is subject to your current services agreement . • NumberSeqGlobal. • NumberSequenceHistory holds a log of all changes made to the number sequence. Chapter 2: Number Sequences • NumberSequenceTTS holds the transaction id of a number before it has been completely assigned. • NumberSeq_Fast is used for number sequences that are not continuous. It is used during the clean-up process. handles continuous number sequences. • NumberSeqCleanUp looks for numbers in the list that have not been completed. It handles records being deleted and ensures that two users cannot use the same number. and is better performance-wise. and. frees up the number for later use. It does not keep a record of the status or store transaction ids for later clean up. looks for the session that created them. is available once instantiated. • NumberSeqDataArea is used in the clean-up process. a global instance. Classes The main classes used for number sequences are: • NumberSeq assigns numbers and vouchers. NumberSeqReference is the super class used. and there is a sub class for each module. • NumberSeqReference creates the link between the function and the number sequence. if the session is no longer active. in case of a system crash. It is used in with NumberSeqNumCache.

• _dontThrowOnMissingRefSetUp . An example of this is provided in Microsoft Dynamics® AX in the ProdTableType. The name of the static methods describes their functions.This is set to true so that if a number sequence has not been set up for this reference. one set is called newGet<function> and the other is newReserve<function>. then set to be used later. • _voucherSequenceReference . a number is assigned. 2-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . you can use the num() or voucher() methods: Voucher = NumberSeq. The method uses NumberSeq::NewGetNum() to assign a new InventTransId.Insert() class method. The following code shows an example of using the NumberSeq::NewGetNumAndVoucherMethod.This finds the number sequence used for the number.voucher(). • _makeDecisionLater . you need to first instantiate the NumberSeq class. it does not return a number. SalesParamters::NumRefInvoiceVoucher(). newGetNumAndVoucherFromCode() enables the instance to return both a number and a voucher from a number sequence code (instead of a reference). NumberSeq = NumberSeq::NewGetNumAndVoucher( SalesParameter::NumRefInvoiceId(). This handles the case where a record is created in a form.This finds the number sequence used for the voucher. Use one of the static methods attached to the NumberSeq class. For example.This signifies that the number is assigned first. For the method newGetNumAndVoucher the parameters are: • _numberSequenceReference .Development IV in Microsoft Dynamics® AX2009 Assign a New Number To assign a new number. an error message is displayed. Otherwise. These methods are identical. and may be used when posting an invoice where an invoice number and a voucher number are required. false) To retrieve the number or voucher. newGetNum is the same as newReserveNum. There are two sets of methods. false. but the record is never committed to the database.

If you do not make the decision later. If you do require to format a number in your code. as this is controlled using TTS. Adding TTSBEGIN and TTSCOMMIT around the code fixes the problem. The format is specified using a combination of characters. Refer to the NumberSeq. The message "System does not support setup of continuous number sequence. and cleans it up later. Any fixed characters should be entered. Additionally. Chapter 2: Number Sequences Continuous Number Sequences When using a continuous number sequence. Num would be set to "ABD". You can commit the number immediately. decide what to do if the number sequence has been set up as continuous. this can be done by using the NumberSeq::numInsertFormat() static method. Format a Number The method to format a number is called from the num() method.Used() and NumberSeq. Use NumberSeq."&&&").abort() to update the numbers sequence list that the number is either used or aborted. This is caused by attempting to get a new number from a number sequence set up as continuous. to have Microsoft Dynamics AX convert the integer to letters. which takes an integer number and a format as parameters. the decision may be made later. and sets a status of Active. Microsoft Official Training Materials for Microsoft Dynamics ® 2-5 Your use of this content is subject to your current services agreement .GetNumFromTable() method. during the TTSCOMMIT. as the user may delete the record. but not doing so inside a TTS.ttsNotifyCommit() method. The clean up is called in the xApplication. enter "&" for each mandatory letter. so normally you do not need to call this method from your code. When writing code to assign a new number. Num = NumberSeq::numInsertFormat(30. the system stores numbers as they are assigned in NumberSequenceList. the system creates the number in NumberSequenceList. In this case. In a form. or place it in the list to be updated later. you do not need the decision to be made later." displays. Any mandatory numerals can be specified using a "#". In a process.

shows retrieving numbers from the cache. For example. The clean-up process is called when the current transaction is committed. 2-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Number Pre-Allocation Processes that use many numbers from a single number sequence can improve performance by using number pre-allocation. The overall speed can be increased by allowing pre-allocation on the number sequence for Closing Vouchers in Inventory Parameters.isProcessDead()). Pre-allocation uses a global instance of the class NumberSeqGlobal. the numbers are only retrieved in the NumberSeq_Fast class. The getNumInternal() method. Clean Up Process Automatic clean up is done by storing a list in memory of number sequences that must be checked.setClean() shows the trans id and number sequence code being stored in a list for clean up later. which means that once it is instantiated. application. it is available until the session is closed. The pre-allocated numbers are stored in a list. looks at any records in the NumberSequenceList.fillCache() class method. Basically. which is mapped to a key of a combination of company and number sequence code. this pulls a set number of numbers into the memory and provides faster access. You can see where it stores the reserved numbers in the NumberSeqNumCache. It goes through this list (created in setClean()) and finds any entries that have dead sessions (NumberSeqCleanUp. It is declared in the global class. This function is only available for non-continuous number sequences. the inventory close process uses voucher numbers if posting to the ledger. The manually started clean up process goes through either a specified number sequence or all number sequences. and checks whether they should be deleted. NumberSeqDataArea.

This is not mandatory. The loadModule() method shows a number of blocks of code.formMethodDataSourceDelete(). call the NumberSequenceFormHandler class. Procedure: Create a new number sequence Creating a new number sequence is achieved by creating a new reference for the sequence. 2. but it is a best practice. • _FieldIdNum is the field id of the field that is to use the number. The names of the methods clearly define where they should go. • _dontThrowOnMissingSetup defines whether an error message should be displayed if the number sequence has not been set up. • _FormDataSource is the data source on the form for the record that is to use the number. The parameters are: • _NumberSequenceCode is the code of the number sequence to be used. For example: numberSeqFormHandler. Create a new Extended Data Type (EDT). a newly created data type that needs sequential numbers assigned to it. Use the following steps to create a new number sequence: 1. for example. The CustTable form shows an example of how to use this class correctly. should be placed in the data source delete() method. Chapter 2: Number Sequences Form Handler To help use number sequences in forms correctly. Decide which module's parameters this number sequence reference should be included in. Often this EDT extends num. and find the corresponding NumberSeqReference sub class. 3. NumberSeqReference To create a new number sequence reference. Instantiate the class using the static method NewForm(). which creates records in the table NumberSequenceReference. have the new data type created in the number sequence references. You must add code to call methods in the various datasource methods. Microsoft Official Training Materials for Microsoft Dynamics ® 2-7 Your use of this content is subject to your current services agreement . This displays it in the appropriate modules parameters form. • _callerForm is the calling form.

For example: salesParameters::NumRefSalesID() This returns the record in NumberSequenceReference that contains the reference for SalesId. The reference can then be referred to using this static method. There are a number of wizard fields used for default values when using the wizard to create number sequences. Summary This lesson provides an overview of how number sequences are used in the application. 2-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . o referenceHelp is the longer description of the reference shown in the top part of the Number sequence tab of the parameters form. Parameters tables show methods beginning with numRef. 5. o sortfield defines the sequence that the references are displayed on the Number sequence tab of the parameters form. Copy one of these blocks and change the following fields: o DataTypeID is the type Id of the new data type. o referenceLabel is the description shown in the left column of the Number sequence tab on the parameters form. 6. Create a static method that will be used to retrieve the reference. It shows how number sequence API works and how to implement number sequence API in the code. Use one of these methods as a template. 7.Development IV in Microsoft Dynamics® AX2009 4. This is usually done on the relevant parameters table.

When assigning numbers from the numberseq class. From which method would you get the number sequence reference used for a sales order number? Microsoft Official Training Materials for Microsoft Dynamics ® 2-9 Your use of this content is subject to your current services agreement . What does it mean that a number sequence is continuous? 3. Chapter 2: Number Sequences Test Your Knowledge 1. when would you use newGetNumAndVoucherFromCode() and newGetNumAndVoucher()? 2.

Add a new element POSModule. b. Label = POS module. Create method "numberSeqModule" \and return enum NumberSeqModule with the value NumberSeqModule::POSModule. Use NumberSeqReference_Sales as a reference. The POS module should have its own sub class of NumberSeqReference. Create new class NumberSeqReference_POSModule as follows: a. 2. Challenge Yourself! In the POS Module. c. 2-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . create a new reference for the new EDT POSPayId.1 .Development IV in Microsoft Dynamics® AX2009 Lab 2.loadModule() and numberSeqModule() . Need a Little Help? 1. EnumValue = 100. e. 2. Step by Step 1. a new Number Sequence needs to be added for the POS module. d. b. You need the same methods . but should be displayed in the SalesParameters form. c.Add Pay Id number sequence Scenario To make sure POS transactions can be traced and are unique. You also need to modify the methods NumberSeqReference::construct() and NumberSeqReference::ModuleList().and adapt them accordingly. 3. Use the previously created extended datatype POSPayId for the data type reference. Extend numberSeqReference. Modify BaseEnum NumberSeqModule: a. Use logisticBasic: as the configuration key. Create method "loadModule" similar to the method loadModule on the NumberSeqReference_SalesOrder class.

" to return an object of the type NumberSeqReference. Initialize above declared variable like this: numberSeqReferencePOSModule = SalesParameters::numberSeqReference_POS(). Create new method "numberSeqReference_POS. Declare variable NumberSeqReference numberSeqReferencePOSModule in the class declaration. Add following to the method "numberSeqPreInit:" a. 4. 8. 6. 5.visible method call in the method numberSeqPostInit. numberSeqReferencePOSModule. Chapter 2: Number Sequences 3. Modify NumberSeqReference class as follows: a. Create new method numRefPOSPayId. and referenceSameAsLabel.load(). Modify CustParameters form as follows: a. Create new method "numberSeqModule_POS. Add SalesParameters::numberSeqModule_POS() to the this. 7. c. which returns a NumberSequenceReference table with the value found in NumberSeqReference::findReference(typeId2ExtendedTypeId(t ypeid(POSPayId))).object method call.queryRun statement in the method NumberSequenceReference:ExecuteQuery. b. Add following to the tmpIdRef.sameAsActive() to the numberSequenceReference_ds. with the value found in method NumberSeqReference::construct(SalesParameters::numberSeqM odule_POS()) similar to method numberSeqReference on salesParameters. Add numberSeqReferencePOSModule.setTempDate SalesParameters::numberSeqModule_POS())). 9. Microsoft Official Training Materials for Microsoft Dynamics ® 2-11 Your use of this content is subject to your current services agreement . Modify SalesParameters table as follows: a." to return a NumberSeqModule enum with the value found in NumberSeqReference_POSModule::numberSeqModule() similar to method numberSeqModule on salesParameters. Modify the method construct to initialize the newly created class and return NumberSeqReference_POSModule(_module) if the module parameter passed into this method is equal to NumberSeqReference_POSModule::numberSeqModule().

see the custTable form. 4. Override method LinkAcitve on the salesTable datasource. 2-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . They should be added using the form handler class. Challenge Yourself! Add the NumberSeqFormHandler methods to the forms POSTable and POSPayTable to create new number for SalesId and POSPayId. Override method write on the salesTable datasource. 7. Create new method named numberSeqFormHandler.Use Form Handler Scenario The POS form should use the sales id and pay id number sequences. Step by Step 1.Development IV in Microsoft Dynamics® AX2009 Lab 2. 8. see the custTable form. Override method delete on the salesTable datasource. Look for all references to numberSeqFormHandler(). Modify the POSTable form as follows: 2. Declare variable NumberSeqFormHandler numberSeqFormHandler in the class declaration method. Need a Little Help? Use the CustTable form as inspriration. see the custTable form. 6. 3.2 . Override method validateWrite on the salesTable datasource. see the custTable form. Override the method created on the salesTable datasource.Use POS values instead of custTable values. 5. see the custTable form. see the custTable form.

2. Chapter 2: Number Sequences Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1. 3. Microsoft Official Training Materials for Microsoft Dynamics ® 2-13 Your use of this content is subject to your current services agreement .

From which method would you get the number sequence reference used for a sales order number? MODEL ANSWER: SalesParameters. 2. When assigning numbers from the numberseq class. when would you use newGetNumAndVoucherFromCode() and newGetNumAndVoucher()? MODEL ANSWER: NewGetNumAndVoucher() is used to instantiate NumberSeq from NumberSeqReference.Development IV in Microsoft Dynamics® AX2009 Solutions Test Your Knowledge 1. 3. NewGetNumAndVoucherFromCode() is used to instantiate NumberSeq from a NumberSeqCode. What does it mean that a number sequence is continuous? MODEL ANSWER: A continuous number sequence ensures that all numbers in the sequence are used.NumRefSalesId(). 2-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .

Furthermore. the class SysPrintOptions is briefly introduced. It is a system class that contains methods and variables to hold all the settings that determine where and how the output is handled. and can also format all the options such that they can be easily saved and retrieved later. Microsoft Official Training Materials for Microsoft Dynamics ® 3-1 Your use of this content is subject to your current services agreement . Chapter 3: PrintJobSettings CHAPTER 3: PRINTJOBSETTINGS Objectives The objectives are: • Set Print Options • Retrieve Print Options • Use Pack and Unpack to Store Settings • Use SysPrintOptions Introduction The PrintJobSettings class is used with report output. It can be used both to get and set these options. This lesson explains and provides examples on how to set and retrieve print options and how to use pack and unpack to store these settings.

1 THE PRINT OPTIONS SCREEN (SYSPRINTFORM) All these options. • printJobSettings.Development IV in Microsoft Dynamics® AX2009 Set Print Options When printing a report. it does not make sense to set the Mail To option. • printJobSettings. and more.format(printFormat) sets the file format when writing to a file or to e-mail.mailTo(str) sets the 'Mail To' option.fitToPage(Boolean) specifies whether the report can be shrunk to fit the page.allPages(boolean) specifies whether to print all pages. For example: printJobSettings. Some examples of the other options are: • printJobSettings.setTarget(PrintMedium::Mail) sets the Send To option to E-mail recipient. 3-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . • printJobSettings. where PrtnterOrientation is an ENUM. This is shown in the Cheque_US report in the init() method. • printJobSettings. the normal print options form is shown.paperOrientation(PrinterOrientation) sets the orientation of the report. Str contains one or more email addresses. Print Options methods Additional options depend on what the target is as to whether it makes sense to use them. If the target is Screen. can be set within the code. where it forces the target to be a printer. FIGURE 3.

enablePrintTo). public Boolean prompt(Boolean enableCopy=TRUE. enableProperties. Chapter 3: PrintJobSettings Example using Print Options The following example shows how the prompt method in a report can be overridden to force a copy of the report to be printed in a different tray. Boolean enableProperties=TRUE. -1. int trayCount. printJobSettings.deviceName().printJobSettings().addTrayPageCopy(0. enablePages. printJobSettings printJobSettings = element. } Microsoft Official Training Materials for Microsoft Dynamics ® 3-3 Your use of this content is subject to your current services agreement . 1) // from copy one use this tray } return ret. // number of copies to print printJobSettings. Boolean enableDevice=TRUE.copies(1). Boolean enablePages=TRUE. enableDevice. if (ret) { // store the name of the printer the user selected above deviceName = printJobSettings. Boolean enablePrintTo=TRUE) { Boolean ret. int i. // <- this line may not be needed. ret = super(enableCopy.

printButton. and if the target is Screen. in a normal live situation. it may be necessary to determine what the user has selected to take appropriate action. name = report name. For example. This can be stored in a field of type container for later retrieval. Calling ReportRun. you do not print invoices to the Screen. A container that includes printer options can be used when instantiating PrintJobSettings which sets all the options. Use of Pack and Unpack to Store Settings All the settings the user selects or that you set within the code can be stored and retrieved.validate() class method.PackPrintJobSettings() to create a container with all options. it confirms that this is correct. They can be seen in the Usages Data form. Use PrintJobSettings. This contains an example of both packing and unpacking a print options container. where the instance of PrintJobSettings is instantiated using a container stored for each document type and user. type = Report. during a sales update.unpackPrinterSettings(container) retrieves the printer options for that report from the container. 3-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The code for this can be seen in the SalesFormLetter. Last user-selected printer settings are stored in the Usage Data (sysLastValue) as with values stored in pack and unpack in RunBase.Development IV in Microsoft Dynamics® AX2009 Retrieve Print Options As with setting the print options. The system checks what target has been selected and if the user has selected the screen. then a warning is given. Review the clicked method on form ProdParmStartUp.

SysPrintOptions can be used to circumvent these issues. sysPrintOptions.buildPrinterMap(). map printerMap. } } Microsoft Official Training Materials for Microsoft Dynamics ® 3-5 Your use of this content is subject to your current services agreement . mapIterator. processing is done on the Application Object Server (AOS).value()). while (mapIterator. When printing. sysPrintOptions = new sysPrintOptions().next().more()) { info(mapIterator. sysPrintOptions sysPrintOptions.begin(). printerMap = sysPrintOptions. but the printer may be local to the client. mapIterator mapIterator. static void ShowListOfPrinters(Args _args) { printJobSettings printJobSettings. or not installed on the server. mapIterator. sysPrintOptions. Chapter 3: PrintJobSettings Use of SysPrintOptions SysPrintOptions is a class that has methods written for using PrintJobSettings. and is not normally needed to be called by the developer. .getPrinterMap(). This class is used by the system to control printing. Printing works differently on the server than on the client. printJobSettings = SysPrintOptions::newPrintJobSettingsOnServer(). mapIterator = new mapIterator(printerMap).setPrintJobSettings(printJobSettings). Build list of Printers The following example shows how to use SysPrintOptions to display a list of all available printers.

Also. the class SysPrintOptions is briefly introduced.Development IV in Microsoft Dynamics® AX2009 Summary This lesson describes how to use the system class PrintJobSettings in connection with report output. 3-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The lesson explains and provides examples on how to set and retrieve print options and how to use pack and unpack to store these settings.

Which method would you use to initialize printJobSettings for a specific report. Chapter 3: PrintJobSettings Test Your Knowledge 1. What is the syntax for setting the default printer option to e-mail in the PrintJobSetting class? 2. when this report is called from a class? 3. Where does Microsoft Dynamics AX store the previously selected printer settings for a specific report? Microsoft Official Training Materials for Microsoft Dynamics ® 3-7 Your use of this content is subject to your current services agreement .

The report to modify is SalesLinesExtended. the report needs to be scaled to fit onto the page. the systems developer. A message is shown saying that the report has been scaled.suppressScalingMessage(true). Isaac. element.Suppress Scaling Message Scenario When the sales order lines report is run with all options selected. even if the report has been scaled.printJobSettings().Development IV in Microsoft Dynamics® AX2009 Lab 3. Step by Step Add the following code to the init() method of the report SalesLinesExtended.suppressScalingMessage() to stop the message from appearing.1 . It should go after the call to super(). Challenge Yourself! Use the printJobSettings. 3-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . has been asked to stop the message from appearing.

HINT: Look at the Production order Startup parameterspick list printer settings. Add a container field to the register table. Need a Little Help? 1. Chapter 3: PrintJobSettings Lab 3. pick list printer settings. To see similar functionality where printer settings are set and saved. Step by Step 1.printJobSettins.Print Job Settings Scenario Each POS Register has a printer. Challenge Yourself! In the POS module. Create a new method on table POSRegisterTable to call the standard printer options form and store the return container in POSRegisterTable. Microsoft Official Training Materials for Microsoft Dynamics ® 3-9 Your use of this content is subject to your current services agreement . type = POSRegisterPrintJobSettings. Create a new field POSRegisterTable. 2. enable printer options to be set up and saved for each register. A function to set which printer each register uses is needed. Create a new container EDT. 3. 4.PrintJobSettings. look at the Production order Startup parameters.2 . 2. to store the print job settings for the register. Add a button to the POS Register table form to call this new method. POSRegisterPrintJobSettings.

set the printer options to the options stored against the appropriate register. Use the method this. Challenge Yourself! When the receipt is printed.Development IV in Microsoft Dynamics® AX2009 Lab 3. Step By Step 1. In the receipt report. Retrieve the register id from the sales order record.UnpackPrintJobSettings() to set the printer settings for the report from the container.3: Print the receipt to the correct printer Scenario When a receipt is printed. set the printJobSettings from the container stored against the register table. the system should automatically pick which printer to use based which register is being used. 2. 3. 3-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .PrintJobSettings().

Challenge Yourself! Remove the ability for the user to change the printer options on the receipt by not displaying any prompt for the report. Microsoft Official Training Materials for Microsoft Dynamics ® 3-11 Your use of this content is subject to your current services agreement . Override the prompt method on the report. the user should not have to select which printer to use. Use the print options selected for the register. and remove the call to super(). it should print. Return true from the method. As soon as the user clicks the Receipt button.4 . The print options form should not be displayed.Bypass Print Options Scenario When a receipt is printed. Step By Step 1. Chapter 3: PrintJobSettings Lab 3.

Development IV in Microsoft Dynamics® AX2009 Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1. 2. 3-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . 3.

Microsoft Official Training Materials for Microsoft Dynamics ® 3-13 Your use of this content is subject to your current services agreement .UnpackPrintJobSettings. What is the syntax for setting the default printer option to e-mail in the PrintJobSetting class? MODEL ANSWER: PrintJobSettings. Where does Microsoft Dynamics AX store the previously selected printer settings for a specific report? MODEL ANSWER: Usage Data (SysLastValue). 2. when this report is called from a class? MODEL ANSWER: ReportRun. Which method would you use to initialize printJobSettings for a specific report.SetTarget(PrintMedium::Mail). 3. Chapter 3: PrintJobSettings Solutions Test Your Knowledge 1.

Development IV in Microsoft Dynamics® AX2009 3-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .

Chapter 4: Business Connector CHAPTER 4: BUSINESS CONNECTOR Objectives The objectives are: • Describe the purpose of the Business Connector. other than Microsoft Dynamics AX 2009. • Describe the architecture of the Business Connector. • Debug code through the Business Connector. • Set up and manage the Business Connector. • List various uses of the Business Connector. Introduction When using the Microsoft Dynamics® AX 2009 Business Connector. • Use the managed classes in the Business Connector. which enables the use of applications as front ends. This implies that the application can gain access to the data and business logic of Microsoft Dynamics AX 2009.NET object. Microsoft Official Training Materials for Microsoft Dynamics ® 4-1 Your use of this content is subject to your current services agreement . other applications can access Microsoft Dynamics AX 2009 as a .

NET Platform The Business Connector is based on the . and Application Integration server roles.Development IV in Microsoft Dynamics® AX2009 Business Connector Overview The Business Connector is a Microsoft Dynamics AX 2009 component that enables external applications to interact with Application Object Server instances. which "acts-on-behalf-of" Microsoft Dynamics AX 2009 users who cannot be fully authenticated. . The Business Connector can be installed as a stand-alone component and used to develop third- party applications that integrate with Microsoft Dynamics AX 2009. • Automatically registered during installation. It supports the functionality in the Enterprise Portal server. • The Business Connector Proxy user.NET platform and provides a set of managed classes that provide easy access to X++ functionality in Microsoft Dynamics AX 2009. Reporting server. 4-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The following are some characteristics of the Business Connector: • Requires Microsoft Windows® authentication.

Windows 2000. The Microsoft Dynamics AX 2009 Business Connector logs specific events to the Application Log of the Event Viewer. go to Control Panel > Administrative Tools > Event Viewer. and Windows NT 4. For more information on the proxy user. select the Application Log folder." Debugging In Microsoft Dynamics AX 2009 it is possible to enable user breakpoints for X++ code running in the Business Connector. consult the Microsoft Dynamics AX 2009 Administrator Guide. which is an integrated part of the Microsoft Windows Vista. Microsoft Official Training Materials for Microsoft Dynamics ® 4-3 Your use of this content is subject to your current services agreement . A global breakpoint is one that is set for a computer.0 operating system. Event Monitoring The Microsoft Dynamics AX 2009 Business Connector interfaces with the Event Viewer component. Proxy The Business Connector Proxy is a Windows domain user account that is used to enable the Business Connector to "act-on-behalf" of Microsoft Dynamics AX 2009 users who cannot be fully authenticated. Windows XP. found under the Help menu. To open the Event Viewer in Windows Vista. In the Event Viewer. The Business Connector Proxy has unique configuration settings that can be modified. the Microsoft Dynamics AX 2009 Business Connector logs whenever it is started or stopped. For instance. instead of a user. and global breakpoints for X++ code running in the Business Connector or in a user session. during installation. Chapter 4: Business Connector Business Connector Setup and Configuration Registration The Business Connector in Microsoft Dynamics AX 2009 is registered automatically. and can be shared between developers. A configuration target field has been added to the utility to enable you to select the Business Connector Proxy. Any unexpected events are also logged in the Application Log for further investigation by the administrator. Only Administrators and Power Users on a computer running Microsoft Dynamics AX 2009 with a Business Connector proxy user can modify the Business Connector proxy user configuration options. All events logged by the Microsoft Dynamics AX 2009 Business Connector have a source name of "Microsoft Dynamics AX Business Connector. XP and Windows 2000.

1 MICROSOFT DYNAMICS AX 2009 CONFIGURATION UTILITY. Select the Local Client setting in the Configuration target.Enabling Breakpoints in the Business Connector Use the following procedure to enable breakpoints in the Business Connector: 1. Select Enable user breakpoints to debug code running in the Business Connector and/or Enable global breakpoints to debug code running in the Business Connector or client. FIGURE 4. 5. Select the Configuration that you want to enable breakpoints for. 6. 4. Open the Microsoft Dynamics AX 2009 Configuration Utility. A warning message may appear explaining that debugging is enabled but not started. Click OK. DEVELOPER TAB 2.2 WARNING MESSAGE WHEN CLOSING CONFIGURATION TOOL 4-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . 3.Development IV in Microsoft Dynamics® AX2009 Procedure . FIGURE 4.

3 OPTIONS FORM. FIGURE 4. Debugging must also be enabled on the Application Object Server (AOS). Chapter 4: Business Connector To start debugging.4 MICROSOFT DYNAMICS AX SERVER CONFIGURATION UTILITY Microsoft Official Training Materials for Microsoft Dynamics ® 4-5 Your use of this content is subject to your current services agreement . Open the Microsoft Dynamics AX Server Configuration tool. Make sure Debug mode is set to When Breakpoint. and follow this path: Tools > Options > Developer tab. DEVELOPMENT TAB 8. log on to the client. FIGURE 4. 7.

To ensure that the Visual Studio debugger jumps to the Microsoft Dynamics AX 2009 debugger. For a . • An instance of the Microsoft Dynamics AX 2009 Debugger is running. 11. On the profile for the AOS instance that the Business Connector will talk to. When running the . • The Visual Studio . 10. the following must be in place: • Debugging is enabled on Microsoft Dynamics AX 2009 AOS configuration.NET code in Visual Studio.Development IV in Microsoft Dynamics® AX2009 9. launched from a Client running the same configuration.NET code.NET application to use the Microsoft Dynamics AX 2009 debugger for displaying breakpoints. on a Client running the same configuration. This can be achieved by following this path in a Microsoft Dynamics AX client: Tools > Development tools > Debugger. an instance of the Microsoft Dynamics AX 2009 debugger must be running. select Enable breakpoints to debug X++ code running on this server.NET code is running in Debug mode. • Debug mode is set to When Breakpoint in Client Options in Microsoft Dynamics AX 2009. 4-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . • Debugging is enabled on Microsoft Dynamics AX 2009 client configuration. when a breakpoint exists in X++ code called from . it must be run in debug mode for the X++ breakpoints to work.

through the . Microsoft Official Training Materials for Microsoft Dynamics ® 4-7 Your use of this content is subject to your current services agreement . • Interpreter layer: Executes X++ and communicates with the AOS. • Transition layer: Maps the managed classes to the corresponding interpreter functions. FIGURE 4. the . Each class contains a collection of methods that can be called to perform business logic in Microsoft Dynamics AX 2009.NET Business Connector: • Axapta • AxaptaBuffer • AxaptaContainer • AxaptaObject • AxaptaRecord • VariantWrapper These classes can be used in Visual Studio projects to interface with Microsoft Dynamics AX 2009.5 SIMPLIFIED .NET BUSINESS CONNECTOR ARCHITECTURE Managed Classes The following managed classes are provided by the .NET Business Connector consists of three layers: • Managed classes: Exposes public methods that can be called to interact with Microsoft Dynamics AX 2009.NET Business Connector. Chapter 4: Business Connector Business Connector Architecture From a simplified architecture viewpoint.

The Axapta class also contains methods to call static class methods.The AxaptaObject class provides the ability to call Microsoft Dynamics AX 2009 class methods. and buffer objects. There are 27 exception or invalid classes available in the Microsoft. which execute Microsoft Dynamics AX 2009 business logic through the Business Connector. AxaptaRecord Class .BusinessConnectorNet.dynamics.Dynamics. object axapta1).Development IV in Microsoft Dynamics® AX2009 All these classes are found in the namespace: Microsoft. AxaptaContainer Class . and perform other Microsoft Dynamics AX 2009 system tasks.Dynamics. The following are examples of Visual Basic code in Visual Studio. and TTS commands.The AxaptaBuffer class provides the ability to add data to and retrieve data from a Microsoft Dynamics AX 2009 buffer. create Microsoft Dynamics AX 2009 record. create Microsoft Dynamics AX 2009 classes. An AxaptaBuffer object can be used with AxaptaContainer objects.businessconnectornet. (Examples using other . container. 4-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . AxaptaContainerNotValidException). execute transactions.NET Framework topic in the Developing for Microsoft Dynamics AX helpbook within the application.The Axapta class provides the ability to connect to the Microsoft Dynamics AX 2009 system.The AxaptaContainer class provides the ability to read and write to and from Microsoft Dynamics AX 2009 containers. For more information on these classes. All of these classes (except Axapta) have a corresponding NotValidException class (for example.The AxaptaRecord class provides functionality for reading and modifying Microsoft Dynamics AX 2009 records. jobs. view the Microsoft Dynamics AX . AxaptaObject Class .dll which is located in the bin directory in the Microsoft Dynamics AX 2009 Client directory) Axapta Class .) Subsequent boxes assume that previous variables and objects are still available (for example.BusinessConnectorNet namespace.NET languages can be found in the Developer Help in the Microsoft Dynamics AX 2009 application. static table methods.Dynamics. AxaptaBuffer Class .BusinessConnectorNet (in microsoft. and assembly Microsoft.

This parameter is optional and is used to override the corresponding parameter in the configuration being used. Chapter 4: Business Connector Log on to Microsoft Dynamics AX through the Business Connector Dim company As String Dim language As String Dim objectServer As String Dim configuration As String Dim axapta1 As New Axapta company ="dmo" language ="en-us" objectServer ="objectServerName" configuration ="configurationName" axapta1. domain (String) The domain associated with the Windows user. language (String) The language to use for Microsoft Dynamics AX 2009 labels. company (String) The company to activate. language. configuration) Log on as the Business Connector Proxy User to Microsoft Dynamics AX Parameter Description user (String) Name of the Windows user to use for logging on to Microsoft Dynamics AX 2009. This parameter is optional and is used to override the corresponding parameter in the configuration being used.NET network credential object. Microsoft Official Training Materials for Microsoft Dynamics ® 4-9 Your use of this content is subject to your current services agreement . This parameter is optional bcProxyCredentials (NetworkCredential) A . objectServer. objectServer (String) Name of the Microsoft Dynamics AX 2009 Object Server to connect to. This parameter is optional and is used to override the corresponding parameter in the configuration being used. This parameter is optional.Logon(company.

Development IV in Microsoft Dynamics® AX2009 Parameter Description configuration (String) Name of Microsoft Dynamics AX 2009 configuration to use while logging on. The following is a code example using the LogonAs() method: Dim company As String Dim language As String Dim objectServer As String Dim configuration As String Dim axapta1 As Axapta Dim bcProxyCredentials As New NetworkCredential("proxyUsername". domain. then this parameter is used to specify the path which points to an exported configuration file. configuration) 4-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement ."proxyPassword". language."domain") Dim username As String Dim domain As String company ="dmo" language ="en-us" objectServer ="objectServerName" configuration ="configurationName" username ="proxyUsername" domain ="domain" axapta1. objectServer. This parameter is optional. If null is specified for this parameter and Business Connector is being executed within the context of an interactive Windows account. Business Connector will use the default configuration (maintained by the Microsoft Dynamics AX Client Configuration Utility). company.LogonAs(username. If Business Connector is being executed within the context of a non-interactive Windows account (such as the Business Connector Proxy AD user). bcProxyCredentials.

qty) Executing SQL Statement Against the Microsoft Dynamics AX InventTable Table Dim statement As String Dim inventTableRecord As AxaptaRecord Dim tableName As String tableName ="InventTable" inventTableRecord = axapta1. itemId.itemId=='001'" axapta1.ExecuteStmt(statement.CreateAxaptaObject(className) returnValue = salesLine_Net.Call(methodName. Chapter 4: Business Connector Calling calcPrice Method from a Custom X++ Class Called SalesLine_Net Dim className As String Dim methodName As String Dim itemId As Object Dim qty As Object Dim returnValue As Object Dim salesLine_Net As AxaptaObject className ="salesLine_Net" methodName ="calcPrice" itemId ="001" qty ="5" salesLine_Net = axapta1. inventTableRecord) Microsoft Official Training Materials for Microsoft Dynamics ® 4-11 Your use of this content is subject to your current services agreement .CreateAxaptaRecord(tableName) statement ="select * from %1 where %1.

Besides the most common use of supporting the connection between SharePoint and Microsoft Dynamics AX 2009 for the Enterprise Portal. By understanding how to effectively install and configure the Business Connector. the applications developed for the business are more coordinated and effective. 4-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . the Business Connector also opens up the existing Microsoft Dynamics AX 2009 business logic and data to external applications within your business scope. and then write and debug code on both sides of the Connector (both .NET and X++).Development IV in Microsoft Dynamics® AX2009 Summary The Business Connector provides a conduit between Microsoft Dynamics AX 2009 and other applications.

What is the Business Connector Proxy User account used for? Microsoft Official Training Materials for Microsoft Dynamics ® 4-13 Your use of this content is subject to your current services agreement . Do you need to register the .NET connector into the Global Assembly Cache after it is installed? 3. Describe the purpose of the Business Connector. 2. Chapter 4: Business Connector Test Your Knowledge 1.

NET Business Connector? 6.NET language. What is the purpose of the Managed Classes in the . Using a . How is debugging through the Business Connector enabled? 5. in Visual Studio how would you create a new instance of the SalesFormLetter Microsoft Dynamics AX 2009 class? 4-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 4.

using the files from POSConsole_Complete. but you need to add the procedure to call the post invoice function. The form should have a large display. as detailed below.zip. this form has been created for you.NET form.Business Connector Scenario This is a part of the Point-of-Sale Case Study. Step by Step As you may not be familiar with . included in the file POSConsole. There are two versions available for use: The first version. POSConsole_Complete is completed and needs no additional programming in C# .NET as the syntax for C# is similar to X++.NET. which then uses the Microsoft Dynamics AX 2009 Business Connector to communicate with the installation.exe. You still need to write the necessary code in Microsoft Dynamics AX 2009. can display item descriptions and prices. Microsoft Official Training Materials for Microsoft Dynamics ® 4-15 Your use of this content is subject to your current services agreement .zip. run the executable POSConsole. and to complete an order. It has been created using C# . and a large number pad (so touch screens can be used). Challenge Yourself! Create a front end for the POS module using a . See Chapter 1 for details. You may still view the C# code for thus console by following the steps below. The second version has most of the interface built already. To use this version. • Create the touch screen front end in a . Chapter 4: Business Connector Lab 4.NET.NET form that can be used in a 'supermarket' environment.1 . delete last sales line. There should also be buttons that can complete an order and delete the last line. • Create buttons to add a sales line.

CSharp_SalesOrder.ico o assemblyInfo. which can then be found in the directory Visual Studio Projects \ POSConsole \ Bin \ Debug.completeOrder() to the method buttonComplete_Click() so the invoice posts when the Complete Order button is clicked.createSO(): creates a sales order and returns the sales id. Add a call to the Microsoft Dynamics AX 2009 class method CSharp_SalesOrder. post a payment.NET project solution.checkItemId(itemId _itemId) :returns true if item id is valid.cs o POSConsole. In Microsoft Dynamics AX 2009 The POS executable calls the following class methods.Development IV in Microsoft Dynamics® AX2009 Do as follows: In Visual Studio 2005 1. CSharp_SalesOrder.sln file 3. and settle the transactions are written in chapter 11. qty _qty.deleteSalesOrder(SalesId _SalesId): deletes all lines and the salesTable record for the specified sales id.zip and contain the C# . Place them in a new directory called POSConsole in the Visual Studio Projects directory: o app.resx o POSConsole. Create these classes and methods: 1. CSharp_SalesOrder. Class CSharp_SalesOrder which is used in conjunction with creating and deleting sales orders. 4.sln 2. The following files are included in POSConsole_Incomplete. a. The routines to post an invoice.csproj o POSConsole. CSharp_SalesOrder. CSharp_SalesOrder. Select build > build posconsole to build the executable.deleteSalesLine(SalesId _salesId. Open the C# .insertSalesLine(itemId _itemId.cs o POSConsole. b. 4-16 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .completeOrder(SalesId _SalesId): posts an invoice for the specified sales order.NET development environment: select file > open solution and select the POSConsole. Use a parameter driven customer account. qty and sales id. f. e. c. so this method can remain empty for now. salesId _SalesId): Creates a sales line for the specified item. d. itemId +itemId): Deletes sales line using sales id and item id. CSharp_SalesOrder.

sln 2. Place them in a new directory called POSConsole in the Visual Studio Projects directory: o app. c.cs o POSConsole. Microsoft Official Training Materials for Microsoft Dynamics ® 4-17 Your use of this content is subject to your current services agreement . 4.getItemName(ItemId _itemId): returns item name or specified item id. which can then be found in the directory Visual Studio Projects \ POSConsole \ Bin \ Debug.completeOrder() to the method buttonComplete_Click() so the invoice posts when the Complete Order button is clicked. 4. Open the C# .csproj o POSConsole. qty _qty): returns the sales price for the item id and the qty specified.sln file 3. SalesOrderIntegration.ico o assemblyInfo.NET development environment: select file > open solution and select the POSConsole. Add a call to the Microsoft Dynamics AX 2009 class method CSharp_SalesOrder. Select build > build posconsole to build the executable. Class SalesOrderIntegration a.cs o POSConsole. The following files are included in POSConsole_Incomplete.getSalesTotal(SalesId _salesId): returns the total amount for the specified sales order. SalesOrderIntegration. SalesOrderIntegration.getSalesPrice(ItemId _itemId.resx o POSConsole. Do as follows: In Visual Studio 2005 1. Chapter 4: Business Connector 2.zip and contain the C# .NET project solution. b.

CSharp_SalesOrder.getSalesPrice(ItemId _itemId. qty and sales id. a. SalesOrderIntegration. SalesOrderIntegration.insertSalesLine(itemId _itemId. CSharp_SalesOrder.getItemName(ItemId _itemId): returns item name or specified item id. CSharp_SalesOrder. SalesOrderIntegration. so this method can remain empty for now. c. post a payment. 2. c. CSharp_SalesOrder. Create these classes and methods: 1. CSharp_SalesOrder. qty _qty. f.deleteSalesLine(SalesId _salesId. Use a parameter driven customer account. b. e. itemId +itemId): Deletes sales line using sales id and item id. Class CSharp_SalesOrder which is used in conjunction with creating and deleting sales orders.createSO(): creates a sales order and returns the sales id. CSharp_SalesOrder. qty _qty): returns the sales price for the item id and the qty specified.getSalesTotal(SalesId _salesId): returns the total amount for the specified sales order. salesId _SalesId): Creates a sales line for the specified item.checkItemId(itemId _itemId) :returns true if item id is valid.completeOrder(SalesId _SalesId): posts an invoice for the specified sales order. and settle the transactions are written in chapter 11.Development IV in Microsoft Dynamics® AX2009 In Microsoft Dynamics AX 2009 The POS executable calls the following class methods. b.deleteSalesOrder(SalesId _SalesId): deletes all lines and the salesTable record for the specified sales id. Class SalesOrderIntegration a. The routines to post an invoice. 4-18 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . d.

NET project solution.csproj o POSConsole. 4. Microsoft Official Training Materials for Microsoft Dynamics ® 4-19 Your use of this content is subject to your current services agreement . Open the C# . but you will need to add the procedure to post the invoice.NET development environment: select file > open solution and select the POSConsole. 3. Place them in a new directory called POSConsole in the Visual Studio Projects directory: o app. The following files are included in POSConsole_Incomplete.1 . and a large number pad (so touch screens can be used).sln file 3. 4. Add a call to the Microsoft Dynamics AX 2009 class method CSharp_SalesOrder. Step by Step Do as follows: In Visual Studio 2005 1. Chapter 4: Business Connector Lab 4.ico o assemblyInfo.cs o POSConsole.resx o POSConsole. can display item descriptions and prices. The form should have a large display. This form already has most of the interface built already. Select build > build posconsole to build the executable.Business Connector (Solution) Scenario Either: Create a front end for the POS module using a . There should also be buttons that can complete an order and delete the last line.NET form that could be used in a 'supermarket' environment.sln 2.cs o POSConsole. which can then be found in the directory Visual Studio Projects \ POSConsole \ Bin \ Debug.completeOrder() to the method buttonComplete_Click() so the invoice posts when the Complete Order button is clicked. Or: You may use the front end already created for you in C#.zip and contain the C# .

SalesOrderIntegration. post a payment.getSalesPrice(ItemId _itemId. c. CSharp_SalesOrder. salesId _SalesId): Creates a sales line for the specified item.getItemName(ItemId _itemId): returns item name or specified item id. Create these classes and methods: 1.Development IV in Microsoft Dynamics® AX2009 In Microsoft Dynamics AX 2009 The POS executable calls the following class methods. CSharp_SalesOrder. a.getSalesTotal(SalesId _salesId): returns the total amount for the specified sales order. qty _qty): returns the sales price for the item id and the qty specified. Use a parameter driven customer account. SalesOrderIntegration. f. CSharp_SalesOrder. b. b. 4-20 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . and settle the transactions are written in chapter 11. CSharp_SalesOrder. d. CSharp_SalesOrder. so this method can remain empty for now.deleteSalesOrder(SalesId _SalesId): deletes all lines and the salesTable record for the specified sales id. 2. Class CSharp_SalesOrder which is used in conjunction with creating and deleting sales orders. CSharp_SalesOrder.checkItemId(itemId _itemId) :returns true if item id is valid.insertSalesLine(itemId _itemId. Class SalesOrderIntegration a. The routines to post an invoice.completeOrder(SalesId _SalesId): posts an invoice for the specified sales order. qty and sales id.createSO(): creates a sales order and returns the sales id. itemId +itemId): Deletes sales line using sales id and item id. qty _qty. e.deleteSalesLine(SalesId _salesId. c. SalesOrderIntegration.

2. Chapter 4: Business Connector Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1. Microsoft Official Training Materials for Microsoft Dynamics ® 4-21 Your use of this content is subject to your current services agreement . 3.

"".NET language.Logon("".NET Business Connector? MODEL ANSWER: They expose public methods that can be called to interact with Microsoft Dynamics AX. It is registered automatically during installation. "") className = "salesFormLetter" salesFormLetter = axapta1. 5.Development IV in Microsoft Dynamics® AX2009 Solutions Test Your Knowledge 1. in Visual Studio how would you create a new instance of the SalesFormLetter Microsoft Dynamics AX 2009 class? MODEL ANSWER: //Visual Basic Dim salesFormLetter As AxaptaObject Dim axapta1 As Axapta Dim className As String axapta1. How is debugging through the Business Connector enabled? MODEL ANSWER: Enable debugging on the AOS configuration.CreateAxaptaObject(className) 4-22 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . What is the purpose of the Managed Classes in the . Set Debug mode to When Breakpoint. Open an instance of the Microsoft Dynamics AX debugger.NET connector into the Global Assembly Cache after it is installed? MODEL ANSWER: No. Enable debugging on the Client configuration. What is the Business Connector Proxy User account used for? MODEL ANSWER: It is used to enable the Business Connector to "act-on- behalf" of Microsoft Dynamics AX users who cannot be fully authenticated 4. Do you need to register the . 2. 3. Describe the purpose of the Business Connector. "". 6. Using a . MODEL ANSWER: The Business Connector enables external applications to interact with Microsoft Dynamics AX 2009 Application Object Server instances.

Chapter 5: CLR Interoperability CHAPTER 5: CLR INTEROPERABILITY Objectives The objectives are: • Reference Common Runtime Language (CLR) assemblies in the Microsoft Dynamics® AX 2009 Application Object Tree (AOT). Microsoft Official Training Materials for Microsoft Dynamics ® 5-1 Your use of this content is subject to your current services agreement . Introduction The Common Runtime Language (CLR) Interoperability (shortened to Interop) feature enables X++ developers to add CLR assemblies to the AOT and to write X++ code that interoperates with objects in these assemblies. • Understand how and where the use of DLL's is implemented in Microsoft Dynamics AX 2009. • Consume external web services from X++ code. • Write X++ code that interacts with managed code in external applications. to leverage functions already available in the operating system or external applications. This provides access to a vast array of prefabricated code. • Add assemblies to the Global Assembly Cache. • Secure CLR Interop code. This lesson describes how to reference assemblies in Microsoft Dynamics AX 2009 and leverage them in X++ code.

However. 3. expand the References node. The following figure illustrates the sys layer assembly references. The Add reference form contains all the assemblies that have been registered in the Global Assembly Cache (GAC). Click the Browse… button to select an assembly from another location. 4. 5-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .1 THE REFERENCES NODE ON THE AOT Procedure . The assemblies often take the form of DLL files. a developer must first create a reference to the assembly in the Microsoft Dynamics AX 2009 AOT. To see the assemblies already referenced in the AOT. FIGURE 5. you are not restricted to just these assemblies. 2.Development IV in Microsoft Dynamics® AX2009 Reference CLR Assemblies in the AOT CLR assemblies contain managed code designed to be consumed by other applications. Right-click AOT > References.Reference a New Assembly in the AOT Use the following procedure to reference a new assembly in the AOT: 1. To use the managed code within an assembly in X++ code. The Add Reference form appears. Select Add Reference.

Office.Interop.Office. and culture information (if provided)). using the corresponding private key.Office. to retain the referenced location in the AOT. which contains the names and hashes of all the files that make up the assembly). Microsoft® Visual Studio® . It provides a controlled central repository for all DLL files on a server. The GAC is located in the following path: \%winnt%\assembly Install assemblies available to all clients into the GAC on each Application Object Server (AOS) servicing the clients. IMPORTANT: Code using assemblies installed on the AOS must be set to run on the server. the Development. Assemblies with the same strong name are expected to be identical. The assemblies are visible in the AOT > References node. Remember to install server assemblies into the GAC on the development.Word and Microsoft. It is generated from an assembly file (the file that contains the assembly manifest. test.Word and Microsoft. A strong name consists of the assembly's identity (the simple text name.Excel. Alternatively. The assemblies in the lower window are added to the AOT by clicking OK. and production AOS servers. For example: C:\Program Files\Microsoft Dynamics AX0\Client\Bin Microsoft Official Training Materials for Microsoft Dynamics ® 5-3 Your use of this content is subject to your current services agreement . Test and Production servers). not on the client. Be sure to install the assemblies in the same location on each machine. Adding Assemblies to the Global Assembly Cache or Client The Global Assembly Cache (GAC) is a directory in the Windows Server file system. a public key and a digital signature.NET and other development tools provided in the .Interop.Interop. The recommended location for client assemblies is the bin directory on the client. In this example choose Microsoft. version number.Excel which are both available from the GAC list. it is possible to install assemblies on each of the client machines. 6.Office. The GAC enforces that all assemblies installed into it are strongly named. The following new assemblies are referenced in the AOT: Microsoft.NET Framework SDK can assign strong names to an assembly. across different servers (for example. click OK. HINT: Refer to the MSDN on strongly named assemblies for more information. After selecting all the assemblies. Chapter 5: CLR Interoperability 5. 7. Click the Select button to include one or more assemblies in the lower window. to avoid problems that can arise when DLL files are stored in different places by each developer.Interop.

Net.MailMessage mailMessage. NOTE: CLR assemblies and their contents are case sensitive. attachementCollection.Attachment attachment.NET. as described in the previous section.jpg").Net. to create an email with a multiple attachments: System.c om").Net.Mail assembly.Attachment("c:\myfile. 5-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . attachment = new System. One example is the System. which provides code to send e- mails.Net. System.Development IV in Microsoft Dynamics® AX2009 Leverage CLR Managed Code Within X++ Code To use the functionality in managed code in an assembly.NET assemblies available in the Windows operating system.Mail."you@contoso.Net. The following is an example of X++ code which leverages the code in the System. Referenced assembly names can then be used in X++ code. Alternatively.Mail assembly.MailMessage("me@contoso.Add(attachment).Mail.Attachment("c:\myphoto.Mail.Mail. first reference the assembly in the AOT. System. custom assemblies can be created in . mailMessage = new System. There are many .Mail.com". attachementCollection.Net. attachment = new System. attachementCollection = mailMessage. .Mail.Net.AttachmentCollection attachementCollection.Net.txt").get_Attachments().Add(attachment).

int b) { return a + b. } } } If this assembly was available as a DLL file. str s. int i. Once referenced.add(18.sayHello(). info(s). call the assemblies contents directly in X++ code. s = hw. i = hw. it could be added to the References in the AOT. Chapter 5: CLR Interoperability Refer to this example of a small . } public int add(int a. } When JobCLR() is run. info(int2str(i)). .NET assembly: //. The following X++ code example leverages the . the result is two lines in the Infolog: • Hello CLR Interop World! • 47 Microsoft Official Training Materials for Microsoft Dynamics ® 5-5 Your use of this content is subject to your current services agreement .NET code in the previous assembly: //X++ code static void JobCLR(Args _args) { SampleCLR. hw = new DemoCLR.HelloWorld().NET code namespace SampleCLR { public class HelloWorld { public string sayHello() { return "Hello CLR Interop World!".29).HelloWorld hw.

} Web service references The Microsoft Dynamics AX 2009 programmability model now supports services.some xml code here. 5-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . When granting permission to CLR Interop classes.. the following demonstrations illustrate how to call the Microsoft Live Search Web service. To illustrate how to consume a Web service. and then X++ code can refer to the web reference like any other native Microsoft Dynamics AX 2009 AOT object.xml'). it can be invoked from X++ and the available methods can be seen using Intellisense. xmlDoc = new System. This feature is useful for pulling real-time information from sources published on the web. .Xml. use the InteropKind::CLRInterop value. xmlDoc. a reference to the Web service must first be created. After creating a reference to the Web service. This means external Web services can be consumed from X++ code in a similar way to CLR references.XmlDocument().. that classes categorized as "secured" require a permission class to run. To consume an external Web service from X++..XmlDocument xmlDoc. The new method of this class requires an InteropKind type parameter. The following is an example of CLR Interop code with a permission class: public server void JobCLRPermissions(Args _args) { System.Save('c:\test. Calling and managing external Web services is done entirely within Microsoft Dynamics AX 2009.assert(). new InteropPermission(InteropKind::CLRInterop). which is an enum.Development IV in Microsoft Dynamics® AX2009 InteropPermission Class Recall from the Writing Secure X++ Code topic in the Development III course. They have a permission class called InteropPermission. //. A web reference is created in the AOT. The CLR Interop classes are classified as "secured" APIs..Xml.

This name is used as the name of the . The following are valid formats for the WSDL URL: o http://soap. and then click Add service reference.asmx?wsdl o http://localhost/WebServices/SalesTableservice. http://soap. right-click the References node. enter a unique name for the .msn. In the WSDL URL field.asmx?wsdl.or - In the AOT. . 2. In the Service description field. a file share. From the Tools menu select Development tools. The following screen appears: FIGURE 5. In the . 6. The Web reference is generated and the proxy files are saved to the following directory: <Microsoft Dynamics AX Install Directory>Application\Appl\DynamicsAx\ServiceReferences###BOT_TEXT###lt;Web Service Name>.NET code namespace field. In the Reference name field.search.Create a reference to the Web service Perform the following steps to create a reference to the Web service: 1. or an Internet address.com/webservices. This is the namespace in which the generated proxy assembly and other files will reside.NET assembly that is created and the name of the directory that contains the generated Web reference files.com/webservices.wsdl 4. select Application Integation Framework.asmx?WSDL o c:\WebServices\SalesTableService. enter a description for the Web service.NET namespace such as WindowsLiveSearch.2 ADD SERVICE REFERENCE DIALOG 3. enter the location of the service WSDL.search. 5. Chapter 5: CLR Interoperability Demonstration . enter a unique name for the Web service without spaces or special characters such as LiveSearch. Microsoft Official Training Materials for Microsoft Dynamics ® 5-7 Your use of this content is subject to your current services agreement . This field can contain a path to the local file system. and then select Add service reference.msn. 7. Click OK.

SourceRequest[] array. . conpeek(searchResults. 4. In the AOT. try { new InteropPermission(InteropKind::ClrInterop). // Display the search results.%1"..SourceType sourceType. // This will search for string "Microsoft Dynamics AX 2009". right-click and select New Class.Development IV in Microsoft Dynamics® AX2009 Demonstration . public static void main(Args _args) { Container searchResults. info(strfmt("Total # of hits. This adds a main method that calls the search service with a search string and displays the results in an Infolog window. Right-click the class and select New Method. Replace the method with the following code in the code editor.Consume a web service from X++ Perform the following steps to consume a Web service from X++ 1. navigate to the Classes node. This method creates the source request and puts it in an array. public static WindowsLiveSearch. 2. 2)). Set the Name property to LiveSearchTest..SourceRequest[] getSourceRequestArray() { WindowsLiveSearch. 5.SourceRequest sourceRequest. WindowsLiveSearch. info(conpeek(searchResults. WindowsLiveSearch. Right-click the class and select New Method.assert(). 3. searchResults = LiveSearchTestClass:: searchLive("Microsoft Dynamics AX 2009"). // Call the method to issue the search with the search criteria. 1))). int i. Replace the method with the following code in the code editor. 5-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Right-click the new class and select Properties. } 6. Set the RunOn property to Server.

} catch(Exception::CLRError) { throw error(AifUtil::getClrErrorMessage()). Replace the method with the following code in the code editor. resultsLength. public static container searchLive(str searchQuery) { #File WindowsLiveSearch.assert().set_Source(sourceType). return array. // Add the source request to an array. Microsoft Official Training Materials for Microsoft Dynamics ® 5-9 Your use of this content is subject to your current services agreement . idx2. WindowsLiveSearch.SearchRequest searchRequest. TextBuffer searchResultBuff. description. try { searchResultBuff = new TextBuffer(). resultsArray. array.SetValue(sourceRequest.Result searchResult. This is the method that calls the Live Search Web service and returns the search results in a container. url. WindowsLiveSearch.SourceResponse[] sourceResponseArray.SearchResponse searchResponse.SourceType::Web. sourceRequest = new WindowsLiveSearch. } } 7.MSNSearchPortTypeClient searchService. ArrayIdx idx1. . // Replace this string with your Application ID.SearchRequest(). Right-click the class and select New Method. sourceType = WindowsLiveSearch.SourceResponse sourceResponse. int srcResponseLength. totalHits. searchRequestObj. searchRequestObj = new WindowsLiveSearch. new InteropPermission(InteropKind::ClrInterop). WindowsLiveSearch.SourceRequest[1](). sourceRequest. WindowsLiveSearch. // Create the search request.SourceRequest(). str title. 0). ClrObject sourceRequestArray. Chapter 5: CLR Interoperability // Create the source request and designate the type // of search. WindowsLiveSearch. array = new WindowsLiveSearch.

get_Length(). searchResponse = searchService. title = searchResult.get_Total()).get_Results().NET array so start at zero. // Iterating through a .MSNSearchPortTypeClient().Search(searchRequest).set_AppID("YOUR_LIVESEARCH_APP_ID").appendText(#delimiterCRLF). searchResultBuff. sourceResponseArray = searchResponse.Development IV in Microsoft Dynamics® AX2009 searchRequestObj. idx1++) { sourceResponse = sourceResponseArray.appendText(description).appendText(title). searchResultBuff. and URL and appends // it to the search results. idx1 < srcResponseLength . srcResponseLength = sourceResponseArray. searchRequestObj.appendText(#delimiterCRLF).GetValue(idx2).GetValue(idx1). searchRequest = searchRequestObj. sourceRequestArray = LiveSearchTestClass::getSourceRequestArray().get_Responses().appendText(#delimiterCRLF). url = searchResult.get_Description(). for(idx1=0. totalHits = ClrInterop::getAnyTypeForObject( sourceResponse.get_Url().set_Requests(sourceRequestArray). description = searchResult. // Iterating through .NET array so start at zero.set_CultureInfo("en-us"). searchResultBuff. searchResultBuff. searchService = new WindowsLiveSearch. idx2 < resultsLength .set_Query(searchQuery). //Create the service and call it.get_Length(). description.get_Title(). searchRequestObj. searchResultBuff. searchResultBuff. searchResultBuff. idx2++) { searchResult = resultsArray. // Gets the title. resultsLength = resultsArray.appendText(url).appendText("-------------- ------- 5-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . // Iterate through the search results. resultsArray = sourceResponse. for(idx2=0. searchRequestObj.

appendText(#delimiterCRLF).3 INFOLOG WINDOW WITH SEARCH RESULTS Microsoft Official Training Materials for Microsoft Dynamics ® 5-11 Your use of this content is subject to your current services agreement . Chapter 5: CLR Interoperability --------------------------------------- -----"). searchResultBuff. return [totalHits. } } You should now have a class named LiveSearchTest with three methods: • getSourceRequestArray • main • SearchLive 8. searchResultBuff. } catch(Exception::CLRError) { throw error(AifUtil::getClrErrorMessage()). } } CodeAccessPermission::revertAssert(). Compile the class and Run the main method.getText()]. FIGURE 5. // Convert the buffer to a string and add it to a container. The search results should appear in an Infolog window as shown in the following figure.

such as Kernel32.txt”).dll dumpbin /exports c:\windows\system32\kernel32. • Declare and instantiate an instance of the class DLL.exe program. This implements useful functions from kernel32. • Set the type of all parameters that function accepts. This is shipped with Microsoft® Visual Studio® .dll.NET.dll and user32. MSDN describes some of the functions available in a few main Windows DLL's. One method used to view a list of functions in a DLL is the dumpbin. Use the following line in a command prompt to obtain a list of functions in Kernel32. fileSize = winAPI::FileSize(“c:\myfile. or which window is currently active. and others. such as the amount of free space on a disk.dll The best example of using a DLL within Microsoft Dynamics AX 2009 is the WinAPI class. } This method uses two other methods to obtain the desired result. Each DLL has one or more functions that can be called. Analyze the getFileSize() method to understand how to implement a specific function. passing the name of the DLL as a parameter into the new method. passing the DLL object and the name of the function as a parameter into the new method. For example: { int fileSize. . They are often used to find information about the current environment.dll. as documentation or definition files are often not installed with the DLL. • Set the type of the return value. • Declare and instantiate an instance of the class DLLFunction. user32.dll. • Call the function. 5-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Implementing a DLL A Dynamic Link Library (DLL) is a collection of small Windows programs that can be called upon to complete a particular function. It is not always easy to find all the available functions and how to use them.

Create a new form called CustTransGraph.ChartFX . and the z-axis is customers. Chapter 5: CLR Interoperability ChartFX Another example of using DLLs in Microsoft Dynamics AX 2009 is the use of ChartFX. Add a new Chart Object type ActiveX control to the design and change the following properties: o Name: designGraph o AutoDeclaration: Yes o Width: 750 o Height: 375 4. This enables a high-quality graphical representation of data on forms. 3. Follow this example: The following example uses customer transactions in a graph. the y-axis is customer balance.dll. This form is dynamically linked to the CustTable. 2.Using ChartFX DLL in a form Perform the following steps to use ChartFX DLL in a form: 1. Microsoft Official Training Materials for Microsoft Dynamics ® 5-13 Your use of this content is subject to your current services agreement . where the x-axis is time. so keeping the new form open together with the customer form. As a result. means a new row appears every time you highlight a new customer. Example . Add CustTable to the data source. Declare the form variable as follows: Graphics graphData 5. Override the form's init method and add the following before super(): #MACROLIB. the new customer's transactions are added to the graph.

9.Development IV in Microsoft Dynamics® AX2009 6. 5-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . qbd. //Title X-Axis "Amount". QueryBuildDatasource qbd. graphData. while (queryRun.showGraph(). //Title Y-Axis "Customer". Add this menu item to the button group on the custTable form.2). Create a display menu item for the form.custTrans. Override the executeQuery method on the datasource custTable with the following code: public void executeQuery() { Query query = new Query(). //ExtType 0). //ActiveX control 750. //Width 375.2.value(SysQuery::value(custTable.2. CustTrans custTrans. //Type #CS_ALL.loadData( date2str(custTrans. accountNum)). //Style #CTE_STEPLINES. QueryRun queryRun.TransDate. //Height "Customer transaction".2. //ExtStyle 7.next()) { custTrans = queryRun.addRange(fieldnum(CustTrans. custTrans.AccountNum. qbd = query. //Title Z-Axis #Bar | /*#CT_SHOWVALUES |*/ #CT_CLUSTER | #CT_3D | #CT_TOOL | #CT_SHOWZERO | #CT_LEGEND. //Title "Date".123. } 8. } graphData.get(tablenum(custTrans)). queryRun = new QueryRun(query).AccountNum)).addDataSource(tablenum(CustTrans)). .AmountMST). Add the following after super(): graphData = graphics::newGraphicsTitlesLayout( designGraph.2. super().

Microsoft Official Training Materials for Microsoft Dynamics ® 5-15 Your use of this content is subject to your current services agreement . Chapter 5: CLR Interoperability Clicking the button for a customer in the custTable form opens a form similar to the following (provided some customer transactions exist): FIGURE 5. This lesson demonstrated how to: • Reference CLR assemblies in Microsoft Dynamics AX 2009 AOT • Add to the Global Assembly Cache • Write X++ code that interacts with managed code in external applications • Use DLL's within X++ code.4 FORM USING A DLL FILE TO RENDER THE CONTENTS OF AN ACTIVEX CONTROL Summary The Common Runtime Language (CLR) Interoperability (shortened to Interop) feature enables X++ developers to add CLR assemblies to the AOT and to write X++ code that interoperates with objects in these assemblies.

What code do you use.Development IV in Microsoft Dynamics® AX2009 Test Your Knowledge 1. Are CLR Interop assemblies. and methods case-sensitive when referenced in X++ code? 3. How do you make CLR Interop assemblies visible to Microsoft Dynamics AX 2009 X++ code? 2. to provide Code Access Security permission to a CLR Interop class? 5-16 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . classes.

dll and user32. URL b. The location of the Web service. the generated Web reference files. WSDL a. Reference name d. Which class contains multiple methods. . Identifying text for the Web service. Which node on the AOT are Web service references found? 5. Where the generated proxy assembly and other files _____ 4. Chapter 5: CLR Interoperability 4. description 6.dll objects to communicate with the Windows environment? Microsoft Official Training Materials for Microsoft Dynamics ® 5-17 Your use of this content is subject to your current services agreement . Service will reside. Match the following properties of a Web service reference. _____ 2. What is used as the name of the .NET assembly that code namespace is created and the name of the directory that contains _____ 3.NET c. using the kernel32. _____ 1. to its description.

Net.Mail.com Need a Little Help? • Use the InteropPermission class and InteropKind::CLRInterop enum to satisfy Code Access Security. • You can assume the email address of the sender is me@abc. • Use the System.Mail. 5-18 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . • Use the System.com and that the SMTP server is smtp.Mail. • Loop through the EmplTable to retrieve all employee names and email addresses.CLR Interop Scenario You are required to use CLR Interop code to send personalized mail messages to everyone in the company.Net. • The method accepts two parameters . • Add a line of code to address the recipient personally with "Dear <insert name here>" at the start of the email body.Mail assembly.Development IV in Microsoft Dynamics® AX2009 Lab 5.Net.1 .the subject of the email. Challenge Yourself! • Write a class method that uses CLR Interop code to send a personalized email to every employee in the company.Net. System.abc.MailMessage.MailAddress and System. and the contents of the email body.SmtpClient classes.

com').Net. adrSend. smtpClient = new System. while select Name.Net.the subject of the email.com Step by Step • Create a new class.Net. and a new method within it.SmtpClient('smtp.Mail.com and that the SMTP server is smtp. and the contents of the email body. new InteropPermission(InteropKind::ClrInterop). • The method accepts two parameters . System.MailAddress adrRecp. SysEmailContents _contents) { System. • You can assume the email address of the sender is me@abc. • Write a class method that uses CLR Interop code to send a personalized email to every employee in the company.CLR Interop (Solution) Scenario You are required to use CLR Interop code to send personalized mail messages to everyone in the company. • The code inside should look like this: void sendPersonalizedEmail(SysEmailSubject _subject.SmtpClient smtpClient.1 .Net.Mail.Mail.abc.MailMessage msg.abc. Chapter 5: CLR Interoperability Lab 5.assert(). EmplTable eT. . System. • Add a line of code to address the recipient personally with "Dear <insert name here>" at the start of the email body.Mail. Email from emplTable { Microsoft Official Training Materials for Microsoft Dynamics ® 5-19 Your use of this content is subject to your current services agreement .

Net. _subject = strfmt('Dear %1.MailAddress('me@abc.Mail.Mail.Name) + _subject.Mail. smtpClient. emplTable.Net.com').Net.set_Body(_contents). msg. adrRecp).Development IV in Microsoft Dynamics® AX2009 adrRecp = new System. \n'.Email).MailAddress(emplTable. adrSend = new System. msg = new System. } } 5-20 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Send(msg).MailMessage(adrSend.set_Subject(_subject). msg.

Microsoft Official Training Materials for Microsoft Dynamics ® 5-21 Your use of this content is subject to your current services agreement . Need a Little Help? Follow the ChartFX example to graph the balance of a customer over time.2 . Challenge Yourself! Create a new form that shows a graph of the balance of a customer over time. Chapter 5: CLR Interoperability Lab 5.Implementing DLL's Scenario Management wants a graphical way to view data.

BalancePerDate() to find the balance. Follow the step-by-step example in training manual. Step by Step 1. However instead of using transaction amount. Follow the ChartFX procedure in the chapter for inspiration. Use CustTable. Create a new form that shows a graph of the balance of a customer over time. 5-22 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .2 .Implementing DLL's (Solution) Scenario Management wants a graphical way to view data.Development IV in Microsoft Dynamics® AX2009 Lab 5. use the balance of the customer on the date of the transaction.

Chapter 5: CLR Interoperability Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1. 3. 2. Microsoft Official Training Materials for Microsoft Dynamics ® 5-23 Your use of this content is subject to your current services agreement .

The location of the Web service. They are case sensitive 3. using the kernel32.dll objects to communicate with the Windows environment? MODEL ANSWER: WinAPI 5-24 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . 5. Identifying text for the Web service. Reference name d. the generated Web reference files. b 1. to provide Code Access Security permission to a CLR Interop class? MODEL ANSWER: new InteropPermission(InteropKind) 4. Which class contains multiple methods.Development IV in Microsoft Dynamics® AX2009 Solutions Test Your Knowledge 1.dll and user32.NET assembly that code namespace is created and the name of the directory that contains c 3. Match the following properties of a Web service reference. Which node on the AOT are Web service references found? MODEL ANSWER: The References node. to its description. under the References node. What code do you use. URL b. How do you make CLR Interop assemblies visible to Microsoft Dynamics AX 2009 X++ code? MODEL ANSWER: You add references to the assembly files in the AOT. d 2.NET c. Are CLR Interop assemblies. Service will reside. WSDL a. classes. Where the generated proxy assembly and other files a 4. and methods case-sensitive when referenced in X++ code? MODEL ANSWER: Yes. . What is used as the name of the . description 6. 2.

many modifications to other modules or automation of ledger procedures may require writing code that creates ledger transactions. Chapter 6: Ledger CHAPTER 6: LEDGER Objectives The objectives are: • Create ledger transactions using LedgerVoucher • Create ledger transactions using a Ledger Journal Introduction All Microsoft Dynamics® AX 2009 modules interface with the General Ledger module in some way. 2. Use a journal which is more straightforward to use. However. It is also the module that has the least modifications made to it due to the commonality in accounting procedures throughout the world. Microsoft Official Training Materials for Microsoft Dynamics ® 6-1 Your use of this content is subject to your current services agreement . Use the LedgerVoucher class and sub-classes. this lesson examines how to use both methods. which is the more direct and controllable route. Since these procedures are used regularly but rarely modified. but does not go into details about how these methods work. it is regarded as one of the most important modules. There are two methods to consider when posting transactions to the ledger: 1.

the system posts them all to the General Ledger module at once. The idea is to build up a list of vouchers to be posted and to build up a list of transactions within each voucher. Instantiate the LedgerVoucher class. The End method creates ledger transaction records from the temporary postings. Once these lists are completed.Development IV in Microsoft Dynamics® AX2009 Scenario Isaac. A structure is built as follows: Posting (LedgerVoucher) • Voucher (LedgerVoucherObject) o Trans (LedgerVoucherTransObject) o Trans • Voucher o Trans o Trans LedgerVoucher harnesses the posting of multiple vouchers at one time. the Systems Developer. He has been asked to evaluate the best method to achieve this and to write a program that can be used during the data migration. The LedgerVoucher class holds all the vouchers in temporary storage (a list array) until the End method is called. 6-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . LedgerVoucher When using LedgerVoucher. Possible rounding of postings is carried out if necessary. is developing a process to import opening ledger balances for a new company that is to be migrated to Microsoft Dynamics AX2009. Each voucher in the LedgerVoucher is contained in a LedgerVoucherObject. remember that all vouchers in Microsoft Dynamics AX 2009 must balance . Each LedgerVoucherObject holds transactions in temporary storage (a list array) until the end() method is called.an equal credit and debit side. Each transaction in each voucher is contained in a LedgerVoucherTransObject. It checks that the posting is correct and that the voucher balances. The procedure is: 1. All transactions on one voucher must be posted on the same date.

Loop over the vouchers to instantiate LedgerVoucherObject classes. _posting]). Chapter 6: Ledger 2. _sysModule. The parameters are: • _detailSummary – Value specifying either summary or details. when the voucher has already been used. • _transactionLogType – Used in the audit trail (optional). LedgerVoucherPost.it stamps the ledger transaction with the code that was used. • _voucherSeriesCode – Number sequence code used for numbering the vouchers. • _sysModule – System module from which transactions are made. The method constructs one of the sub-classes. LedgerVoucherPostExPosting is used in the production module to reduce the number of transactions created during production order updates. for instance. LedgerVoucherPostApprove is used when the final posting is approved by the user. For each voucher. This value can also be used for posting transactions from custom modules. and voucher. LedgerVoucherPostExPosting. and register these in the LedgerVoucher class. date. LedgerVoucherPost is used for normal posting to the general ledger. LedgerVoucherPostApprove. for example. This does not automatically allocate the voucher number . if a vendor invoice approval journal needs to bypass some checks. currency. Microsoft Official Training Materials for Microsoft Dynamics ® 6-3 Your use of this content is subject to your current services agreement . _transactionLogText. and register these in the LedgerVoucher class. [_transactionLogType. Specifying summary results in summarizing the amounts per account. _voucherSeriesCode. A detailed description of these steps follows. loop over the transactions to instantiate LedgerVoucherTransObject classes. _approveJournal. 3. Instantiation of LedgerVoucher LedgerVoucher can be instantiated as follows: LedgerVoucher::newLedgerPost(_detailSummary.

look in the base enum OperationsTax details. _correction. (Optional) • _sysModule – System module from which transactions are made. _documentDate. • _approveJournal – True returns LedgerVoucherPostApprove (optional). (Optional) • _documentNum – Use to stamp a document number onto a transaction. Default value LedgerTransType:None. To view all available ledger transaction types. The default value is the current date. The default value is OperationsTax::Current. (Optional) • _LedgerTransType – Ledger transaction type. (Optional) • _operationsTax – Indicates the type of operation tax used when posting a transaction. _documentNum. [_transDate. _tmpVoucherMap. This value can also be used for posting transactions from other modules. _ledgerTransType. For all available OperationTax codes. Instantiation of LedgerVoucherObject LedgerVoucherObject can be instantiated as follows: LedgerVoucherObject::newVoucher(_voucher. refer to base enum LedgerTransType. (Optional) • _correction – Indicates whether the voucher is a reversing entry (credit note). _sysModule.Development IV in Microsoft Dynamics® AX2009 • _transactionLogText – Used in the audit trail (optional). The parameters are: • _voucher – Number of the voucher. • _transDate – Date of transaction. _operationsTax. (Optional) 6-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . _acknowledgementDate]). • _posting – False returns LedgerVoucherPostExPosting (optional).

The newCreateTrans() method is most commonly used.AddVoucher(ledgerVoucherObject). Instantiation of LedgerVoucherTransObject There are many other constructor methods for this class used in different situations. _sourceRecId. _ledgerAccount. _ExchRatesTriangulation. _amountMST]) Microsoft Official Training Materials for Microsoft Dynamics ® 6-5 Your use of this content is subject to your current services agreement . (Optional Italy country specific functionality) Registering the LedgerVoucherObject with the LedgerVoucher A LedgerVoucherObject can be added to LedgerVoucher as follows: ledgerVoucher. _projLedger. _markBridging. Chapter 6: Ledger • _documentDate – Use to stamp a document date onto a transaction. _amountCur. _exchRate _exchRateSecond. _currencyCode. _ledgerPostingType. _dimension. (Optional) • _tmpVoucherMap – Use during posting when it is required that all voucher numbers are continuous (Optional) • _acknowledgementDate – Date when the company gains knowledge of the transaction. LedgerVoucherTransObject::newCreateTrans( _ledgerVoucherObject. [_LedgerQty.

SalesLine). • _SourceRecid – The record ID of the originating record (for example. Providing the Transaction Text Add transaction text to a transaction by using the following code. • _ledgerAccount – The ledger account number on which transactions will be made. (Optional) • _exchRate – Use to specify an exchange rate. currency calculation will be made. 6-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .addTrans(ledgerVoucherTransObject). • _currencyCode – Currency in which transactions are made. If calculation has already been made. _transTxt . if any. • _dimension – The transaction dimension.Development IV in Microsoft Dynamics® AX2009 • _ledgerVoucherObject – The object containing the corresponding voucher. attached to the transaction. Registering the LedgerVoucherTransObject with the LedgerVoucher ledgerVoucher. (Optional) • exchRatesTriangulation – Can override currency's setting for Euro Triangulation. This adds the transaction initiated in the newCreateTrans() method to the posting. (Optional) • _projLedger – Use in the project module to create project-specific transactions from the ledger transactions. For all available posting types. (Optional) • _markBridging – No longer used. • _LedgerQty – The quantity. If blank. • _amountCur – The amount in currency (this is converted to MST in the newCreateTrans method). It has already been added to the LedgerVoucherObject. This was used in a journal to mark a transaction posted to a temporary bridging account. the exchange rate in the system for the transaction date is used. ledgerVoucherTransObject. (Optional) • _exchRateSecond – Use to specify an exchange rate for the secondary currency (if used). then specifying the amountMST (monetary standard amount) increases performance.parmTransTxt(_transTxt). (Optional) • _amountMST – If not specified. the exchange rate in the system for the transaction date is used. If blank. • _ledgerPostingType – A type of posting.Transaction text. look in base enum LedgerPostingType details.

LedgerVoucher. user input or a calculation. NumberSequenceCode NumberSequenceCode = 'Acco_18'. The accounts and amounts are set in the variable declaration. // Petty cash ledgerAccount accountNumOffsetOffice = '606300'. A coding example using the ledgerVoucher class is provided in the application as the TutorialLedgerVoucher class. Usually these would be obtained from parameters. // Office Supplies ledgerAccount accountNumOffsetPostage = '606500'. LedgerVoucherTransObject ledgerVoucherTransObject. // Postage amountMST amountPetty = 55. LedgerBalancesTrans and LedgerBalancesDimTrans are updated. Chapter 6: Ledger Finalizing the Posting When all the vouchers and transactions have been added. //First Step . Microsoft Official Training Materials for Microsoft Dynamics ® 6-7 Your use of this content is subject to your current services agreement . the whole posting can be committed. The runJournalPost method exemplifies posting from a journal. Final checks are made and the transactions are finalized. ttsbegin. amountMST amountPostage = 5. numSeq = NumberSeq::newGetNumFromCode(NumberSequenceCode). NumberSeq numSeq. Example: Using LedgerVoucher The following job posts a petty cash disbursement for a payment for a stapler and some stamps. These tables store balances by period and by dimension. static void ExampleLedgerVoucher(Args _args) { LedgerVoucher ledgerVoucher. ledgerAccount accountNumPetty = '110180'. amountMST amountOffice = 50.Create Voucher ledgerVoucher = ledgerVoucher::newLedgerPost(DetailSummary::Summary. . Dimension dimension.end(). The runSalesPost method exemplifies posting a sales order with its lines. Also.

//Create the second Transaction ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucher.Development IV in Microsoft Dynamics® AX2009 SysModule::Ledger.this is the credit side of the transaction (-55) //The other two DR transactions should total to the CR otherwise it won't post. LedgerPostingType::LedgerJournal. 6-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . dimension. - amountPetty.Create Voucher Number ledgerVoucher. Sysmodule::Ledger. LedgerPostingType::LedgerJournal.num(). // ReciID ledgerVoucherTransObject. ledgerVoucher.findLedgerVoucherObject(). ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucher. accountNumPetty. CompanyInfo::standardCurrency(). // Ledger Account dimension.AddVoucher(LedgerVoucherObject::newVoucher(nu mseq. // TableId 0).NumberSequen ce) . LedgerTransType::None)).addTrans(ledgerVoucherTransObject). accountNumOffsetOffice. //Second Step .parmTransTxt("Petty cash disbursement"). // Amount 0. today(). //Create the first Transaction .findLedgerVoucherObject(). LedgerParameters::numRefLedgerExchAdjVoucher().

parmTransTxt("Stamps"). // Amount 0. 0. ttsCommit.addTrans(ledgerVoucherTransObject). ledgerVoucher. Chapter 6: Ledger CompanyInfo::standardCurrency(). amountOffice. // TableId 0). // TableId 0).findLedgerVoucherObject(). //Last Step . numseq. CompanyInfo::standardCurrency(). ledgerVoucher.parmTransTxt("Red stapler"). dimension. // ReciID ledgerVoucherTransObject.used(). // ReciID ledgerVoucherTransObject.addTrans(ledgerVoucherTransObject).To Balance Voucher and Close ledgerVoucher. } Microsoft Official Training Materials for Microsoft Dynamics ® 6-9 Your use of this content is subject to your current services agreement . //Create third Transaction ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucher. accountNumOffsetPostage. LedgerPostingType::LedgerJournal. amountPostage.end().

fill it in with data and call upon Microsoft Dynamics AX2009's method for posting the journal. 2. Post the journal. All error checking and posting are performed simultaneously without additional programming.Development IV in Microsoft Dynamics® AX2009 LedgerJournal Journals are the easiest way of posting in Microsoft Dynamics AX2009. 6-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . classes. When using a Journal lines table. 3. or one line per transaction. The journal framework consists of a number of tables. Within these groups. LedgerJournalTrans contains data used to create the individual transactions that will be posted. Ledger Journal structure The three main journal groups in Microsoft Dynamics AX2009 are Ledger. but differ slightly in what information they require and the end result. This is often useful during data migration. the tables used are LedgerJournalName. In the ledger module. and Project. Create a journal table record or use an existing one. LedgerJournalTable. Using journals requires less work when grouping the transactions and vouchers appropriately. there are many types that use the same tables. Journals also present the possibility of not posting immediately but allowing the user to verify what is to be posted. LedgerJournalTable is the header record for the journal. maps. This could be one line per pair of balanced transactions. and LedgerJournalTrans. The steps used to create a journal are: 1. There can be more than one LedgerJournalName per type. Inventory. LedgerJournalName contains default data for a specific journal type. There is one record per journal. This checks the journal before posting. There can be one or more lines per journal. This step is left out if the journal is to be checked by the user before posting. and forms designed so that all journals behave similarly and have the same look and feel across modules. Create lines for each transaction to be posted. A more detailed description of the steps involved follows.

JournalNum which is mandatory. The easiest way is to create an instance of this class using newLedgerJournalTable static method and then run the class. Microsoft Official Training Materials for Microsoft Dynamics ® 6-11 Your use of this content is subject to your current services agreement . Creating Lines All transactions must be posted in the journal lines table. ledgerJournalTable.insert().JournalName = SalesParameters::find().PayJournal is a new field of type LedgerJournalNameId. Look in the table method ledgerJournalTable.Insert(). Two fields of interest when creating journal lines are: LedgerJournalTrans. Fill in other mandatory fields in the journal lines table as necessary.Voucher which is the transaction voucher number. Where SalesParameters::find(). Fill the record with data and then insert it.Name = 'Payment Journal' ledgerJournalTable. Each journal type requires different fields and field combinations to be correctly entered. Chapter 6: Ledger Creating the Journal To create a new journal. check and post the journal. Parameters for this method are: • _ledgerJournalTable – Record in LedgerJournalTable representing the journal which should be posted. Posting Journals After transactions are created in the journal. ledgerJournalTable. use a journal name record to get the default data. Notice it handles the creation of the journal number. Any errors that show up while posting are displayed by validating a journal through the journal lines form. Look at Extended Data Type (EDT) LedgerJournalNameIdApproval for an example of how to create an EDT for a journal name of a specific type. and the initializing from LedgerJournalName. and LedgerJournalTrans. LedgerJournalTrans. Use a journal name of an appropriate type.PayJournal. for example. which is the primary key defining the relationship between the journal table and the lines.CurrencyCode. use the LedgerJournalCheckPost class. because transactions are assigned to one of the journals.

LedgerJournalTrans ledgerJournalTrans. amountCur amountCur = 102. //Generate the transaction line ledgerJournalTrans.JournalName.VoucherS eries).Name = 'Hotel'. //Created the ledgerJournalTable ledgerJournalTable. LedgerJournalTable ledgerJournalTable. posting is done.JournalNum = ledgerJournalTable.ExchRate = Currency::exchRate(ledgerJournalTrans. Yes indicates that all vouchers with errors are transferred into a new journal with the same name and description.CurrencyCode). ledgerAccount offsetAccount = '601500'. • _transferErrors – NoYes parameter for transferring vouchers with errors to another journal. BankAccountID BankAccountID = 'EUR OPER'.JournalName = LedgerJournalName.Development IV in Microsoft Dynamics® AX2009 • _post – NoYes parameter for specifying if it checks only a journal or completes both checking and posting. LedgerJournalNameId LedgerJournalNameId = 'GenJrn'. NumberSeq numberseq. ledgerJournalTrans. Yes indicates that after checking. but with different batch numbers. static void ExampleLedgerJournal(Args _args) { LedgerJournalName LedgerJournalName. ledgerJournalTable.insert(). ttsbegin. numberseq = NumberSeq::newGetVoucherFromCode(ledgerJournalName. The default value is No.JournalNum. ledgerJournalTrans. LedgerJournalCheckPost ledgerJournalCheckPost. Example: Using Ledger Journal The following is an example of creating a journal with one journal line and then posting the journal. .Voucher = numberseq. 6-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . ledgerJournalTable. ledgerJournalTrans.initFromLedgerJournalName().voucher(). ledgerJournalTable.CurrencyCode = 'EUR'. // Find a ledgerJournalName record select firstonly LedgerJournalName where LedgerJournalName.JournalName == LedgerJournalNameId.

AccountType = LedgerJournalACType::Bank. ledgerJournalCheckPost. } Summary This lesson introduces and explains two methods for posting transactions to the ledger table. • Using a journal. info(strfmt('Journal Id: %1'.JournalNum)).ledgerJournalTable. ledgerJournalTrans. ledgerJournalTrans.run(). The two methods are: • Using the LedgerVoucher class and sub-classes.AccountNum = BankAccountID. Microsoft Official Training Materials for Microsoft Dynamics ® 6-13 Your use of this content is subject to your current services agreement .OffsetAccount = offsetAccount.TransDate = today().Txt = 'Room Stay'.OffsetAccountType = LedgerJournalACType::Ledger. ledgerJournalTrans. ttscommit. ledgerJournalTrans. • The best method to use depending on the situation. ledgerJournalTrans.AmountCurCredit = amountCur. Chapter 6: Ledger ledgerJournalTrans. //Post the Journal ledgerJournalCheckPost = ledgerJournalCheckPost::newLedgerJournalTable(ledgerJournal Table. ledgerJournalTrans.insert().NoYes::Yes). This lesson provides a basic understanding of: • The concepts behind the two main methods of posting transactions. ledgerJournalTrans.

Development IV in Microsoft Dynamics® AX2009 Test Your Knowledge 1. Which table stores default values that initialize a LedgerJournalTable record? 6-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The transaction log type and transaction log text are used in the ________ trail. 3. Which class holds a list of transactions that are going to be posted for a particular voucher? 2.

Which class posts a journal? Microsoft Official Training Materials for Microsoft Dynamics ® 6-15 Your use of this content is subject to your current services agreement . Chapter 6: Ledger 4.

4. Post the journal. 5. 2. Write a program that imports these opening balances into a journal and optionally posts it automatically. Set a class variable to store the voucher number. 4. 3. Create a new class that extends RunBaseBatch. Create a line for the offset account entered by the user for the inverse of the total amount of the balances imported. 6-16 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . One voucher can be used for all transactions.Development IV in Microsoft Dynamics® AX2009 Lab 6. Prompt for: o offset account o posting date o filename 3. o Find the first journal name of type = daily. Challenge Yourself! 1. The voucher number is obtained from the number sequence attached to the journal name record. o Set the journal name of the JournalTable record = journal name of JournalName record. posting date. 2. Create a method to generate the journal header. Create a journal header. Prompt for offset account. and filename. Read in the file and create a journal line for each account and balance. you need to enter opening balances for the general ledger. Step by Step 1.1 – Create and Post a Ledger Journal Scenario During data migration when implementing Microsoft Dynamics AX2009 for a new customer. but remember to ensure that it balances. o Insert the JournalTable record.

Create a method to generate the journal lines. and the accounttype. Microsoft Official Training Materials for Microsoft Dynamics ® 6-17 Your use of this content is subject to your current services agreement . to post the journal. the date. Call LedgerJournalCheckPost (use static method newLedgerJournalTable). o Set the account number. o Set the voucher number. o Create a line for the negative of the total amount of the transactions for the offset account specified in the prompt. call the method to create the journal line. o Accept the account number and amount as parameters. o Read the file. the amount. o For each line. Chapter 6: Ledger 5. 6.

Development IV in Microsoft Dynamics® AX2009 Lab 6. 6. a. Prompt for the RegisterId of the register to process. 8. e. 2. Post the counted amount to the bank account.End-of-day routine Scenario This is a part of the Point-of-Sale Project. 7. Set the journal name of the JournalTable record = journal name of JournalName record. Find the first journal name of type = daily. In the next lesson you post the payments to the holding account and the AR sub-ledger. 2. 4. and any difference between the counted amount and the recorded amount is posted to a specified ledger account. Write this routine. Prompt for the cash or bank account and the difference account. Challenge Yourself! 1. Prompt for: o Register Id o Counted amount b. Payments are entered into the register by clicking Payment on the POS form which opens the POSPayment form. c. At any cash register.2 – POS . an End of Day routine counts the actual cash taken. Step by Step 1. Create a new class that extends RunBaseBatch. Post the difference to the register difference account. Set a class variable to store the voucher number. The voucher number is obtained from the number sequence attached to the journal name record. Calculate the difference between the counted amount and the posted amount. Flag the payment lines as having been posted at EOD. 6-18 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . 3. 9. Prompt for the counted cash amount. This is posted to the ledger. Insert the JournalTable record. Post the inverse of the posted amount to the register holding account. Create a method to create the journal header. Total up the amount entered during that day for that register. In a live application this would also open the cash drawer. d. 5.

Find the Register table record for the specified register. and the accounttype. Create a method to create the journal lines. b. the amount. Microsoft Official Training Materials for Microsoft Dynamics ® 6-19 Your use of this content is subject to your current services agreement . Create a journal line for the inverse of the total amount posted for that register for the register holding account. a. to post the journal. d. 4. Create a journal line for the difference between the posted amount and the counted amount for the difference account specified in a parameter. Chapter 6: Ledger 3. Update the register transactions to reflect that they have been posted. Call LedgerJournalCheckPost (use static method newLedgerJournalTable). 5. e. Accept the account number and amount as parameters. Set the voucher number. the date. Create a journal line for the total counted amount for the bank account. f. g. Set the account number. c.

6-20 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1. 3. 2.

Chapter 6: Ledger Solutions Test Your Knowledge 1. 3. Which table stores default values that initialize a LedgerJournalTable record? MODEL ANSWER: LedgerJournalName 4. Which class holds a list of transactions that are going to be posted for a particular voucher? MODEL ANSWER: LedgerVoucherObject 2. Which class posts a journal? MODEL ANSWER: LedgerJournalCheckPost Microsoft Official Training Materials for Microsoft Dynamics ® 6-21 Your use of this content is subject to your current services agreement . The transaction log type and transaction log text are used in the ________ trail. MODEL ANSWER: The transaction log type and transaction log text are used in the audit trail.

Development IV in Microsoft Dynamics® AX2009 6-22 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .

and issuing and receiving payments. similar constructs and procedures also apply for AP. where only AR is referenced. In this chapter. and make good use of table maps to reduce the amount of coding needed. the element that every company modifies is the printed sales invoice. but the basic ideas are similar. Recognize that what is true for SalesLine is also true for PurchLine. Microsoft Official Training Materials for Microsoft Dynamics ® 7-1 Your use of this content is subject to your current services agreement . The AR and AP modules are similar in their structure regarding both data dictionary and update procedures. PurchTableType. SalesLineType. Not everything is the same between the two modules. For instance. Chapter 7: Trade CHAPTER 7: TRADE Objectives The objectives are: • Use SalesTableType. This is sometimes a rearrangement of the data available to the invoice. but is more often a complete redesign that includes additional. The trade modules revolve around buying and selling inventory. and PurchLineType • Post and Print Document Updates • Post Transactions • Use Settlements • Use Trade Agreements Introduction The most frequently modified modules in Microsoft Dynamics® AX 2009 are the Accounts Receivable (AR) and Accounts Payable (AP) modules. company-specific data.

ValidateWrite() has not been overridden. and line types are posted • Where postings to ledger are made FIGURE 7. ok = ok && this.SalesType.Type() method calls SalesLineType. PurchTable.ValidateWrite() is called.validateWrite_server(_skipCreditLimitCheck).contrstruct() which constructs the instance according to the value of SaleLine. SalesLineType is instantiated using the SalesLine. so SalesLineType. After calling the system validation using super().Development IV in Microsoft Dynamics® AX2009 TableType and LineType SalesTable. For a line type of ReturnItem. SalesLine. View the SalesLine. the method has been overridden. 7-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The SalesLine.validateWrite() method: ok = super().Type() method.ValidateWrite() is called. SalesLineType. SalesLineType. After SalesLineType has been instantiated. and PurchLine make use of the InventType construct to control: • What values are acceptable • What happens when any field values are modified • How the different order types. return ok.1 SALES TABLE TYPE Demonstration .SalesLineType 1. For most sales line types.

insert(). } if (ok && salesLine.InitValue().calls SalesLineType.CreateLine(). After calling super() to provide validation for other line types. SalesTable. View the SalesLineType_ReturnItem. SalesLine. show that they all use the inventType sub-classes.Update().returnJournal()) { // Expected return quantity must not be zero ok = checkFailed("@SYS105646").ExpectedRetQty * salesLine. } if (ok && salesLine. creating sales orders within code. This can be used when. For example. Note that SalesLine.SkipUpdate == InterCompanySkipUpdate::No) { // Quantity of returned items orders must be negative. The three table methods that are used: SalesTable.CreateLine() calls SalesLine.ValidateWrite() method: ok = super(_skipCreditLimitCheck).ExpectedRetQty == 0 && salesLine.returnJournal() && salesLine.Insert().Insert() which calls SalesLineType. for instance. These inventType sub-class methods are often called from the system methods on salesLine and salesTable. if (salesLine. Microsoft Official Training Materials for Microsoft Dynamics ® 7-3 Your use of this content is subject to your current services agreement . Chapter 7: Trade 2.Update().SalesQty > 0 && salesLine. and SalesLine. } return ok. The examples below show how a sales order and sales order line are created within code.LineAmount < 0) { //The sign on Quantity and Net amount have to be the same ok = checkFailed("@SYS78848"). ok = checkFailed("@SYS53512"). the method has one additional check to ensure that the quantity of the return line is negative. meaning that instantiating SalesTableType or SalesLineType is not necessary.

initValue().clear(). // Validate NoYes::Yes.numberSequence). salesLine. // searchMarkup NoYes::Yes). NumberSeq = NumberSeq::newGetNumFromCode(SalesParameters::numRefSalesId (). salesTable. NumberSeq NumberSeq. // searchPrice } 7-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . salesLine.ItemId = _itemId. salesTable. ItemId _itemId) { SalesLine salesLine. salesTable. // calcInventQty NoYes::Yes.Development IV in Microsoft Dynamics® AX2009 Example: Create a Sales Order static void createSalesTable(CustAccount _custAccount) { SalesTable salesTable. salesTable. // initFromSalesTable NoYes::Yes. . salesLine. } Example: Create a Sales Line static void createSalesLine(SalesId _salesId.CustAccount = _custAccount.createLine(NoYes::Yes.SalesId = NumberSeq. salesTable. // initFromInventTable NoYes::Yes.num(). salesLine.initFromCustTable(). .insert().SalesId = _salesId.

the SalesFormLetter. they are displayed using the SalesEditLines form. To handle this parm tables are used. the system populates these parm tables. For instance. Microsoft Official Training Materials for Microsoft Dynamics ® 7-5 Your use of this content is subject to your current services agreement .dialog method is called . one record in SalesParmTable per sales order. and then displays them for final adjustments before the posting takes place. based on a class called formLetter (which extends RunBaseBatch). For instance. but if one of the lines is still open.lowestSalesStatus() shows where this is set. the update occurs. use SalesParmUpdate. They are populated when the SalesFormLetter.2 SALESFORMLETTER Orders can be fully or partially updated. Once the parm tables are populated. or Invoiced. The SalesStatus field shows the last sales status posted for the order. For example. Although there are significant differences between what is posted. When a user updates an order. a delivery note update posts the inventory movement. SalesParmTable. then the order is also open. Chapter 7: Trade Post and Print Document Updates Sales and purchase orders go through different stages or sales statuses. of the attached lines. For instance. The status displayed on the sales order is the lowest status. Each update involves different postings. Sales order updates. The table method SalesLine. When the user makes alterations and clicks OK. then the status of the order is delivered. based on the enum SalesStatus. Delivered. and can be updated one order at a time or in a batch of orders. the procedures to perform the update are similar. a sales order can be Open Order. if all lines are delivered. FIGURE 7. and SalesParmLine. and one record in SalesParmLine per line to be updated. with one record in SalesParmUpdate per update. and therefore use a sub-class structure.ChooseLines() method uses the SalesUpdate query to select appropriate salesLines records and populates SalesParmLine accordingly.

proforma()) { journalList = this.run() method: query = this. journalList is a list of documents to be printed later. batchHeader.RecId). 2. 7-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Demonstration .newJournalList().salesTable().num().get(tablenum(SalesParmTable)). while (query. } if (this. The query is then executed: infoLogCounter = infolog.SalesFormLetter 1.queryBuild() builds a query based on SalesParmUpdate and SalesParmTable. } setprefix("@SYS25781"). if (printout == Printout::Current || this.addRuntimeTask(formLetterMultiThread.SalesId) { salesTable = salesParmTable. infolog.next()) { SalesFormLetter.queryBuild(). } salesParmTable = query.SalesId != salesTable.checkIfSalesOrderExist(salesTable)) { try { if (batchHeader) { formLetterMultiThread = FormLetterMultiThread::newFormLetter(this). if (salesParmTable.parmC urrentBatch().this. View the SalesFormLetter.proforma()) { journalList = this.newJournalList(). if (printout == Printout::After && ! this.updateViewSet(this).

3. 4. if (this. If the order is to be posted (that is. this.updateNow()) { this. voucher] = this.createJournal() is then called.Proforma) this. rather in its sub-classes.BatchDependencyStatus::FinishedOrError).ParmId. and a check is made on the sales order. Posting number (e.initFromSalesTotals(salesTotals).SumSalesId.allocateNumAndVoucher().SumBy.insertProforma().documentStatus()). Microsoft Official Training Materials for Microsoft Dynamics ® 7-7 Your use of this content is subject to your current services agreement .insertJournal().UpdateNow() is called.SpecQty.for mLetterMultiThread. salesParmUpdate.getNumAndVoucher(). View the SalesFormLetter. this. salesParmUpdate.addDependency(salesFormLetterEndMultiThread.g. invoice or delivery note) and voucher are created then SalesFormLetter. Order totals and tax totals are calculated: if (salesParmUpdate. The different sub-classes UpdateNow()use a list of SalesParmLine records (created when the order totals were calculated). SalesFormLetter. salesParmUpdate.createJournal() method: salesTotals = SalesTotals::construct( salesParmTable. salesParmUpdate. } else { this. [number.createJournal(). The UpdateNow() method is not implemented in SalesFomrLetter.insertJournal() is called: numberSeq = this. SalesFormLetter. not pro-forma). else this. } } SalesParmTable is retrieved from the query. Chapter 7: Trade batchHeader.postUpdate().

first(salesParmLine).UpdateNow() method: this. 7.initJournal(). salesParmLine. while (salesParmLine) { if (! this. this.updPhysicalUnit(). The ledgerVoucher and ledgerVoucherObject classes are instantiated. recordListSalesParmLine. updateNowInvent = -inventUpd_Physical.initRecordListInventReportDimHistory(). 8.updateInventory(inventMovement).ReduceOnHand).initTransactionTxt().updateInventory () method: inventUpd_Physical = InventUpd_Physical::newSalesPackingSlip( _inventMovement. InventMovement is instantiated using SalesLine.checkDiscardLine()) { CustPackingSlipJour is initialized using values from the update and from SalesTable. inventUpd_Physical. this. The first SalesParmLine from the list is retrieved: inventMovement = InventMovement::construct(salesLine). The physical update to inventory is slightly different depending on which update is made. updateNow = - inventUpd_Physical.updateNow(ledgerVoucher).clear(). View the SalesFormLetter_PackingSlip. Transaction text is initialized. 7-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . salesLine.clear(). transactionTxt = this.initLedgerVoucher(transactionTxt).Development IV in Microsoft Dynamics® AX2009 5. 6. View the SalesFormLetter_PackingSlip. which may be used if posting physical movement to ledger. salesParmLine. salesParmUpdate. number. so the updateInventory() method is overridden in SalesFormLetter_PackingSlip. this.updPhysical().

.writeJournalLine(). The quantity may be reduced due to insufficient inventory. SalesFormLetter_PackingSlip. 11. this.update().InventNow = updateNowInvent.UpdateNow(): if (salesParmLine.writeJournalLine() finalizes CustPackingSlipTrans and commits it to the database: salesLineType = SalesLineType::construct(salesLine). salesParmLine. Chapter 7: Trade InventUpd_Physical posts the physical movement of the inventory. salesParmLine. and is then used to return the actual quantity updated. Microsoft Official Training Materials for Microsoft Dynamics ® 7-9 Your use of this content is subject to your current services agreement . the user is informed and the parm table record is updated to ensure that later updates are correct. this. info(strfmt("@SYS26397". If the quantity is reduced.. } 10.setLineAmount(salesLine). salesParmLine. . salesLineType. salesLine.InventNow != updateNowInvent) { salesParmLine = SalesParmLine::findRecId(salesParmLine.RemainAfter += salesParmLine. true).updateNow)). 9.writeProjTrans(inventMovement).DeliverNow = updateNow. Return to SalesFormLetter_PackingSlip.DeliverNow != updateNow || salesParmLine.updateNow. salesParmLine.DeliverNow .doUpdate().setRemainAfterInvent(). salesParmLine. salesParmLine. qtyReduced = true.updateSalesLine(inventMovement.RecId.transIdSum()).

salesTotals. salesParmUpdate.calc(). } 13. custPckSlpJour.tax()). salesParmUpdate.WriteJournal() finalizes CustPackingSlipJour and commits it to the database.run() method: if (printout == Printout::After && ! salesParmUpdate. this. The status of the SalesLine record is updated (which may also update the SalesTable record): if (qtyReduced) { salesTotals = SalesTotals::construct(salesTable. 15.writeJournal(). this.sendAsXML(). 7-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . this. View the SalesFormLetter_PackingSlip. journalList).writeRecordListInventReportDimHistory(). The following is an example of using SalesFormLetter. 14. salesParmUpdate.updateSalesShippingStat(salesParmTable). SalesFormLetter_PackingSlip. } CustPackingSlipJour. this. salesParmUpdate. If the quantity is reduced.Proforma) this.tax(salesTotals.len() > 0) { if (printFormletter) { this.ParmId. the totals are recalculated and the tax is adjusted: this. Return to the SalesFormLetter.SumSalesId.documentStatus()). The sub-classes override this method so that the specific report can be called.printJournal(). In this case. this.printJournal() contains code that calls the report. If the document is to be printed.printJournal(this. it is called using printJournal().Development IV in Microsoft Dynamics® AX2009 12.SumBy.SpecQty.postMarkupTable().PrintJournal() method: if (journalList. the sales order has been created and will be invoiced.

NoYes::No. The process is similar to posting ledger transactions using the ledgerVoucher. salesFormLetter. LedgerAccount _ledgerAccount) { CustTrans custTrans. //Transaction date SalesUpdate::All. The following example illustrates how a customer transaction could be posted. CustVendVoucher custVoucher. one of the LedgerVoucherTransObject instances is replaced with a CustVendVoucher instance which handles posting to both the AR sub-ledger and the AR ledger account.update( _salesTable. Chapter 7: Trade Example: Posting an Invoice static void createInvoice(SalesTable _salesTable) { SalesFormLetter salesFormLetter. LedgerVoucherObject ledgerVoucherObject. Microsoft Official Training Materials for Microsoft Dynamics ® 7-11 Your use of this content is subject to your current services agreement . This creates the transaction in the sub-ledger and the AR or AP account. //Should document be printed Posting Transactions Customer and vendor transactions can be posted using a ledger journal. //SalesTable record to be posted systemDateGet(). . This can be manually created or created within code. as with a normal daily journal. LedgerVoucherTransObject ledgerVoucherTransObject. but still uses the same LedgerVoucher object. The sales revenue transaction is created elsewhere in the update. Similar to ledger transactions. salesFormLetter = SalesFormLetter::construct(DocumentStatus::Invoice). Example: Posting a Customer Transaction static void createTransActions( NumberSequenceCode _numberSequenceCode. customer and vendor transactions can be posted by using a CustVendVoucher object. NumberSeq numberSeq. CustAccount _custAccount. AmountMst _amountMST. //Which qty should be used AccountOrder::None. SalesFormLetter_Invoice. LedgerVoucher ledgerVoucher. //Is document a proforma NoYes::No).createCustTrans() shows where the invoice posting creates the customer transaction. but here. You must still create transactions in another account to balance the posting. .

NumberSequen ce). SysModule::Cust. ttscommit.Dimension. LedgerPostingType::CustPayment).addTrans(ledgerVoucherTransObject). CustTable::find(_custAccount). CustTable::find(_custAccount). ledgerVoucher. ''. ledgerVoucher. numberSeq = NumberSeq::newGetVoucherFromCode( NumberSequenceTable::find(_numberSequenceCode). ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucherObject. SysModule::Cust. ledgerVoucherObject = LedgerVoucherObject::newVoucher( numberSeq. custVoucher. LedgerTransType::Payment). ledgerVoucherTransObject. _amountMST. CustTable::find(_custAccount).Currency. SystemDateGet(). ledgerVoucher = LedgerVoucher::newLedgerPost( DetailSummary::Detail. } 7-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . custVoucher. ledgerVoucher. custVoucher = CustVendVoucher::construct( SysModule::Cust.Dimension.parmTransTxt("Sales Transaction"). -_amountMST.voucher(). NumberSequenceTable::find(_numberSequenceCode).Development IV in Microsoft Dynamics® AX2009 ttsbegin.NumberSequen ce). LedgerPostingType::CustPayment. 0). LedgerTransTxt::CustPaymentCust.parmTransTxt('Customer Transaction'). _custAccount.AddVoucher(ledgerVoucherObject). _ledgerAccount.post(CustTrans).Currency. CustTable::find(_custAccount).end(). ledgerVoucher.

To mark transactions for settlement. . Settlement takes place in the CustVendSettle class. The class Specification can be used to handle creation of SpecTrans records and also to handle marked transactions. and the settle amount. markForSettlement() on CustTrans and VendTrans can simplify the process further. and using transaction markings. This stores the RecId's of the transactions to be settled. with most of the work done in CustVendSettle. a method.SettleNow(). CustTrans _custTrans2) { CustTable custTable.AccountNum). } Microsoft Official Training Materials for Microsoft Dynamics ® 7-13 Your use of this content is subject to your current services agreement . Additionally. Example: Settling Two Customer Transactions static void createSettlement(CustTrans _custTrans1.markForSettlement(custTrans2). CustTable = CustTable::find(CustTrans1. This method handles settlement using a FIFO principle (oldest invoice gets settled first). Chapter 7: Trade Settlement When customer or vendor invoices are paid the payment transactions and the invoice transactions must be settled against each other to close the transaction. use the SpecTrans table. custTrans1. CustTrans::settleTransact(custTable). The CustSettlement and VendSettlement tables hold each settlement that has taken place and stores the recIds of the transactions that are settled against each other.

Demonstration .accountRelation(accountCode. To set up complicated pricing structures. itemRelation = itemCode == 0 ? itemId : ''. There are different methods for calculating the price: • A line discount • A multi-line discount • A total discount Note that prices cannot be set up for groups of items or all items. accountCode = idx div 3. The Find Next field that can be cleared to stop the calculation from looking for any further prices once it has found one. They are applicable to: • Single items • Single customers • Groups of items • Groups of customers • All items • All customers This means that a single item/customer combination can have multiple prices. Companies often have unique and imaginative pricing structures.findPriceAgreement() method: while (idx < 9) { itemCode = idx mod 3. so the calculation is modified regularly. accountRelation = this. View the PriceDisc. The trade agreement calculation searches through all combinations of item/customer/group/all in a particular order and finds the lowest price. 7-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Trade Agreement Trade agreements are flexible in the way they can be set up. it is important to understand the logic behind the calculation. _priceGroupId).PriceDisc This demonstration shows the calculation for the item price: 1.

ItemCode == itemCode && priceDiscTable. accountCode = 0. while select priceDiscTable index PriceDiscIdx // equals order by QuantityAmount where priceDiscTable.InventDimId == _inventDimId && (discDate >= priceDiscTable.FindLineDisc() and note the item relation is set in the same way as the account relation.FromDate) && (discDate <= priceDiscTable. For both itemCode and accountCode. and validation is performed on the values. priceParameters)) { if (PriceDisc::validateRelation(accountCode.ToDate) { Microsoft Official Training Materials for Microsoft Dynamics ® 7-15 Your use of this content is subject to your current services agreement . The system counts idx from 0 to 9.UnitId == unitID && priceDiscTable. The trade agreement activation is checked to see if this combination is allowed. 1 = group and 2 = all. accountCode = 1 etc. then itemCode = 2. 2. accountRelation) && PriceDisc::validateRelation(itemCode. 0 = table. which means as it loops itemcode = 0. then itemCode = 0. itemCode. and groups to view.FromDate || ! priceDiscTable.ItemRelation == itemRelation && priceDiscTable. customers. then itemCode = 1. accountCode = 0. accountCode. The item relation and account relation are set according to the item code and account code.Currency == currency && priceDiscTable. the itemCode = 1 or 2 is meaningless. Since the system is calculating the price. if (PriceDiscTable::activation(relation.AccountCode == accountCode && priceDiscTable.Relation == relation && priceDiscTable. Look in PriceDisc. accountCode = 0. itemRelation )) { 3. Chapter 7: Trade The idx variable controls which combination of items.ToDate || ! priceDiscTable.AccountRelation == accountRelation && priceDiscTable.

the loop ends. The trade agreement table is searched for the item\customer combination and includes the from. and if there is a price or a miscellaneous charge amount.markup().SearchAgain) { idx = 9. actualPriceTable = priceDiscTable.price(). Data on the price is stored for later retrieval when the final price is located. priceExist = true.date. Concepts such as document updates.Development IV in Microsoft Dynamics® AX2009 4. then continue. calendarDays = priceDiscTable. and if this price is less than any previously found price.and to. using settlements and searching trade agreements should now be familiar.CalendarDays.priceUnit(). If the quantity calculated on the line is greater than any quantity break set up on the trade agreement. Summary In this lesson.DeliveryTime. if (priceDiscTable. 6. if (! priceDiscTable. posting transactions. 7-16 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . deliveryDays = priceDiscTable. break. price = priceDiscTable. Also included is the inventDimId found using active dimensions (as discussed in Chapter 6).calcPriceAmount(absQty) < this. the some of the most commonly used development concepts in the Accounts Receivable and Accounts Payable modules have been introduced.data(). } If the price set to not search for more prices. and developing modifications with them is now possible.calcPriceAmount(absQty) || ! priceExist) { 5. To view the priceDisc class.QuantityAmount <= absQty) { if (priceDiscTable. markup = priceDiscTable. priceUnit = priceDiscTable. refer to the setPriceAgreement.

Chapter 7: Trade Test Your Knowledge 1. What is the name of the class used when posting vendor transactions that handle both posting to the AP sub-ledger and the AP ledger account? Microsoft Official Training Materials for Microsoft Dynamics ® 7-17 Your use of this content is subject to your current services agreement . True or False: SalesLineType is a sub-class of SalesTableType. In which method in SalesFormLetter are the records in SalesParmLine created? 3. 2.

What is 8 div 3? (answer without writing a program to test it!) 7-18 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 4.

Create a new journal header. Challenge Yourself! Create a process that can post a payment transaction for the payment entered into the POS screen. Chapter 7: Trade Lab 7. that have not previously been posted to the ledger. Loop over all POSRegisterTrans records linked to the sales order. See Chapter 1 for details. Need a Little Help? 1. 2. 3.Trade Scenario This is a part of the Point-of-Sale Case Study. 4. Microsoft Official Training Materials for Microsoft Dynamics ® 7-19 Your use of this content is subject to your current services agreement . Flag the payment lines as having been posted to the register. Create a new class and retrieve the sales order id from the caller. 5. and offset to the register holding account. create a journal line for each.1 . The journal lines should post customer account.

amount and payment reference as parameters. b. c. Create a method post the payment lines. o Voucher comes from a class variable.Development IV in Microsoft Dynamics® AX2009 Lab 7. o Use a LedgerJournalName record of type Daily. d. Loop through all unposted register transaction records and call the method to create a journal line for each payment line. Account. Step by Step 1.1 . Get a payment id from a number sequence and stamp each payment transaction.Trade (Solution) Scenario Create a process that can post a payment transaction for the payment entered into the POS screen. f. POSPostPayment: a. o Accept LedgerJournalAccountType. Use this id as the payment reference on the journal line. Create a method to create a LedgerJournalTrans record. Create a new class. e. Override the new method and set a class variable to hold the sales id of the order being processed. 7-20 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Create a method to create a LedgerJournalTable record.

This should be followed by the standard invoice update. Create a new class. See Chapter 1 for details.2 . the payment posting routine should be called. DocumentStatus::Invoice. 2. Call the payment posting class and the invoice posting class when the Post button is clicked. POSPostInvoice that posts an invoice.Payment Posting and Invoice Update Scenario This is a part of the Point-of-Sale Case Study. Instantiate SalesFormLetter. Challenge Yourself! When the OK button on the payment lines screen is clicked. L Microsoft Official Training Materials for Microsoft Dynamics ® 7-21 Your use of this content is subject to your current services agreement . Call SalesFormLetter. 3. 4.Update(). Chapter 7: Trade Lab 7. Need a Little Help? 1.

2 . the payment posting routine should be called. Step by Step 1. This should be followed by the standard invoice update. o Call SalesFormLetter. DocumetnStatus::Invoice. which posts an invoice: o Instantiate SalesFormLetter. 7-22 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 ab 7. o Call the payment posting class and the invoice posting class when the Post button is clicked.Payment Posting and Invoice Update (Solution) Scenario When the OK button on the payment lines screen is clicked. POSPostInvoice.Update(). Create a new class.

2.FindPriceAgreement to look for prices with the CampaignFlag equal to a class variable that is set when the class is instantiated. they should be settled against each other.3 . and should settle against each other no matter what other transactions are open for the customer. 2. Modify the select statement in priceDisc.Settlement Scenario This is a part of the Point-of-Sale Case Study. Ensure that this happens. Need a Little Help? 1. Instantiate the PriceDisc class using the CampaignPrice flag from SalesTable. Post the settlement using CustTrans::SettleTransact(). Need a Little Help? (Optional 1. See Chapter 1 for details. It should only be selected if it is the lowest price available to the customer. Challenge Yourself! When posting an invoice and payment from the POS. Find the invoice and payment transactions and mark them against each other for settlement using CustTrans. Microsoft Official Training Materials for Microsoft Dynamics ® 7-23 Your use of this content is subject to your current services agreement .markForSettlement(). Challenge Yourself! (Optional) Create a Campaign Price flag on the trade agreements that is only selected if a similar flag on the sales order header on the POS screen has been selected. This should happen whether automatic settlement is enabled or not. Chapter 7: Trade Lab 7.

3 (Solution) Scenario When posting an invoice and payment from the POS. o Hint: Use CustTrans::settleTransact(custTable). b. EnumType = NoYes. o Post the settlement. Display the field on forms PriceDiscTable. 2. POSCampaignPrice. 5. o Hint: Use CustTransInvoice. they should be settled against each other. Modify static method newFromSalesPurchLine() to look at the flag on SalesTable and pass as a parameter in the new() method. 3. c. o Find the payment customer transaction associated with the order (you can use the payment id). Create a new class variable. CampaignPrice. Step by Step (Optional) 1. and Sales Table.markForSettlement(custTable). Ensure that this happens. Set this variable in the new method from a parameter. In the PriceDisc class: a.markForSettlement(custTable). 4. o Mark each transaction to be settled against each other. Create a new enum EDT. type = NoYes. to tables SalesTable and PriceDiscTable. Create a new class POSSettlement: o Find the invoice customer transaction associated with the sales order. o CustTransPayment. and should settle against each other no matter what other transactions are open for the customer. This should happen whether automatic settlement is enabled or not. Add a new field CampaignPrice.Development IV in Microsoft Dynamics® AX2009 Lab 7. Step by Step 1. 7-24 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Modify the select statement in the findPriceAgreement method to only find campaign prices when this variable is set.

3. 2. Microsoft Official Training Materials for Microsoft Dynamics ® 7-25 Your use of this content is subject to your current services agreement . Chapter 7: Trade Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1.

CreateParmLine() 3. True or False: SalesLineType is a sub-class of SalesTableType. MODEL ANSWER: False 2. In which method in SalesFormLetter are the records in SalesParmLine created? MODEL ANSWER: SalesFormLetter. What is 8 div 3? (answer without writing a program to test it!) MODEL ANSWER: Two 7-26 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Solutions Test Your Knowledge 1. What is the name of the class used when posting vendor transactions that handle both posting to the AP sub-ledger and the AP ledger account? MODEL ANSWER: CustVendVoucher 4.

there are useful classes and methods written that help you achieve excellent results. Microsoft Official Training Materials for Microsoft Dynamics ® 8-1 Your use of this content is subject to your current services agreement . Chapter 8: Inventory CHAPTER 8: INVENTORY Objectives The objectives are: • Create and post inventory journals • Use inventory dimensions • Use InventSum • Use InventMovement • Use InventUpdate Introduction Similar to Ledger. This lesson discusses both creating and posting inventory transactions. and using the data correctly after it has been posted. Unlike the ledger module. Although they may seem complicated to use. Inventory is closely linked to many modules within Microsoft Dynamics® AX and is a vital module to understand. This lesson introduces some of the classes used to manipulate inventory data. A significant part of the inventory module is its inventory dimensions. modifications to the inventory system can be significant with regard to the work required.

InventJournalTable is the header record for the journal. Post the journal. There can be more than one InventJournalName per type. Procedure: Creating an Inventory Journal Use the following steps to create an inventory journal: 1. the tables used are InventJournalName. such as profit\loss and transfer.Development IV in Microsoft Dynamics® AX2009 Scenario Isaac. Create a journal table record or use an existing one. InventJournalTrans contains data used to create the individual transactions that will be posted. InventJournalName contains the default data for a specific journal type. There can be one or more lines per journal. This checks the journal before posting. A detailed description of these steps follows. Create lines for each transaction to be posted. This step is omitted if the journal is checked by the user before posting. the Systems Developer. InventJournalTable. To be able to do this he must understand how the inventory system works in Microsoft Dynamics AX. 3. has been asked to add a field on the sales order that shows the current on-hand inventory of an item. and InventJournalTrans. Set the journal type according to the posting you require. based on the visible inventory dimensions. Inventory Journals Inventory Journals are similar to Ledger Journals and can be created in a similar way. There is one record per journal. 8-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Tables In the inentory module. Application elements are similar in design but are physically different elements. 2.

Run validate and post highlights errors. Post indicates that after checking to post to the journal.MovementJournalNameId). because transactions are assigned to one of the journals • InventJournalTrans. check and post the journal using the InventJournalCheckPost class. You must fill the record with data and then insert it. Creating Lines All transactions must be posted in the journal lines table. InventJournalTable. _InventJournalTable – Record in InventJournalTable representing the journal to receive the posting. use a journal name record to get the default data. Parameters for this method are: _journalCheckPostType – Check or post parameter for specifying whether to check a journal only or check and post. Look in the InventJournalTable.insert(). There are two important fields to be filled every time you insert a new record: • InventJournalTrans.Insert() table method.JournalId which is mandatory. InventJournalTable. The journal name is commonly set either from a parameter or by prompting the user to enter it in a dialog. and then manually opening the journal in the journal forms.Voucher which is the transaction voucher number Other fields in the transaction table are mandatory according to the journal types and should be filled as necessary. Posting Journals After transactions are created in the journal. Create an instance of this class using newJournalCheckPost static method and then run the class. test the code by letting it create a journal. Chapter 8: Inventory Creating the Journal Header To create a new journal. Use a journal name of an appropriate type. While developing.Name = 'Movement Journal'. Microsoft Official Training Materials for Microsoft Dynamics ® 8-3 Your use of this content is subject to your current services agreement . InventJournalTable.InitFromInventJournalName(InventJournalN ame). which is the primary key defining the relationship between the journal table and the lines. xInventJournalName = InventJournalName::find( InventParameters::find(). Note that it handles the creation of the journal number.

CheckPost = InventJournalCheckPost::newJournalCheckPost( journalCheckPostType::Post. pallet. They define whether an item is tracked by: • Storage dimension. This table is a temporary table created according to which dimensions are in use. batch number. and each combination can be assigned an ID number. There is one record per inventory dimension per dimension group.findOrCreate() method looks for a particular combination. The InventDim. size. } Inventory Dimensions Inventory dimensions are a powerful. and efficient way to track variations in inventory movements. This offers many possibilities when grouping and summing data. versatile. location. (warehouse. Void PostJournal(InventJournalTable _InventJournalTable) { InventJournalCheckPost CheckPost.Development IV in Microsoft Dynamics® AX2009 The following example shows how to post an inventory journal. or configuration) There are a finite number of combinations of inventory dimensions. Tables Available tables are defined as follows: InventDim holds every combination of inventory dimensions used in the system and the corresponding inventDimId. InventDimSetup sets up each dimension group. 8-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . _InventJournalTable) CheckPost. rather than every dimension. InventDimGroup groups items by inventory dimensions used.run(). Any reference to a particular combination of dimensions can be referred to by the ID number. and creates it if it does not exist. InventDimParm flags which dimensions to use in different situations. or serial number) • Item dimension (color.

InventDimSearch creates a list of InventDimSetup records in a list and iterates through it. InventDimParm. View the InventDimSearch::financialInvent() method: static void financialInvent(InventDimGroupId _dimGroupId. } A static method on InventDimSearch is called. } Microsoft Official Training Materials for Microsoft Dynamics ® 8-5 Your use of this content is subject to your current services agreement .initFinancialInvent() is used.dimSearc hBase(). Chapter 8: Inventory Classes The available classes include: InventDimGlobal is a global class that holds a cache of dimension field ids and names. InventDimOnHand finds current inventory levels for specific dimensions. 1.data(classfactory. this). Procedure: Creating InventDimParm To create the correct InventDimParm record. The method being analyzed is InventDimParm.CalcCostValue() method to determine which dimensions to use when calculating cost value.InitFinancialInvent() method: void initFinancialInvent(InventDimGroupId _dimGroupId) { . View the InventDimParm.inventDimGlobal(). 2.clear(). InventDimSearch::financialInvent(_dimGroupId. This example illustrates how InventDimSearch is used to create an InventDimParm record.financialInvent(_dimGroupId)). in the InventTrans. the system needs to look at the dimension group for an item.initFinancialInvent(). InventDimParm _inventDimParm) { if (_dimGroupId) _inventDimParm. for example. This method will set the flags for each inventory dimension that financial inventory option checked. The flags on the InventDimParm record need to be set according to the situation in which it will be used. This is used mainly by InventDimSearch. else _inventDimParm.

initInventDimCache(_groupId).dimFinancialInvent()) { inventDimParmFinancialInvent. } 8-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .first() is called. then the InventDimParm flag for this dimension is set to Yes. If not. and if both are true. and placed in the global cache.Development IV in Microsoft Dynamics® AX2009 If a dimension group is specified. and the value is an InventDimParm record holding the values for each inventory dimension.lookup(_groupId).dimActive() && _dimSearch.first(_dimGroupId)) do { After initializing the various maps that are used. 3.(y) = NoYes::Yes. The first time it is accessed. This iterates through a list of the inventory dimensions that are active. The key is the group id.exists(_groupId)) this. View InventDimSearchBase.initInventDimCache() if (_dimSearch.dimFieldId(). if (_dimSearch. 5. the InventDmParm record is set to the values returned by the method InventDimSearchBase. View InventDimSeachBase. In this method.financialInvent(). the map is checked to see if the values have already been created for this group. The following code shows where the flags for the dimension being active and to post financial inventory are examined. Note the use of the global cache for inventory dimension setup data.financialInvent() public InventDimParm financialInvent(InventDimGroupId _groupId) { if (!_groupId) return null. then it will call the method to initialize these values. Additionally the field id which is used to refer to which dimension this is for is stored in a container. conFinancialInventFields += _dimSearch. 4. if (!financialInvent. InventDimSearch. Inventory dimensions are made inactive through the application configuration keys. } financialInvent is a map that contains the setup data for each group for the financial inventory. Many setup options are examined. return financialInvent. all the possible lookups for that specific inventory dimension group are found and stored in maps.

inventDimParmFinancialInvent). Microsoft Official Training Materials for Microsoft Dynamics ® 8-7 Your use of this content is subject to your current services agreement . the system: 1. The method being analyzed is PriceDisc. Example: Using InventDimParm This example shows how to use InventDim and InventDimParm. configuration). This method is used.1 ITEM NUMBER Prices are created for sizes allowed for this item. For sales prices. Also create sales prices for the different dimensions.findPrice(). for example. as shown Select main menu>inventory management>items>general tab FIGURE 8. colour. financialInvent. Searches for a match of the dimensions on the sales line to the dimensions on the price. 2. when setting the sales price on a sales line. Searches for a match of only item dimensions (size.insert(_dimGroupId. Chapter 8: Inventory 6. Use an item with a dimension group containing dimensions set to Use in price search. The InventDimParm record is then stored in the map to make further lookups quicker due to not having to go to the database to retrieve the data. The Use in sales price search flag means that when looking for a price for the item.

Development IV in Microsoft Dynamics® AX2009

3. Searches for a price with blank dimensions.
4. It ignores dimensions altogether.

When entered into sales lines, the price is calculated using the size set on the line:

Procedure - Using InventDimParm
The PriceDisc class is instantiated in the SalesPurchLine.setPriceAgreement()
method. SalesPurchLine is a table map. The itemId and inventDim record of the
sales line is passed into the class at this point.

1. View the PriceDisc.FindPrice() method. Look for the following
code:

switch (moduleType)
{
case ModuleInventPurchSales::Purch:

inventDimAllActivated.copyActivatePurchPriceAll(inventTable
.DimGroupId, inventDim);
break;
case ModuleInventPurchSales::Sales:

inventDimAllActivated.copyActivateSalesPriceAll(inventTable
.DimGroupId, inventDim);
break;
default:

inventDimAllActivated.copyItemDim(inventTable.DimGroupId,
inventDim);
}

For moduleType = sales, calls inventDimParmAll.copyActivateSalesPriceAll()
(InventDimParmAll is instance of InventDimParm).

2. View the InventDimParm.copyActivateSalesPriceAll() method:

container dimFields =
InventDimSearch::activateSalesPriceAllFields(_dimGroupId);
;
len = conlen(dimFields);
for (h=1;h<=len;h++)
{
x = conpeek(dimFields, h);
this.(x) = _fromInventDim.(x);
}

The static method to initialize or retrieve the cached InventDimParm record for
this group, that has the flags set for all dimensions that has the Sales Price option
set, is called. The return value is used to determine which fields to use from the
InventDim record that is referenced on the sales line.

8-8 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Chapter 8: Inventory

3. Return to the PriceDisc.findPrice() method:

inventDimItemDimActivated.copyItemDim(inventTable.DimGroupI
d, inventDimAllActivated);

InventDimItemDimActivated is copied from the InventDimAllActivated but only
copies the fields that are item dimensions (color, size, or configuration).

Two InventDim records remain; one holding all values of dimensions only
applicable to the sales price search, and another holding values of item
dimensions applicable to the sales price search.

findAll =
!InventDim::isInventDimEqual(inventDimAllActivated,
inventDimItemDimActivated);
findItemDim =
!InventDim::isInventDimEqual(inventDimItemDimActivated,inve
ntDimNoneActivated);

findAll is set if InventDimAllActiviated = InventDimItemDimActivated.

findItemDim is set if InventDimItemDimActivated is blank.

inventDimAllActivated = findAll ?
InventDim::findDim(inventDimAllActivated) :
inventDimAllActivated;
inventDimItemDimActivated = findItemDim ?
InventDim::findDim(inventDimItemDimActivated) :
inventDimItemDimActivated;

If findAll = true, an existing InventDim record is searched for and placed in
InventDimAllActivated.

If findItemDim = true, an existing InventDim record is searched for and placed in
InventDimItemDimActivated.

return ((findAll && inventDimAllActivated.RecId &&
this.findPriceAgreement(_priceGroupId,
inventDimAllActivated.InventDimId)) ||
(findItemDim && inventDimItemDimActivated.RecId &&
this.findPriceAgreement(_priceGroupId,
inventDimItemDimActivated.InventDimId)) ||

this.findPriceAgreement(_priceGroupId,
InventDim::inventDimIdBlank()) ||
(_useItemPrice && this.findItemPrice()));

Search for a price with the inventory dimension id for the InventDimAllActivated
record. All inventory dimensions match if the found method returns true.

Microsoft Official Training Materials for Microsoft Dynamics ® 8-9
Your use of this content is subject to your current services agreement

Development IV in Microsoft Dynamics® AX2009

Then, search for a price with the item dimension. If a price is found, the method
returns true.

Then, search for a price with blank item dimensions. If a price is found, the
method returns true.

Finally, search for a price ignoring dimensions all together. If a price is found,
the method returns true.

InventSum
InventSum can be regarded as one of the most important tables in Microsoft
Dynamics AX. It is used to store current values of on-hand inventory. Any
function that creates an inventory transaction, including creating, updating or
deleting a sales line, purchase order line, inventory journal line or production
order, will cause an update to InventSum.

Due to the high number of processes that can update InventSum, optimistic
locking of InventSum is not appropriate. It is likely that a process that has
retrieved an InventSum record, is then going to update it. View the properties of
the table and note that the Occ property is set to No.

Instead, any changes to InventSum, are temporarily stored in another table,
InventSumDelta, and are only applied to InventSum when the current transaction
is committed. This ensures that InventSum records are locked for only a short
amount of time.

Tables
Tables that are associated with InventSum operations are as follows:

InventSum contains current inventory levels per item per inventory dimension
combination.

InventSumDelta contains information about on-hand changes that are not yet
committed to the database.

InventTrans automatically updates InventSum whenever a record is created,
updated, or deleted.

Classes
There are many classes used to retrieve data from InventSum. Some examples
are as follows:

InventOnHand contains calculations for finding inventory levels for different
inventory dimensions.

InventSumDate calculates the inventory level on a particular date.

8-10 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Chapter 8: Inventory

Invent Macros
There are some useful macros available when using InventSum:

#InventDimExistsJoin joins any other table, commonly InventSum, to InventDim
when related to InventDim through InventDimId. It uses InventDimParm to flag
the dimensions included in the join. The exists join improves performance and
should only be used if the joined InventDim record will not be used later in the
code.

#InventDimSelect selects records in InventDim according to the flags in
InventDimParm. This is used with a join to another table, commonly InventSum.

Demonstration - Code Walkthrough - Updating InventSum
The following walkthrough demonstrates how the system updates InventSum:

1. View the InventTrans.Insert() method:

if (InventSum::mustInventTransBeUpdated(this))
{
inventSum.initFromInventTrans(this);
inventSum.updateInventTrans(this,NoYes::Yes);
}

inventSum::mustInventTransBeUpdated() returns true if fields relevant to the
update of InventSum have been modified.

inventSum.initFromInventTrans() sets inventSum.itemId and
inventSum.inventDimId from inventTrans.

inventSum.updateInventTrans() is called passing the InventTrans record.

2. View the InventSum.updateInventTrans() method:

if (plus)
inventSum.addInventTransOnSum(inventTrans);
else
inventSum.subInventTransOnSum(inventTrans);

This method is called from the inventTrans.insert(), inventTrans.update() and
inventTrans.delete(). When it is called from inventTrans.insert() and
inventTrans.update(), the plus parameter is set to true. When it is called from
inventTrans.delete(), the plus parameter is set to false. This controls whether the
values in inventTrans are added or subtracted from InventSum.

Microsoft Official Training Materials for Microsoft Dynamics ® 8-11
Your use of this content is subject to your current services agreement

Qty.ReservOrdered-= inventTrans.Qty. This is due to the frequency with which it is contructed.StatusIssue) { case StatusIssue::Sold: this.AddInventTransOnSum() method: switch(inventTrans.initFromInventSum(inventSum). The inventUpdateOnHand. 5. break. View the method application.updateInventTrans method: inventSumDelta.OnOrder -= inventTrans. 4. case StatusIssue::OnOrder: this.Qty.addInv entSumDelta(inventSumDelta.inventUpdateOnhand().Development IV in Microsoft Dynamics® AX2009 3. View the InventSum. case StatusIssue::ReservPhysical: this. break.Qty. The inventUpdateOnHand class is a class held in the global cache. inventSumDelta. Return to the inventSum.Qty. break.initFromInventTrans(inventTrans). default: } According to the status of the InventTrans record.ttsNotifyPreCommit().ReservPhysical-= inventTrans. case StatusIssue::Deducted: this.inventUpdateOnhandGlobal().Qty. break. break.Deducted -= inventTrans.Picked -= inventTrans. case StatusIssue::Picked: this. case StatusIssue::QuotationIssue: this.ttsNotifyPreCommit() this.inventUpdateOnhandGlobal(). break. This method is called during a ttsCommit by the system classes that commit a transaction to the database. appl.inventUpdateOnHand() method sets the current ttsId on the InventSumDelta record and then inserts the record in the database. 8-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .inventTrans).Qty.QuotationIssue-= inventTrans. break. case StatusIssue::ReservOrdered: this.PostedQty += inventTrans. specific fields in InventSum are updated. The inventSumDelta record is updated using data from inventTrans and inventSum.

Chapter 8: Inventory

6. View the method
InventUpdateOnHandGlobal.ttsNotifyPreCommit(). The method
changes company in the case that some of the transaction has been
performed in another company. In each company it calls the
following code.

inventUpdateOnhandMap.lookup(newExt).ttsNotifyPreCommit()

This finds the global instance of the class InventUpdateOnHand and calls the
ttsNotifyPreCommit() method.

7. View the method InventUpdateOnHand.ttsNotifyPreCommit(). The
two method calls to note called from here are as follows:
8. View the method InventUpdateOnHand.insertInventSum()

while select ItemId, InventDimId from inventSumDelta
group by ItemId, InventDimId

where inventSumDelta.ttsId == this.tTSId() &&
inventSumDelta.IsAggregated ==
NoYes::No
notexists join inventSum

where inventSum.ItemId ==
inventSumDelta.ItemId &&
inventSum.InventDimId ==
inventSumDelta.InventDimId

All records in InventSumDelta that were created in the current transaction and do
not have a related InventSum record, are retrieved. An InventSum record created
based on the InventSumDelta record and is added to a recordInsertList. When all
records have been added to the list, the records are committed to the database.

9. View the method InventUpdateOnHand.updateInventSum(). If only
one record is to be updated from InventSumDelta to InventSum, the
updateInventSumSimple() method is called. This method adds the
InventSumDelta record values to InventSum. If more than one
update is needed, the updateInventSumAdvance() method is called.

if (inventSumDeltaCnt == 1)
this.updateInventSumSimple();
else
this.updateInventSumAdvanced();

Microsoft Official Training Materials for Microsoft Dynamics ® 8-13
Your use of this content is subject to your current services agreement

Development IV in Microsoft Dynamics® AX2009

10. View the method
InventUpdateOnHand.UpdateInventSumAdvanced(). This method
calls the method InventUpudateOnHand.sqlupdateStr(). This method
builds a direct SQL statement that will add all InventSumDelta
records to the corresponding InventSum records in one call to the
database. This ensures that the performance of the write operation to
the database is maximized and the InventSum records are locked for
as short a time as possible.

container con = this.sqlUpdateStr();
Integer i;
str statement;
SqlStatementExecutePermission permission;
;
//Call updates in a cycle for all generated statements
for (i=1;i<=conlen(con);i++)
{
statement = any2str(conpeek(con,i));
permission = new
SqlStatementExecutePermission(statement);
permission.assert();

//BP Deviation documented
new
Connection().createStatement().executeUpdate(statement);
permission = null;
}

When building the SQL statement string, the system uses the field groups called
DeltaFields on InventSum and InventSumDelta to determine which fields need to
be updated. If you need to add more fields to InventSum, and therefore
InventSumDelta, you do not need to alter the SQL statement. Simply add the
fields to the field groups and the code will handle the update for you.

Demonstration - Code Walkthrough - Using InventOnHand
The following demonstrates how to use InventOnHand:

1. View the static method InventOnHand::newInventDim():

InventOnhand inventOnhand = new InventOnhand();
;

inventOnhand.parmInventDim(_inventDim);
inventOnhand.parmInventDimParm(_inventDimParm);
inventOnhand.parmItemId(_itemId);

return inventOnhand;

The class is instantiated and InventDim, InventDimParm, and ItemId class
variables are set from the parameters. There are other constructor methods
available, all of which set different parameters to calculate the InventSum record.

8-14 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Chapter 8: Inventory

2. View the InventOnHand.ReservePhysical() method:

this.setInventSum();

return inventSum.ReservPhysical;

The method returns the value of InventSum.ReservPhysical; however, this value
is first calculated with InventOnHand.setInventSum().

3. View the InventOnHand.setInventSum() method:

if (sumRead)
return;

this.findSumJoin();

sumRead = true;

If the calculation has not already been made, InventOnHand.findSumJoin() is
called.

4. View the InventOnHand.findSumJoin() method:

if (inventDimId)
{
inventSum = InventSum::find(itemId,inventDimId);
}
else if (inventDimParm.ItemIdFlag)
{
inventSum = InventSum::findSum(itemId,
inventDimCriteria, inventDimParm, InventSumFields::All);
}

If an InventDimId is specified the InventSum record is found.

If inventory values for a specific itemId are needed, InventSum::findSum() is
called.

5. View the InventSum::findSum() method:

if (_inventDimParm.InventSerialIdFlag &&
_inventDimCriteria.InventSerialId)
{
switch (_sumFields)
{

Different select statements are used because of performance differences between
the dimensions. For example, when a serial number dimension is enabled, the
serial number is unique to an item, whereas a warehouse dimension is used by all
items.

Microsoft Official Training Materials for Microsoft Dynamics ® 8-15
Your use of this content is subject to your current services agreement

Development IV in Microsoft Dynamics® AX2009

The method selects InventSum, summing the relevant fields (financial, physical,
or all). The join to InventDim ensures all relevant records in InventSum are
summed.

6. Return to the InventOnHand.FindSumJoin() method:

Again, different select statements are used depending on what data is required. If
only the Pallet Id is required, the select statement is different from when any
other dimensions are required.

After the InventSum agregrated record has been calculated, the InventSumDelta
records need to be included. The addInventSumDelta() method is called.

this.addInventSumDelta();

7. View the InventOnHand.addInventSumDelta() method.

if (!itemId ||
InventUpdateOnhandGlobal::mustAddInventSumDeltaOnhand(itemI
d))
inventSum.addInventSumDelta(this.findSumJoinDelta());

If the item has records in InventSumDelta, the inventSum.addInventSumDelta
method is called. This method adds an InventSumDelta record to InventSum. The
InventSumDelta record is found in the InventOnHand.findSumJoinDelta()
method.

8. View InventOnHand.findSumJoinDelta() method.

if (inventDimId)
{
inventSumDelta =
InventSumDelta::findSumDeltaDimId(itemId,inventDimId,Invent
SumFields::All);
}
else if (inventDimParm.ItemIdFlag)
{
inventSumDelta =
InventSumDelta::findSumDelta(itemId,inventDimCriteria,inven
tDimParm,InventSumFields::All);
}

Similar to the InventOnHandFindSumJoin() method, this method retrieves an
agregated InventSumDelta record based on the dimensions required.

8-16 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

6. Note the following 1.1 – On-hand Inventory on Sales Order Form Scenario Issac. Instantiate using newParameters static method. return inventOnHand. 2. 4. Create a display method on the SalesLine datasource in SalesTable form. InventOnhand = InventOnhand::newParameters(_salesLine. InventOnHand. element.inventDimSetupObject().inventDim(). Chapter 8: Inventory Lab 8. . has been asked to display the current on hand inventory levels on the Sales Order form. Use the InventOnHand class. InventOnHand.parmDimParmVisibleGrid() for InventDimParm.availPhysical(). 5. the systems developer. 3. Add field to sales line using the display method. display inventQty availPhysical(SalesLine _SalesLine) { InventOnhand InventOnhand. _salesLine. 2.parmDimParmVisibleGrid returns the InventDimParm for the visible inventory dimensions. Use inventDimFormSetup.ItemId. The quantity displayed should be based on the item id and any inventory dimensions that are shown in the grid. There should be a single field displaying the physically available quantity and it should automtically adjust if the user modifies the dimensions that are displayed. InventDimFormSetup.AvailPhysical() returns the quantity available. Challenge Yourself! Create a display method on the SalesLine data source to return the physcally avaiable inventory based on the current inventory dimensions that are displayed. } Microsoft Official Training Materials for Microsoft Dynamics ® 8-17 Your use of this content is subject to your current services agreement .availPhysical() returns available quantity. Step by Step 1.parmDimParmVisibleGrid()).

InventMovement is instantiated using SalesLine passed in through the buffer parameter. For instance.2 INVENTMOVEMENT STRUCTURE Any lines that can have inventory transactions attached.InventMovement When a sales line item is modified. The sub-classes control how the updates differ. SalesLines. It is similar to a data carrier used by other classes when updating inventory data. Demonstration . it is used to find if and where to post to Ledger. 1.modified()method calls the static method InventMovement::bufferSetTransQtyUnit(salesLine). InventJournalTrans. View the InventMovement::bufferSetTransQtyUnit() method: InventMovement movement = InventMovement::construct(buffer). The following figure shows the hierarchy tree for the InventMovementClass FIGURE 8. 8-18 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 InventMovement Use the InventMovement class and subclasses to check and prepare data to update inventory transactions.Code Walkthrough . can be used in the construct method of the class. the quantity field is set according to certain parameters. and the appropriate sub-class is instantiated accordingly. PurchLines. On the SalesTable form. for example.ItemId. the SalesLine_ds.

transUnitId()methods. 4. Others. so InventMov_Sales is instantiated. Chapter 8: Inventory 2. if (!movement) throw error("@SYS20765").InventTable::inventDecimals(movement.setTransQtyUnit(qty). Return to the InventMovement::bufferSetTransQtyUnit() method: qty = UnitConvert::qty(movement. Note this method tests the table id of the record that it was called with and instantiates the relevant sub-class of InventMovement. return movement. Note that theses methods return the value of a field from the SalesLine record used to instantiate the class.inventTable(). 3. Using this method enables the same methods to be used throughout the application when creating and updating inventory transactions. can instantiate different sub-classes depending on values of certain fields. The quantity is set according to the values returned from the movement. When instantiating the class. you can throw an error if the class cannot be instantiated.transUnitId().transQtyUnit(). View the InventMovement::Construct() method: InventMovement movement = InventMovement::constructNoThrow(buffer.transQtyUnit(). View the InventMovement:ConstructNoThrow() method: case tablenum(SalesLine) : return new InventMov_Sales(buffer). movement. such as SalesPickingListJournalLine have their own methods written for instantiating InventMovement.inventUnitId().childBuffer ).JournalType.setTransQty(qty). call InventMovement::ConstructNoThrow directly. movement.tr ansUnitId())). movement. movement. If you do no want to throw an error.subType.itemId()) ). movement.and so on. Some tables. In this example the table is SalesLines. qty = decround(qty.Unit::decimals(movement. such as InventJournalTrans.itemId() ). like InventJournalTrans.transQtyUnit(). qty = decround(movement. movement. Microsoft Official Training Materials for Microsoft Dynamics ® 8-19 Your use of this content is subject to your current services agreement .

3 INVENT UPDATE STRUCTURE The class and subclasses are related to the base enums for inventory receipts and issues.4 ISSUE STATUS 8-20 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The following figure shows the hierarchy tree for InventMovement: FIGURE 8.Development IV in Microsoft Dynamics® AX2009 InventUpdate InventUpdate is the class that creates and updates inventory transactions and is always used in conjunction with InventMovement. The following figure shows the Issue Status: FIGURE 8.

Once the class has been instantiated. salesParmSubLine. The sub classes are used for different types of required updates. Demonstration: Code Walkthrough . The value of the inventory posts to the inventory account and the inventory transaction is stamped with a financial date. Chapter 8: Inventory The following figure shows the Receipt Status: FIGURE 8. The following procedure demonstrate how to use InventUpdate: 1. number. rather than using a constructor on the super class. ledgerVoucher. InventUpd_Reservation reserves an outflow against an inflow. others have static methods that can be used in certain circumstances. Some of the sub-classes should be instantiated using the new() method.updateInventory() method: inventUpd_Financial = InventUpd_Financial::newSalesInvoice(_inventMovement. the inventory is received or shipped. View the SalesFormLetter_Invoice. in other words. for example. localSalesParmLine.InventUpdate SalesFormLetter_Invoice. InventUpd_Physical posts the physical movement of the inventory. calling updateNow() posts the required update. InventUpd_Estimated creates the initial transaction when. a salesLine is created.5 RECEIPT STATUS The class and subclasses are instantiated directly. Microsoft Official Training Materials for Microsoft Dynamics ® 8-21 Your use of this content is subject to your current services agreement .updateInventory() posts the financial movement of a sales line.

which has previously been instantiated with SalesLine. InventUpd_Financial is instantiated using InventMovement. 2. if (physical || remainPhysical != movement. ledgerVoucher.lastTransDate(). If the transaction has not physically posted.parmCostAmountCur(). localInvoiceUpdatedOnly += - inventUpd_Financial.0 && movement. this. which contains the voucher number for posting the ledger transactions. View the InventUpdFinancial.ReduceOnHand). physicalUnit.mustBeDeducted()) { throw error("@SYS117598").updFinancialUnit().parmCurrencyCode(). 8-22 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . LedgerVoucher.updateNow(). physical. localUpdateNow += - inventUpd_Financial. } inventUpd_Physical = InventUpd_Physical::newInventUpdFinancial(movement. inventUpd_Financial. } if (financial < 0.UpdateNow() method. Currency::mstAmount(this. InventUpdFinancial. localUpdateNowInvent += - inventUpd_Financial. this is done first.updPhysicalUnit().remainPhysical() || physicalUnit || remainPhysicalUnit != movement. Number.mustBeReceived()) { throw error("@SYS117599"). this.updFinancial(). and SalesParmLine which holds the quantity and amounts to update.Development IV in Microsoft Dynamics® AX2009 salesParmUpdate.UpdateNow() posts the transaction.0 && movement.remainPhysicalUnit()) { if (financial > 0. which is the invoice number.

updateLedgerFinancial(ledgerVoucher. Chapter 8: Inventory this. Some values.parmExchRatesTriangulation().lastTransDate() .parmExchRateSecondary())). this.updateInventTransPosting(ledgerVoucher.RemainSalesFinancial are updated to reflect the values that have been posted. Calculate the cost value of the transaction and post to the general ledger: costAmountMST = movement.lastVoucher()). ledgerVoucher. if (financial < 0) { this. Create a reference to the posting in InventTransPosting: this.parmExchRate().updateInventTransPosting(ledgerVoucher.lastTransDate() . Some values.lastVoucher()).RemainSalesFinancial are updated to reflect the values that have been posted. this). Some checking is then performed using inventMovement. Microsoft Official Training Materials for Microsoft Dynamics ® 8-23 Your use of this content is subject to your current services agreement . ledgerVoucher. such as SalesLine. such as SalesLine.updateFinancialIssue(costAmountMST). } } Create a reference to the posting in InventTransPosting: this. this.updateFinancialReceipt(costAmountMST). } else { if (financial > 0) { this.

reserveQty. reservation = InventUpd_Reservation::newMovement(movement. Inventory is closely linked to many modules within Microsoft Dynamics AX. InventMovement movement. } The InventUpd_Reservation class is instantiated using InventMovement. This lesson demonstrate both creating and posting inventory transactions. the quantity should be negative. It is not possible to reserve more than what is ordered from the sales order line. use the InventUpd_Rservation class: void SalesReserveQty(SalesLine _salesLine.updateNow(). true) reservation. To reserve more against an outflow. movement = InventMovement::construct(_salesLine). .Development IV in Microsoft Dynamics® AX2009 InventUpd_Reservation To reserve incoming inventory against an outflow. this lesson introduces some of the classes used to manipulate inventory data. In addition. Summary Similar to Ledger. Modifications to the inventory system can be significant with regard to work required. The second parameter determines the additional quantity to be reserved. 8-24 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . and using the data correctly after it has been posted. InventQty _reserveQty) { InventUpd_Reservation reservation. You can unreserve by specifying a positive amount.

In which method is an InventDim record created? 3. Which class is used to create inventory transactions? Microsoft Official Training Materials for Microsoft Dynamics ® 8-25 Your use of this content is subject to your current services agreement . Chapter 8: Inventory Test Your Knowledge 1. Is the InventDimParm table a temporary table? 2.

Why has the Inventory Multi-transaction Tracking system been introduced? 5.Development IV in Microsoft Dynamics® AX2009 4. 8-26 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . True or false: An InventDimId is always unique to an itemId.

9. The batch job should reallocate any reserved inventory to the sales lines based on classification. Display all new fields on relevant forms. Write a routine that unreserves all open orders. ReservationClassification. The classification should be copied to the sales table and sales line. EnumType = ABC. 5. Create a new class to reserve items according to classification.ReservationClassification is initialized from CustTable. 10. After all open lines are unreserved. To achieve this he should add a Reservation ABC classification field to the customer table. has been asked by the Sales department to create a job that will allocate inventory based on an ABC classification set on the customer. type = ReservationClassifcation to CustTable. SalesTable and SalesLine. Use InventTransIdSum to find the quantity reserved. Chapter 8: Inventory Lab 8. Find all open sales order lines. 3. The RecordSortedList should sort by ReservationClassifcation. System reserves remaining quantity. 7. or available quantity. Attempting to reserve the total quantity on a line reserves any that are available to be reserved. 6. Microsoft Official Training Materials for Microsoft Dynamics ® 8-27 Your use of this content is subject to your current services agreement .ReservationClassificaition. 8. 2. Add open lines to a RecordSortedList while looping. 3. Create new Enum EDT. iterate through the list and attempt to reserve the sales quantity for each line. and then reserve according to the classification. Use InventTransIdSum to find the existing reserved quantity. Add new field. 2. Challenge Yourself! 1. Reserving a negative quantity removes the reservation. then createdDate.ReservationClassificaition. the systems developer. Remove any reservations on the lines by reserving a negative quantity of what is already reserved. Ensure SalesTable.ReservationClassification is initialized from SalesTable. 4.2 – Create an ABC allocation Scenario Isaac. Step by Step 1. 4. Ensure SalesLine.

Add menu item button to call action item InventDimParmFixed. Use same functionality as in SalesTable form. 2. Declare a form instance of InventDimCtrl_Frm_Mov. 8-28 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Add a method UpdateDesign.Display inventory dimensions Scenario Add inventory dimensions to the POS form. 4. 5.3 – POS .Development IV in Microsoft Dynamics® AX2009 Lab 8. Add inventDimSetupObject form method to return instance of InventDimCtrl_Frm_Mov. 6. 1. Adda call to UpdateDesign to init method. Add the Dimension Display button so that the user can adjust what dimensions are displayed. Step by Step Inspiration for the following may be drawn from the SalesTable form. Look for all references to InventDimSetupObject. Use the InventDimCtrl_Frm_Mov as used by sales table form. 3. Set the number of columns in the grid according to the number of fields already displayed + number of invent dim fields displayed. Challenge Yourself! Use the SalesTable form as inspiration.

Add a display method to display an inventQty on SalesLine datasource: 2. 6. Chapter 8: Inventory Lab 8.parmDimParmVisibleGrid returns the InventDimParm for the visible inventory dimensions. Instantiate using newParameters static method.4 – POS . 5. Challenge Yourself! 1. display inventory on hand for dimensions that are displayed. Microsoft Official Training Materials for Microsoft Dynamics ® 8-29 Your use of this content is subject to your current services agreement . Step by Step 1.availPhysical() returns the available quantity. 3. Use the InventOnHand class. Use inventDimFormSetup. InventDimFormSetup.Display on hand inventory Scenario In the POS form.AvailPhysical() returns the quantity available. InventOnHand. InventOnHand.parmDimParmVisibleGrid() for InventDimParm. 4. Add field to sales line using display method. 2.

2. 3. 8-30 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1.

Why has the Inventory Multi-transaction Tracking system been introduced? MODEL ANSWER: To solve deadlocking in InventSum 5. In which method is an InventDim record created? MODEL ANSWER: InventDim::FindOrCreate() 3. Which class is used to create inventory transactions? MODEL ANSWER: InventUpdate 4. True or false: An InventDimId is always unique to an itemId. MODEL ANSWER: False Microsoft Official Training Materials for Microsoft Dynamics ® 8-31 Your use of this content is subject to your current services agreement . Is the InventDimParm table a temporary table? MODEL ANSWER: Yes 2. Chapter 8: Inventory Solutions Test Your Knowledge 1.

Development IV in Microsoft Dynamics® AX2009

8-32 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Chapter 9: Production

CHAPTER 9: PRODUCTION
Objectives
The objectives are:

• Use the ProdMulti classes.
• Use the ProdStatusType classes.
• Use the ProdUpd classes.
• Schedule production orders.

Introduction
Production orders in Microsoft Dynamics® AX 2009 can have many components
and resources. One production order can be linked to many others through sub-
BOMs and reference production orders.

The Production module is designed to set up items that are produced, indicate
how they are produced, what components they are made up of, how long it takes,
and so on, and then to let the system calculate:

• When they can be made
• What resources to use
• How much it will cost

This is done by updating the production order status at each stage of the process.

The status update process is an important part of the production module and is
often modified to include parameters unique to a company's production line. The
key to modifying the update process is knowing the function of the many classes
involved.

Microsoft Official Training Materials for Microsoft Dynamics ® 9-1
Your use of this content is subject to your current services agreement

Development IV in Microsoft Dynamics® AX2009

ProdMulti
Production orders can be updated either one at a time, or multiple orders at once.
The RunBaseMultParm structure enables the use of different parm tables and
different updates to run, all using the same structure.

FIGURE 9.1 THE RUNBASEMULTPARM STRUCTURE

Demonstration: Code Walkthrough - ProdMulti
An update to a production order can be called from either the Production table
form or from main menu > periodic > update. Both places call the same menu
items, which run the appropriate ProdMulti class. For instance, updating to
Estimated calls ProdMultiCostEstimation::main().

1. View the ProdMultiCostEstimation::main() method:

prodMultiCostEstimation =
ProdMultiCostEstimation::construct(args);

RunBaseMultiParm::initFromForm(prodMultiCostEstimation,args
);

ProdMultiCostEstimation is instantiated, and then passed into the static method
RunBaseMultiParm::initFromForm(), along with args.

9-2 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Chapter 9: Production

2. View the RunBaseMultiParm::initFromForm() method:

FormDataSource fdS;
Common common;
ParmBuffer parmBuffer =
runBaseMultiParm.defaultParmBuffer();
ParmUpdate parmUpdate =
runBaseMultiParm.defaultParmUpdate();
;
RunBaseMultiParm::initParm(runBaseMultiParm); //sets
the parm id

parmBuffer is a table map that is mapped to the different parm tables.
RunBaseMultiParm.defaultParmBuffer() is overridden in the sub-classes and
returns the appropriate parm table.

RunBaseMultiParm::initParm() retrieves saved data (sysLastValue) and sets the
ParmId used in the update.

if (args && args.dataset() &&
args.record().dataSource())
{
//init specific update tables
fdS = args.record().dataSource();
for (common=fdS.getFirst(true)
? fdS.getFirst(true)
:
args.record();common;common=fdS.getNext())
{
parmBuffer.Linenum++;

runBaseMultiParm.insert(common,parmBuffer);
}
}

All selected records in the form data source are added to the appropriate parm
table. If the update has been called from the main menu, there is no data source
and no records are found.

3. Return to the ProdMultiCostEstimation::main() method:

if (! prodMultiCostEstimation.prompt())
return;

prodMultiCostEstimation.run();

The prompt displays the form where the user can change the settings to update
the order. There is also a function to select more records, which must be used
when the update is called from the main menu.

The run() method is then called.

Microsoft Official Training Materials for Microsoft Dynamics ® 9-3
Your use of this content is subject to your current services agreement

Development IV in Microsoft Dynamics® AX2009

4. View the ProdMultiCostEstimation.run() method:

while (curParmCostEstimation)
{
try
{
prodTable =
this.initProdTable(curParmCostEstimation.ProdId);

prodTable.status().runCostEstimation(curParmCostEstimation,
false,prodPurch,this);
}

All records in the parm table are looped over. The ProdStatusType sub-class is
instantiated using the status of the prodTable record, then the update is called.

ProdStatusType
Production order updates are controlled using the ProdStatusType class and sub-
classes.

FIGURE 9.2 THE PRODSTATUSTYPE CLASS

Each stage of the update process must take place. If the current status of an order
is Estimated, and you try to update it to Report as Finished, then it must be
Scheduled, Released, and Started before it can be reported as Finished.

Before each update is run it checks to see if the previous status has already been
processed. If not, then it runs that update. It also handles what updates can take
place to a production order. For instance, a production order with status Finished,
cannot be Estimated.

Demonstration: Code Walkthrough - ProdStatusType
Update a production order with a status of Released to a status of Report as
Finished. The update to the status is called by ProdMultiReportFinished, which
is discussed in the next section.

9-4 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Chapter 9: Production

The following steps demonstrate the use of ProdStatusType:

1. View ProdMultiReportFinish.Run():

try
{

this.initProdTable(prodParmReportFinished.ProdId).status().
runReportFinished(prodParmReportFinished,false,this,sysSign
);
}

ProdMultiReportFinish.Run() instantiates the ProdStatusType_Released sub-
class using the status of the production order, and calls
ProdStatusType_Released.runReportFinished().

2. View ProdStatusType_Released.runReportFinished():

if (!ask)
{

ProdUpdReportFinished::runPreviousJob(prodParmReportFinishe
d,_multi);

prodTable.type().runReportFinished(prodParmReportFinished,_
multi,_sysSign);
}
return true;

ask is set to true only when the method is called to ask whether the update is
allowed, not to run the update.

ProdUpdReportFinished::RunPreviousJob runs the update to status Started.

3. View ProdUpdReportFinished::RunPreviousJob:

ProdParmStartUp prodParmStartUp =
ProdUpdStartUp::initParmBufferFromRepFin(prodParmReportFini
shed);
;
prodParmStartUp.insert();

ProdTable::find(prodParmStartUp.ProdId).status().runStartUp
(prodParmStartUp,false,null,_multi);

A record in ProdParmStartUp is created using the ProdParmReportFinished
record that is used for the update to Report as Finished.

ProdStatusType_Released sub-class is instantiated using the status of the
production order and calls ProdStatusType_Released.runStartUp().

Microsoft Official Training Materials for Microsoft Dynamics ® 9-5
Your use of this content is subject to your current services agreement

Development IV in Microsoft Dynamics® AX2009

4. View the ProdStatusType_Released.runStartUp() method:

if (!ask)

prodTable.type().runStartUp(prodParmStartUp,_multi);
return true;

Since the status previous to Started is released, and this order is already released,
there is no need to run the previous job.

Once the update to status Started has taken place, it returns to
ProdStatusType_Released.runReportFinished(), then runs the update to Report as
Finished.

ProdUpd
The update to the production order is taken handled by the ProdUpd class.

FIGURE 9.3 THE PRODUPD CLASS

When a production order is updated, there are two events that can occur.

• The status is updated to the new status.
• Journals can be created and posted to consume items and operations
as required, depending on the settings on the update, the production
parameters, and the item itself. For instance, updating to Started may
post the BOM journal and consume all items in the BOM at this
point.

9-6 Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

View the ProdStatusType_Released. ProdUpdStartUp. ProdUpdStartUp. ProdUpdStartUp.setParameters() retrieves ProdTable and initializes BomCalc. ProdUpdStartUp is instantiated using the parm table. Chapter 9: Production Demonstration: Code Walkthrough .updateBOMConsumption().status(). this.StartedUpQty. prodTable.updateRouteConsumption().true).run(). this. prodTable. 2. The following steps demonstrate the use of ProdUpd: 1.Status.StUpDate.run() method: try { ttsbegin. viewCacheProdRoute activates cache on all prodRoute records for the current production order.RunStartUp() runs the update to Startup status. if (! this.setParameters().updateProduction updates to prodTable. Microsoft Official Training Materials for Microsoft Dynamics ® 9-7 Your use of this content is subject to your current services agreement . this.validate()) throw Exception::Error. It is called when component dimensions are used in the calculation of item consumption. .updateProduction(). View the ProdUpdStartUp. prodStartUp. viewCacheProdRoute = null. it also posts the journal.startUpUpdateRouteJobs(this).RunStartUp() method: ProdUpdStartUp prodStartUp = ProdUpdStartUp::newParmBuffer(prodParmStartUp).ProdUpd ProdStatusType. and prodTable. this. If the update is set to post the BOM consumption. and then run.updateBomConsumption() creates the BOM consumption journal.ProdId. viewCacheProdRoute = ProdRoute::viewCacheProdId(prodTable.

prodTable. and productions to give starting and ending dates and times. This temporary data is handled by classes that have the postfix Data.ProdId. and the parm table record is updated to show it has been posted. To handle all the factors involved in an efficient manner. Scheduling Production orders are scheduled using a sequence specified by the user according to what is currently available with respect to material and work center capacity. The scheduling direction and scheduling date must also be considered. ttscommit. If limited material and capacity are used. the system indicates separate operations and.startupReferences(). Scheduling can be done by operation or by job. which can be applied back up through the tree of jobs. the time to carry out each job or operation can be calculated. this. There are a number of factors that determine when an operation or job can be scheduled. Each production order is split into route operations and held in WrkCtrRouteData. production orders to be scheduled are placed into the WrkCtrMasterData data storage class. separates the jobs. the data is stored in temporary tables and arrays. strfmt("@SYS76498". if job scheduling.updateJobJournal(ParmJobStatus::Executed). for example.Scheduling ProdUpdScheduling controls the update of production orders to scheduled status. While scheduling a specific production. "@SYS77138")). as this covers both operation and job scheduling. 9-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . then all the materials and work centers must be available. this. operations. ProdMultiSchedulingJob selects the production orders. When all the temporary data has been created.Development IV in Microsoft Dynamics® AX2009 The production route is updated and the route journal is created and posted. TransactionLog::create(TransactionLogType::ProdStartUp. This instance shows scheduling by job. Demonstration: Code Walkthrough . Any references (production orders created due to this production order) are also updated. initializes the ProdParmScheduling records. routes. and allows the user to set the scheduling direction and sort order.

The load method creates records in the TmpSchedMasterData temporary table that refer to each production order to be scheduled. View the wkCtrScheduleJobs. Chapter 9: Production The following steps demonstrate the use of ProdUpdScheduling: 1. if (! this. wrkCtrScheduleJob. 3. try { ttsbegin. (wrkCtrScheduleJobs is instantiated as an instance of wrkCtrScheduleJob_Detail in ProdUpdScheduling_Job.run(). and super() is called. wrkCtrMasterData = new WrkCtrMasterData_Prod(). View the ProdUpdScheduling_Job.ProdId)). Some of the classes to be used are instantiated.runMaster()) { Microsoft Official Training Materials for Microsoft Dynamics ® 9-9 Your use of this content is subject to your current services agreement . wrkCtrMasterData has been instantiated as wrkCtrMasterData_Prod.run() is called.run(). if (!this.run()is not overridden).run() method: try { ttsbegin. 2. masterData.run() method: setprefix(#PrefixField(ProdParmScheduling.load(). wrkCtrScheduleJob = new WrkCtrScheduleJobs_Detail(wrkCtrParmSchedule. but wkCtrScheduleJobs. wkCtrScheduleJobs.wrkCtrMasterDa ta). After some initial validation. This includes any child or parent production orders if the Schedule References option was selected in the Scheduling Update form. super().run() method: setprefix(ProdMultiSchedulingJob::description()). wrkCtrParmSchedule = WrkCtrParmSchedule::newProdParmScheduling(prodParmSchedulin g).validate()) throw Exception::Error. View the ProdUpdScheduling.

runMaster() runs the scheduling. setMasterStartDateTime initializes the scheduled start and end date and time to the schedule date and time. this.masterDirection() == SchedDirection::Forward) { this. 4.prefixNumId()).masterIteration(1).rec_FromDate()). Note that if references are not scheduled. while (doFirst) { if (this.masterDirection(parmSchedule.rec_FromDate()). further checks are made.runMaster(): this. routeData = masterData. and the class array variables are populated with the data from ProdRoute records attached to the production order.rec_FromTime()).last().rec_Iteration() == this.masterDirection() == SchedDirection::Forward) doNext = masterData.setMasterStartDateTime(). this.routeSchedTime(masterData.rec_FromTime()). this. If the production order level is the level currently being scheduled.masterSchedTime(masterData. if (! masterData.Development IV in Microsoft Dynamics® AX2009 wrkCtrScheduleJobs. else doNext = masterData. while (doNext) { if (masterData. View wrkCtrScheduleJobs. 9-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . this.newRouteData().first().routeSchedDate(masterData. only one production order is in the temporary table.masterIteration()) { setprefix(masterData.schedDirection()).masterSchedDate(masterData. the last production is scheduled first. this. The scheduling direction dictates the sequence that the production orders are retrieved. wrkCtrRouteData is instantiated. if (this.check()) throw error("@SYS18447"). If the scheduling direction is forward.

} The scheduling date on the master and route data is set according to the scheduling direction. The data in wkrCtrRouteData is looped and initial dates are set.runRoute()) return false.rec_OprNum() Microsoft Official Training Materials for Microsoft Dynamics ® 9-11 Your use of this content is subject to your current services agreement .runJobLink() is called. wrkCtrScheduleJob.routeSchedDate(masterData. 7.rec_NumId() && _prodRouteJob.routeDirection() == SchedDirection::Forward) doNext = routeData.rec_ToDate()). if (!this.rec_ToDate()). 5.masterSchedTime(masterData. View the wrkCtrJobLinkData_ProdJob. this.first().runJobLink()) return false. this. Chapter 9: Production } else { this.runJobLink() method: jobLinkData.load(). RunRoute is called.ProdId == masterData. View the wrkCtrScheduleJob.load() is called.last(). 6.masterSchedDate(masterData.runRoute() method: while (doFirst) { if (this.routeSchedTime(masterData. JobLinkData. else doNext = routeData.load() method: while select forupdate _prodRouteJob index ProdOprIdx where _prodRouteJob.OprNum == routeData.rec_ToTime()).rec_ToTime()). this. View the wrkCtrScheduleJobs. if (! this.

_currentLinkIdx. _prodRouteJob.PropertyId. _prodRoute._prodRoute.WrkCtrId. _calcTime.bomCalcData().JobType. 1. _prodRoute) * 3600.calcJobSchedJobTime(_prodRouteJob.Locked )._ calcTime).rec_JobLastIdx(). _prodJobType. _prodRouteJob. _currentJobIdx = jobData. _prodRouteJob. including the calculated time is stored using wrkCtrJobData. _prodRoute.routeGroup()). _prodRoute. Job data. _prodRouteJob. this. _prodRouteJob. _prodRouteJob.routeGroup()). _prodJobType.scheduleCapacity(_prodRoute.RecId. _prodRouteJob. _jobTime = _prodJobType.insert(_prodRouteJob. _calcTime = _prodJobType.scheduleWorkTime(_prodRoute. 9-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Jobs attached to the current route are selected. _prodRoute.JobStatus >= ProdJobStatus::Completed ? 0 : _jobTime. The time needed for each job is calculated.calcWrkCtrHours(masterData.WrkCtrLoadPct.OprPriority.JobId.

rec_OprNum(). oprNum = routeData.rec_OprNum(). 9.runRoute() method: if (this. Each operation in the route has the start and end date set according to start and end date of the jobs attached to it.rec_ToTime(). Return to wrkCtrScheduleJobs.rec_ToDate(jobLinkData.runJobLink(): oprNum = routeData.rec_FromDate(jobLinkData.rec_ToDate().rec_EndTime(endTime). while (jobLinkData.rec_FromTime()). endDate = jobLinkData.routeSchedOk()) { routeData.rec_ToDate()).rec_ToTime()).rec_ToTime())) { endDate = jobLinkData. Chapter 9: Production 8.rec_ToTime(jobLinkData.update() commits the data to the database. endTime = jobLinkData.rec_FromDate()). This method using JobLinkData.rec_ToDate(). Return to the wrkCtrSchedule. routeData. Each operation in the route is retrieved and routeDate.rec_ToDate() || (endDate == jobLinkData. routeData. } } routeData.update(). routeData. Microsoft Official Training Materials for Microsoft Dynamics ® 9-13 Your use of this content is subject to your current services agreement .first(oprNum)) { routeData.next(oprNum)) { if (endDate < jobLinkData. routeData.rec_EndDate(endDate).update() and JobData.update() is called.rec_FromTime(jobLinkData.savePosition(). while (oprNum) { if (jobLinkData.rec_ToTime(). while (oprNum) { routeData.rec_ToDate() && endTime < jobLinkData. endTime = jobLinkData.

how long it takes. Greater productivity can be achieved by automating these and other business processes. The production module is designed to set up items that are produced.Development IV in Microsoft Dynamics® AX2009 Summary Production orders in Microsoft Dynamics AX 2009 can have many components and resources. indicate how they are produced. 9-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . and then to let the system perform the calculations. and so on. what components they are made up of.

Which parm table is used when updating the status from Scheduled to Released? 2. WrkCtrRouteData is a data storage class which holds all ____________ that are in a route. Microsoft Official Training Materials for Microsoft Dynamics ® 9-15 Your use of this content is subject to your current services agreement . Chapter 9: Production Test Your Knowledge 1. Which class controls whether a production order can be updated from one status to another? 3.

and through master planning. 9-16 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . ProdBOM is initialized from ProdTable in ProdBOM. Make sure this field is copied to the production order when the production order is created directly from the sales line (sales table form > sales lines > inquiries > production). Chapter 1. which is copied to the BOM journal and printed on the production order picking list.1 .initFromProdTable(). Need a Little Help? 1.Production Scenario This is part of the POS Case Study. Challenge Yourself! Add a free text field Special Instructions to the production order.Development IV in Microsoft Dynamics® AX2009 Lab 9. Add the Special Instructions field to the sales lines. 2.

Instruction. 4.1 . Add ProdTable. Make sure ProdBOM. Add new field Instructions to tables ProdTable. which is copied to the BOM journal and printed on the production order picking list. Chapter 9: Production Lab 9. ProdInstructions. ProdBOM and ProdJournalBOM. 3. Ensure ProdJournalBOM. Microsoft Official Training Materials for Microsoft Dynamics ® 9-17 Your use of this content is subject to your current services agreement . type = ProdInstruction.Instrution field to ProdPickList report.Production (Solution) Scenario Add a free text field Special Instructions to the production order. Step by Step 1. 2.Instruction is initialized from ProdTable.Instruction is initialized from ProdBOM. 5. Create a new string EDT.Instrucation.

Need a Little Help? 1. ProdTable is initialized from SalesLine in ProdTable.Production Scenario Challenge Yourself! Add the Special Instructions field to sales lines. ReqCalc. 9-18 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .2 .covCreatePlannedOrder() and ReqTrans. 2. When firming an order from a planned order. Make sure this field is copied to the production order when the production order is created both directly from the sales line (sales table form > sales lines > inquiries > production). This is for creating a production order directly from a sales line. view ProdTable. In the requirement calculation. view RecCalc. and through master planning.initTransFromInventTrans().InitFromReqPO().InitFromReqPO().initFromSalesLine(). 3.Development IV in Microsoft Dynamics® AX2009 Lab 9.

Instructions in ReqCalc.Instructions from ReqTrans.Instructions in ReqTrans. set ProdTable.InitFromSalesLine(). Microsoft Official Training Materials for Microsoft Dynamics ® 9-19 Your use of this content is subject to your current services agreement . Set ReqTrans. Chapter 9: Production Lab 9.Instructions using InventTransId to look up the sales line in ReqCalc.2 . 5.Instructions from ReqPO. 3.Instructions from SalesLine in ProdTable. Step by Step 1.InitFromReqPO(). Set ReqTrans. Set ReqPO. To set the field in ProdTable when creating a production order directly from a sales order. type = ProdInstruction. and through master planning.Production (Solution) Scenario Add the Special Instructions field to sales lines.initTransFromInventTrans(). To set the field in ProdTable when firming the order.Instructions from SalesLine. 6.InitFromReqPO().covCreatePlannedOrder(). 4. ReqTrans and ReqPO. 2. Add new field Instructions to tables SalesTable.Instructions from ReqPO in ProdTable. Ensure this field is copied to the production order when the production order is created both directly from the sales line (sales table form > sales lines > inquiries > production). set ProdTable.

9-20 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Quick Interaction: Lessons Learned Take a moment and write down three Key Points you have learned from this chapter 1. 2. 3.

WrkCtrRouteData is a data storage class which holds all ____________ that are in a route. Chapter 9: Production Solutions Test Your Knowledge 1. Which class controls whether a production order can be updated from one status to another? MODEL ANSWER: ProdStatusType 3. Which parm table is used when updating the status from Scheduled to Released? MODEL ANSWER: ProdParmRelease 2. Microsoft Official Training Materials for Microsoft Dynamics ® 9-21 Your use of this content is subject to your current services agreement . MODEL ANSWER: WrkCtrRouteData is a data storage class that holds all operations that are in a route.

Development IV in Microsoft Dynamics® AX2009 9-22 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .

how transactions are created and posted. which calculates running costs. This lesson describes how the project module is designed. Chapter 10: Project Accounting CHAPTER 10: PROJECT ACCOUNTING Objectives The objectives are: • Know the structure and design of the project module • Post transactions to the project module • Make modifications to the project invoice proposal procedure • Make modifications to the project invoice procedure Introduction The Project module is used to estimate and record costs and revenue transactions against individual projects. total costs of the project. and invoices customers for costs incurred. Microsoft Official Training Materials for Microsoft Dynamics ® 10-1 Your use of this content is subject to your current services agreement . and how invoices are created.

ProjRevenueTrans. ProjOnAccTrans. Each project has one record in ProjTable. they are stored in another set of five tables. Rather than use a Type field on one table and many redundant fields. ProjProposalOnAcc. Revenue. ProjInvoiceCost: Contain transactions related to costs incurred by the project. the header record is held in ProjProposalJour. ProjProposalCost. ProjInvoiceOnAcc: Contain pre-arranged invoice amounts. ProjTable: This is the main table for projects. Design Transactions posted against projects can be one of five different types: Hour (Employee). When transactions are invoiced. Different transactions are stored in five different tables. and On Account. ProjProposalEmpl. Item. ProjEmplTrans. and invoice at the same time. to make some modifications to the project module. ProjItemTrans. ProjInvoiceRevenue: Contain transactions related to revenue created by the project. ProjInvoiceEmpl: Contain transactions related to hours spent working on a project by an employee. Some work is billable. ProjProposalItem. CustTable: Each invoice project is attached to a customer for invoicing and payment. Cost. ProjCostTrans. Once transactions are posted against projects. ProjProposalRevenue. Invoice projects allows you to create multiple projects for one customer. other work is carried out under warranty. The project module in Contoso is used to track time and costs used while installing and servicing home theatre equipment. ProjInvoiceTable: At least one invoice project is created for each customer. the System Developer. The system creates a suggested invoice based on user defined criteria. 10-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . an invoice proposal can be created.Development IV in Microsoft Dynamics® AX2009 Scenario The Servicing department has asked Isaac. ProjInvoiceItem: Contain transactions related to item consumption by the project. ProjProposalJour: When an invoice proposal is created. project transactions are recorded in five tables. ProjInvoiceJour: Each invoice created has a header record in ProjInvoiceJour.

1 PROJTRANS CLASS STRUCTURE For instance. Note that ForecastSales is the same table that is used for item forecasts in the Inventory and Sales modules. and each sub- classe has a sub-class for all the stages in a project. ProjForecastEmpl.invoiced() method returns true if the cost transaction has already been invoiced. ProjTransBudget: Contains a summary of all transactions of each type. Chapter 10: Project Accounting ProjForecastCost. ForecastSales. These tables are used when calculating totals for the projects. Microsoft Official Training Materials for Microsoft Dynamics ® 10-3 Your use of this content is subject to your current services agreement . ProjTrans Class The ProjTrans super class and its sub-classes control the creation and posting of transactions. ProjForecastRevenue. ProjTrans has a sub-class for each transaction type. ProjTransPosting. This table is used as it is considered during master planning calculations. ProjForecastOnAcc: Contain forecast transactions for the project. the ProjTransCostTrans. FIGURE 10.

You must use a journal name from an existing ProjJournalName record to create a journal header in ProjJournalTable.invoiced() method: //BP Deviation Documented display boolean invoiced() { return ProjInvoiceCost::find(this.Development IV in Microsoft Dynamics® AX2009 View the ProjTransCostTrans.transId()). they create ProjCostTrans or ProjItemTrans records. On Account transactions are created directly in the ProjOnAccTrans table.. journals are used. 10-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . } If a ProjInvoiceCost record exists with a matching transaction id. ledger transactions are attached to the On Account transaction records. and then add lines in ProjJournalTrans. and hours and revenue transactions use a project journal. Posting Transactions When posting transactions against a project. When invoiced. item consumption transactions use an inventory journal.. the transaction has already been invoiced. When ledger or inventory journals are posted and ProjId is marked on the line. Use ProjJournalCheckPost to post the journal.RecId ? true : false. Cost transactions use a ledger journal.Trans table. Project journals are handled similar to inventory and ledger journals. All transaction types are created in a Proj.

Chapter 10: Project Accounting Invoice Proposal Project invoices are created by using an invoice proposal. this. Code Walkthrough . This proposal is populated according to selections made by the user. From and To dates specified by the user are also entered into the query. Invoice proposals are created using the ProjInvoiceChoose super class and sub classes. The progress bar is initialized. Microsoft Official Training Materials for Microsoft Dynamics ® 10-5 Your use of this content is subject to your current services agreement . which can be modified if necessary and then posted.assignTables() is called. progress.run() method: this. clicking Create Invoice instantiates ProjInvoiceChooseNormal which extends ProjInvoiceChoose. On account transactions use a specific sub-class. For each transaction found. #AviFormLetter). 1. View the ProjInvoiceChoose. ProjInvoiceChooseNormal. The prompt is called. If a transaction type is to be excluded the corresponding datasource is disabled in the query.progressInit("@SYS54552". the user is prompted to select which type of transactions are to be invoiced and can also delimit the transactions using the query. The initQuery() method updates the query according to selections made by the user.initQuery().ProjInvoiceChoose On the Invoice Proposal form.assignTables(). followed by run(). This query is executed to retrieve any un-invoiced transactions and populate the ProjProposal transaction tables. progressTotal. while (queryRun.next()) { this.setText("@SYS26577"). When ProjInvoiceChoose is run.

this.parmProjEmplTrans(). View the ProjInvoiceChooseNormal.parmProjEmplTra ns(). Records returned by the query are placed in appropriate table variables.doProposal().setProjProposalJour(this. a method populates the ProjProposal transaction tables.parmProjEmplTrans(). ProjInvoiceChoose.TransDate)). if (queryCost && queryRun. View the ProjInvoiceChooseNormal.ProjId.this.doEmpl() method: if(this.get(tablenum(ProjEmplTrans)).ProjInvoiceProjId).get(tablenum(ProjRevenueTrans)).doEmpl().run() then calls ProjInvoiceChooseNormal.parmProjEmplTrans().canBeInvoiced()) { If a transaction record exists and has not been invoiced. 10-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . For each transaction type. pProjInvoiceTable = ProjInvoiceTable::find(pProjTable. the transaction can be added to this proposal. } if (queryEmpl && queryRun.doCost().doRevenue().CurrencyI d). if ((queryRevenue || querySubscription) && queryRun.changed(tablenum(ProjTable))) { pProjTable = queryRun.progressUpdate(strfmt("@SYS26810".changed(tablenum(ProjRevenueTrans))) this.this.changed(tablenum(ProjEmplTrans))) pProjEmplTrans = queryRun.changed(tablenum(ProjCostTrans))) this. 3.Development IV in Microsoft Dynamics® AX2009 2. View the ProjInvoiceChoose. if (queryRevenue || querySubscription) pProjRevenueTrans = queryRun.get(tablenum(ProjTable)).assignTables() method: if(queryRun. if the record has changed. 4.parmProjEmplTrans() && this.changed(tablenum(ProjEmplTrans))) this.doProposal() method: if (queryEmpl & queryRun. this.

InvoiceAccount ) == NoYes::Yes && pProjInvoiceTable.eInvoiceAccountCode = pProjInvoiceTable.ProposalId. Chapter 10: Project Accounting An invoice proposal header is created and the progress bar is updated. projProposalEmpl. } if (projProposalEmpl. After validation.ProposalId = this. The projProposalEmpl record is initialized from the ProjEmplTrans record and the invoice proposal header.validateWrite()) { projProposalEmpl. projProposalEmpl = ProjProposalEmpl::initProposaleFromTrans(this. the projProposalEmpl record is committed to the database.eInvoiceAccountCode.parmProjEmplT rans()).parmProjProposalJour(). Microsoft Official Training Materials for Microsoft Dynamics ® 10-7 Your use of this content is subject to your current services agreement .insert().eInvoiceLineSpec == NoYes::Yes) { projProposalEmpl. if (CustTable::isCustDKPublic(pProjInvoiceTable.

form LetterMultiThread.run() method: if(projProposalJour) { try { if (batchHeader) { formLetterMultiThread = FormLetterMultiThread::newFormLetter(this).tax(projProposalTotals.Development IV in Microsoft Dynamics® AX2009 Invoice Invoicing takes place in the ProjFormLetter class and the ProjFormLetter_Invoice sub-class. recordListProjProposalEmpl = projProposalTotals.BatchDependencyStatus::FinishedOrError). View the ProjFormLetter. } } Invoices are created from Invoice proposals. recordListProjProposalCost = projProposalTotals. batchHeader.calc(). projProposalTotals = new ProjProposalTotals(projProposalJour. parmId). recordListProjProposalRevenue = projProposalTotals.recordListProjProposalRevenue(). batchHeader. View the ProjFormLetter. If the job is running in batch.addRuntimeTask(formLetterMultiThread.addDependency(projFormLetterEndMultiThread.recordListProjProposalEmpl(). some tasks are created to improve performance.this.recordListProjProposalcost(). 10-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . The structure for these classes is similar to the FormLetter classes used in Accounts Receivable (AR) and Accounts Payable (AP). } else { this. otherwise the createJournal() method is called 2.parmC urrentBatch().createJournal().createJournal() method: projProposalJour. so projProposalJour must exist. Code Walkthrough – ProjFormLetter 1.InvoiceDate = projInvoiceParmTable.InvoiceDate. this. projProposalTotals.RecId).tax()).

Microsoft Official Training Materials for Microsoft Dynamics ® 10-9 Your use of this content is subject to your current services agreement . projProposalJour = this. this.recordListProjProposalOnAcc().transactionLogType().initMarkup().this. true). transaction texts.createProjInvoiceEmpl().insertJournal() method: if (this.updateNow()) { TransactionLog::create(this.createProjInvoiceRevenue(). View the ProjFormLetter_Invoice. Ledger voucher. this.insertJournal() is called.getProjProposalJour(projInvoiceParmTable. ttscommit. if (proforma) this.createProjInvoiceItem().createProjInvoiceCost().UpdateNow() method: this.recordListProjProposalItem_Project().createProjInvoiceSalesLine(). this.createPayment().createProjInvoiceOnAcc(). 3. ProjFormLetter.tranS actionLogTxt()).insertProforma().initTransactionTxt(creditNote ? LedgerTransTxt::ProjectCreditNoteLedger : LedgerTransTxt::ProjectInvoiceLedger. If the invoice is to be posted. this. else this. this. } The bulk of the work is done in updateNow(). Totals are calculated and the project transactions are put into lists which can be used by the invoicing process. and the invoice journal are initialized. Chapter 10: Project Accounting recordListProjProposalItem = projProposalTotals. this. this. this. projProposalJour). which is overridden in the sub- class. View the ProjFormLetter. 4. recordListProjProposalOnAcc = projProposalTotals. this.initLedgerVoucher().insertJournal().

SalesOrderbalance.CashDiscCode && TaxParameters::canApplyCashDiscOnInvoice_ES()) { this. salesFormLetter. salesFormLetter. • How to make modifications to the project invoice procedure. this. this.postInvoiceRoundOff(). The invoice journal is finalized and final postings are made.createCustTrans(). how to create and post transactions.deleteFullyInvoiced(). and how to create invoices.LineProperty = ProjLinePropertyCode::Invoiced. From this you should learn: • About the structure and design of the project module. this. projProposalJour. } ledgerVoucher. • How to post transactions to the project module.createCashDisc().LedgerVoucher.postMarkupTable().end(). this. if (projInvoiceJour.SalesOrderbalance = projInvoiceJour. 10-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . projProposalJour. projProposalJour.Development IV in Microsoft Dynamics® AX2009 Invoice transactions are created and the necessary ledger and inventory postings are handled. • How to make modifications to the project invoice proposal procedure.postEndDisc().update().LedgerVoucher = projInvoiceJour. this.postTax(). Summary This lesson discusses how to design the project module. projProposalJour.parmDeleteFullyInvoiced(true).

True or False: A project is linked to the customer table through ProjTable. Chapter 10: Project Accounting Test Your Knowledge 1. In which class would you find a method that returns whether an employee hours transaction has already been invoiced? 3. 2.projProposalTotals.calc()? Microsoft Official Training Materials for Microsoft Dynamics ® 10-11 Your use of this content is subject to your current services agreement . When posting a project invoice. which method calls the project totals calculation method .CustAccount.

2. called Warranty Repairs.WarrantyItemId in static table method ProjEmplTrans::InitTransFromJournal(). 3. and requires employees to record time against a single project.WarrantyItemId = ProjJournalTrans. type = itemId to the journal lines used for employee time entry. Set ProjEmplTrans. It is required that the employee record in which item the repair work is carried out. type = ProjWarrantyItemId to table ProjJournalTrans and ProjEmplTrans. Step by Step 1. Create a new string EDT. 10-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . ProjWarrantyItemId.Development IV in Microsoft Dynamics® AX2009 Lab 10.Warranty Item Scenario The Contoso Company offers repairs to the items that they sell. and ensure this item id is also copied to the appropriate project transactions when the journal is posted. Challenge Yourself! Add a WarrantyItemId field. WarrantyItemId. Add a new field.1 .

Add a new NoYes field. If this field is set. OnHold to ProjProposalJour. to return false if a proposal transaction exists. OnHold. 3. In the classes. ProjTransCostTrans. The invoice proposal will be put on hold while transactions are investigated in the case that the Prakash. This requires a new field. 2. modify the method proposal(). ProjTransItemTrans. but is on hold. Challenge Yourself! Enable an invoice proposal to be put on hold. type = NoYes. the Project Manager.2 .Place Invoice Proposal On Hold Scenario Isaac. Chapter 10: Project Accounting Lab 10. and a new invoice proposal can be created that may include transactions that were included on the OnHold proposal. believes that there might be an error. Microsoft Official Training Materials for Microsoft Dynamics ® 10-13 Your use of this content is subject to your current services agreement . ProjTransOnAccTrans. ProjTransRevenueTrans. Display this field on form ProjInvociceProposal. has been asked to create a function that will enable Invoice Proposals to be placed "On Hold". ProjTransEmplTrans. then the invoice cannot be posted. Step by Step 1. the Systems Developer.

10-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 Quick Interaction: Lessons Learned Take a moment and write down three Key Points you have learned from this chapter 1. 2. 3.

CustAccount. MODEL ANSWER: False 2. True or False: A project is linked to the customer table through ProjTable. When posting a project invoice. Chapter 10: Project Accounting Solutions Test Your Knowledge 1.calc()? MODEL ANSWER: CreateJournal Microsoft Official Training Materials for Microsoft Dynamics ® 10-15 Your use of this content is subject to your current services agreement .projProposalTotals. which method calls the project totals calculation method . In which class would you find a method that returns whether an employee hours transaction has already been invoiced? MODEL ANSWER: ProjTransEmplTrans 3.

Development IV in Microsoft Dynamics® AX2009 10-16 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .

• Apply a workflow to a form • Create Event Handlers and apply them to a workflow • Configure a workflow • Submit a record for workflow processing • Use the workflow processor Introduction Workflow is a module in Microsoft Dynamics® AX 2009. This lesson introduces the development side of creating an workflow. For example. Chapter 11: Workflow CHAPTER 11: WORKFLOW Objectives The objectives are: • Identify the components required prior to using workflow • Specify which application module a workflow is applicable to using a workflow category • Create a new workflow template • Link tables to workflows using a workflow document • Define what happens when the workflow is approved or denied. for which you will need to use skills developed from this class and the Morph X development class. a purchase requisition may need to be approved by a number of different employees according to the requisition's total amount. A Workflow in Microsoft Dynamics AX uses a combination of AOT elements created by IT. and configuration that may be set up by a user. and each employee has to approve it before the next employee in the approval route. Microsoft Official Training Materials for Microsoft Dynamics ® 11-1 Your use of this content is subject to your current services agreement . that allows flexible task and approval routes for documents created by users.

Right-click on the newly created workflow category and select Properties 5. Modules are defined by the SysModule enum. Change the name property to SalesCreditLimitApproval 11-2 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . the sales order cannot be picked.a system account used to provide access to the workflow tables. the systems developer. This is the workflow engine and is installed using the Microsoft Dynamics AX installation files. packed or invoiced. • Workflow accounts. has been asked to create a new workflow that will be used to approve a new sales order for a customer that has reached their credit limit. For more information about workflow installation. There are two accounts used . Until it is approved. the sales order should be submitted to the Accounts Receivable (AR) manager.Development IV in Microsoft Dynamics® AX2009 Scenario Isaac. Demonstration: Creating a Workflow Category This demonstration shows you how to create a category that allows the workflow to be configured from the Projects module. • Workflow website. The website and the accounts are required to run this installation. Open the AOT 2. and an execution account that is used to execute business logic. This is an IIS website that controls the flow of the workflows. They will either approve or deny the sales order. The requirement is that when a new sales order is entered that takes the customer over their credit limit. Right-click on the Workflow Category node and select New Workflow Category. 4. Create a Workflow Category A workflow category defines the module in which the workflow will be available. refer to the Administrator Guide. NOTE: This course does not cover the installation of the workflow system components. Expand the Workflow node 3. • Microsoft Dynamics AX workflow server component. 1. A new workflow category called Workflow Category1 will be created. Workflow Installation A number of the workflow system components are required to be installed before you can begin to create and configure workflows in Microsoft Dynamics AX. however you need to be aware of the requirements.

8. Right-click on the newly created workflow category and select Save. Change the label property to Sales credit limit approval. 2. Open the AOT. 7.1 Create a Workflow Template A workflow template brings all the different elements of the workflow together. Right-click on the newly created workflow template and select Properties. Chapter 11: Workflow 6. The template defines which actions are allowed and which are required. FIGURE 11. Right-click on the Workflow Templates node and select New Workflow Template. Change the Module property to Cust. 4. A new workflow template named WorkflowTemplate1 will be created. Expand the Workflow node. Workflow configurations are created based on a template. and many configurations can be based on the same template. 3. 1. Microsoft Official Training Materials for Microsoft Dynamics ® 11-3 Your use of this content is subject to your current services agreement . Demonstration: Creating a Workflow Template This demonstration creates a workflow template and binds it to the workflow category created in the previous demonstration.

Open another AOT window. It can define one or more tables and all or selected fields on that table. 8. 6. Expand the newly created query. 11-4 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Change the category property to SalesCreditLimitApproval. FIGURE 11. 1.2 Create a Workflow Document A workflow document defines what data is affected by the workflow. 5. Expand Data Dictionary > Tables. 6. 4. Use a class to bind that query to the workflow template. Change the name property to SalesCreditLimitApproval. Right-click on the Query node and select New Query. Open the AOT. Change the label property to Sales credit limit approval.Development IV in Microsoft Dynamics® AX2009 5. 3. This is done by using a query. 7. Rename the query to SalesCreditLimitApproval. 2. Demonstration: Creating a Workflow Document A query defines what tables are used to determine that a workflow can be initiated. Right-click on the newly created workflow template and select Save.

The Workflow Approval element determines which of these outcomes is allowed and what happens in the event of each outcome. 9. 1. Right-click on the newly created approval and select properties. In the AOT. Demonstration: Creating a Workflow Approval This demonstration creates a workflow approval and specifies how the approval route can be defined. Change the ParticipantProvider property to WorkflowUserGroupParticipantProvider. Expand the workflow node. 15. right-click on the Classes node and select New Class. Change the Name property to SalesCreditLimitApproval. } Create a Workflow Approval An approval route may contain a number of outcomes. Each outcome can trigger specific code by specifying a menu item for each item. 2. 10. Microsoft Official Training Materials for Microsoft Dynamics ® 11-5 Your use of this content is subject to your current services agreement . Press F8 to save the method 13. 17. 3. Open the AOT. It may be approved. Find the table SalesTable. Find the SalesCreditLimitApproval workflow template in the AOT. 14. Right-click on the class and select override method > getQueryName. Press F8 to save the method 16. Right-click on the workflow template and select Properties. Right-click on approvals and select New Approval. 6. 19. 8. class ProjTimeApproval extends workFlowDocument { } QueryName getQueryName() { return queryStr(SalesCreditLimitApproval). Right click on the SalesCreditLimitApproval query and select Save. enter SalesCreditLimitApproval. 18. Copy the following code into the ClassDeclaration. rejected. returned or a change may be requested. Right-click on the workflow template and select Save. 5. Copy the following code in to the method. In the document property. Change the Document property to SalesCreditLimitApproval. 4. Drag the SalesTable table to the Data Sources node of the SalesCreditLimitApproval query. 7. Chapter 11: Workflow 7. 11. 12.

The Providers specify classes that enable rules to be defined for the workflow. therefore call the same class from two different menu items. 5. or other providers can be used in their place.3 Demonstration: Creating Approval Outcomes Use a standard class that acts as an engine for all approval outcomes. Right-click on the newly created Action item and select Properties. Change the DocumentMenuItem to SalesTable. You are not required to do anything but set the workflow to either Approved or Denied. Change the HierarchyProvider to WorkflowLimitHierarchyProvider.Development IV in Microsoft Dynamics® AX2009 8. Expand Menu Items. 9. Open the AOT. The two menu items simply allow you to use two different labels. 4. 1. FIGURE 11. 2. Change the DueDateProvider to WorkflowWorkCalendarDueDateProvider. 3. 11-6 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Change the Name property to SalesCreditLimitApprove. These providers are standard application classes but can be overridden and modified. Right-click on Action and select New Menu Item. 10. In more complex workflows it may be necessary to override or copy and modify this class rather than use it directly.

Change the Enabled property to No. Change the ObjectType property to Class. 18. 12. 8. 10. Right-click on the SalesCreditLimitApproval approval node and select Save. Change the Label property to Reject. Right-click on Action and select New Menu Item. Change the Object property to WorkflowWorkItemActionManager. FIGURE 11. 25. Right-click on the RequestChange node and select Properties. 19. Right-click on the SalesCreditLimitApprove menu item and select Save. Change the Object property to WorkflowWorkItemActionManager. 20. 22. 15. Right-click on the Reject node and select Properties. 14. Change the ActionMenuItem property to SalesCreditLimitApprove. Change the Name property to SalesCreditLimitReject. 13. Right-click on the Approve node and select Properties. 7. 11. Change the Enabled property to No 26. Right-click on the SalesCreditLimitReject menu item and select Save. 17. Chapter 11: Workflow 6. Change the Label property to Approve. Right-click on the newly created Action item and select Properties. 23. In the AOT. Right-click on the Deny node and select Properties. 16. 24. Change the ActionMenuItem property to SalesCreditLimitReject. 9.4 Microsoft Official Training Materials for Microsoft Dynamics ® 11-7 Your use of this content is subject to your current services agreement . 21. expand Workflow > Approvals > SalesCreditLimitApproval > Outcomes. Change the ObjectType property to Class.

11. Add four elements to the Enum called NotSubmitted. 6. 7. 11-8 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Expand Workflow > Approvals. Demonstration: Add a WorkflowState Field Any form that uses the same table in the datasource as is specified in a workflow document is able to use that document for workflow. Change the EnumType property to SalesCreditLimitApprovalStatus. Right-click on Fields and select New > Enum. 10. Right-click on the SalesTable node and select Save. 4. Find SalesCreditLimitApproval. 7. Enable Workflow on a Form Now that the workflow template is defined. Right-click on the newly created field and select Properties. Expand Workflow > Workflow Templates > SalesCreditLimitApproval. Expand Tables > SalesTable. 3. Open the AOT.Development IV in Microsoft Dynamics® AX2009 Demonstration: Attaching an Approval to a Template The approval needs to be attached to the template. 1. Right-click on Base Enums and select New 4. you can specify which forms will use this template. use a new field on the SalesTable table. Rename the new enum to SalesCreditLimitApprovalStatus 5. 5. One of these conditions must be that it has not already been submitted. Drag the SalesCreditLimitApproval approval to the Required Elements node of the SalesCreditLimitApproval template. Rejected. 3. Open the AOT. This demonstration shows you how to attach an approval to a template. Submitted. 6. Approved. Expand Data Dictionary. This demonstration shows how to enable workflow on the Project Hours journal form. 2. 8. Open another AOT window. 2. To test this condition. Change the Name property to CreditLimitApprovalStatus. Right-click on the SalesCreditLimitApproval workflow template and select save. You can specify conditions under which a workflow is eligible for submission. 1. 9.

Save the changes made to the table. 8. Expand Forms > SalesTable > Designs. custTable custTable. 3. 2. return true.custTable_InvoiceAccount(). Right-click on the form Methods node and select Override Method > canSubmitToWorkflow. 6. Right-click on the design node and select Properties. Create a new method and add the first method in the following code.balanceMST(). .CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::NotSubmitted) return false. Change the WorkflowEnabled property to Yes. 7.CreditMax - custTable. 9.amountRemainSalesPhysical() < creditBalance) return false.amountRemainSalesFinancial() + this. } Microsoft Official Training Materials for Microsoft Dynamics ® 11-9 Your use of this content is subject to your current services agreement . boolean canSubmitToWorkflow() { amountMST creditBalance. if (!custTable. } public boolean canSubmitToWorkflow() { return salesTable. 4. Chapter 11: Workflow Demonstration: Enable Workflow on the Form Workflow on the form is enabled using properties on the design node. This demonstration shows you how to enable workflow on a form. 5. Open the AOT. creditBalance = custTable. 1. Expand Tables > SalesTable. Change the WorkflowDatasource property to SalesTable. custTable = this. Copy the second method in the following code into the method.canSubmitToWorkflow(). if (!this. if (this.CreditMax) return false. 10. and by overiding a form method.

call standard code to prompt the user for a comment and to process the submisson. Right-click and select Properties. // Hardcoded template name WorkflowTemplateName workflowTemplateName = workflowtemplatestr(SalesCreditLimitApproval). class SalesCreditLimitSubmit { } void submit(Args args) { // Variable declaration. 2. Change the SubmitToWorkFlowMenuItem property to SalesCreditLimitSubmit. 10. Right-click on the SalesCreditLimitSubmit menu item and select Save. recId recId = args.caller(). WorkflowCorrelationId workflowCorrelationId. Open another AOT and expand Menu Items. Copy the following code in to the classDeclaration. Demonstration: Create a Submit to Workflow Class To submit a document to workflow. 6. submit method and the main method. SalesTable SalesTable. // Opens the submit to workflow dialog. Change the Label property to Submit.record(). Right-click on the newly created Actions node and select Properties.Development IV in Microsoft Dynamics® AX2009 The canSubmitToWorkflow method returns true if the ProjJournalTable record has not already been submitted and the total hours entered in the transactions is greater than 40. This demonstration shows you how to create a submit to workflow class. 3. 7. 1. 11. Press F8 to save and compile the code. 8. WorkflowSubmitDialog workflowSubmitDialog.RecId.getActiveWork flowConfiguration()). // Initial note is the information that users enter when they // submit the document for workflow. 9. workflowSubmitDialog = WorkflowSubmitDialog::construct(args. 4. WorkflowComment note ="". Drag the SalesCreditLimitSubmit class to the Actions node. 5. Locate the workflow template node in the AOT. . Open the AOT and create a new class. 11-10 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .

RecId. } Microsoft Official Training Materials for Microsoft Dynamics ® 11-11 Your use of this content is subject to your current services agreement . info("Submitted to workflow.record(). } public static void main(Args _args) { SalesCreditLimitSubmit SalesCreditLimitSubmit = new SalesCreditLimitSubmit(). SalesTable = args."). SalesTable. recId. // Get comments from the submit to workflow dialog. note.").record().CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Submitted.parmIsClosedOK()) { recId = args.submit(_args).caller(). if (workflowSubmitDialog. } } args. try { ttsbegin. // Send an Infolog message. } catch(exception::Error) { info("Error on workflow activation. note = workflowSubmitDialog. SalesCreditLimitSubmit. . workflowCorrelationId = Workflow::activateFromWorkflowTemplate(workflowTemplateName .run(). Chapter 11: Workflow workflowSubmitDialog.updateWorkFlowControls().parmWorkflowComment(). ttscommit. NoYes::No).

for example when the workflow is started or completed. this event handler would raise if the configuration was deleted or updated. WorkflowCompletedEventHandler This event raises when the workflow instance ends after it is completed. 1.Development IV in Microsoft Dynamics® AX2009 Create Event Handlers Event handlers are used to execute business logic at specific events in the workflow. WorkflowConfigDataChangeEventHandler This event raises when the workflow configuration data changes. for example when anyone approves or rejects a step in the approval. Use this event handler to identify when a configuration has changed. or at an element level. Event handlers are implemented by creating a class that implements one or more of the EventHandler interfaces. Add the following ClassDeclaration and methods. Use this event handler to perform any clean up operations needed. They can be implemented at the workflow level. Demonstration: Add Workflow Level Event Handlers This demonstration shows you how to add workflow level event handlers. Create a new class. WorkflowCanceledEventHandler This event raises when the workflow instance ends after it is canceled. 2. For example. 11-12 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . Open the properties form for the SalesCreditLimitApproval workflow template. The interfaces at the workflow level are as follows: Event Description WorkflowStartedEventHandler This event raises when the workflow instance starts. if you create an association between the application data and a workflow configuration.

update().CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Submitted) { SalesTable. WorkflowCompletedEventHandler { } public void cancelled(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable. . SalesTable. select forupdate SalesTable where SalesTable. ttscommit. } ttscommit. select forupdate SalesTable where SalesTable. } public void completed(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::NotSubmitted. if (salesTable.update().RecId == _workflowEventArgs.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Approved. SalesTable.parmWorkflowContext().parmRecId().parmWorkflowContext().parmRecId(). } Microsoft Official Training Materials for Microsoft Dynamics ® 11-13 Your use of this content is subject to your current services agreement . SalesTable. WorkflowCanceledEventHandler.RecId == _workflowEventArgs. Chapter 11: Workflow 3. Set StartedEventHandler. CompletedEventHandler and CanceledEventHandler properties to SalesCreditLimitEventHandler class SalesCreditLimitEventHandler implements WorkflowStartedEventHandler. ttsbegin. ttsbegin. .

.update().Development IV in Microsoft Dynamics® AX2009 public void returned(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable. SalesTable. SalesTable.parmWorkflowContext(). . ttsbegin. select forupdate SalesTable where SalesTable. } 11-14 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . select forupdate SalesTable where SalesTable.update().parmWorkflowContext().RecId == _workflowEventArgs. SalesTable. } public void started(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable. ttscommit.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Submitted. SalesTable. ttscommit.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Rejected.parmRecId().parmRecId(). ttsbegin.RecId == _workflowEventArgs.

you can use this event to transition the workflow document state from the current state to Canceled. you can use this event to transition the workflow document state from the current state to RequestChange. WorkflowElementCompletedEventHandler This event raises when the task or approval is completed. For approvals. Chapter 11: Workflow Element Level Event Handlers The interfaces at the workflow element level are as follows: Event Description WorkflowElementStartedEventHandler This event raises when the task or approval starts. you can use this event to transition the workflow document state from Submitted to PendingApproval. For approvals. WorkflowElemChangeRequestedEventHandler This event raises when an approver requests a change to the task or approval. you can use this event to transition the workflow document state from PendingApproval to Approved. For approvals. WorkflowElementCanceledEventHandler This event raises when the task or approval is canceled. WorkflowElementReturnedEventHandler This event raises when the task or approval is returned to the originator. For approvals. For approvals. you can use this event to transition the workflow document state from PendingApproval to RequestChange. Microsoft Official Training Materials for Microsoft Dynamics ® 11-15 Your use of this content is subject to your current services agreement .

Development IV in Microsoft Dynamics® AX2009 Demonstration: Add Element Level Event Handlers This demonstration shows you how to add element level event handlers. WorkflowElementCanceledEventHandler. SalesTable. Create a class and add the following ClassDeclaration and methods. WorkflowElementStartedEventHandler { } public void returned(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable. .parmWorkflowContext(). WorkflowElementReturnedEventHandler. Find the SalesCreditLimitApproval Workflow Approval element 3. Expand the node and open the properties for the Reject node. Set the EventHandler property to SalesCreditLimitElementHandler class SalesCreditLimitElementHandler implements WorkflowElementCompletedEventHandler. 2.update(). 4. WorkflowElemChangeRequestedEventHandler. SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Rejected. ttscommit. } 11-16 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .parmRecId(). select forupdate SalesTable where SalesTable.RecId == _workflowEventArgs. 1. ttsbegin.

4. 5. Enter "Credit limit approval" as the name. 3. Chapter 11: Workflow Configure a Workflow Now that you have created a template and enabled it on a form. 9. 6. click on Assignment tab. Under Step details. 2. 10. Click the Details tab. Create a new sales order and create lines such that the balance of the customer plus the total amount on the lines is greater than the credit limit. The workflow submit button and dialog should appear. 13. Expand the Forms node. Open the AOT. 2. Click Create Instruction. 8. Select Sales credit limit approval and click Create configuration. On the configuration form click Set as active. Select User based. expand SalesCreditLineApproval. Right-click on this form and select Open. Click Start. 12. Click Set as default. 8. 3. Click the Overview tab. Select a customer from the customer table and set a credit limit. 7. 4. Open the main menu and select Accounts Receivable > Setup > Workflow configurations. 5. 11. Demonstration: Test the Workflow This demonstration shows you how to can test the workflow by creating a timesheet 1. 6. and click on Step 1. Click the Choose button. Click the submit button and enter a comment. 1. 9. Microsoft Official Training Materials for Microsoft Dynamics ® 11-17 Your use of this content is subject to your current services agreement . you can configure it for use. 7. The workflow is now ready for use. Demonstration: Configuring a Workflow This demonstration shows you how to configure a workflow from the main menu. enter a user in the Select users field and then click OK. Find the form Tutorial_WorkFlowProcessor. Click New. enter "Please approve" and then click OK. Close the approval form.

Logon as the user who should approve the sales order 13. The workflow has now been approved. Open the sales order form. 14. Click the workflow Actions button and select Approve. 12. Open the Tutorial_WorkflowProcessor form again and click Start. You will see that the document is waiting for approval by the person you assigned to approve it. 15. 16. click Stop and go back to the sales table form. wait for it to complete and click Stop. 11-18 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .Development IV in Microsoft Dynamics® AX2009 10. Select Actions > History. When the form says that it has zero records in queue. 11.

CreditMax) return true. the sales order cannot be posted until the workflow has been approved. Challenge Yourself! Add conditions to the posting functions on the sales order form that will prevent posting to picking. Microsoft Official Training Materials for Microsoft Dynamics ® 11-19 Your use of this content is subject to your current services agreement . Add the following method CanPostCreditLimit to the salesTable table. then the postings should be allowed. boolean canPostCreditLimit() { amountMST creditBalance. 2. custTable custTable. packing or invoicing until the workflow has been approved. Add the following code to the methods canPickingListBeUpdate(). creditBalance = custTable.1 .CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Rejected || this. if (this.amountRemainSalesFinancial() + this. return false. . once a credit limit has been reached.balanceMST(). if (this.Add Another Condition to the Submit Action Scenario Isaac has been asked to ensure that. if (this. custTable = this. Chapter 11: Workflow Lab 11.CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Submitted) return false. Step by Step 1.CreditMax - custTable. canPackingSlipBeUpdated() and canInvoiceBeUpdated() in the salesTableType class.CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Approved) return true. If the credit limit has not been reached.amountRemainSalesPhysical() < creditBalance) return true.custTable_InvoiceAccount(). if (!custTable.

. 11-20 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .. } Code Walkthrough: Submitting a workflow When a record is submitted to workflow.main() method created in the Create A Submit to Workflow Class demonstration. return ok. The user is prompted for a comment while submitting the workflow workflowSubmitDialog = WorkflowSubmitDialog::construct(args.. return ok. the main() method in the submit to workflow class is called... 1......canPostCreditLimit(). } boolean canPackingslipBeUpdated() { . ok = ok && salesTable..canPostCreditLimit().getActiveWork flowConfiguration())..Development IV in Microsoft Dynamics® AX2009 } boolean canPickingListBeUpdated() { . } boolean canInvoiceBeUpdated() { .. ok = ok && salesTable. workflowSubmitDialog. View the ProjTimeApprovalsSTWF. ok = ok && salesTable.. return ok..caller().run().canPostCreditLimit().

_recId. _recId. // Activate the workflow. tableId. _submittingUser. NoYes::No). _activatingFromWeb). The workFlowContext class holds all the relevant data for the workflow submission. Microsoft Official Training Materials for Microsoft Dynamics ® 11-21 Your use of this content is subject to your current services agreement . Return to the ProjTimeApprovalsSTWF.main() method ProjJournalTable. The SysWorkFlowEventDispatcher class creates records that will be read by the Workflow Processor class to determine which actions should be executed in the next step of the workflow. // Get comments from the submit to workflow dialog. _initialNote. try { ttsbegin. configTable. } 3. _initialNote = workflowSubmitDialog.ConfigurationId. View the method Workflow::activateFromWorkflowTemplate() tableId = Workflow::getDocumentTableId(_workflowTemplateName). 2. _workflowCorrelationId = Workflow::activateFromWorkflowTemplate(_workflowTemplateNam e.parmWorkflowComment(). The tableId that the workflow is to be performed on is retrieved from the query specified in the workflow document class.WorkFlowState = true. The journal is marked as submitted. correlationId). _initialNote. which runs the submit process. tableId). workflowContext = WorkflowContext::newRootWorkflowContext(curext(). _recId. ProjJournalTable = args. configTable = Workflow::findWorkflowConfigToActivateForTemplate(_workflow TemplateName. try { SysWorkflowEventDispatcher::onWorkflowSubmit(workflowContex t. Chapter 11: Workflow The record is retrieved from the calling form and the recId is passed to the static method Workflow::activateFromWorkflowTemplate().record().

1. while select workflowWorkItemTable where workflowWorkItemTable. 11-22 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . cntWorkItems++.parmWorkflowActivityInstanceKey(). View the method SysWorkflowEventDispatcher::onWorkItemEscalation() workItemTable = WorkflowWorkItemTable::findPendingActivityInstanceId(_workI temContext. The WorkflowWorkItem::escalateWorkItem() is called 2. } All records due for processing are retrieved.DueDateTime < DateTimeUtil::getSystemDateTime() { WorkflowWorkItem::escalateWorkItem(SysWorkflowWorkItemConte xt::newWorkflowWorkItemContextFromWorkItem(workflowWorkItem Table)).parmWorkflowAc tivityInstanceId(). The workItemTable record is retrieved. View the method WorkflowWorkItem::escalateWorkItem() try { workItemId = SysWorkflowEventDispatcher::onWorkItemEscalation(_workItemC ontext).Development IV in Microsoft Dynamics® AX2009 Code Walkthrough: Workflow Processor All workflows are processed through a batch process. true).Status == WorkflowWorkItemStatus::Delegated) && workflowWorkItemTable.Status == WorkflowWorkItemStatus::Pending || workflowWorkItemTable. based on the configuration. View the form method doMessageProcessing on the form Tutorial_WorkflowProcessor. } 3.Type == WorkflowWorkItemType::WorkItem && (workflowWorkItemTable. use the form Tutorial_WorkflowProcessor. To view a simulation of how the workflows are processed. This is the next pending activity on the workflow.

EscalationAction. // always set the auto- escalate user to the workflow originator "@SYS110277").EscalationType) { case WorkflowEscalationType::Action: workItemInstanceId = workItemTable. Microsoft Official Training Materials for Microsoft Dynamics ® 11-23 Your use of this content is subject to your current services agreement .Originator.Status = SysWorkflowEventDispatcher::completeWorkItem( _workItemContext. The next step is completed. stepTable.Id. workflowTable. workItemTable. workItemTable. workItemTable.UserId. Chapter 11: Workflow The action to be performed is examined switch (stepTable.

it should be able to be resubmitted.Enable Resubmit Scenario Issac is required to ensure the workflow can be resubmitted after it has been rejected. if (_args. // Hardcoded template name WorkflowTemplateName _workflowTemplateName = workflowtemplatestr(SalesCreditLimitApproval).record().menuItemName() == menuitemactionstr(SalesCreditLimitSubmit)) { SalesCreditLimitSubmit. WorkflowCorrelationId _workflowCorrelationId. 11-24 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .2 . set the ResubmitMenuItem property to SalesCreditLimitResubmit public static void main(Args _args) { SalesCreditLimitSubmit SalesCreditLimitSubmit = new SalesCreditLimitSubmit(). 3. Challenge Yourself! When a workflow is rejected.resubmit(_args). Step by Step 1. Set the ObjectTypePropety to class. On the SalesCreditLimitApproval approval element.Development IV in Microsoft Dynamics® AX2009 Lab 11. Modify the Submit to Workflow class so that it can resubmit the workflow after a rejection Use the PurchReqWorkflow class as inspriration.RecId. recId _recId = args. .submit(_args). the Object property to SalesCreditLimitSubmit and the Label property to Resubmit. Modify the Main method on the SalesCreditLimitSubmit class and add a new method Resubmit as follows: 4. } else { SalesCreditLimitSubmit. Create a new action menu item called SalesCreditLimitResubmit 2. } } void resubmit(Args args) { // Variable declaration.

args.getActiveWorkflowWorkItem(). // Send an Infolog message.RecId.getActiveWorkflowWorkItem().parmIsClosedOK()) { _recId = args.run(). curUserId(). SalesTable.menuItemName(). WorkflowWorkItemActionType::Resubmit. SalesTable = args. try { ttsbegin.caller(). MenuItemType::Action)). WorkflowWorkItemActionDialog WorkflowWorkItemActionDialog.record().caller(). .parmWorkflowComment(). SalesTable SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Submitted. _initialNote = workflowWorkItemActionDialog. // Opens the submit to workflow dialog."). new MenuFunction(menuitemactionstr(PurchReqReSubmit). _initialNote. info("Resubmitted to workflow. WorkflowWorkItemActionManager::dispatchWorkItemAction( args. WorkflowWorkItemActionType::Resubmit. workflowWorkItemActionDialog. WorkflowComment _initialNote ="". workflowWorkItemActionDialog = WorkflowWorkItemActionDialog::construct( args. // Get comments from the submit to workflow dialog. false). Chapter 11: Workflow // Initial note is the information that users enter when they // submit the document for workflow.record(). Microsoft Official Training Materials for Microsoft Dynamics ® 11-25 Your use of this content is subject to your current services agreement . if (WorkflowWorkItemActionDialog.

by using Morph X and some standard code templates. } Summary The workflow module is a highly configurable and flexible module. 11-26 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement . } catch(exception::Error) { info("Error on workflow activation. However.Development IV in Microsoft Dynamics® AX2009 ttscommit."). This lesson explores some of the possibilities the workflow framework offers. it can be configured for any part of the Microsoft Dynamics AX application.caller().updateWorkFlowControls(). and explores some of the different ways it can be used to cover most workflow requirements. } } args.

Which application element is used to define to which module a workflow is applicable? ( ) Workflow template ( ) Workflow category ( ) A field in the workflow configuration ( ) SalesTable 2. There are three types of providers that define what rules the workflow can follow. Which two properties on a form data source need to be modified to allow the form to use a workflow? ( ) WorkflowTemplate ( ) WorkflowEnabled ( ) WorkflowDocument ( ) WorkflowDatasource Microsoft Official Training Materials for Microsoft Dynamics ® 11-27 Your use of this content is subject to your current services agreement . Which type of AOT element needs to be created to specify which tables will be affected by a workflow? ( ) Extended data type ( ) Class ( ) Form ( ) Query 3. What are they? ( ) Participant provider ( ) DueDate provider ( ) Hierarchy provider ( ) Internet provider 4. Chapter 11: Workflow Test Your Knowledge 1.

2.Development IV in Microsoft Dynamics® AX2009 Quick Interaction: Lessons Learned Take a moment and write down three key points you have learned from this chapter 1. 3. 11-28 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .

Which two properties on a form data source need to be modified to allow the form to use a workflow? ( ) WorkflowTemplate (√) WorkflowEnabled ( ) WorkflowDocument (√) WorkflowDatasource Microsoft Official Training Materials for Microsoft Dynamics ® 11-29 Your use of this content is subject to your current services agreement . Chapter 11: Workflow Solutions Test Your Knowledge 1. There are three types of providers that define what rules the workflow can follow. Which type of AOT element needs to be created to specify which tables will be affected by a workflow? ( ) Extended data type ( ) Class ( ) Form (•) Query 3. What are they? (√) Participant provider (√) DueDate provider (√) Hierarchy provider ( ) Internet provider 4. Which application element is used to define to which module a workflow is applicable? ( ) Workflow template (•) Workflow category ( ) A field in the workflow configuration ( ) SalesTable 2.

Development IV in Microsoft Dynamics® AX2009 11-30 Microsoft Official Training Materials for Microsoft Dynamics ® Your use of this content is subject to your current services agreement .