Professional Documents
Culture Documents
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
Welcome ............................................................................................................ 0-1 Microsoft Dynamics Courseware Contents ........................................................ 0-2 Documentation Conventions .............................................................................. 0-3 Student Objectives ............................................................................................. 0-4
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
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 Your use of this content is subject to your current services agreement
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
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
Table of Contents
Settlement ........................................................................................................ 7-13 Trade Agreement ............................................................................................. 7-14 Summary .......................................................................................................... 7-16 Test Your Knowledge ....................................................................................... 7-17 Lab 7.1 - Trade ................................................................................................. 7-19 Lab 7.1 - Trade (Solution) ................................................................................ 7-20 Lab 7.2 - Payment Posting and Invoice Update ............................................... 7-21 ab 7.2 - Payment Posting and Invoice Update (Solution) ................................. 7-22 Lab 7.3 - Settlement ......................................................................................... 7-23 Lab 7.3 (Solution) ............................................................................................. 7-24 Quick Interaction: Lessons Learned ................................................................. 7-25 Solutions ........................................................................................................... 7-26
Chapter 8: Inventory
8-1
Objectives ........................................................................................................... 8-1 Introduction ......................................................................................................... 8-1 Scenario ............................................................................................................. 8-2 Inventory Journals .............................................................................................. 8-2 Inventory Dimensions ......................................................................................... 8-4 InventSum ........................................................................................................ 8-10 Lab 8.1 On-hand Inventory on Sales Order Form ......................................... 8-17 InventMovement ............................................................................................... 8-18 InventUpdate .................................................................................................... 8-20 Summary .......................................................................................................... 8-24 Test Your Knowledge ....................................................................................... 8-25 Lab 8.2 Create an ABC allocation ................................................................. 8-27 Lab 8.3 POS - Display inventory dimensions ................................................ 8-28 Lab 8.4 POS - Display on hand inventory ..................................................... 8-29 Quick Interaction: Lessons Learned ................................................................. 8-30 Solutions ........................................................................................................... 8-31
Chapter 9: Production
9-1
Objectives ........................................................................................................... 9-1 Introduction ......................................................................................................... 9-1 ProdMulti ............................................................................................................ 9-2 ProdStatusType .................................................................................................. 9-4 ProdUpd ............................................................................................................. 9-6 Scheduling .......................................................................................................... 9-8 Summary .......................................................................................................... 9-14 Test Your Knowledge ....................................................................................... 9-15 Lab 9.1 - Production ......................................................................................... 9-16 Lab 9.1 - Production (Solution) ......................................................................... 9-17 Lab 9.2 - Production ......................................................................................... 9-18 Lab 9.2 - Production (Solution) ......................................................................... 9-19 Quick Interaction: Lessons Learned ................................................................. 9-20 Solutions ........................................................................................................... 9-21
10-1
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
iii
11-1
Objectives ......................................................................................................... 11-1 Introduction ....................................................................................................... 11-1 Scenario ........................................................................................................... 11-2 Workflow Installation ........................................................................................ 11-2 Create a Workflow Category ............................................................................ 11-2 Create a Workflow Template ............................................................................ 11-3 Create a Workflow Document .......................................................................... 11-4 Create a Workflow Approval ............................................................................. 11-5 Enable Workflow on a Form ............................................................................. 11-8 Create Event Handlers ................................................................................... 11-12 Configure a Workflow ..................................................................................... 11-17 Lab 11.1 - Add Another Condition to the Submit Action ................................. 11-19 Code Walkthrough: Submitting a workflow ..................................................... 11-20 Code Walkthrough: Workflow Processor ........................................................ 11-22 Lab 11.2 - Enable Resubmit ........................................................................... 11-24 Summary ........................................................................................................ 11-26 Test Your Knowledge ..................................................................................... 11-27 Quick Interaction: Lessons Learned ............................................................... 11-28 Solutions ......................................................................................................... 11-29
iv
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Introduction
Online Training
Online Training delivers convenient, in-depth training to you in the comfort of your own home or office. Online training provides immediate access to training 24 hours-a-day. It is perfect for the customer who does not have the time or budget to travel. Our newest online training option, eCourses, combine the efficiency of online training with the in-depth product coverage of classroom training, with at least two weeks to complete each course.
Classroom Training
Classroom Training provides serious, in-depth learning through hands-on interaction. From demonstrations to presentations to classroom activities, you receive hands-on experience with instruction from our certified staff of experts. Regularly scheduled throughout North America, you can be sure you will find a class convenient for you.
Training Materials
Training Materials enable you to learn at your own pace, on your own time with information-packed training manuals. Our wide variety of training manuals feature an abundance of tips, tricks, and insights you can refer to again and again:
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
0-1
Challenge Yourself!
Level 3 exercises are the most challenging. These exercises are designed for the experienced student who requires little instruction to complete the required task.
Step by Step
Level 1 exercises are geared towards new users who require detailed instructions and explanations to complete the exercise. Level 1 exercises guide you through the task, step by step, including navigation.
0-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
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. 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. Hints are used to suggest time-saving features or alternative methods for accomplishing a specific task. NOTE: Notes are found throughout the training manual and are preceded by the word NOTE in bold. Notes are used to provide information which, while not critical, may be valuable to an end user. BEYOND THE BASICS: Advanced information found throughout the training manual is preceded by the words BEYOND THE BASICS in bold. Beyond the Basics provides additional detail, outside of standard functionality, that may help you to more optimally use the application. EXAMPLE: Examples are found throughout the training manual and are preceded by the word EXAMPLE in bold. Examples bring to light business scenarios that may better explain how an application can be used to address a business problem.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
0-3
Student Objectives
What do you hope to learn by participating in this course? List three main objectives below. 1.
2.
3.
0-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Introduction
To practice using the knowledge and skills you learn during this course, you will develop a POS module which encompasses most of the modules that are discussed. This lesson describes functional requirements and technical design suggestions as applied to a fictitious company. This lesson also describes the basic POS design which is built upon during the course, adding functionality appropriate to the lesson being reviewed.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
1-1
Overview
The following is an example of how the POS form looks when completed.
FIGURE 1.1
FIGURE 1.2
1-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Functional Design
The POS module in this scenario is for The Light Company used in the standard Microsoft Dynamics AX demo data. It is not a supermarket-type cash register, where very little information is displayed, but shows more information, which could include information such as: delivery address, quantity on hand and special instructions. Because this POS is for people who walk in and pay for items immediately, do not create a customer account each time. Instead, use a one-time customer parameter. This is normally used as a template for creating a new customer for each sale, but you will use one customer for every sale.
Sales Order
The POS has a Register ID to distinguish each register. Payments can be posted against each register, which enables an end of day routine to be processed. The sales order type should be Journal, meaning that inventory transactions only get posted at the time of physical movement. This increases performance when entering lines. In this case, the time of physical movement is when an invoice is posted, as this is the only order update available. 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 Your use of this content is subject to your current services agreement
1-3
Include the capability to print a receipt from the sales line (for now, it is a proforma receipt). 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.
Technical Design
The POS module sits on top of the standard sales module, and uses some of the sales module code, tables, and procedures. Create the following elements:
Tables
Table Name POSRegisterTable RegisterId Description POSRegisterId Description Field Name Field Type Comment
1-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Field Name HoldingAccount RegisterId SalesId PayId LineNum PayMode Amount Posted PostedEOD
Field Type LedgerAccount POSRegisterId SalesId POSPayId LineNum CustPayMode AmountMST NoYes NoYes
Comment
POSTable Form
Form Name POSTable Data Sources SalesTable SalesLine Design Header SalesTable.SalesId RegisterId OrderTotal Lines SalesLine.ItemId SalesLine.SalesQty SalesLine.SalesPrice SalesLine.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. Use Tab and Grid Use Tab Location Control Comments
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
1-5
POSRegisterTrans Form
The header section contains two buttons - one to call the POSRegisterTrans form, and one to call the POSReceipt report. Form Name POSRegisterTrans Data Sources POSRegisterTrans Design POSRegisterTrans.PayModeId POSRegisterTrans.AmountMST RegisterId, SalesId, LineNum, PayDate, PayTime, and UserId are populated by the system. Use Tab and Grid Location Control Comments
Reports
Element Name POSReciept Data Sources SalesTable SalesTable SalesLine POSRegisterTrans Design Header Inner join to SalesTable Inner join to SalesTable Location Control Comments
1-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Element Name
Location
Comments
Summary
This lesson leads you through creating the base elements for the POS module that will be used throughout the entire Development IV course.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
1-7
2.
3.
1-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Introduction
Number sequences handle the automatic allocation of ID numbers, vouchers, and journal numbers. Numbers are seen and referred to by the user; vouchers are used by the system for tracking and linking transactions posted at the same time. In some instances you can define a voucher series to follow a number series, for example, invoice numbers and invoice vouchers. There are many number sequences needed for the application, and all can be set up so that they have a unique format and numbering range.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2-1
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, and also the next number to be used. The format field controls the length of the number and is used to insert fixed characters when desired. 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, such as when a sales order is deleted before it is saved, that number can be used later. If a number from a continuous number sequence is used and the connection is lost completely (if a machine crashes), the status of that number may be unknown. A clean up job is available to set the status appropriately. 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. Number sequences are assigned to a specific function using various parameter forms in the application, against the journal names, and also by using a number sequence group, for example, on the customer table.
Tables
The tables used for number sequences are: NumberSequenceTable contains the definitions of each number sequence. NumberSequenceList holds numbers for continuous number sequences that have not been completed or are currently reserved. NumberSequenceReference holds which number sequence is used for which function. NumberSequenceGroup is a list of number sequence groups. NumberSequenceGroupRef contains the number sequence references specific to a group.
2-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Classes
The main classes used for number sequences are: NumberSeq assigns numbers and vouchers, handles continuous number sequences, and calls Clean up when appropriate. NumberSeq_Fast is used for number sequences that are not continuous. It does not keep a record of the status or store transaction ids for later clean up, and is better performance-wise. NumberSeqCleanUp looks for numbers in the list that have not been completed, looks for the session that created them, and, if the session is no longer active, frees up the number for later use. NumberSeqDataArea is used in the clean-up process. NumberSeqFormHandler is used whenever a number sequence assigns a number in a form. It handles records being deleted and ensures that two users cannot use the same number. NumberSeqReference creates the link between the function and the number sequence. NumberSeqReference is the super class used, and there is a sub class for each module. NumberSeqNumCache contains the method to manipulate the cache of reserved numbers. NumberSeqGlobal, a global instance, is available once instantiated. It is used in with NumberSeqNumCache.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2-3
false)
To retrieve the number or voucher, you can use the num() or voucher() methods:
Voucher = NumberSeq.voucher();
An example of this is provided in Microsoft Dynamics AX in the ProdTableType.Insert() class method. The method uses NumberSeq::NewGetNum() to assign a new InventTransId.
2-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Format a Number
The method to format a number is called from the num() method, so normally you do not need to call this method from your code. If you do require to format a number in your code, this can be done by using the NumberSeq::numInsertFormat() static method, which takes an integer number and a format as parameters. The format is specified using a combination of characters. Any fixed characters should be entered. Any mandatory numerals can be specified using a "#". Additionally, to have Microsoft Dynamics AX convert the integer to letters, enter "&" for each mandatory letter.
Num = NumberSeq::numInsertFormat(30,"&&&");
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2-5
Number Pre-Allocation
Processes that use many numbers from a single number sequence can improve performance by using number pre-allocation. Basically, this pulls a set number of numbers into the memory and provides faster access. For example, the inventory close process uses voucher numbers if posting to the ledger. The overall speed can be increased by allowing pre-allocation on the number sequence for Closing Vouchers in Inventory Parameters. Pre-allocation uses a global instance of the class NumberSeqGlobal, which means that once it is instantiated, it is available until the session is closed. It is declared in the global class, application. The pre-allocated numbers are stored in a list, which is mapped to a key of a combination of company and number sequence code. You can see where it stores the reserved numbers in the NumberSeqNumCache.fillCache() class method. This function is only available for non-continuous number sequences; the numbers are only retrieved in the NumberSeq_Fast class. The getNumInternal() method, shows retrieving numbers from the cache.
Clean Up Process
Automatic clean up is done by storing a list in memory of number sequences that must be checked. NumberSeqDataArea.setClean() shows the trans id and number sequence code being stored in a list for clean up later. The clean-up process is called when the current transaction is committed. It goes through this list (created in setClean()) and finds any entries that have dead sessions (NumberSeqCleanUp.isProcessDead()). The manually started clean up process goes through either a specified number sequence or all number sequences, looks at any records in the NumberSequenceList, and checks whether they should be deleted.
2-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Form Handler
To help use number sequences in forms correctly, call the NumberSequenceFormHandler class. Instantiate the class using the static method NewForm(). The parameters are: _NumberSequenceCode is the code of the number sequence to be used. _callerForm is the calling form. _FormDataSource is the data source on the form for the record that is to use the number. _FieldIdNum is the field id of the field that is to use the number. _dontThrowOnMissingSetup defines whether an error message should be displayed if the number sequence has not been set up.
You must add code to call methods in the various datasource methods. The names of the methods clearly define where they should go. For example: numberSeqFormHandler.formMethodDataSourceDelete(); should be placed in the data source delete() method. The CustTable form shows an example of how to use this class correctly.
NumberSeqReference
To create a new number sequence reference; for example, a newly created data type that needs sequential numbers assigned to it, have the new data type created in the number sequence references. This displays it in the appropriate modules parameters form.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2-7
Summary
This lesson provides an overview of how number sequences are used in the application. It shows how number sequence API works and how to implement number sequence API in the code.
2-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3. From which method would you get the number sequence reference used for a sales order number?
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2-9
Challenge Yourself!
In the POS Module, create a new reference for the new EDT POSPayId. The POS module should have its own sub class of NumberSeqReference, but should be displayed in the SalesParameters form.
Step by Step
1. Modify BaseEnum NumberSeqModule: a. Add a new element POSModule. b. Label = POS module. c. EnumValue = 100. 2. Create new class NumberSeqReference_POSModule as follows: a. Extend numberSeqReference. b. Create method "numberSeqModule" \and return enum NumberSeqModule with the value NumberSeqModule::POSModule. c. Create method "loadModule" similar to the method loadModule on the NumberSeqReference_SalesOrder class. d. Use the previously created extended datatype POSPayId for the data type reference. e. Use logisticBasic: as the configuration key.
2-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2-11
Challenge Yourself!
Add the NumberSeqFormHandler methods to the forms POSTable and POSPayTable to create new number for SalesId and POSPayId.
Step by Step
1. Modify the POSTable form as follows: 2. Declare variable NumberSeqFormHandler numberSeqFormHandler in the class declaration method. 3. Create new method named numberSeqFormHandler, see the custTable form.Use POS values instead of custTable values. 4. Override the method created on the salesTable datasource, see the custTable form. 5. Override method delete on the salesTable datasource, see the custTable form. 6. Override method write on the salesTable datasource, see the custTable form. 7. Override method validateWrite on the salesTable datasource, see the custTable form. 8. Override method LinkAcitve on the salesTable datasource, see the custTable form.
2-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2.
3.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2-13
Solutions
Test Your Knowledge
1. When assigning numbers from the numberseq class, when would you use newGetNumAndVoucherFromCode() and newGetNumAndVoucher()? MODEL ANSWER: NewGetNumAndVoucher() is used to instantiate NumberSeq from NumberSeqReference. NewGetNumAndVoucherFromCode() is used to instantiate NumberSeq from a NumberSeqCode. 2. 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. 3. From which method would you get the number sequence reference used for a sales order number? MODEL ANSWER: SalesParameters.NumRefSalesId().
2-14
Microsoft Official Training Materials for Microsoft Dynamics 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 is a system class that contains methods and variables to hold all the settings that determine where and how the output is handled. It can be used both to get and set these options, and can also format all the options such that they can be easily saved and retrieved later. 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. Furthermore, the class SysPrintOptions is briefly introduced.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3-1
All these options, and more, can be set within the code. For example: printJobSettings.setTarget(PrintMedium::Mail) sets the Send To option to E-mail recipient. This is shown in the Cheque_US report in the init() method, where it forces the target to be a printer.
3-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
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.
public Boolean prompt(Boolean enableCopy=TRUE, Boolean enablePages=TRUE, Boolean enableDevice=TRUE, Boolean enableProperties=TRUE, Boolean enablePrintTo=TRUE) { Boolean ret; int trayCount; int i;
if (ret) { // store the name of the printer the user selected above deviceName = printJobSettings.deviceName(); // <this line may not be needed.
printJobSettings.copies(1); // number of copies to print printJobSettings.addTrayPageCopy(0, -1, 1) // from copy one use this tray } return ret; }
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3-3
3-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 3: PrintJobSettings
Use of SysPrintOptions
SysPrintOptions is a class that has methods written for using PrintJobSettings. When printing, processing is done on the Application Object Server (AOS), but the printer may be local to the client, or not installed on the server. Printing works differently on the server than on the client. SysPrintOptions can be used to circumvent these issues. This class is used by the system to control printing, and is not normally needed to be called by the developer.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3-5
Summary
This lesson describes how to use the system class PrintJobSettings in connection with report output. 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. Also, the class SysPrintOptions is briefly introduced.
3-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 3: PrintJobSettings
2. Which method would you use to initialize printJobSettings for a specific report, 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 Your use of this content is subject to your current services agreement
3-7
Challenge Yourself!
Use the printJobSettings.suppressScalingMessage() to stop the message from appearing. The report to modify is SalesLinesExtended.
Step by Step
Add the following code to the init() method of the report SalesLinesExtended. It should go after the call to super().
element.printJobSettings().suppressScalingMessage(true);
3-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 3: PrintJobSettings
Challenge Yourself!
In the POS module, enable printer options to be set up and saved for each register.
Step by Step
1. Create a new container EDT, POSRegisterPrintJobSettings. 2. Create a new field POSRegisterTable.printJobSettins, type = POSRegisterPrintJobSettings. 3. Create a new method on table POSRegisterTable to call the standard printer options form and store the return container in POSRegisterTable.PrintJobSettings. HINT: Look at the Production order Startup parameterspick list printer settings. 4. Add a button to the POS Register table form to call this new method.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3-9
Challenge Yourself!
When the receipt is printed, set the printer options to the options stored against the appropriate register.
Step By Step
1. Retrieve the register id from the sales order record. 2. In the receipt report, set the printJobSettings from the container stored against the register table. 3. Use the method this.PrintJobSettings().UnpackPrintJobSettings() to set the printer settings for the report from the container.
3-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 3: 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. Use the print options selected for the register. As soon as the user clicks the Receipt button, it should print.
Step By Step
1. Override the prompt method on the report, and remove the call to super(). Return true from the method.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3-11
2.
3.
3-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 3: PrintJobSettings
Solutions
Test Your Knowledge
1. What is the syntax for setting the default printer option to e-mail in the PrintJobSetting class? MODEL ANSWER: PrintJobSettings.SetTarget(PrintMedium::Mail). 2. Which method would you use to initialize printJobSettings for a specific report, when this report is called from a class? MODEL ANSWER: ReportRun.UnpackPrintJobSettings. 3. Where does Microsoft Dynamics AX store the previously selected printer settings for a specific report? MODEL ANSWER: Usage Data (SysLastValue).
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3-13
3-14
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Introduction
When using the Microsoft Dynamics AX 2009 Business Connector, other applications can access Microsoft Dynamics AX 2009 as a .NET object. This implies that the application can gain access to the data and business logic of Microsoft Dynamics AX 2009, which enables the use of applications as front ends, other than Microsoft Dynamics AX 2009.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-1
.NET Platform
The Business Connector is based on the .NET platform and provides a set of managed classes that provide easy access to X++ functionality in Microsoft Dynamics AX 2009. It supports the functionality in the Enterprise Portal server, Reporting server, and Application Integration server roles. The Business Connector can be installed as a stand-alone component and used to develop thirdparty applications that integrate with Microsoft Dynamics AX 2009. The following are some characteristics of the Business Connector: Requires Microsoft Windows authentication. Automatically registered during installation. The Business Connector Proxy user, which "acts-on-behalf-of" Microsoft Dynamics AX 2009 users who cannot be fully authenticated.
4-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
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. The Business Connector Proxy has unique configuration settings that can be modified. A configuration target field has been added to the utility to enable you to select the Business Connector Proxy. 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. For more information on the proxy user, consult the Microsoft Dynamics AX 2009 Administrator Guide, found under the Help menu.
Event Monitoring
The Microsoft Dynamics AX 2009 Business Connector interfaces with the Event Viewer component, which is an integrated part of the Microsoft Windows Vista, Windows XP, Windows 2000, and Windows NT 4.0 operating system. The Microsoft Dynamics AX 2009 Business Connector logs specific events to the Application Log of the Event Viewer. For instance, the Microsoft Dynamics AX 2009 Business Connector logs whenever it is started or stopped. Any unexpected events are also logged in the Application Log for further investigation by the administrator. To open the Event Viewer in Windows Vista, XP and Windows 2000, go to Control Panel > Administrative Tools > Event Viewer. In the Event Viewer, select the Application Log folder. All events logged by the Microsoft Dynamics AX 2009 Business Connector have a source name of "Microsoft Dynamics AX Business Connector."
Debugging
In Microsoft Dynamics AX 2009 it is possible to enable user breakpoints for X++ code running in the Business Connector, and global breakpoints for X++ code running in the Business Connector or in a user session. A global breakpoint is one that is set for a computer, instead of a user, and can be shared between developers.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-3
2. Select the Local Client setting in the Configuration target. 3. Select the Configuration that you want to enable breakpoints for. 4. 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. 5. Click OK. 6. A warning message may appear explaining that debugging is enabled but not started.
4-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8. Debugging must also be enabled on the Application Object Server (AOS). Open the Microsoft Dynamics AX Server Configuration tool.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-5
4-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Managed Classes
The following managed classes are provided by the .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, through the .NET Business Connector. Each class contains a collection of methods that can be called to perform business logic in Microsoft Dynamics AX 2009.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-7
4-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
language
objectServer
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-9
Parameter configuration
Description (String) Name of Microsoft Dynamics AX 2009 configuration to use while logging on. 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). If Business Connector is being executed within the context of a non-interactive Windows account (such as the Business Connector Proxy AD user), then this parameter is used to specify the path which points to an exported configuration file.
company ="dmo" language ="en-us" objectServer ="objectServerName" configuration ="configurationName" username ="proxyUsername" domain ="domain"
4-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-11
Summary
The Business Connector provides a conduit between Microsoft Dynamics AX 2009 and other applications. Besides the most common use of supporting the connection between SharePoint and Microsoft Dynamics AX 2009 for the Enterprise Portal, the Business Connector also opens up the existing Microsoft Dynamics AX 2009 business logic and data to external applications within your business scope. By understanding how to effectively install and configure the Business Connector, and then write and debug code on both sides of the Connector (both .NET and X++), 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
2. Do you need to register the .NET connector into the Global Assembly Cache after it is installed?
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-13
5. What is the purpose of the Managed Classes in the .NET Business Connector?
6. Using a .NET language, 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
Challenge Yourself!
Create a front end for the POS module using a .NET form that can be used in a 'supermarket' environment. The form should have a large display, can display item descriptions and prices, and a large number pad (so touch screens can be used). There should also be buttons that can complete an order and delete the last line. Create the touch screen front end in a .NET form. Create buttons to add a sales line, delete last sales line, and to complete an order.
Step by Step
As you may not be familiar with .NET, this form has been created for you. It has been created using C# .NET as the syntax for C# is similar to X++. There are two versions available for use: The first version, POSConsole_Complete is completed and needs no additional programming in C# .NET. You may still view the C# code for thus console by following the steps below, using the files from POSConsole_Complete.zip. To use this version, run the executable POSConsole.exe, included in the file POSConsole.zip, which then uses the Microsoft Dynamics AX 2009 Business Connector to communicate with the installation. You still need to write the necessary code in Microsoft Dynamics AX 2009, as detailed below. The second version has most of the interface built already, but you need to add the procedure to call the post invoice function.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-15
4-16
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-17
4-18
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Step by Step
Do as follows: In Visual Studio 2005 1. The following files are included in POSConsole_Incomplete.zip and contain the C# .NET project solution. Place them in a new directory called POSConsole in the Visual Studio Projects directory: o app.ico o assemblyInfo.cs o POSConsole.cs o POSConsole.resx o POSConsole.csproj o POSConsole.sln 2. Open the C# .NET development environment: select file > open solution and select the POSConsole.sln file 3. 3. Add a call to the Microsoft Dynamics AX 2009 class method CSharp_SalesOrder.completeOrder() to the method buttonComplete_Click() so the invoice posts when the Complete Order button is clicked. 4. 4. Select build > build posconsole to build the executable, which can then be found in the directory Visual Studio Projects \ POSConsole \ Bin \ Debug.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-19
4-20
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2.
3.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
4-21
Solutions
Test Your Knowledge
1. Describe the purpose of the Business Connector. MODEL ANSWER: The Business Connector enables external applications to interact with Microsoft Dynamics AX 2009 Application Object Server instances. 2. Do you need to register the .NET connector into the Global Assembly Cache after it is installed? MODEL ANSWER: No. It is registered automatically during installation. 3. What is the Business Connector Proxy User account used for? MODEL ANSWER: It is used to enable the Business Connector to "act-onbehalf" of Microsoft Dynamics AX users who cannot be fully authenticated 4. How is debugging through the Business Connector enabled? MODEL ANSWER: Enable debugging on the AOS configuration, Enable debugging on the Client configuration, Set Debug mode to When Breakpoint, Open an instance of the Microsoft Dynamics AX debugger. 5. What is the purpose of the Managed Classes in the .NET Business Connector? MODEL ANSWER: They expose public methods that can be called to interact with Microsoft Dynamics AX. 6. Using a .NET language, 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.Logon("", "", "", "") className = "salesFormLetter" salesFormLetter = axapta1.CreateAxaptaObject(className)
4-22
Microsoft Official Training Materials for Microsoft Dynamics 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. This provides access to a vast array of prefabricated code, to leverage functions already available in the operating system or external applications. This lesson describes how to reference assemblies in Microsoft Dynamics AX 2009 and leverage them in X++ code.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-1
5-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-3
Alternatively, custom assemblies can be created in .NET. NOTE: CLR assemblies and their contents are case sensitive.
5-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
If this assembly was available as a DLL file, it could be added to the References in the AOT. Once referenced, call the assemblies contents directly in X++ code. The following X++ code example leverages the .NET code in the previous assembly:
//X++ code static void JobCLR(Args _args) { SampleCLR.HelloWorld hw; str s; int i; ; hw = new DemoCLR.HelloWorld(); s = hw.sayHello(); info(s); i = hw.add(18,29); info(int2str(i)); }
When JobCLR() is run, the result is two lines in the Infolog: Hello CLR Interop World! 47
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-5
InteropPermission Class
Recall from the Writing Secure X++ Code topic in the Development III course, that classes categorized as "secured" require a permission class to run. The CLR Interop classes are classified as "secured" APIs. They have a permission class called InteropPermission. The new method of this class requires an InteropKind type parameter, which is an enum. When granting permission to CLR Interop classes, use the InteropKind::CLRInterop value. The following is an example of CLR Interop code with a permission class:
public server void JobCLRPermissions(Args _args) { System.Xml.XmlDocument xmlDoc; ; new InteropPermission(InteropKind::CLRInterop).assert(); xmlDoc = new System.Xml.XmlDocument(); //...some xml code here... xmlDoc.Save('c:\\test.xml'); }
5-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
3. In the WSDL URL field, enter the location of the service WSDL, http://soap.search.msn.com/webservices.asmx?wsdl. This field can contain a path to the local file system, a file share, or an Internet address. The following are valid formats for the WSDL URL: o http://soap.search.msn.com/webservices.asmx?wsdl o http://localhost/WebServices/SalesTableservice.asmx?WSDL o c:\WebServices\SalesTableService.wsdl 4. In the .NET code namespace field, enter a unique name for the .NET namespace such as WindowsLiveSearch. This is the namespace in which the generated proxy assembly and other files will reside. 5. In the Reference name field, enter a unique name for the Web service without spaces or special characters such as LiveSearch. This name is used as the name of the .NET assembly that is created and the name of the directory that contains the generated Web reference files. 6. In the Service description field, enter a description for the Web service. 7. Click OK. The Web reference is generated and the proxy files are saved to the following directory: <Microsoft Dynamics AX Install Directory>Application\Appl\DynamicsAx\ServiceReferences\<Web Service Name>.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-7
6. Right-click the class and select New Method. Replace the method with the following code in the code editor. This method creates the source request and puts it in an array.
public static WindowsLiveSearch.SourceRequest[] getSourceRequestArray() { WindowsLiveSearch.SourceRequest[] array; WindowsLiveSearch.SourceRequest sourceRequest; WindowsLiveSearch.SourceType sourceType; try { new InteropPermission(InteropKind::ClrInterop).assert();
5-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7. Right-click the class and select New Method. Replace the method with the following code in the code editor. This is the method that calls the Live Search Web service and returns the search results in a container.
public static container searchLive(str searchQuery) { #File WindowsLiveSearch.MSNSearchPortTypeClient searchService; ClrObject sourceRequestArray, searchRequestObj; WindowsLiveSearch.SearchRequest searchRequest; WindowsLiveSearch.SearchResponse searchResponse; WindowsLiveSearch.SourceResponse[] sourceResponseArray, resultsArray; ArrayIdx idx1, idx2; int srcResponseLength, resultsLength, totalHits; WindowsLiveSearch.Result searchResult; WindowsLiveSearch.SourceResponse sourceResponse; TextBuffer searchResultBuff; str title, description, url; ; try { searchResultBuff = new TextBuffer(); new InteropPermission(InteropKind::ClrInterop).assert(); // Create the search request. searchRequestObj = new WindowsLiveSearch.SearchRequest(); // Replace this string with your Application ID.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-9
searchRequestObj.set_AppID("YOUR_LIVESEARCH_APP_ID"); searchRequestObj.set_CultureInfo("en-us"); searchRequestObj.set_Query(searchQuery); sourceRequestArray = LiveSearchTestClass::getSourceRequestArray(); searchRequestObj.set_Requests(sourceRequestArray); //Create the service and call it. searchRequest = searchRequestObj; searchService = new WindowsLiveSearch.MSNSearchPortTypeClient(); searchResponse = searchService.Search(searchRequest); sourceResponseArray = searchResponse.get_Responses(); // Iterate through the search results. srcResponseLength = sourceResponseArray.get_Length(); // Iterating through a .NET array so start at zero. for(idx1=0; idx1 < srcResponseLength ; idx1++) { sourceResponse = sourceResponseArray.GetValue(idx1); totalHits = ClrInterop::getAnyTypeForObject( sourceResponse.get_Total()); resultsArray = sourceResponse.get_Results(); resultsLength = resultsArray.get_Length(); // Iterating through .NET array so start at zero. for(idx2=0; idx2 < resultsLength ; idx2++) { searchResult = resultsArray.GetValue(idx2); // Gets the title, description, and URL and appends // it to the search results. title = searchResult.get_Title(); searchResultBuff.appendText(title); searchResultBuff.appendText(#delimiterCRLF); description = searchResult.get_Description(); searchResultBuff.appendText(description); searchResultBuff.appendText(#delimiterCRLF); url = searchResult.get_Url(); searchResultBuff.appendText(url); searchResultBuff.appendText(#delimiterCRLF); searchResultBuff.appendText("--------------------
5-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
You should now have a class named LiveSearchTest with three methods: getSourceRequestArray main SearchLive
8. Compile the class and Run the main method. The search results should appear in an Infolog window as shown in the following figure.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-11
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. They are often used to find information about the current environment, such as the amount of free space on a disk, or which window is currently active. Each DLL has one or more functions that can be called. It is not always easy to find all the available functions and how to use them, as documentation or definition files are often not installed with the DLL. MSDN describes some of the functions available in a few main Windows DLL's, such as Kernel32.dll and user32.dll. One method used to view a list of functions in a DLL is the dumpbin.exe program. This is shipped with Microsoft Visual Studio .NET. Use the following line in a command prompt to obtain a list of functions in Kernel32.dll
dumpbin /exports c:\windows\system32\kernel32.dll
The best example of using a DLL within Microsoft Dynamics AX 2009 is the WinAPI class. This implements useful functions from kernel32.dll, user32.dll, and others. For example:
{ int ; fileSize;
fileSize = winAPI::FileSize(c:\\myfile.txt); }
This method uses two other methods to obtain the desired result. Analyze the getFileSize() method to understand how to implement a specific function. Declare and instantiate an instance of the class DLL, passing the name of the DLL as a parameter into the new method. Declare and instantiate an instance of the class DLLFunction, passing the DLL object and the name of the function as a parameter into the new method. Set the type of the return value. Set the type of all parameters that function accepts. Call the function.
5-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5. Override the form's init method and add the following before super():
#MACROLIB.ChartFX ;
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-13
7. Override the executeQuery method on the datasource custTable with the following code:
public void executeQuery() { Query QueryBuildDatasource QueryRun CustTrans ; super();
qbd = query.addDataSource(tablenum(CustTrans)); qbd.addRange(fieldnum(CustTrans, accountNum)).value(SysQuery::value(custTable.AccountNum)); queryRun = new QueryRun(query); while (queryRun.next()) { custTrans = queryRun.get(tablenum(custTrans)); graphData.loadData( date2str(custTrans.TransDate,123,2,2,2,2,2), custTrans.AccountNum,custTrans.AmountMST); } graphData.showGraph(); }
8. Create a display menu item for the form. 9. Add this menu item to the button group on the custTable form.
5-14
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
FIGURE 5.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. 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.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-15
2. Are CLR Interop assemblies, classes, and methods case-sensitive when referenced in X++ code?
3. What code do you use, 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
5. Match the following properties of a Web service reference, to its description. _____ 1. WSDL URL _____ 2. .NET code namespace _____ 3. Reference name _____ 4. Service description a. Identifying text for the Web service. b. The location of the Web service. c. What is used as the name of the .NET assembly that is created and the name of the directory that contains the generated Web reference files. d. Where the generated proxy assembly and other files will reside.
6. Which class contains multiple methods, using the kernel32.dll and user32.dll objects to communicate with the Windows environment?
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-17
Challenge Yourself!
Write a class method that uses CLR Interop code to send a personalized email to every employee in the company. The method accepts two parameters - the subject of the email, and the contents of the email body. Add a line of code to address the recipient personally with "Dear <insert name here>" at the start of the email body. You can assume the email address of the sender is me@abc.com and that the SMTP server is smtp.abc.com
5-18
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Write a class method that uses CLR Interop code to send a personalized email to every employee in the company. The method accepts two parameters - the subject of the email, and the contents of the email body. Add a line of code to address the recipient personally with "Dear <insert name here>" at the start of the email body. You can assume the email address of the sender is me@abc.com and that the SMTP server is smtp.abc.com
Step by Step
Create a new class, and a new method within it. The code inside should look like this:
void sendPersonalizedEmail(SysEmailSubject _subject, SysEmailContents _contents) { System.Net.Mail.MailMessage msg; System.Net.Mail.MailAddress adrRecp, adrSend; System.Net.Mail.SmtpClient smtpClient; EmplTable eT; ; new InteropPermission(InteropKind::ClrInterop).assert(); smtpClient = new System.Net.Mail.SmtpClient('smtp.abc.com'); while select Name, Email from emplTable {
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-19
5-20
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Challenge Yourself!
Create a new form that shows a graph of the balance of a customer over time.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-21
Step by Step
1. Follow the step-by-step example in training manual. However instead of using transaction amount, use the balance of the customer on the date of the transaction. Use CustTable.BalancePerDate() to find the balance.
5-22
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2.
3.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
5-23
Solutions
Test Your Knowledge
1. 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, under the References node. 2. Are CLR Interop assemblies, classes, and methods case-sensitive when referenced in X++ code? MODEL ANSWER: Yes. They are case sensitive 3. What code do you use, to provide Code Access Security permission to a CLR Interop class? MODEL ANSWER: new InteropPermission(InteropKind) 4. Which node on the AOT are Web service references found? MODEL ANSWER: The References node. 5. Match the following properties of a Web service reference, to its description. b 1. WSDL URL d 2. .NET code namespace c 3. Reference name a 4. Service description a. Identifying text for the Web service. b. The location of the Web service. c. What is used as the name of the .NET assembly that is created and the name of the directory that contains the generated Web reference files. d. Where the generated proxy assembly and other files will reside.
6. Which class contains multiple methods, using the kernel32.dll and user32.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
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; it is regarded as one of the most important modules. It is also the module that has the least modifications made to it due to the commonality in accounting procedures throughout the world. However, many modifications to other modules or automation of ledger procedures may require writing code that creates ledger transactions. There are two methods to consider when posting transactions to the ledger: 1. Use the LedgerVoucher class and sub-classes, which is the more direct and controllable route. 2. Use a journal which is more straightforward to use. Since these procedures are used regularly but rarely modified, this lesson examines how to use both methods, but does not go into details about how these methods work.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-1
Scenario
Isaac, the Systems Developer, is developing a process to import opening ledger balances for a new company that is to be migrated to Microsoft Dynamics AX2009. 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.
LedgerVoucher
When using LedgerVoucher, remember that all vouchers in Microsoft Dynamics AX 2009 must balance - an equal credit and debit side. All transactions on one voucher must be posted on the same date. The idea is to build up a list of vouchers to be posted and to build up a list of transactions within each voucher. Once these lists are completed, the system posts them all to the General Ledger module at once. A structure is built as follows: Posting (LedgerVoucher) Voucher (LedgerVoucherObject) o o Trans (LedgerVoucherTransObject) Trans
LedgerVoucher harnesses the posting of multiple vouchers at one time. It checks that the posting is correct and that the voucher balances. Possible rounding of postings is carried out if necessary. The LedgerVoucher class holds all the vouchers in temporary storage (a list array) until the End method is called. The End method creates ledger transaction records from the temporary postings. Each voucher in the LedgerVoucher is contained in a LedgerVoucherObject. Each LedgerVoucherObject holds transactions in temporary storage (a list array) until the end() method is called. Each transaction in each voucher is contained in a LedgerVoucherTransObject. The procedure is: 1. Instantiate the LedgerVoucher class.
6-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
2. Loop over the vouchers to instantiate LedgerVoucherObject classes, and register these in the LedgerVoucher class. 3. For each voucher, loop over the transactions to instantiate LedgerVoucherTransObject classes, and register these in the LedgerVoucher class. A detailed description of these steps follows.
Instantiation of LedgerVoucher
LedgerVoucher can be instantiated as follows:
LedgerVoucher::newLedgerPost(_detailSummary, _sysModule, _voucherSeriesCode, [_transactionLogType, _transactionLogText, _approveJournal, _posting]);
The method constructs one of the sub-classes, LedgerVoucherPost, LedgerVoucherPostApprove, LedgerVoucherPostExPosting. LedgerVoucherPost is used for normal posting to the general ledger. LedgerVoucherPostApprove is used when the final posting is approved by the user; for example, if a vendor invoice approval journal needs to bypass some checks, for instance, when the voucher has already been used. LedgerVoucherPostExPosting is used in the production module to reduce the number of transactions created during production order updates. The parameters are: _detailSummary Value specifying either summary or details. Specifying summary results in summarizing the amounts per account, date, currency, and voucher. _sysModule System module from which transactions are made. This value can also be used for posting transactions from custom modules. _voucherSeriesCode Number sequence code used for numbering the vouchers. This does not automatically allocate the voucher number - it stamps the ledger transaction with the code that was used. _transactionLogType Used in the audit trail (optional).
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-3
Instantiation of LedgerVoucherObject
LedgerVoucherObject can be instantiated as follows:
LedgerVoucherObject::newVoucher(_voucher, [_transDate, _sysModule, _ledgerTransType, _correction, _operationsTax, _documentNum, _documentDate, _tmpVoucherMap, _acknowledgementDate]);
The parameters are: _voucher Number of the voucher. _transDate Date of transaction. The default value is the current date. (Optional) _sysModule System module from which transactions are made. This value can also be used for posting transactions from other modules. (Optional) _LedgerTransType Ledger transaction type. To view all available ledger transaction types, refer to base enum LedgerTransType. Default value LedgerTransType:None. (Optional) _correction Indicates whether the voucher is a reversing entry (credit note). (Optional) _operationsTax Indicates the type of operation tax used when posting a transaction. The default value is OperationsTax::Current. For all available OperationTax codes, look in the base enum OperationsTax details. (Optional) _documentNum Use to stamp a document number onto a transaction. (Optional)
6-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
_documentDate Use to stamp a document date onto a transaction. (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. (Optional Italy country specific functionality)
Instantiation of LedgerVoucherTransObject
There are many other constructor methods for this class used in different situations. The newCreateTrans() method is most commonly used.
LedgerVoucherTransObject::newCreateTrans( _ledgerVoucherObject, _ledgerPostingType, _ledgerAccount, _dimension, _currencyCode, _amountCur, _sourceRecId, [_LedgerQty, _exchRate _exchRateSecond, _ExchRatesTriangulation, _markBridging, _projLedger, _amountMST])
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-5
This adds the transaction initiated in the newCreateTrans() method to the posting. It has already been added to the LedgerVoucherObject.
6-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
Finalizing the Posting
When all the vouchers and transactions have been added, the whole posting can be committed.
LedgerVoucher.end();
Final checks are made and the transactions are finalized. Also, LedgerBalancesTrans and LedgerBalancesDimTrans are updated. These tables store balances by period and by dimension. A coding example using the ledgerVoucher class is provided in the application as the TutorialLedgerVoucher class. The runSalesPost method exemplifies posting a sales order with its lines. The runJournalPost method exemplifies posting from a journal.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-7
SysModule::Ledger, LedgerParameters::numRefLedgerExchAdjVoucher().NumberSequen ce) ; //Second Step - Create Voucher Number ledgerVoucher.AddVoucher(LedgerVoucherObject::newVoucher(nu mseq.num(), today(), Sysmodule::Ledger, LedgerTransType::None)); //Create the first Transaction - this is the credit side of the transaction (-55) //The other two DR transactions should total to the CR otherwise it won't post. ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucher.findLedgerVoucherObject(), LedgerPostingType::LedgerJournal, accountNumPetty, // Ledger Account dimension, CompanyInfo::standardCurrency(), amountPetty, TableId 0); ReciID // // Amount 0, //
//Create the second Transaction ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucher.findLedgerVoucherObject(), LedgerPostingType::LedgerJournal, accountNumOffsetOffice, dimension,
6-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
//Create third Transaction ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucher.findLedgerVoucherObject(), LedgerPostingType::LedgerJournal, accountNumOffsetPostage, dimension, CompanyInfo::standardCurrency(), amountPostage, 0, // TableId 0); // ReciID
ledgerVoucherTransObject.parmTransTxt("Stamps"); ledgerVoucher.addTrans(ledgerVoucherTransObject); //Last Step - To Balance Voucher and Close ledgerVoucher.end(); numseq.used(); ttsCommit; }
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-9
LedgerJournal
Journals are the easiest way of posting in Microsoft Dynamics AX2009. Using journals requires less work when grouping the transactions and vouchers appropriately. When using a Journal lines table, fill it in with data and call upon Microsoft Dynamics AX2009's method for posting the journal. All error checking and posting are performed simultaneously without additional programming. Journals also present the possibility of not posting immediately but allowing the user to verify what is to be posted. This is often useful during data migration.
6-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
Creating the Journal
To create a new journal, use a journal name record to get the default data. Use a journal name of an appropriate type.
ledgerJournalTable.JournalName = SalesParameters::find().PayJournal;
Where SalesParameters::find().PayJournal is a new field of type LedgerJournalNameId. Look at Extended Data Type (EDT) LedgerJournalNameIdApproval for an example of how to create an EDT for a journal name of a specific type.
ledgerJournalTable.Name = 'Payment Journal' ledgerJournalTable.insert();
Look in the table method ledgerJournalTable.Insert(). Notice it handles the creation of the journal number, which is the primary key defining the relationship between the journal table and the lines, and the initializing from LedgerJournalName.
Creating Lines
All transactions must be posted in the journal lines table. Fill the record with data and then insert it. Two fields of interest when creating journal lines are: LedgerJournalTrans.JournalNum which is mandatory, because transactions are assigned to one of the journals, and LedgerJournalTrans.Voucher which is the transaction voucher number. Fill in other mandatory fields in the journal lines table as necessary, for example, LedgerJournalTrans.CurrencyCode. Each journal type requires different fields and field combinations to be correctly entered. Any errors that show up while posting are displayed by validating a journal through the journal lines form.
Posting Journals
After transactions are created in the journal, check and post the journal; use the LedgerJournalCheckPost class. The easiest way is to create an instance of this class using newLedgerJournalTable static method and then run the class. Parameters for this method are: _ledgerJournalTable Record in LedgerJournalTable representing the journal which should be posted.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-11
6-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
ledgerJournalTrans.AccountNum = BankAccountID; ledgerJournalTrans.AccountType = LedgerJournalACType::Bank; ledgerJournalTrans.AmountCurCredit = amountCur; ledgerJournalTrans.TransDate = today(); ledgerJournalTrans.Txt = 'Room Stay'; ledgerJournalTrans.OffsetAccount = offsetAccount; ledgerJournalTrans.OffsetAccountType = LedgerJournalACType::Ledger; ledgerJournalTrans.insert(); info(strfmt('Journal Id: %1',ledgerJournalTable.JournalNum)); //Post the Journal ledgerJournalCheckPost = ledgerJournalCheckPost::newLedgerJournalTable(ledgerJournal Table,NoYes::Yes); ledgerJournalCheckPost.run(); ttscommit; }
Summary
This lesson introduces and explains two methods for posting transactions to the ledger table. The two methods are: Using the LedgerVoucher class and sub-classes. Using a journal.
This lesson provides a basic understanding of: The concepts behind the two main methods of posting transactions. The best method to use depending on the situation.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-13
2. The transaction log type and transaction log text are used in the ________ trail.
6-14
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
4. Which class posts a journal?
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-15
Challenge Yourself!
1. Prompt for offset account, posting date, and filename. 2. Create a journal header. 3. Read in the file and create a journal line for each account and balance. 4. Create a line for the offset account entered by the user for the inverse of the total amount of the balances imported. 5. Post the journal.
Step by Step
1. Create a new class that extends RunBaseBatch. 2. Prompt for: o offset account o posting date o filename 3. Create a method to generate the journal header. o Find the first journal name of type = daily. o Set the journal name of the JournalTable record = journal name of JournalName record. o Insert the JournalTable record. 4. Set a class variable to store the voucher number. The voucher number is obtained from the number sequence attached to the journal name record.
6-16
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
5. Create a method to generate the journal lines. o Accept the account number and amount as parameters. o Set the voucher number. o Set the account number, the amount, the date, and the accounttype. o Read the file. o For each line, call the method to create the journal line. o Create a line for the negative of the total amount of the transactions for the offset account specified in the prompt. 6. Call LedgerJournalCheckPost (use static method newLedgerJournalTable), to post the journal.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-17
Challenge Yourself!
1. 2. 3. 4. 5. 6. 7. 8. 9. Prompt for the RegisterId of the register to process. Prompt for the counted cash amount. Prompt for the cash or bank account and the difference account. Total up the amount entered during that day for that register. Calculate the difference between the counted amount and the posted amount. Post the counted amount to the bank account. Post the inverse of the posted amount to the register holding account. Post the difference to the register difference account. Flag the payment lines as having been posted at EOD.
Step by Step
1. Create a new class that extends RunBaseBatch. a. Prompt for: o Register Id o Counted amount b. Create a method to create the journal header. c. Find the first journal name of type = daily. d. Set the journal name of the JournalTable record = journal name of JournalName record. e. Insert the JournalTable record. 2. Set a class variable to store the voucher number. The voucher number is obtained from the number sequence attached to the journal name record.
6-18
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
3. Create a method to create the journal lines. a. Accept the account number and amount as parameters. b. Set the voucher number. c. Set the account number, the amount, the date, and the accounttype. d. Find the Register table record for the specified register. e. Create a journal line for the inverse of the total amount posted for that register for the register holding account. f. Create a journal line for the total counted amount for the bank account. g. Create a journal line for the difference between the posted amount and the counted amount for the difference account specified in a parameter. 4. Call LedgerJournalCheckPost (use static method newLedgerJournalTable), to post the journal. 5. Update the register transactions to reflect that they have been posted.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-19
2.
3.
6-20
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 6: Ledger
Solutions
Test Your Knowledge
1. Which class holds a list of transactions that are going to be posted for a particular voucher? MODEL ANSWER: LedgerVoucherObject 2. 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. 3. Which table stores default values that initialize a LedgerJournalTable record? MODEL ANSWER: LedgerJournalName 4. Which class posts a journal? MODEL ANSWER: LedgerJournalCheckPost
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
6-21
6-22
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
CHAPTER 7: TRADE
Objectives
The objectives are: Use SalesTableType, SalesLineType, PurchTableType, 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. For instance, the element that every company modifies is the printed sales invoice. This is sometimes a rearrangement of the data available to the invoice, but is more often a complete redesign that includes additional, company-specific data. The trade modules revolve around buying and selling inventory, and issuing and receiving payments. The AR and AP modules are similar in their structure regarding both data dictionary and update procedures, and make good use of table maps to reduce the amount of coding needed. In this chapter, where only AR is referenced, similar constructs and procedures also apply for AP. Recognize that what is true for SalesLine is also true for PurchLine. Not everything is the same between the two modules, but the basic ideas are similar.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-1
Demonstration - SalesLineType
1. View the SalesLine.validateWrite() method:
ok = super(); ok = ok && this.validateWrite_server(_skipCreditLimitCheck); return ok;
After calling the system validation using super(), SalesLineType is instantiated using the SalesLine.Type() method. The SalesLine.Type() method calls SalesLineType.contrstruct() which constructs the instance according to the value of SaleLine.SalesType. After SalesLineType has been instantiated, SalesLineType.ValidateWrite() is called. For most sales line types, SalesLineType.ValidateWrite() has not been overridden, so SalesLineType.ValidateWrite() is called. For a line type of ReturnItem, 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
Chapter 7: Trade
2. View the SalesLineType_ReturnItem.ValidateWrite() method:
ok = super(_skipCreditLimitCheck); if (salesLine.SalesQty > 0 && salesLine.SkipUpdate == InterCompanySkipUpdate::No) { // Quantity of returned items orders must be negative. ok = checkFailed("@SYS53512"); } if (ok && salesLine.ExpectedRetQty == 0 && salesLine.returnJournal()) { // Expected return quantity must not be zero ok = checkFailed("@SYS105646"); } if (ok && salesLine.returnJournal() && salesLine.ExpectedRetQty * salesLine.LineAmount < 0) { //The sign on Quantity and Net amount have to be the same ok = checkFailed("@SYS78848"); } return ok;
After calling super() to provide validation for other line types, the method has one additional check to ensure that the quantity of the return line is negative. These inventType sub-class methods are often called from the system methods on salesLine and salesTable. For example, SalesLine.Update(),calls SalesLineType.Update(). This can be used when, for instance, creating sales orders within code, meaning that instantiating SalesTableType or SalesLineType is not necessary. The examples below show how a sales order and sales order line are created within code. The three table methods that are used: SalesTable.InitValue(), SalesTable.insert(), and SalesLine.CreateLine(), show that they all use the inventType sub-classes. Note that SalesLine.CreateLine() calls SalesLine.Insert() which calls SalesLineType.Insert().
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-3
7-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
Orders can be fully or partially updated, and can be updated one order at a time or in a batch of orders. To handle this parm tables are used. For instance, Sales order updates, use SalesParmUpdate, SalesParmTable, and SalesParmLine, with one record in SalesParmUpdate per update, one record in SalesParmTable per sales order, and one record in SalesParmLine per line to be updated. When a user updates an order, the system populates these parm tables, and then displays them for final adjustments before the posting takes place. They are populated when the SalesFormLetter.dialog method is called - the SalesFormLetter.ChooseLines() method uses the SalesUpdate query to select appropriate salesLines records and populates SalesParmLine accordingly. Once the parm tables are populated, they are displayed using the SalesEditLines form. When the user makes alterations and clicks OK, the update occurs.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-5
SalesFormLetter.queryBuild() builds a query based on SalesParmUpdate and SalesParmTable. journalList is a list of documents to be printed later. 2. The query is then executed:
infoLogCounter = infolog.num(); infolog.updateViewSet(this); if (printout == Printout::Current || this.proforma()) { journalList = this.newJournalList(); } salesParmTable = query.get(tablenum(SalesParmTable)); if (salesParmTable.SalesId != salesTable.SalesId) { salesTable = salesParmTable.salesTable(); } if (this.checkIfSalesOrderExist(salesTable)) { try { if (batchHeader) { formLetterMultiThread = FormLetterMultiThread::newFormLetter(this); batchHeader.addRuntimeTask(formLetterMultiThread,this.parmC urrentBatch().RecId);
7-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
SalesParmTable is retrieved from the query, and a check is made on the sales order. SalesFormLetter.createJournal() is then called. 3. View the SalesFormLetter.createJournal() method:
salesTotals = SalesTotals::construct( salesParmTable, salesParmUpdate.SpecQty, salesParmUpdate.SumBy, salesParmUpdate.ParmId, salesParmUpdate.SumSalesId, this.documentStatus()); this.initFromSalesTotals(salesTotals);
if (this.updateNow()) { this.postUpdate();
Posting number (e.g. invoice or delivery note) and voucher are created then SalesFormLetter.UpdateNow() is called. The UpdateNow() method is not implemented in SalesFomrLetter, rather in its sub-classes. The different sub-classes UpdateNow()use a list of SalesParmLine records (created when the order totals were calculated).
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-7
CustPackingSlipJour is initialized using values from the update and from SalesTable. 6. Transaction text is initialized. The ledgerVoucher and ledgerVoucherObject classes are instantiated, which may be used if posting physical movement to ledger. 7. The first SalesParmLine from the list is retrieved:
inventMovement = InventMovement::construct(salesLine); this.updateInventory(inventMovement);
InventMovement is instantiated using SalesLine. The physical update to inventory is slightly different depending on which update is made, so the updateInventory() method is overridden in SalesFormLetter_PackingSlip. 8. View the SalesFormLetter_PackingSlip.updateInventory () method:
inventUpd_Physical = InventUpd_Physical::newSalesPackingSlip( _inventMovement, salesParmLine, number, salesParmUpdate.ReduceOnHand); inventUpd_Physical.updateNow(ledgerVoucher); updateNow = inventUpd_Physical.updPhysicalUnit(); updateNowInvent = -inventUpd_Physical.updPhysical();
7-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
InventUpd_Physical posts the physical movement of the inventory, and is then used to return the actual quantity updated. The quantity may be reduced due to insufficient inventory. 9. Return to SalesFormLetter_PackingSlip.UpdateNow():
if (salesParmLine.DeliverNow != updateNow || salesParmLine.InventNow != updateNowInvent) { salesParmLine = SalesParmLine::findRecId(salesParmLine.RecId, true); info(strfmt("@SYS26397",updateNow)); qtyReduced = true; salesParmLine.RemainAfter += salesParmLine.DeliverNow - updateNow; salesParmLine.setRemainAfterInvent(); salesParmLine.DeliverNow = updateNow; salesParmLine.InventNow = updateNowInvent; salesParmLine.setLineAmount(salesLine); salesParmLine.update(); }
10. If the quantity is reduced, the user is informed and the parm table record is updated to ensure that later updates are correct.
this.writeJournalLine(); this.writeProjTrans(inventMovement);
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-9
13. If the quantity is reduced, the totals are recalculated and the tax is adjusted:
this.writeJournal(); this.writeRecordListInventReportDimHistory(); this.postMarkupTable(); this.updateSalesShippingStat(salesParmTable);
SalesFormLetter_PackingSlip.WriteJournal() finalizes CustPackingSlipJour and commits it to the database. 14. Return to the SalesFormLetter.run() method:
if (printout == Printout::After && ! salesParmUpdate.Proforma) this.printJournal();
If the document is to be printed, it is called using printJournal(). The sub-classes override this method so that the specific report can be called. 15. View the SalesFormLetter_PackingSlip.PrintJournal() method:
if (journalList.len() > 0) { if (printFormletter) { this.sendAsXML(); custPckSlpJour.printJournal(this, journalList); }
CustPackingSlipJour.printJournal() contains code that calls the report. The following is an example of using SalesFormLetter. In this case, the sales order has been created and will be invoiced.
7-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
Example: Posting an Invoice
static void createInvoice(SalesTable _salesTable) { SalesFormLetter salesFormLetter; ; salesFormLetter = SalesFormLetter::construct(DocumentStatus::Invoice); salesFormLetter.update( _salesTable, //SalesTable record to be posted systemDateGet(), //Transaction date SalesUpdate::All, //Which qty should be used AccountOrder::None, NoYes::No, //Is document a proforma NoYes::No); //Should document be printed
Posting Transactions
Customer and vendor transactions can be posted using a ledger journal. This can be manually created or created within code, as with a normal daily journal. Similar to ledger transactions, customer and vendor transactions can be posted by using a CustVendVoucher object. This creates the transaction in the sub-ledger and the AR or AP account. You must still create transactions in another account to balance the posting. SalesFormLetter_Invoice.createCustTrans() shows where the invoice posting creates the customer transaction. The sales revenue transaction is created elsewhere in the update, but still uses the same LedgerVoucher object. The following example illustrates how a customer transaction could be posted. The process is similar to posting ledger transactions using the ledgerVoucher, but here, 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.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-11
7-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
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. 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. Settlement takes place in the CustVendSettle class, with most of the work done in CustVendSettle.SettleNow(). This method handles settlement using a FIFO principle (oldest invoice gets settled first), and using transaction markings. To mark transactions for settlement, use the SpecTrans table. This stores the RecId's of the transactions to be settled, and the settle amount. The class Specification can be used to handle creation of SpecTrans records and also to handle marked transactions. Additionally, a method, markForSettlement() on CustTrans and VendTrans can simplify the process further.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-13
Trade Agreement
Trade agreements are flexible in the way they can be set up. 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. To set up complicated pricing structures, it is important to understand the logic behind the calculation. Companies often have unique and imaginative pricing structures, so the calculation is modified regularly. The trade agreement calculation searches through all combinations of item/customer/group/all in a particular order and finds the lowest price. The Find Next field that can be cleared to stop the calculation from looking for any further prices once it has found one. 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.
Demonstration - PriceDisc
This demonstration shows the calculation for the item price: 1. View the PriceDisc.findPriceAgreement() method:
while (idx < 9) { itemCode accountCode
7-14
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
The idx variable controls which combination of items, customers, and groups to view. The system counts idx from 0 to 9, which means as it loops itemcode = 0, accountCode = 0, then itemCode = 1, accountCode = 0, then itemCode = 2, accountCode = 0, then itemCode = 0, accountCode = 1 etc. For both itemCode and accountCode, 0 = table, 1 = group and 2 = all. 2. The item relation and account relation are set according to the item code and account code. Since the system is calculating the price, the itemCode = 1 or 2 is meaningless. Look in PriceDisc.FindLineDisc() and note the item relation is set in the same way as the account relation.
3. The trade agreement activation is checked to see if this combination is allowed, and validation is performed on the values.
while select priceDiscTable index PriceDiscIdx // equals order by QuantityAmount where priceDiscTable.Relation == relation && priceDiscTable.ItemCode == itemCode && priceDiscTable.ItemRelation == itemRelation && priceDiscTable.AccountCode == accountCode && priceDiscTable.AccountRelation == accountRelation && priceDiscTable.UnitId == unitID && priceDiscTable.Currency == currency && priceDiscTable.InventDimId == _inventDimId && (discDate >= priceDiscTable.FromDate || ! priceDiscTable.FromDate) && (discDate <= priceDiscTable.ToDate || ! priceDiscTable.ToDate) {
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-15
5. If the quantity calculated on the line is greater than any quantity break set up on the trade agreement, and if there is a price or a miscellaneous charge amount, and if this price is less than any previously found price, then continue.
priceUnit price markup deliveryDays calendarDays actualPriceTable priceExist = = = = = = = priceDiscTable.priceUnit(); priceDiscTable.price(); priceDiscTable.markup(); priceDiscTable.DeliveryTime; priceDiscTable.CalendarDays; priceDiscTable.data(); true;
6. Data on the price is stored for later retrieval when the final price is located.
if (! priceDiscTable.SearchAgain) { idx = 9; break; }
If the price set to not search for more prices, the loop ends. To view the priceDisc class, refer to the setPriceAgreement.
Summary
In this lesson, the some of the most commonly used development concepts in the Accounts Receivable and Accounts Payable modules have been introduced. Concepts such as document updates, posting transactions, using settlements and searching trade agreements should now be familiar, and developing modifications with them is now possible.
7-16
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
3. 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 Your use of this content is subject to your current services agreement
7-17
7-18
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
Challenge Yourself!
Create a process that can post a payment transaction for the payment entered into the POS screen.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-19
Step by Step
1. Create a new class, POSPostPayment: a. Override the new method and set a class variable to hold the sales id of the order being processed. b. Create a method to create a LedgerJournalTable record. o Use a LedgerJournalName record of type Daily. c. Create a method to create a LedgerJournalTrans record. o Accept LedgerJournalAccountType, Account, amount and payment reference as parameters. o Voucher comes from a class variable. d. Create a method post the payment lines. e. Loop through all unposted register transaction records and call the method to create a journal line for each payment line. f. Get a payment id from a number sequence and stamp each payment transaction. Use this id as the payment reference on the journal line.
7-20
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
Challenge Yourself!
When the OK button on the payment lines screen is clicked, the payment posting routine should be called. This should be followed by the standard invoice update.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-21
Step by Step
1. Create a new class, POSPostInvoice, which posts an invoice: o Instantiate SalesFormLetter, DocumetnStatus::Invoice. o Call SalesFormLetter.Update(). o Call the payment posting class and the invoice posting class when the Post button is clicked.
7-22
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
Challenge Yourself!
When posting an invoice and payment from the POS, they should be settled against each other. Ensure that this happens. This should happen whether automatic settlement is enabled or not, and should settle against each other no matter what other transactions are open for the customer.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-23
Step by Step
1. Create a new class POSSettlement: o Find the invoice customer transaction associated with the sales order. o Find the payment customer transaction associated with the order (you can use the payment id). o Mark each transaction to be settled against each other. o Hint: Use CustTransInvoice.markForSettlement(custTable). o CustTransPayment.markForSettlement(custTable). o Post the settlement. o Hint: Use CustTrans::settleTransact(custTable).
7-24
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 7: Trade
2.
3.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
7-25
Solutions
Test Your Knowledge
1. 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.CreateParmLine() 3. 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. 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
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, Inventory is closely linked to many modules within Microsoft Dynamics AX and is a vital module to understand. Unlike the ledger module, modifications to the inventory system can be significant with regard to the work required. This lesson discusses both creating and posting inventory transactions, and using the data correctly after it has been posted. A significant part of the inventory module is its inventory dimensions. Although they may seem complicated to use, there are useful classes and methods written that help you achieve excellent results. This lesson introduces some of the classes used to manipulate inventory data.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-1
Scenario
Isaac, the Systems Developer, has been asked to add a field on the sales order that shows the current on-hand inventory of an item, based on the visible inventory dimensions. To be able to do this he must understand how the inventory system works in Microsoft Dynamics AX.
Inventory Journals
Inventory Journals are similar to Ledger Journals and can be created in a similar way. Application elements are similar in design but are physically different elements.
Tables
In the inentory module, the tables used are InventJournalName, InventJournalTable, and InventJournalTrans. InventJournalName contains the default data for a specific journal type. There can be more than one InventJournalName per type. InventJournalTable is the header record for the journal. There is one record per journal. InventJournalTrans contains data used to create the individual transactions that will be posted. There can be one or more lines per journal.
8-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
Creating the Journal Header
To create a new journal, use a journal name record to get the default data. The journal name is commonly set either from a parameter or by prompting the user to enter it in a dialog. Use a journal name of an appropriate type.
xInventJournalName = InventJournalName::find( InventParameters::find().MovementJournalNameId); InventJournalTable.InitFromInventJournalName(InventJournalN ame); InventJournalTable.Name = 'Movement Journal'; InventJournalTable.insert();
Look in the InventJournalTable.Insert() table method. Note that it handles the creation of the journal number, which is the primary key defining the relationship between the journal table and the lines.
Creating Lines
All transactions must be posted in the journal lines table. You must fill the record with data and then insert it. There are two important fields to be filled every time you insert a new record: InventJournalTrans.JournalId which is mandatory, because transactions are assigned to one of the journals InventJournalTrans.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. While developing, test the code by letting it create a journal, and then manually opening the journal in the journal forms. Run validate and post highlights errors.
Posting Journals
After transactions are created in the journal, check and post the journal using the InventJournalCheckPost class. Create an instance of this class using newJournalCheckPost static method and then run the class. Parameters for this method are: _journalCheckPostType Check or post parameter for specifying whether to check a journal only or check and post. Post indicates that after checking to post to the journal. _InventJournalTable Record in InventJournalTable representing the journal to receive the posting.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-3
Inventory Dimensions
Inventory dimensions are a powerful, versatile, and efficient way to track variations in inventory movements. They define whether an item is tracked by: Storage dimension, (warehouse, batch number, location, pallet, or serial number) Item dimension (color, size, or configuration)
There are a finite number of combinations of inventory dimensions, and each combination can be assigned an ID number. Any reference to a particular combination of dimensions can be referred to by the ID number, rather than every dimension. This offers many possibilities when grouping and summing data.
Tables
Available tables are defined as follows: InventDim holds every combination of inventory dimensions used in the system and the corresponding inventDimId. The InventDim.findOrCreate() method looks for a particular combination, and creates it if it does not exist. InventDimGroup groups items by inventory dimensions used. InventDimSetup sets up each dimension group. There is one record per inventory dimension per dimension group. InventDimParm flags which dimensions to use in different situations. This table is a temporary table created according to which dimensions are in use.
8-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
Classes
The available classes include: InventDimGlobal is a global class that holds a cache of dimension field ids and names. This is used mainly by InventDimSearch. InventDimSearch creates a list of InventDimSetup records in a list and iterates through it. InventDimOnHand finds current inventory levels for specific dimensions.
A static method on InventDimSearch is called. This method will set the flags for each inventory dimension that financial inventory option checked. 2. View the InventDimSearch::financialInvent() method:
static void financialInvent(InventDimGroupId _dimGroupId, InventDimParm _inventDimParm) { if (_dimGroupId) _inventDimParm.data(classfactory.inventDimGlobal().dimSearc hBase().financialInvent(_dimGroupId)); else _inventDimParm.clear(); }
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-5
financialInvent is a map that contains the setup data for each group for the financial inventory. The key is the group id, and the value is an InventDimParm record holding the values for each inventory dimension. In this method, the map is checked to see if the values have already been created for this group. If not, then it will call the method to initialize these values. 4. View InventDimSeachBase.initInventDimCache()
if (_dimSearch.first(_dimGroupId)) do {
After initializing the various maps that are used, InventDimSearch.first() is called. This iterates through a list of the inventory dimensions that are active. Inventory dimensions are made inactive through the application configuration keys. 5. Many setup options are examined. The following code shows where the flags for the dimension being active and to post financial inventory are examined, and if both are true, then the InventDimParm flag for this dimension is set to Yes. Additionally the field id which is used to refer to which dimension this is for is stored in a container.
if (_dimSearch.dimActive() && _dimSearch.dimFinancialInvent()) { inventDimParmFinancialInvent.(y) = NoYes::Yes; conFinancialInventFields += _dimSearch.dimFieldId(); }
8-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
6. 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.
financialInvent.insert(_dimGroupId, inventDimParmFinancialInvent);
Prices are created for sizes allowed for this item. The Use in sales price search flag means that when looking for a price for the item, the system: 1. Searches for a match of the dimensions on the sales line to the dimensions on the price. 2. Searches for a match of only item dimensions (size, colour, configuration).
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-7
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);
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 Your use of this content is subject to your current services agreement
8-9
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.
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 Your use of this content is subject to your current services agreement
8-11
According to the status of the InventTrans record, specific fields in InventSum are updated. 4. Return to the inventSum.updateInventTrans method:
inventSumDelta.initFromInventTrans(inventTrans); inventSumDelta.initFromInventSum(inventSum); appl.inventUpdateOnhandGlobal().inventUpdateOnhand().addInv entSumDelta(inventSumDelta,inventTrans);
The inventSumDelta record is updated using data from inventTrans and inventSum. The inventUpdateOnHand class is a class held in the global cache. This is due to the frequency with which it is contructed. The inventUpdateOnHand.inventUpdateOnHand() method sets the current ttsId on the InventSumDelta record and then inserts the record in the database. 5. View the method application.ttsNotifyPreCommit()
this.inventUpdateOnhandGlobal().ttsNotifyPreCommit();
This method is called during a ttsCommit by the system classes that commit a transaction to the database.
8-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
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 Your use of this content is subject to your current services agreement
8-13
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.
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 Your use of this content is subject to your current services agreement
8-15
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
Chapter 8: Inventory
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. Note the following 1. InventDimFormSetup.parmDimParmVisibleGrid returns the InventDimParm for the visible inventory dimensions. 2. InventOnHand.AvailPhysical() returns the quantity available.
Step by Step
1. Create a display method on the SalesLine datasource in SalesTable form. 2. Use the InventOnHand class. 3. Instantiate using newParameters static method. 4. Use inventDimFormSetup.parmDimParmVisibleGrid() for InventDimParm. 5. InventOnHand.availPhysical() returns available quantity. 6. Add field to sales line using the display method.
display inventQty availPhysical(SalesLine { InventOnhand InventOnhand; ; InventOnhand = InventOnhand::newParameters(_salesLine.ItemId, _salesLine.inventDim(), element.inventDimSetupObject().parmDimParmVisibleGrid()); return inventOnHand.availPhysical(); } _SalesLine)
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-17
InventMovement
Use the InventMovement class and subclasses to check and prepare data to update inventory transactions. For instance, it is used to find if and where to post to Ledger. It is similar to a data carrier used by other classes when updating inventory data. The following figure shows the hierarchy tree for the InventMovementClass
Any lines that can have inventory transactions attached, for example, SalesLines, PurchLines, InventJournalTrans, can be used in the construct method of the class, and the appropriate sub-class is instantiated accordingly. The sub-classes control how the updates differ.
8-18
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 InventMovement::Construct() method:
InventMovement movement = InventMovement::constructNoThrow(buffer,subType,childBuffer ); if (!movement) throw error("@SYS20765"); return movement;
When instantiating the class, you can throw an error if the class cannot be instantiated. If you do no want to throw an error, call InventMovement::ConstructNoThrow directly. 3. View the InventMovement:ConstructNoThrow() method:
case tablenum(SalesLine) InventMov_Sales(buffer); : return new
Note this method tests the table id of the record that it was called with and instantiates the relevant sub-class of InventMovement. Some tables, such as SalesPickingListJournalLine have their own methods written for instantiating InventMovement. Others, such as InventJournalTrans, can instantiate different sub-classes depending on values of certain fields, like InventJournalTrans.JournalType. In this example the table is SalesLines, so InventMov_Sales is instantiated. 4. Return to the InventMovement::bufferSetTransQtyUnit() method:
qty = UnitConvert::qty(movement.transQtyUnit(), movement.transUnitId(),
The quantity is set according to the values returned from the movement.transQtyUnit(), movement.transUnitId()methods,and so on. Note that theses methods return the value of a field from the SalesLine record used to instantiate the class. Using this method enables the same methods to be used throughout the application when creating and updating inventory transactions.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-19
InventUpdate
InventUpdate is the class that creates and updates inventory transactions and is always used in conjunction with InventMovement. The following figure shows the hierarchy tree for InventMovement:
The class and subclasses are related to the base enums for inventory receipts and issues. The following figure shows the Issue Status:
8-20
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
The following figure shows the Receipt Status:
The class and subclasses are instantiated directly, rather than using a constructor on the super class. Some of the sub-classes should be instantiated using the new() method, others have static methods that can be used in certain circumstances. Once the class has been instantiated, calling updateNow() posts the required update. The sub classes are used for different types of required updates. InventUpd_Estimated creates the initial transaction when, for example, a salesLine is created. InventUpd_Physical posts the physical movement of the inventory, in other words, the inventory is received or shipped. InventUpd_Reservation reserves an outflow against an inflow.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-21
InventUpd_Financial is instantiated using InventMovement, which has previously been instantiated with SalesLine, LedgerVoucher, which contains the voucher number for posting the ledger transactions, Number, which is the invoice number, and SalesParmLine which holds the quantity and amounts to update. InventUpdFinancial.UpdateNow() posts the transaction. 2. View the InventUpdFinancial.UpdateNow() method. If the transaction has not physically posted, this is done first.
if (physical || remainPhysical != movement.remainPhysical() || physicalUnit || remainPhysicalUnit != movement.remainPhysicalUnit()) { if (financial > 0.0 && movement.mustBeReceived()) { throw error("@SYS117599"); } if (financial < 0.0 && movement.mustBeDeducted()) { throw error("@SYS117598"); } inventUpd_Physical = InventUpd_Physical::newInventUpdFinancial(movement, this, physical, physicalUnit, Currency::mstAmount(this.parmCostAmountCur(), this.parmCurrencyCode(), ledgerVoucher.lastTransDate(),
8-22
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
Some checking is then performed using inventMovement. Calculate the cost value of the transaction and post to the general ledger:
costAmountMST = movement.updateLedgerFinancial(ledgerVoucher, this); if (financial < 0) { this.updateFinancialIssue(costAmountMST); } else { if (financial > 0) { this.updateFinancialReceipt(costAmountMST); } }
Some values, such as SalesLine.RemainSalesFinancial are updated to reflect the values that have been posted. Create a reference to the posting in InventTransPosting:
this.updateInventTransPosting(ledgerVoucher.lastTransDate() , ledgerVoucher.lastVoucher());
Some values, such as SalesLine.RemainSalesFinancial are updated to reflect the values that have been posted.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-23
The InventUpd_Reservation class is instantiated using InventMovement. The second parameter determines the additional quantity to be reserved. To reserve more against an outflow, the quantity should be negative. It is not possible to reserve more than what is ordered from the sales order line. You can unreserve by specifying a positive amount.
Summary
Similar to Ledger, Inventory is closely linked to many modules within Microsoft Dynamics AX. Modifications to the inventory system can be significant with regard to work required. This lesson demonstrate both creating and posting inventory transactions, and using the data correctly after it has been posted. In addition, this lesson introduces some of the classes used to manipulate inventory data.
8-24
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-25
8-26
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
Challenge Yourself!
1. Write a routine that unreserves all open orders, and then reserve according to the classification. 2. Reserving a negative quantity removes the reservation. 3. Use InventTransIdSum to find the existing reserved quantity. 4. Attempting to reserve the total quantity on a line reserves any that are available to be reserved.
Step by Step
1. Create new Enum EDT, ReservationClassification, EnumType = ABC. 2. Add new field, type = ReservationClassifcation to CustTable, SalesTable and SalesLine. 3. Ensure SalesTable.ReservationClassification is initialized from CustTable.ReservationClassificaition. 4. Ensure SalesLine.ReservationClassification is initialized from SalesTable.ReservationClassificaition. 5. Display all new fields on relevant forms. 6. Create a new class to reserve items according to classification. 7. Find all open sales order lines. 8. Remove any reservations on the lines by reserving a negative quantity of what is already reserved. Use InventTransIdSum to find the quantity reserved. 9. Add open lines to a RecordSortedList while looping. The RecordSortedList should sort by ReservationClassifcation. 10. After all open lines are unreserved, iterate through the list and attempt to reserve the sales quantity for each line. System reserves remaining quantity, or available quantity.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-27
Challenge Yourself!
Use the SalesTable form as inspiration. Look for all references to InventDimSetupObject.
Step by Step
Inspiration for the following may be drawn from the SalesTable form. 1. Declare a form instance of InventDimCtrl_Frm_Mov. 2. Add a method UpdateDesign. Use same functionality as in SalesTable form. 3. Add inventDimSetupObject form method to return instance of InventDimCtrl_Frm_Mov. 4. Adda call to UpdateDesign to init method. 5. Set the number of columns in the grid according to the number of fields already displayed + number of invent dim fields displayed. 6. Add menu item button to call action item InventDimParmFixed.
8-28
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
Challenge Yourself!
1. InventDimFormSetup.parmDimParmVisibleGrid returns the InventDimParm for the visible inventory dimensions. 2. InventOnHand.AvailPhysical() returns the quantity available.
Step by Step
1. Add a display method to display an inventQty on SalesLine datasource: 2. Use the InventOnHand class. 3. Instantiate using newParameters static method. 4. Use inventDimFormSetup.parmDimParmVisibleGrid() for InventDimParm. 5. InventOnHand.availPhysical() returns the available quantity. 6. Add field to sales line using display method.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-29
2.
3.
8-30
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 8: Inventory
Solutions
Test Your Knowledge
1. Is the InventDimParm table a temporary table? MODEL ANSWER: Yes 2. 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. Why has the Inventory Multi-transaction Tracking system been introduced? MODEL ANSWER: To solve deadlocking in InventSum 5. True or false: An InventDimId is always unique to an itemId. MODEL ANSWER: False
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
8-31
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 subBOMs 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 Your use of this content is subject to your current services agreement
9-1
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.
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 Your use of this content is subject to your current services agreement
9-3
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 subclasses.
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.
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 subclass 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 Your use of this content is subject to your current services agreement
9-5
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.
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
Chapter 9: Production
Demonstration: Code Walkthrough - ProdUpd
ProdStatusType.RunStartUp() runs the update to Startup status. The following steps demonstrate the use of ProdUpd: 1. View the ProdStatusType_Released.RunStartUp() method:
ProdUpdStartUp prodStartUp = ProdUpdStartUp::newParmBuffer(prodParmStartUp); ; prodStartUp.run();
ProdUpdStartUp is instantiated using the parm table, and then run. 2. View the ProdUpdStartUp.run() method:
try { ttsbegin; this.setParameters(); if (! this.validate()) throw Exception::Error; viewCacheProdRoute = null; viewCacheProdRoute = ProdRoute::viewCacheProdId(prodTable.ProdId,true); this.updateProduction();
ProdUpdStartUp.setParameters() retrieves ProdTable and initializes BomCalc. It is called when component dimensions are used in the calculation of item consumption. viewCacheProdRoute activates cache on all prodRoute records for the current production order. ProdUpdStartUp.updateProduction updates to prodTable.Status, prodTable.StartedUpQty, and prodTable.StUpDate.
this.updateBOMConsumption();
ProdUpdStartUp.updateBomConsumption() creates the BOM consumption journal. If the update is set to post the BOM consumption, it also posts the journal.
prodTable.status().startUpUpdateRouteJobs(this); this.updateRouteConsumption();
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-7
Any references (production orders created due to this production order) are also updated, and the parm table record is updated to show it has been posted.
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. While scheduling a specific production, the system indicates separate operations and, if job scheduling, separates the jobs. There are a number of factors that determine when an operation or job can be scheduled. If limited material and capacity are used, then all the materials and work centers must be available. The scheduling direction and scheduling date must also be considered. To handle all the factors involved in an efficient manner, the data is stored in temporary tables and arrays. This temporary data is handled by classes that have the postfix Data; for example, production orders to be scheduled are placed into the WrkCtrMasterData data storage class. Each production order is split into route operations and held in WrkCtrRouteData. When all the temporary data has been created, the time to carry out each job or operation can be calculated, which can be applied back up through the tree of jobs, operations, routes, and productions to give starting and ending dates and times.
9-8
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 ProdUpdScheduling: 1. View the ProdUpdScheduling_Job.run() method:
setprefix(ProdMultiSchedulingJob::description()); wrkCtrParmSchedule = WrkCtrParmSchedule::newProdParmScheduling(prodParmSchedulin g); wrkCtrMasterData = new WrkCtrMasterData_Prod(); wrkCtrScheduleJob = new WrkCtrScheduleJobs_Detail(wrkCtrParmSchedule,wrkCtrMasterDa ta); super();
Some of the classes to be used are instantiated, and super() is called. 2. View the ProdUpdScheduling.run() method:
setprefix(#PrefixField(ProdParmScheduling,ProdId)); try { ttsbegin; if (! this.validate()) throw Exception::Error; wrkCtrScheduleJob.run();
After some initial validation, wkCtrScheduleJobs.run() is called. (wrkCtrScheduleJobs is instantiated as an instance of wrkCtrScheduleJob_Detail in ProdUpdScheduling_Job.run(), but wkCtrScheduleJobs.run()is not overridden). 3. View the wkCtrScheduleJobs.run() method:
try { ttsbegin; masterData.load();
wrkCtrMasterData has been instantiated as wrkCtrMasterData_Prod. The load method creates records in the TmpSchedMasterData temporary table that refer to each production order to be scheduled. This includes any child or parent production orders if the Schedule References option was selected in the Scheduling Update form.
if (!this.runMaster()) {
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-9
The scheduling direction dictates the sequence that the production orders are retrieved. Note that if references are not scheduled, only one production order is in the temporary table. setMasterStartDateTime initializes the scheduled start and end date and time to the schedule date and time.
while (doFirst) { if (this.masterDirection() == SchedDirection::Forward) doNext = masterData.last(); else doNext = masterData.first();
If the production order level is the level currently being scheduled, further checks are made, wrkCtrRouteData is instantiated, and the class array variables are populated with the data from ProdRoute records attached to the production order.
if (this.masterDirection() == SchedDirection::Forward) { this.masterSchedDate(masterData.rec_FromDate()); this.masterSchedTime(masterData.rec_FromTime()); this.routeSchedDate(masterData.rec_FromDate()); this.routeSchedTime(masterData.rec_FromTime());
9-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 9: Production
} else { this.masterSchedDate(masterData.rec_ToDate()); this.masterSchedTime(masterData.rec_ToTime()); this.routeSchedDate(masterData.rec_ToDate()); this.routeSchedTime(masterData.rec_ToTime()); }
The scheduling date on the master and route data is set according to the scheduling direction.
if (!this.runRoute()) return false;
== ==
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-11
9-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 9: Production
8. Return to wrkCtrScheduleJobs.runJobLink():
oprNum = routeData.rec_OprNum(); while (oprNum) { if (jobLinkData.first(oprNum)) { routeData.rec_FromDate(jobLinkData.rec_FromDate()); routeData.rec_FromTime(jobLinkData.rec_FromTime()); endDate = jobLinkData.rec_ToDate(); endTime = jobLinkData.rec_ToTime(); while (jobLinkData.next(oprNum)) { if (endDate < jobLinkData.rec_ToDate() || (endDate == jobLinkData.rec_ToDate() && endTime < jobLinkData.rec_ToTime())) { endDate = jobLinkData.rec_ToDate(); endTime = jobLinkData.rec_ToTime(); } }
Each operation in the route has the start and end date set according to start and end date of the jobs attached to it. 9. Return to the wrkCtrSchedule.runRoute() method:
if (this.routeSchedOk()) { routeData.savePosition(); oprNum = routeData.rec_OprNum(); while (oprNum) { routeData.update();
Each operation in the route is retrieved and routeDate.update() is called. This method using JobLinkData.update() and JobData.update() commits the data to the database.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-13
Summary
Production orders in Microsoft Dynamics AX 2009 can have many components and resources. 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 perform the calculations. Greater productivity can be achieved by automating these and other business processes.
9-14
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 9: Production
2. Which class controls whether a production order can be updated from one status to another?
3. WrkCtrRouteData is a data storage class which holds all ____________ that are in a route.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-15
Challenge Yourself!
Add a free text field Special Instructions to the production order, which is copied to the BOM journal and printed on the production order picking list.
9-16
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 9: Production
Step by Step
1. Create a new string EDT, ProdInstructions. 2. Add new field Instructions to tables ProdTable, ProdBOM and ProdJournalBOM, type = ProdInstruction. 3. Make sure ProdBOM.Instruction is initialized from ProdTable.Instruction. 4. Ensure ProdJournalBOM.Instruction is initialized from ProdBOM.Instrucation. 5. Add ProdTable.Instrution field to ProdPickList report.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-17
9-18
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 9: Production
Step by Step
1. Add new field Instructions to tables SalesTable, ReqTrans and ReqPO, type = ProdInstruction. 2. Set ReqTrans.Instructions from SalesLine.Instructions using InventTransId to look up the sales line in ReqCalc.initTransFromInventTrans(). 3. Set ReqPO.Instructions from ReqTrans.Instructions in ReqCalc.covCreatePlannedOrder(). 4. Set ReqTrans.Instructions from ReqPO.Instructions in ReqTrans.InitFromReqPO(). 5. To set the field in ProdTable when firming the order, set ProdTable.Instructions from ReqPO in ProdTable.InitFromReqPO(). 6. To set the field in ProdTable when creating a production order directly from a sales order, set ProdTable.Instructions from SalesLine in ProdTable.InitFromSalesLine().
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-19
2.
3.
9-20
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Chapter 9: Production
Solutions
Test Your Knowledge
1. Which parm table is used when updating the status from Scheduled to Released? MODEL ANSWER: ProdParmRelease 2. Which class controls whether a production order can be updated from one status to another? MODEL ANSWER: ProdStatusType 3. WrkCtrRouteData is a data storage class which holds all ____________ that are in a route. MODEL ANSWER: WrkCtrRouteData is a data storage class that holds all operations that are in a route.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
9-21
9-22
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Introduction
The Project module is used to estimate and record costs and revenue transactions against individual projects, which calculates running costs, total costs of the project, and invoices customers for costs incurred. This lesson describes how the project module is designed, how transactions are created and posted, and how invoices are created.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-1
Scenario
The Servicing department has asked Isaac, the System Developer, to make some modifications to the project module. The project module in Contoso is used to track time and costs used while installing and servicing home theatre equipment. Some work is billable, other work is carried out under warranty.
Design
Transactions posted against projects can be one of five different types: Hour (Employee), Cost, Revenue, Item, and On Account. Rather than use a Type field on one table and many redundant fields, project transactions are recorded in five tables. Once transactions are posted against projects, an invoice proposal can be created. The system creates a suggested invoice based on user defined criteria. Different transactions are stored in five different tables. When transactions are invoiced, they are stored in another set of five tables. CustTable: Each invoice project is attached to a customer for invoicing and payment. ProjInvoiceTable: At least one invoice project is created for each customer. Invoice projects allows you to create multiple projects for one customer, and invoice at the same time. ProjTable: This is the main table for projects. Each project has one record in ProjTable. ProjProposalJour: When an invoice proposal is created, the header record is held in ProjProposalJour. ProjInvoiceJour: Each invoice created has a header record in ProjInvoiceJour. ProjEmplTrans, ProjProposalEmpl, ProjInvoiceEmpl: Contain transactions related to hours spent working on a project by an employee. ProjCostTrans, ProjProposalCost, ProjInvoiceCost: Contain transactions related to costs incurred by the project. ProjRevenueTrans, ProjProposalRevenue, ProjInvoiceRevenue: Contain transactions related to revenue created by the project. ProjItemTrans, ProjProposalItem, ProjInvoiceItem: Contain transactions related to item consumption by the project. ProjOnAccTrans, ProjProposalOnAcc, ProjInvoiceOnAcc: Contain pre-arranged invoice amounts.
10-2
Microsoft Official Training Materials for Microsoft Dynamics 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. ProjTrans has a sub-class for each transaction type, and each subclasse has a sub-class for all the stages in a project.
For instance, the ProjTransCostTrans.invoiced() method returns true if the cost transaction has already been invoiced.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-3
If a ProjInvoiceCost record exists with a matching transaction id, the transaction has already been invoiced.
Posting Transactions
When posting transactions against a project, journals are used. Cost transactions use a ledger journal, item consumption transactions use an inventory journal, and hours and revenue transactions use a project journal. On Account transactions are created directly in the ProjOnAccTrans table. When invoiced, ledger transactions are attached to the On Account transaction records. Project journals are handled similar to inventory and ledger journals. You must use a journal name from an existing ProjJournalName record to create a journal header in ProjJournalTable, and then add lines in ProjJournalTrans. Use ProjJournalCheckPost to post the journal. All transaction types are created in a Proj...Trans table. When ledger or inventory journals are posted and ProjId is marked on the line, they create ProjCostTrans or ProjItemTrans records.
10-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Invoice Proposal
Project invoices are created by using an invoice proposal. This proposal is populated according to selections made by the user, which can be modified if necessary and then posted. Invoice proposals are created using the ProjInvoiceChoose super class and sub classes. On account transactions use a specific sub-class. When ProjInvoiceChoose is run, the user is prompted to select which type of transactions are to be invoiced and can also delimit the transactions using the query. This query is executed to retrieve any un-invoiced transactions and populate the ProjProposal transaction tables.
The progress bar is initialized. The initQuery() method updates the query according to selections made by the user. If a transaction type is to be excluded the corresponding datasource is disabled in the query. From and To dates specified by the user are also entered into the query.
while (queryRun.next()) { this.assignTables();
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-5
Records returned by the query are placed in appropriate table variables. ProjInvoiceChoose.run() then calls ProjInvoiceChooseNormal.doProposal(). 3. View the ProjInvoiceChooseNormal.doProposal() method:
if (queryEmpl & queryRun.changed(tablenum(ProjEmplTrans))) this.doEmpl(); if (queryCost && queryRun.changed(tablenum(ProjCostTrans))) this.doCost(); if ((queryRevenue || querySubscription) && queryRun.changed(tablenum(ProjRevenueTrans))) this.doRevenue();
For each transaction type, if the record has changed, a method populates the ProjProposal transaction tables. 4. View the ProjInvoiceChoose.doEmpl() method:
if(this.parmProjEmplTrans() && this.parmProjEmplTrans().canBeInvoiced()) {
If a transaction record exists and has not been invoiced, the transaction can be added to this proposal.
this.setProjProposalJour(this.parmProjEmplTrans().CurrencyI d); this.progressUpdate(strfmt("@SYS26810",this.parmProjEmplTra ns().ProjId,this.parmProjEmplTrans().TransDate));
10-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
The projProposalEmpl record is initialized from the ProjEmplTrans record and the invoice proposal header. After validation, the projProposalEmpl record is committed to the database.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-7
Invoice
Invoicing takes place in the ProjFormLetter class and the ProjFormLetter_Invoice sub-class. The structure for these classes is similar to the FormLetter classes used in Accounts Receivable (AR) and Accounts Payable (AP).
Invoices are created from Invoice proposals, so projProposalJour must exist. If the job is running in batch, some tasks are created to improve performance, otherwise the createJournal() method is called 2. View the ProjFormLetter.createJournal() method:
projProposalJour.InvoiceDate = projInvoiceParmTable.InvoiceDate; projProposalTotals = new ProjProposalTotals(projProposalJour, parmId); projProposalTotals.calc(); this.tax(projProposalTotals.tax()); recordListProjProposalCost = projProposalTotals.recordListProjProposalcost(); recordListProjProposalEmpl = projProposalTotals.recordListProjProposalEmpl(); recordListProjProposalRevenue = projProposalTotals.recordListProjProposalRevenue();
10-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Totals are calculated and the project transactions are put into lists which can be used by the invoicing process.
if (proforma) this.insertProforma(); else this.insertJournal();
The bulk of the work is done in updateNow(), which is overridden in the subclass. 4. View the ProjFormLetter_Invoice.UpdateNow() method:
this.initTransactionTxt(creditNote ? LedgerTransTxt::ProjectCreditNoteLedger : LedgerTransTxt::ProjectInvoiceLedger, projProposalJour); this.initLedgerVoucher(); this.initMarkup(); projProposalJour = this.getProjProposalJour(projInvoiceParmTable, true);
Ledger voucher, transaction texts, and the invoice journal are initialized.
this.createProjInvoiceEmpl(); this.createProjInvoiceCost(); this.createProjInvoiceRevenue(); this.createProjInvoiceItem(); this.createProjInvoiceOnAcc(); this.createProjInvoiceSalesLine();
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-9
Summary
This lesson discusses how to design the project module, how to create and post transactions, and how to create invoices. From this you should learn: About the structure and design of the project module. How to post transactions to the project module. How to make modifications to the project invoice proposal procedure. How to make modifications to the project invoice procedure.
10-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
2. In which class would you find a method that returns whether an employee hours transaction has already been invoiced?
3. When posting a project invoice, which method calls the project totals calculation method - projProposalTotals.calc()?
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-11
Challenge Yourself!
Add a WarrantyItemId field, type = itemId to the journal lines used for employee time entry, and ensure this item id is also copied to the appropriate project transactions when the journal is posted.
Step by Step
1. Create a new string EDT, ProjWarrantyItemId. 2. Add a new field, WarrantyItemId, type = ProjWarrantyItemId to table ProjJournalTrans and ProjEmplTrans. 3. Set ProjEmplTrans.WarrantyItemId = ProjJournalTrans.WarrantyItemId in static table method ProjEmplTrans::InitTransFromJournal().
10-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Challenge Yourself!
Enable an invoice proposal to be put on hold. This requires a new field, OnHold, type = NoYes. If this field is set, then the invoice cannot be posted, and a new invoice proposal can be created that may include transactions that were included on the OnHold proposal.
Step by Step
1. Add a new NoYes field, OnHold to ProjProposalJour. 2. Display this field on form ProjInvociceProposal. 3. In the classes, ProjTransCostTrans, ProjTransEmplTrans, ProjTransItemTrans, ProjTransOnAccTrans, ProjTransRevenueTrans, modify the method proposal(), to return false if a proposal transaction exists, but is on hold.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-13
2.
3.
10-14
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Solutions
Test Your Knowledge
1. True or False: A project is linked to the customer table through ProjTable.CustAccount. MODEL ANSWER: False 2. In which class would you find a method that returns whether an employee hours transaction has already been invoiced? MODEL ANSWER: ProjTransEmplTrans 3. When posting a project invoice, which method calls the project totals calculation method - projProposalTotals.calc()? MODEL ANSWER: CreateJournal
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
10-15
10-16
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Introduction
Workflow is a module in Microsoft Dynamics AX 2009, that allows flexible task and approval routes for documents created by users. For example, a purchase requisition may need to be approved by a number of different employees according to the requisition's total amount, and each employee has to approve it before the next employee in the approval route. 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. This lesson introduces the development side of creating an workflow, for which you will need to use skills developed from this class and the Morph X development class.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-1
Scenario
Isaac, the systems developer, 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. The requirement is that when a new sales order is entered that takes the customer over their credit limit, the sales order should be submitted to the Accounts Receivable (AR) manager. They will either approve or deny the sales order. Until it is approved, the sales order cannot be picked, packed or invoiced.
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. Workflow website. This is an IIS website that controls the flow of the workflows. Workflow accounts. There are two accounts used - a system account used to provide access to the workflow tables, and an execution account that is used to execute business logic. Microsoft Dynamics AX workflow server component. This is the workflow engine and is installed using the Microsoft Dynamics AX installation files. The website and the accounts are required to run this installation.
NOTE: This course does not cover the installation of the workflow system components; however you need to be aware of the requirements. For more information about workflow installation, refer to the Administrator Guide.
11-2
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
FIGURE 11.1
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-3
FIGURE 11.2
11-4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-5
FIGURE 11.3
11-6
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
FIGURE 11.4
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-7
11-8
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
1. 2. 3. 4. 5. 6. 7. 8. 9.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-9
11-10
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-11
WorkflowCanceledEventHandler
WorkflowConfigDataChangeEventHandler
11-12
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
public void cancelled(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable; ; ttsbegin; select forupdate SalesTable where SalesTable.RecId == _workflowEventArgs.parmWorkflowContext().parmRecId(); SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::NotSubmitted; SalesTable.update(); ttscommit; } public void completed(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable; ; ttsbegin; select forupdate SalesTable where SalesTable.RecId == _workflowEventArgs.parmWorkflowContext().parmRecId(); if (salesTable.CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Submitted) { SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Approved; SalesTable.update(); } ttscommit; }
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-13
public void returned(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable; ; ttsbegin; select forupdate SalesTable where SalesTable.RecId == _workflowEventArgs.parmWorkflowContext().parmRecId(); SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Rejected; SalesTable.update(); ttscommit; } public void started(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable; ; ttsbegin; select forupdate SalesTable where SalesTable.RecId == _workflowEventArgs.parmWorkflowContext().parmRecId(); SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Submitted; SalesTable.update(); ttscommit; }
11-14
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
WorkflowElementCanceledEventHandler
WorkflowElementCompletedEventHandler
WorkflowElementReturnedEventHandler
WorkflowElemChangeRequestedEventHandler
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-15
class SalesCreditLimitElementHandler implements WorkflowElementCompletedEventHandler, WorkflowElementCanceledEventHandler, WorkflowElementReturnedEventHandler, WorkflowElemChangeRequestedEventHandler, WorkflowElementStartedEventHandler { } public void returned(WorkflowEventArgs _workflowEventArgs) { SalesTable SalesTable; ; ttsbegin; select forupdate SalesTable where SalesTable.RecId == _workflowEventArgs.parmWorkflowContext().parmRecId(); SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Rejected; SalesTable.update(); ttscommit; }
11-16
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Configure a Workflow
Now that you have created a template and enabled it on a form, you can configure it for use.
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-17
11-18
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Challenge Yourself!
Add conditions to the posting functions on the sales order form that will prevent posting to picking, packing or invoicing until the workflow has been approved. If the credit limit has not been reached, then the postings should be allowed.
Step by Step
1. Add the following method CanPostCreditLimit to the salesTable table. 2. Add the following code to the methods canPickingListBeUpdate(), canPackingSlipBeUpdated() and canInvoiceBeUpdated() in the salesTableType class.
boolean canPostCreditLimit() { amountMST creditBalance; custTable custTable; ; if (this.CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Approved) return true; if (this.CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Rejected || this.CreditLimitApprovalStatus == SalesCreditLimitApprovalStatus::Submitted) return false; custTable = this.custTable_InvoiceAccount(); if (!custTable.CreditMax) return true; creditBalance = custTable.CreditMax custTable.balanceMST(); if (this.amountRemainSalesFinancial() + this.amountRemainSalesPhysical() < creditBalance) return true; return false;
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-19
11-20
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
The tableId that the workflow is to be performed on is retrieved from the query specified in the workflow document class. The workFlowContext class holds all the relevant data for the workflow submission. 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.
workflowContext = WorkflowContext::newRootWorkflowContext(curext(), tableId, _recId, correlationId); try { SysWorkflowEventDispatcher::onWorkflowSubmit(workflowContex t, _submittingUser, configTable.ConfigurationId, _initialNote, _activatingFromWeb); }
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-21
All records due for processing are retrieved. The WorkflowWorkItem::escalateWorkItem() is called 2. View the method WorkflowWorkItem::escalateWorkItem()
try { workItemId = SysWorkflowEventDispatcher::onWorkItemEscalation(_workItemC ontext); }
The workItemTable record is retrieved. This is the next pending activity on the workflow, based on the configuration.
11-22
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-23
Challenge Yourself!
When a workflow is rejected, it should be able to be resubmitted. Modify the Submit to Workflow class so that it can resubmit the workflow after a rejection Use the PurchReqWorkflow class as inspriration.
Step by Step
1. Create a new action menu item called SalesCreditLimitResubmit 2. Set the ObjectTypePropety to class, the Object property to SalesCreditLimitSubmit and the Label property to Resubmit. 3. Modify the Main method on the SalesCreditLimitSubmit class and add a new method Resubmit as follows: 4. On the SalesCreditLimitApproval approval element, set the ResubmitMenuItem property to SalesCreditLimitResubmit
public static void main(Args _args) { SalesCreditLimitSubmit SalesCreditLimitSubmit = new SalesCreditLimitSubmit(); ; if (_args.menuItemName() == menuitemactionstr(SalesCreditLimitSubmit)) { SalesCreditLimitSubmit.submit(_args); } else { SalesCreditLimitSubmit.resubmit(_args); } } void resubmit(Args args) { // Variable declaration. recId _recId = args.record().RecId; WorkflowCorrelationId _workflowCorrelationId; // Hardcoded template name WorkflowTemplateName _workflowTemplateName = workflowtemplatestr(SalesCreditLimitApproval);
11-24
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
if (WorkflowWorkItemActionDialog.parmIsClosedOK()) { _recId = args.record().RecId; SalesTable = args.record(); // Get comments from the submit to workflow dialog. _initialNote = workflowWorkItemActionDialog.parmWorkflowComment(); try { ttsbegin;
WorkflowWorkItemActionManager::dispatchWorkItemAction( args.caller().getActiveWorkflowWorkItem(),
_initialNote, curUserId(), WorkflowWorkItemActionType::Resubmit, args.menuItemName(), false); SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Submitted; // Send an Infolog message. info("Resubmitted to workflow.");
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-25
Summary
The workflow module is a highly configurable and flexible module. However, by using Morph X and some standard code templates, it can be configured for any part of the Microsoft Dynamics AX application. This lesson explores some of the possibilities the workflow framework offers, and explores some of the different ways it can be used to cover most workflow requirements.
11-26
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
11-27
2.
3.
11-28
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement
Solutions
Test Your Knowledge
1. 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. 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. There are three types of providers that define what rules the workflow can follow. What are they? () Participant provider () DueDate provider () Hierarchy provider ( ) Internet provider 4. 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 Your use of this content is subject to your current services agreement
11-29
11-30
Microsoft Official Training Materials for Microsoft Dynamics Your use of this content is subject to your current services agreement