Using The Refactored Formletter Framework AX2012
Using The Refactored Formletter Framework AX2012
Date: May 2011 http://microsoft.com/dynamics/ax Author: Kenneth Puggaard, Senior Development Lead Send suggestions and comments about this document to [email protected]. Please include the white paper title with your feedback.
Table of Contents
Introduction ................................................................................................ 3 Background ................................................................................................. 3 The formletter framework in Microsoft Dynamics AX 2012 ......................... 5
The FormLetterServiceController class ..................................................................................... 8 The FormLetterContract class ................................................................................................. 9 The FormletterService class ..................................................................................................10 The FormletterParmData class ...............................................................................................11 The FormletterJournalCreate class .........................................................................................12 The FormletterJournalPost class .............................................................................................13 The FormletterJournalPrint class ............................................................................................15 The FormletterProvider class .................................................................................................15 Where to place Microsoft Dynamics AX 2009 customizations .....................................................16
Introduction
The formletter framework in Microsoft Dynamics AX is used when posting documents for sales or purchase orders. This framework has been refactored in Microsoft Dynamics AX 2012 to provide better support for customizations, extensibility, and performance. This document describes the Microsoft Dynamics AX 2012 version of the framework.
Background
In Microsoft Dynamics AX 2009, the formletter framework consisted of the following objects: The FormLetter base class that extended RunBaseBatch. Module-specific classes that extended the FormLetter class, such as SalesFormLetter. A number of document-specific classes that extended the module class, such as SalesFormLetter_PackingSlip.
This set of classes had a number of functions, including the following: Interaction with the posting form, such as SalesEditLines. Creation and maintenance of posting data, such as records in SalesParmTable. Creation of journal data, such as records in CustPackingSlipJour/CustPackingSlipTrans. Validations. Updating subledgers, such as ledger and inventory. Controlling document outputs, such as printing and XML export. Client/server marshaling.
RunBaseBatch
FormLetter
PurchFormLetter
SalesFormLetter
ProjFormLetter
PurchRFQFormLetter
PurchFormLetter_PurchOrder
SalesFormLetter_Confirm
ProjFormLetter_Invoice
PurchRFQFormLetter_Send
PurchFormLetter_ReceiptsList
SalesFormLetter_PickingList
PurchRFQFormLetter_Accept
PurchFormLetter_PackingSlip
SalesFormLetter_PackingSlip
PurchRFQFormLetter_Reject
PurchFormLetter_Invoice
SalesFormLetter_PackingSlipProject
PurchRFQFormLetter_ReSend
SalesFormLetter_Invoice
SalesFormLetter_InvoiceProject
SalesFormLetter_FreeText
Figure 1: Class diagram: Formletter framework in Microsoft Dynamics AX 2009 Because the FormLetter classes had so much functionality and no well-defined APIs in Microsoft Dynamics AX 2009, they were complex for developers to understand and customize.
FormLetterContract
uses
FormletterJournalPost
FormletterProvider
The Microsoft Dynamics AX 2009 base FormLetter class has been split into eight base classes. It also has been changed to run under the SysOperation framework. Switching to the SysOperation framework has the advantage of executing the code on the server tier during posting in IL (intermediate language). Because of the switch to using the SysOperation framework, client callbacks from code running on the server tier are no longer supported. Client callbacks result in an exception.
Figure 3 shows how the various base classes are used when posting a document for an order.
Class FormletterParmData Class FormLetterServiceController main() construct() Form Posting form Class FormLetterContract
Class FormletterService
Class FormletterJournalCreate
createData()
run()
pack()
run()
run()
printJournal() afterOperation()
Figure 4 shows how the various class hierarchies are used when posting a sales order packing slip document.
Class SalesFormletterParmDataPacking slip Class SalesFormLetter_PackingSlip main() construct() Form SalesEditLines Class SalesFormLetterPackingSlipCont ract
Class FormletterService
Class SalesPackingSlipJournalCreate
createData()
run()
pack()
run()
run()
printJournal() afterOperation()
SysOperationServiceController
FormLetterServiceController +run()
SalesFormLetter_Confirm
SalesFormLetter_PickingList
PurchFormLetter_PurchOrder
PurchFormLetter_ReceiptsList
SalesFormLetter_PackingSlip
SalesFormLetter_Invoice
PurchFormLetter_PackingSlip
PurchFormLetter_Invoice
Figure 5: Class diagram: FormLetterServiceController class hierarchy The module-specific classes from Microsoft Dynamics AX 2009, such as SalesFormLetter, have been changed so that they now extend the FormLetterServiceController class. All functionality that does not relate to the interaction with the posting form has been moved to other class hierarchies. The class variables that were assigned a value to be used during the posting process have been moved to the data contract classes. The pattern used for assigning values to the data contract classes is that the parm methods from Microsoft Dynamics AX 2009 have been changed to utilize the data contract class instead of using a global class variable. The following code sample is an example of a parm method:
public boolean parmDirectDeliveryUpdate(boolean _directDeliveryUpdate = salesFormletterContract.parmDirectDeliveryUpdate()) { return salesFormletterContract.parmDirectDeliveryUpdate(_directDeliveryUpdate); }
SalesFormLetterContract
PurchFormLetterContract
SalesFormLetterConfirmContract
SalesFormLetterPickingListContract PurchFormLetterPurchOrderContract
PurchFormLetterReceiptsListContract
SalesFormLetterPackingSlipContract
SalesFormLetterInvoiceContract
PurchFormLetterPackingSlipContract
PurchFormLetterInvoiceContract
SalesFormLetterFreeTextContract
PurchFormLetterApprovalContract
Figure 6: Class diagram: FormLetterContract class hierarchy Parm methods are used to set and get the data from a contract class. The following code sample is an example of a parm method:
[DataMemberAttribute] public NoYes parmDirectDeliveryUpdate(NoYes _directDeliveryUpdate = directDeliveryUpdate) { directDeliveryUpdate = _directDeliveryUpdate; return directDeliveryUpdate; }
FormletterService +run() +postSalesOrderConfirmation() +postSalesOrderPickingList() +postSalesOrderPackingSlip() +postSalesOrderInvoice() +postPurchaseOrderConfirmation() +postPurchaseOrderReceiptList() +postPurchaseOrderPackingSlip() +postPurchaseOrderInvoice()
Figure 7: Class diagram: FormletterService The run method posts documents. The following code roughly shows the pattern used in the run method in the service.
If (lateSelection)//If the late selection option is used. { formletterParmData.CreateData() //Create posting data. } While (next parmTable) //Loop over posting data, one parmTable record per journal. { formletterJournalCreate.Run(); //Create one journal. formletterJournalPost.Run(); //Post one journal. If (printOut == Current) //If printing after each posted journal. { formletterJournalPrint.PrintJournal(); //Print current posted journal. } } If (printOut == After) //If printing all journals after posting. { formletterJournalPrint.PrintJournal(); //Print all posted journals. }
The class also has a service operation method for each of the document types that can be posted by this service, such as PostSalesPackingSlip.
[SysEntryPointAttribute] FormletterOutputContract postSalesOrderPackingSlip(SalesFormletterPackingSlipContract _contract) { formletterContract = _contract; this.run(); return outputContract; } 10 USING THE REFACTORED FORMLETTER FRAMEWORK
SalesFormletterParmData
PurchFormletterParmData
SalesFormletterParmDataConfirm
SalesFormletterParmDataPickingList
PurchFormletterParmDataPurchOrder
PurchFormletterParmDataReceiptList
SalesFormletterParmDataPackingslip
SalesFormletterParmDataInvoice
PurchFormletterParmDataPackingSlip
PurchFormletterParmDataInvoice
PurchFormletterParmDataApproveJournal
PurchInvoiceJournalCreate
FormLetterJournalCreateVersioning PurchApproveJournalCreate
FormLetterJournalCreateInitialVersion
FormLetterJournalCreateCorrection
Figure 9: Class diagram: FormletterJournalCreate class hierarchy There are also document specific classes for each of the documents that can be created by the framework, such as SalesPackingSlipJournalCreate. These classes hold the logic specific for a document. Those document classes that support having multiple versions of the same document extend the FormletterVersionableJournalCreate class. The FormletterService class instantiates this class hierarchy for each of the journals it needs to create and calls run.
The FormletterService class instantiates this class for each of the journals it needs to post and calls run. Figure 10 is an illustration of the FormletterJournalPost class hierarchy.
SalesConfirmJournalPost
SalesPickingListJournalPost
PurchPurchOrderJournalPost
PurchReceiptsListJournalPost
Class SalesPackingSlipJournalPost
SalesInvoiceJournalPost
PurchPackingSlipJournalPost
PurchInvoiceJournalPost
PurchApproveJournalPost
SalesConfirmJournalPrint
SalesPickingListJournalPrint
PurchPurchOrderJournalPrint
PurchReceiptListJournalPrint
SalesPackingSlipJournalPrint
SalesInvoiceJournalPrint
PurchPackingSlipJournalPrint
PurchInvoiceJournalPrint
FormletterProvider
FormletterProviderNull
SalesFormletterProvider
PurchFormletterProvider
SalesFormletter
SalesFormletter_Confirm
Creating parm data Creating journal data Posting a journal Printing Interacting with SalesEditLines form
SalesFormletter_PickingList
Creating parm data Creating journal data Posting a journal Printing Interacting with SalesEditLines form
SalesFormletter_PackingSlip
Creating parm data Creating journal data Posting a journal Printing Interacting with SalesEditLines form
SalesFormletter_Invoice
Creating parm data Creating journal data Posting a journal Printing Interacting with SalesEditLines form
PurchFormletter
PurchFormletter_PurchOrder
Creating parm data Creating journal data Posting a journal Printing Interacting with PurchEditLines form
PurchFormletter_PickingList
Creating parm data Creating journal data Posting a journal Printing Interacting with PurchEditLines form
PurchFormletter_PackingSlip
Creating parm data Creating journal data Posting a journal Printing Interacting with PurchEditLines form
PurchFormletter_Invoice
Creating parm data Creating journal data Posting a journal Printing Interacting with PurchEditLines form
Yes
No
Post journals
Post journals
Post journals
End posting
Done
FormletterService +run()
FormletterService +run()
FormletterServiceMultithread
Use
Creating posting data for each order passed to the class. Rearranging the posting data based on the summary update settings. Utilizing the FormletterServiceMultithread class to post the journals passed to the class. Finalizing the posting process.
FormletterServiceBatchTask
FormletterParmDataCreateDataBatchTask
FormletterServiceEndBatchTask
FormletterParmDataRearrangeBatchTask uses
FormletterServiceMultithread
FormletterService +run()
Microsoft Dynamics is a line of integrated, adaptable business management solutions that enables you and your people to make business decisions with greater confidence. Microsoft Dynamics works like and with familiar Microsoft software, automating and streamlining financial, customer relationship and supply chain processes in a way that helps you drive business success. U.S. and Canada Toll Free 1-888-477-7989 Worldwide +1-701-281-6500 www.microsoft.com/dynamics
This document is provided as-is. Information and views expressed in this document, including URL and other Internet Web site references, may change without notice. You bear the risk of using it. Some examples depicted herein are provided for illustration only and are fictitious. No real association or connection is intended or should be inferred. This document does not provide you with any legal rights to any intellectual property in any Microsoft product. You may copy and use this document for your internal, reference purposes. You may modify this document for your internal, reference purposes. 2011 Microsoft Corporation. All rights reserved. Microsoft, Microsoft Dynamics, and the Microsoft Dynamics logo are trademarks of the Microsoft group of companies. All other trademarks are property of their respective owners.