319 21 512KB
English Pages 142
MorphX Integration
MorphX Integration
Disclaimer: This material is for informational purposes only. Microsoft Business Solutions ApS disclaims all warranties and conditions with regard to use of the material for other purposes. Microsoft Business Solutions ApS shall not, at any time, be liable for any special, direct, indirect or consequential damages, whether in an action of contract, negligence or other action arising out of or in connection with the use or performance of the material. Nothing herein should be construed as constituting any kind of warranty.
Copyright Notice: Copyright © 2002 Microsoft Business Solutions ApS, Denmark.
Trademark Notice: Microsoft, Great Plains, bCentral and Microsoft Windows 2000 are either registered trademarks or trademarks of Microsoft Corporation or Microsoft Business Solutions Corporation in the United States and/or other countries. Microsoft Business Solutions Corporation and Microsoft Business Solutions ApS are wholly owned subsidiaries of Microsoft Corporation. Navision is a registered trademark of Microsoft Business Solutions ApS in the United States and/or other countries. The names of actual companies and products mentioned herein may be the trademarks of their respective owners. No part of this document may be reproduced or transmitted in any form or by any means, whole or in part without the prior written permission of Microsoft Business Solutions ApS. Information in this document is subject to change without notice. Any rights not expressly granted herein are reserved
TABLE OF CONTENTS
LESSON 1. WELCOME TO MICROSOFT® BUSINESS SOLUTIONS– AXAPTA® MORPHX INTEGRATION 1-1 1.1 Introduction
1-1
LESSON 2. BASIC GUIDELINES
2-1
2.1 Project Design Guidelines
2-1
2.2 Integration Possibilities
2-2
LESSON 3. AXAPTEL
3-1
3.1 Axaptel
3-2
3.2 Exercises
3-3
LESSON 4. USING THE JOURNALS
4-1
4.1 Journals
4-1
4.2 Creating the Journal
4-2
4.3 Creating Transactions
4-3
4.4 Posting Journals
4-4
4.5 Exercises
4-7
LESSON 5. USING API
5-1
5.1 Using APIs
5-1
5.2 APIs in General Ledger
5-2
5.3 Trade Series APIs
5-6
5.4 Inventory Management APIs
5-13
5.5 Production Series
5-15
5.6 Number Sequences
5-16
5.7 Exercises
5-21
LESSON 6. USING THE COM INTERFACE
6-1
6.1 What Are COM Objects
6-1
6.2 MS-Agent
6-2
6.3 Axapta Business Connector
6-3
6.4 Exercises
6-4
LESSON 7. ACTIVE X
7-1
7.1 What Is ActiveX
7-1
7.2 ActiveX Explorer
7-2
7.3 Exercises
7-3
LESSON 8. EDITOR SCRIPTS
8-1
8.1 Editor Scripts
8-1
8.2 Exercises
8-2
LESSON 9.
DYNAMIC LINK LIBRARY
9-1
9.1 Use of Dynamic Link Libraries
9-1
9.2 WinApi
9-2
9.3 VarChart
9-3
9.4 Exercises
9-4
LESSON 10. THE RUNBASE CLASS
10-1
10.1 The RunBase class
10-2
10.2 Exercises
10-9
LESSON 11. THE BATCH SYSTEM
11-1
11.1 The Batch System
11-1
11.2 RunBaseBatch
11-2
11.3 Exercises
11-4
LESSON 12. FOUNDATION CLASSES
12-1
12.1 Foundation Classes
12-2
12.2 List
12-3
12.3 Set
12-5
12.4 Map
12-6
12.5 Array
12-7
12.6 Struct
12-8
12.7 Exercises
12-9
LESSON 13. GANTT CLASSES
13-1
13.1 Gantt Classes
13-2
13.2 Projects, Inquiry, Gantt Chart
13-3
13.3 Exercises
13-4
APPENDIX A. WELCOME TO AXAPTA INTEGRATION
I
General Information
II
Before You Start the Class:
IV
Beginning the Course
V
Notes to Introduction Lesson
VI
APPENDIX B. BASIC GUIDELINES
I
Basic Guidelines
II
APPENDIX C. AXAPTEL
I
Axaptel
II
Exercise Solutions
III
APPENDIX D. USING THE JOURNALS
I
Instructor Notes
II
Exercise Solutions
IV
APPENDIX E. USING API
I
Instructor Notes
II
Exercise Solutions
V
APPENDIX F. USING THE COM INTERFACE
I
Using the COM Interface
II
Exercise Solutions
IV
APPENDIX G. ACTIVE X
I
Instructor Notes
II
Exercise Solutions
III
APPENDIX H. EDITOR SCRIPTS
I
Instructor Notes
II
Exercise Solutions
III
APPENDIX I. DYNAMIC LINK LIBRARY
I
Instructor Notes
II
Exercise Solutions
III
APPENDIX J. THE RUNBASE CLASS
I
Instructor Notes
II
Exercise solutions
III
APPENDIX K. THE BATCH SYSTEM
I
Instructor Notes
II
Exercise Solutions
III
APPENDIX L. FOUNDATION CLASSES
I
Instructor Notes
II
Exercise Solutions
III
APPENDIX M. GANTT CLASSES
I
Instructor Notes
II
Exercise Solutions
III
Lesson 1. Welcome to Microsoft® Business Solutions–Axapta® MorphX Integration
At the end of this course, you are expected to be able to: Understand the basic concepts of integration to Axapta Have reviewed the philosophy of several main application programming interfaces used in Axapta Have viewed examples of several main application programming interfaces used in Axapta Be prepared to build your own integrated Axapta applications. Have learned about the COM interface
AX-300-ILT-053-v01.00-ENUS
Welcome to Microsoft® Business Solutions–Axapta® MorphX Integration
1-1
1.1 INTRODUCTION Now you are finished with the MorphX Standards class, and know what the standards of programming are in Axapta. To make your product ready for market, you must integrate your product into Axapta. This course will guide you through the integration process.
About this class In this class you will understand how to create your own projects and integrate those into Axapta. You will get the basic concepts of how additional modules, such as the API (Application Programming Interface) classes can be added to Axapta. Furthermore, you will learn about best practices when developing new projects and how journals can be used in connection with integration to Axapta. The main objective of this course is that the students can create new projects integrated with the standard application.
Course Prerequisites
• • •
Successful completion of the MorphX Essentials and the X++ Basic online courses. It is highly recommended that you have completed the X++ Advanced Classroom course. At least 6 month working knowledge of the application and development environment.
General This Course is comprised of a series of lessons, each explaining a range of specific subjects and functionalities which belong together in Axapta. All lessons are developed in relation to common business logic, and the subjects and functionalities are presented within the perspective of the usual business procedures familiar to most users. This material is a supplement to the instructor’s explanation during the course and not tailored for individual studies without tutoring. In the beginning of each lesson you will find a brief overview of the lesson and a list of objectives, informing you what subjects and functionalities you will get to know in the specific lesson. In each lesson there will be examples; the examples make it easier for you to refer the theoretical
Welcome to Microsoft® Business Solutions–Axapta® MorphX Integration
1-2
aspects of the course to how Axapta works outside classroom training. At the end of each lesson you will find exercises. The exercises are designed to give you a hands-on experience with the functionality described.
Lesson 2. Basic Guidelines
AX-300-ILT-054-v01.00-ENUS
2-1
Basic Guidelines
2.1 PROJECT DESIGN GUIDELINES When a new project is created in Axapta, it should be designed in a manner so that the least possible changes in main Axapta need to be made in the standard application. This will result in efficient time management in updating your product when new versions of Axapta are released. Items like APIs and journals are not likely to change. This consistency is the key to successful Axapta integration. APIs –Application Programming Interface classes, are especially developed for easy integration into Axapta. As a first step in planning your project, find out what kind of APIs are in Axapta and how they can be used.
General Recommendations ∙
For all third party projects in Axapta, it is strongly recommended that the project “stands alone” as much as possible.
∙
Do not, unless absolutely necessary, change the standard Axapta application itself.
2-2
Basic Guidelines
2.2 INTEGRATION POSSIBILITIES There are two basic ways of product integration into Axapta: using Journals and using APIs.
Journals Journals are meant to be tables with lists of transactions to be performed. The functions used to enter data into journals are simple. So it is very easy to use them as a mode of integration into Axapta. Indigenous to your project you can create a method for entering data in a journal, and then post the journal manually or by calling journal posting and finally give the user the possibility to post the journal automatically. In this manner, you will be ensured that transactions are created and controlled on basis of the Axapta Business Logic (the rules applied in the standard application) since all your data will be checked, and posted by Axapta routines. This manner also results in the flexibility to overview your journal and post it manually.
APIs To use APIs is another way of doing the job, but developing wise it is more complex. This method will result in better performance since transactions are directly made using the same classes that Axapta uses. APIs are classes especially designed to be reused in other parts of the application, in order to get direct access to a specific module. Since Axapta applications are made by several groups of programmers, APIs from each group are slightly different. The difference is in the way these APIs can be used: One group of APIs requires only initialization of an instance and then parses parameters to it. Other groups of APIs need to be loaded into a new class. For more detailed information about groups of APIs, and specific instances, see the Lesson – Using APIs, in this document.
Lesson 3. Axaptel
At the end of this lesson, you are expected to be able to: Know about the data model which you will use throughout this course
AX-300-ILT-055-v01.00-ENUS
3-2
Axaptel
3.1 AXAPTEL A new module for hotel management will be developed for Axapta. Primarily, the module will enable customers to make room reservations within specified date intervals. It should also be possible to keep an account of the extra costs associated with the hotel bill, for example, room service, minibar or nightclub. The database design for this module will resemble the following:
Base Enums
HotelRoomType
Extended Data Types
HotelBookingId
STR 10
Tables
HotelBookingTable
ENUM
Single
Ref: HotelBookingTable.
HotelRoomTable
HotelBookingId
Double
HotelRoomId STR 10
Executive
Ref: HotelRoomTable. HotelRoomId
HotelExpenseType Restaurant Minibar Nightclub Transport
Fields HotelRoomTable:
HotelGuestExpenses
3-2
Axaptel
HotelRoomId
STR
HotelRoomType ENUM LedgerAccount STR Rate REAL HotelBookingTable: HotelBookingId STR HotelRoomId
STR
ToDate DATE FromDate DATE CustAccount STR Invoiced ENUM NoYes HotelGuestExpenses: HotelBookingId STR HotelExpenseType ENUM TransDate DATE Amount REAL
3-3
Axaptel
3.2 EXERCISES
Exercise 1
System construction
Import the project: Ax30MXIDemoProject.xpo
Exercise 2
System construction Enter data in the forms
Lesson 4. Using the Journals
At the end of this lesson, you are expected to be able to: Access existing journals and set up lines. Set up journals. Post journals. Know about different journal types Understand the complexity of creating transactions.
AX-300-ILT-056-v01.00-ENUS
4-1
Using the Journals
4.1 JOURNALS In this chapter the word Journal is used for journals like General Journal in General Ledger module, like Payment Journal in Accounts Receivable, or like Invoice Approval Journal in the Accounts Payable module. The general concept behind using journals can be transferred to other types of journals. However, when doing so, you need to investigate the function and data model of the journal. All journals we will write here have a common data model. Thus, it is easy to learn how to use them, once you know how to use at least one of them. Journals are the easiest way of integrating into Axapta. Using Journals you need not learn about the complex logic behind the transactions. Using a Journal lines table, you fill it in with data from your project, and call upon Axapta’s method for posting the journal. All error checking and posting will be simultaneously performed without additional programming.
General Guidelines There are several ways of using Journals for posting the project: •
Creating or using an already created Journal
•
Posting transactions to journal lines
•
Posting or checking Journals
4-2
Using the Journals
4.2 CREATING THE JOURNAL In order to make your project very flexible, every time you post, you create a new journal for this particular posting. In your project, specify what journal name should be used for the new journal. Journal names for different modules are located in xJournalName tables, where “x” is name of the module.
Example LedgerJournalName, InventJournalName
or ProdJournalName.
There is one more type of grouping journal: field JournalType. This enumerated data type field indicates where specific journal names should be used: for payments, periodic, daily journals and so on. All journals are stored in specific module tables, such as: LedgerJournalTable, InventJournalTable and ProdJournalTable. Depending in which module you use, either create, or use an already created journal in these tables. For the creation of a new record, you should fill at least two fields of the record, For example, if you are creating Ledger journal:
Example ledgerJournalTable.JournalName = ’CustPay’; ledgerJournalTable.Name = ’TestJournal’ ledgerJournalTable.insert();
After ledgerJournalTable.Insert (), a record in LedgerJournalTable is created and unique batch number will be assigned to the record. In LedgerJournalTable case, it is the JournalNum field. This unique number is needed in posting transactions; it is a relationship field between the LedgerJournalTable and LedgerJournalTrans table. The same function exists in other modules.
4-3
Using the Journals
4.3 CREATING TRANSACTIONS All transactions must be posted in a journal line table, which usually has the postfix “Trans”, for example: LedgerJournalTrans, InventJournalTrans and so on. Posting to the journal lines is simply the creation of new records in the JournalLines table. You need to fill the record with data and then insert it. There are two important fields to be filled every time you insert a new record: xJournalTrans.JournalNum (xJounalTrans.JournalId in Inventory and Production modules) – a unique number identifying the journal (relationship to JournalTable). This field is mandatory, because transactions are assigned to one of the journals. In our case it is the journal number that we have created, or a previously existing journal number. JournalTrans.Voucher – Transaction voucher number. This number can either be generated automatically, or if you know the exact voucher number you can define it yourself. For automatic generation use the NumberSeq class:
Example NumberSeq numSeq; numberSeq = NumberSeq::newGetNumFromCode(LedgerjournalName::Find('CustPay').Vo ucherSeries);; xJournalTrans.Voucher = numSeq.Num();
In this example xJournalName is the table of journal names in a given module. JournalName (parameter for Find method) is journal name, which you are using. xJournalTrans – table for transactions posting. Another and easier way to get voucher numbers is to use the voucher API to allocate voucher numbers. Other fields in transaction table should be filled in, if necessary. In inventory and production modules, specify quantities, in Ledger amount, to be transferred. Also, fill in the specifications of accounts, transaction texts, approvals and so on. Fields for those types of data are easily accessed. Check xJournalTrans table definitions in modules, for more detailed information. Note: The General Ledger module currency field is mandatory, so you must fill in the currency and exchange rate fields.
4-4
Using the Journals
4.4 POSTING JOURNALS After your transactions are posted to the journal, you need to check and post the journal. Modules have different classes for checking and posting journals.
For checking and posting in modules use: In General Ledger; use the class LedgerJournalCheckPost. The easiest way to do it is to create instance of this class using newLedgerJournalTable static method and then run the class: newLedgerJournalTable – method used when you have a record in the LedgerJournalTable, and want to post all lines in that journal. Parameters for this method are: _ledgerJournalTable - record in LedgerJournalTable representing the journal, which should be posted. _post – NoYes parameter for specifying, if it will be only checking a journal or both checking and posting. Value Yes indicates that after checking, posting should be done. _transferErrors – NoYes parameter for transferring vouchers with errors to another journal. If Yes, all vouchers with errors will be transferred into a new journal with the same name and description, but with different batch numbers. The default value is No.
Example: LedgerJournalCheckPost ledgerJCP; LedgerJCP = LedgerJournalCheckPost::newLedgerJournalTable(lJournalTable,NoYes: :Yes); ledgerJCP.run();
Here lJournalTable exemplifies a record in LedgerJournalTable. A journal can be checked in the same way
4-5
Using the Journals
In Inventory module, use the class InventJournalCheckPost. The easiest way to do it is to create an instance of this class using the newJournalCheckPost static method and then run the class: newJournalCheckPost – method used when you have a journal number from InventJournalTable, and want to post all lines in that journal. Parameters for this method are:
_journalCheckPostType – JournalCheckPostType parameter for specifying, if it will only check a journal or both check and post. Value Post indicates that after checking, posting should be made and value Check indicates it that only checking will be performed. _inventJournalTable - record in inventJournalTable representing the journal, which should be posted.
Example //check inventJournalCheckPost inventJCP; Intg056_1_HotelJournalPost Hjp; ; Hjp = new Intg056_1_HotelJournalPost(); inventJCP = inventJournalCheckPost::newJournalCheckPost(JournalCheckPostType:: check,inventJournalTable::find(Hjp.journalId())); inventJCP.run(); //post inventJournalCheckPost inventJCP; Intg056_1_HotelJournalPost Hjp; ; Hjp = new Intg056_1_HotelJournalPost();
4-6
Using the Journals
inventJCP = inventJournalCheckPost::newJournalCheckPost(JournalCheckPostType:: Post,inventJournalTable::find(Hjp.journalId())); inventJCP.run();
Here inventJournalTable exemplifies a record in InventJournalTable. A journal can be checked in the same way. In the Production module you use one child class from ProdJournalCheckPost depending of the journal that you use in this module. The easiest way to do it is to create an instance of this class using the newJournalCheckPost static method and then run the class: newJournalCheckPost – method used when you have a journal ID in XProdJournalTable, and want to post all lines in that journal. In the ProductionModule exists more than one tables of type xJournalTable. Parameters for this method are: _autoblock – NoYes parameter for specifying if the journal will be blocked or Not. _showInfoResult - NoYes parameter for specifying if the results of posting will appear in Infolog. _journalCheckPostType – JournalCheckPostType parameter for specifying, if it will be only checking a journal or both checking and posting. Value Post indicates that after checking, posting should be made and value Check indicates it will be only checking. _tableId – ID of xProdJournalTable. _JournalId – Identification of Journal that has been created. In other modules there are common functions for working with journals. Note: Remember to use transactions control statements, to be sure that all data will be posted as required. Task: Refer to, Appendixes, Task1 – Creating and posting to the General Journal to have a better understanding how posting a journal works. Then try to implement it.
4-7
Using the Journals
4.5 EXERCISES
Exercise 3
Journal lines
Every time a hotel guest checks out, a transaction needs to be made on the customer’s account, and a sales account added to the ledger module. Create a new class that checks for created lines, or uses an existing journal and which can create journal lines. Make sure that these features can be activated using a button on the form that is used for reservation administration.
Exercise 4
Automatic Posting
Prepare the class above, such that when the user press the check out button the field Invoiced is set to ‘Yes’ and a new journal and line will be created and posted automatically.
Exercise 5 Optional
Consumption
Each day a hotel room has been used, a stock transaction should be made for items that are included in room maintenance, for example, towels or toilet paper. Make sure that these transactions are automatically registered and posted using a stock journal as shown in previous tasks. You must create a button in the HotelRoomTable form for this registration and create a table and a form where Item is included for each Room. You have to create a new field in the HotelRoomTable of the type Date1980. When you
Using the Journals
4-8
run the registration you must write the date of the system in the new field. You need to make sure that two registrations per day are not allowed.
Lesson 5. Using API
At the end of this lesson, you are expected to be able to: Use APIs for posting transactions Use API for purchase and sales lines Use API for automatic number sequences And know about: API Classes in general.
AX-300-ILT-057-v01.00-ENUS
5-1
Using API
5.1 USING APIS APIs are classes providing interface to complex structures, calculations and other processes in the application. The general idea is not to reprogram everything, but to reuse code as much as possible. The APIs function with quite a simple interface. This enables you to follow the rules already defined by Axapta programmers. APIs have different interfaces as there are modules in Axapta written by several groups of programmers. So, in order to use one particular API, you need to check exactly what interface this API provides. If you want to use an API, which is not described in this course, first of all check for similar interface types. Then follow the directions specified, and analyze the new API you want to use. The most commonly used APIs are briefly described below:
5-2
Using API
5.2 APIS IN GENERAL LEDGER Posting Transactions The class LedgerVoucher is the class that 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 will hold all of the transactions in a temporary storage until the End method is called. The End method will create ledger transaction records from the temporary postings. Each voucher in the LedgerVoucher will be contained in a LedgerVoucherObject. Each transaction in each voucher will be contained in a LedgerVoucherTransObject.. In short, the procedure is: 1.
Instantiating the LedgerVoucher class
2.
Looping over the vouchers to instantiate LedgerVoucherObject classes, and registering these in the LedgerVoucher class.
3.
For each voucher, looping over the transactions to instantiate LedgerVoucherTransObject classes, and registering these in the LedgerVoucher class.
Note If default values for the voucher object will suffice, step number two can be omitted. This means that all transactions will be posted as one voucher.
A more detailed description of the steps involved follows:
Instantiation of LedgerVoucher LedgerVoucher::newLedgerPost(_ detailSummary, sysModule, numberSeqCode); }
5-3
Using API
Parameters: ∙
DetailSummary _detailSummary - value specifying either summary or details. Specifying summary will result in summarizing the amounts per account, date and voucher.
∙
SysModule _sysModule – System module, from which transactions are made. This value can also be used for posting transactions from your own modules.
∙
NumbersequenceCode _numberSeqCode – reference to the number sequence used for numbering the vouchers.
Instantiation of LedgerVoucherObject LedgerVoucherObject::newVoucher( voucher, transactionDate, sysModule, transType, creditNote, _operationsTax); 1.
Voucher _voucher number – number of the voucher
2.
TransactionDate _transactionDate – Date of transaction. Default value – current date.
3.
SysModule _sysModule – System module, from which transactions are made. This value can also be used for posting transactions from your own modules.
4.
LedgerTransType _transType – Ledger transaction type. To see all available ledger transaction types, refer to base enum LedgerTransType. Default value LedgerTransType:None.
5.
NoYes creditnote – indicates whether the voucher is a credit note.
6.
OperationsTax operationsTax – Indicates what kind of operation tax should be used when posting a transaction. The default value is OperationsTax::Current. For all available OperationTax codes, look in the base enum OperationsTax details.
5-4
Using API
Providing additional information to LedgerVoucherObject ledgerVoucherObject.parmDocument(transdate, voucher); ledgerVoucherObject.parmTaxReference(tax.taxReference() ); 7.
ParmDocument is used to set original document number and date. The default values are blank and no date.
8.
ParmTaxReference is used to specify a custom link between tax transactions. A typical use is linking tax transactions residing in different tables.
Registering the LedgerVoucherObject with the LedgerVoucher ledgerVoucher.AddVoucher(ledgerVoucherObject);
Instantiation of LedgerVoucherTransObject LedgerVoucherTransObject::newCreateTrans( ledgerVoucherObject, ledgerPostingType, ledgerAccount , dimension, currencyCode, amountCur, _recId)
1.
LedgerVoucherObject _ledgerVoucherObject - is the object containing the corresponding voucher.
2.
LedgerPostingType _ledgerPostingType – is a type of posting. For all available posting types, look in base enum LedgerPostingType details.
3.
LedgerAccount _ledgerAccount– the ledger account number on which transactions will be made.
4.
Dimension _dimension - transaction dimension.
5.
CurrencyCode _currencyCode – currency in which transactions will be made.
6.
AmountCur _amountCur – the amount in currency (specified in step 4.)
5-5
Using API
7.
Recid _recid – the registration ID of the originating row
Providing the transaction text ledgerVoucherTransObject.parmTransTxt(_transTxt); TransTxt _transTxt – Transaction text. Default value ''.
Registering the LedgerVoucherTransObject with the LedgerVoucher ledgerVoucher.addTrans(ledgerVoucherTransObject);
Finalizing the posting ledgerVoucher.addTrans(ledgerVoucherTransObject); LedgerVoucher.end(); A coding example using the ledgerVoucher class is provided in the application as the class TutorialLedgerVoucher. The method runSalesPost exemplifies posting a sales order with its lines. The method runJournalPost exemplifies posting from a journal.
5-6
Using API
5.3 TRADE SERIES APIS CustVendVoucher Used for: This class is used for posting Customers and Vendors transactions. It is tightly connected with LedgerVoucher posting. Methods: Commonly used methods are: New – Initializes new instance of CustVendVoucher class. For all parameters see CustVendVoucher/New, or use Construct method. New is opened from the method construct which is a static method that can be used to create an object from either CustVoucher & VendVoucher. Both are derived Classes from CustVendVoucher. Construct – static method, which creates new instance of CustVoucher or VendVoucher, according to SysModule parameter. Parameters: 1.
SysModule _module – module, where transaction will be created. Two modules are supported: SysModule::Cust and SysModule::Vend. According to this field, CustVoucher or VendVoucher object will be created.
2.
LedgerVoucher_ledgerVoucher – LedgerVoucher. Should be previously instantiated
3.
CustVendAC _accountNum – Customer or vendor account number.
4.
AmountCur _amount – Amount for posting.
5.
CurrencyCode _currencyCode – currency code used in transaction.
6.
LedgerTransTxt _transTxtType - Transaction text for use with new transactions. For all possible transaction texts see base enum LedgerTransTxt declaration.
7.
Dimension _dimension – Transaction dimension. Default value is ''.
8.
PostingProfile _postingProfile – Posting profile being processed. Default value is ''.
9.
LedgerPostingType _posting - Transaction posting type is the specification of the type of transaction. Default value is 0. For all available types see base enum LedgerPostingType declaration.
5-7
Using API
10. PaymCode _paymCode – Terms of payment. Default value is ''. 11. SettlementType _settlement – Specifies how settlement takes place. Default value is SettlementType::None. For all available settlement types see base enum SettlementType declaration. 12. EmplId _approvedBy – User ID, which approved current voucher. Default value is curuserid(), Example: ledgerVoucher = ledgerVoucher::newLedgerPost( DetailSummary::Detail, SysModule::Cust, CustParameters::numRefCustAccount(). NumberSequence); LedgerVoucher.AddVoucher( LedgerVoucherObject::newVoucher(numseq.num (), today(), Sysmodule::Cust, LedgerTransType::Sales)); //CustVoucher custVoucher = CustVendVoucher::construct(SysModule::Cust, //Module ledgerVoucher, customer account, amountCur,
// Amount
CompanyInfo::find().currencyCode, LedgerTransTxt::CustInvoiceCust)
//Currency ;
ledgerVoucherTransObject = LedgerVoucherTransObject::newCreateTrans( ledgerVoucher.findLedgerVoucherObject(), LedgerPostingType::CustPayment, ledgerAccount, dimension, CompanyInfo::standardCurrency(),
5-8
Using API
amountcur, recId); //Transacion text ledgerVoucherTransObject.parmTransTxt(txt); //add transaction ledgerVoucher.addTrans(ledgerVoucherTransObject); //Creo la transaccion de cliente custVoucher.post(custTrans); ledgerVoucher.end(); numseq.used(); ttsCommit; CustVendVoucher class is used together with CustVoucher and VendVoucher classes, which extends to some of the functions in the CustVendVoucher class.
Additional functionality Creating new customers Some customers who are only one-time clients do not need to be created permanently in the CustomersTable. On the sales order table (SalesTable), it is possible to mark a new order, as an order which is specific to a onetime customer. The user does not need to type in a customer number. Instead, Axapta creates a new customer classification based on information from an existing customer, which is used as a template. This template is specified in Accounts receivable, Setup, Parameters. The creation of the customer is done by calling the static method CustTable::createOneTimeAccount(Common). The method can be called with either a SalesTable record or a CustInvoiceJour table record. It calls a method to copy information either from the SalesTable record or the CustInvoiceJour record to the new CustTable record.
Creating new orders Using APIs for purchase and sales orders is done throughout other parts of the Axapta application. The APIs that is used are the PurchAutoCreate and SalesAutoCreate classes. These classes are specifically meant to be used from other modules. If you are integrating into the sales and purchase
5-9
Using API
modules it is recommended that you duplicate the structure used in these classes to do the interface. However, if you just need to create, for example, a sales order with lines, this can also be done in a more direct way. You do this by inserting the tables and using the SalesLine.CreateLines() method together with the SalesTableType class. Make sure that the salestype is set correct and the customer account. The method SalesTable.InitFromCustTable() can, for instance, be used to make sure the right values from the customer table are initialized. The API used in other parts of the application is used as follows: PurchAutoCreate which is derived in PurchAutoCreate_Invent, PurchAutoCreate_Prod, PurchAutoCreate_Purch and PurchAutoCreate_Sales. Thus a derived class for each module that needs to create a purchase order. This is done via the method createPurchLine. When new purchase orders should be created, you should use a PurchAutoCreate class hierarchy. This hierarchy is used for creating purchase orders from sales orders, production orders and master planning. The PurchAutoCreate class basically can create a purchase order with only one line by overriding the method PurchAutoCreate.createPurchLine() An example of how the PurchAutoCreate_Sales Class is used can be seen in PurchCreateFromSalesOrder.run(). Here records with the same vendor account number are created in a temporary table, and passed on as parameters to the static method PurchAutoCreate::construct (Common, Object). PurchAutoCreate.create() creates one record in PurchTable and creates as many records in PurchLine as there are records in the temporary table. A similar class hierarchy to SalesAutoCreate is also made for sales orders. PurchAutoCreate and SalesAutoCreate classes use the following methods: SalesLine.createLine(Boolean = false, Boolean = false, Boolean = false, Boolean = false, Boolean = true, Boolean = false, Boolean = false)
5-10
Using API
PurchLine.createLine(Boolean = false, Boolean = false, Boolean = false, Boolean = false, Boolean = true, Boolean = false) Depending on the parameters, these can initiate order lines from the order header, inventory table, trade agreements, and miscellaneous charges. For more information about these methods, see PurchAutoCreate and SalesAutoCreate class declarations.
Invoicing orders The SalesFormLetter and PurchFormLetter class hierarchies are used for printing and posting sales and purchase order journals. These classes can be called in order to post or print a journal for a single sales or purchase order. The following description is valid for SalesFormLetter class as well as for the PurchFormLetter class hierarchy. The posting or printing is done by first calling the static method SalesFormLetter::construct(DocumentStatus , Boolean = true). The DocumentStatus parameter is a base enum, stating with which kind of journal should be posted or printed, for example, DocumentStatus::Confirmation. The Boolean parameter is optional with the default value = true, stating whether a parameter ID should be retrieved from the Parameter ID number sequence. If this parameters is false, the method SalesFormLetter.parmId(ParmId) should be called in order to set the parameter ID. Thereafter the following method should be called. SalesFormLetter.update(Common, Today(), SalesUpdate = SalesUpdate::All, AccountOrder = AccountOrder::None, NoYes = NoYes::No, NoYes = NoYes::No)
5-11
Using API
The method posts or prints a journal for a sales order according to the parameters parsed: 1.
The first parameter should be the SalesTable record. This journal should be posted or printed. The rest of the parameters are optional.
2.
The second parameter is the transaction date.
3.
The third parameter states which quantity should be used in the journal.
4.
The fourth parameter states whether orders should be summary updated (this parameter is obsolete, as only one sales order can be updated at a time).
5.
The fifth parameter tells the class whether the journal should be posted or if only a proforma journal should be created.
6.
The last parameter states whether the journal should be printed or not.
The only difference between the use of the SalesFormLetter and PurchFormLetter classes is the parameters for the update method. The following method should be called with a PurchTable record as the first parameter. PurchFormLetter.update(Common, Num, Today(), NoYes = NoYes::No, NoYes = NoYes::Yes) The second parameter is the vendors packing slip number or invoice number. The last two parameters are the same as in the SalesFormLetter.update method. The method in connection with purchases is written like this: purchFormLetter.update(
Common, Num, transDate, PurchUpdate::All, AccountOrder::None,
5-12
Using API
NoYes::No, NoYes::Yes)
The method takes the following parameters: 1.
A record from the PurchTable.
2.
Labels/Invoice number
3.
Transaction Date
4.
How many are needed
5.
In which order should the purchase orders be handled.
6.
Pro forma
7.
Do you want a printout?
5-13
Using API
5.4 INVENTORY MANAGEMENT APIS Inventory APIs must be used in a slightly different way than the financial or trade series APIs. In this module, in order to use APIs you should: 1.
create your own class
2.
inherit the API you want to use
3.
overwrite several methods
Only then you will be ready to use this API.
Posting transactions InventMovement class hierarchy The InventMovement class hierarchy is used to provide a uniform access to different tables. You could say that it remedies the fact that the databases supported aren’t object oriented databases where tables can extend other tables. Think of the inventory movement as a data carrier class. InventMovement is a super class in a system of classes used for handling information about Inventory movement. Instance of this class could be created using data from different modules, such as Sales or Purchase. For that reason, a new class should be created and the main class InventMovement should be inherited. In the new class you need to overwrite some of the parent class methods. Most of these methods are designed to provide you with data from different sources. Example: You need to define the transactions date. In the Sales table it is the field confirmedDlv. In PurchTable it should be confirmedDlv if specified and deliveryDate if confirmedDlv is not specified. Then TransDate method in InventMov_Sales should be defined as follows: TransDate transDate() { return salesOrderLine.confirmedDlv; } And in the InventMov_Purch: TransDate transDate()
5-14
Using API
{ return purchLine.confirmedDlv? purchLine.confirmedDlv : purchLine.deliveryDate; } The same concept is used for overwriting other methods, where you can provide the necessary information. Good examples include how InventMovement class can be used for inheritance in classes InventMov_Sales and InventMov_Purch.
Inventory Update The InventUpdate class hierarchy is used to handle different status updates of all kinds of inventory movements. The InventUpdate classes doesn’t reference the origins (for example, sales lines, purchase lines or production orders) directly but accesses these through the InventMovement classes. Think of the InventUpdate classes at the engine. InventUpdate is a super class in a system of classes used for handling information about Inventory updating. It allows changing quantities, locations and so on. You have to create instance of InventMovement class (or child class of it) and then use it in inventory movement. One of the most useful classes in InventUpdate class hierarchy is the InventUpd_Financial class. It has two static methods for creating Purchase or Sales invoice: newPurchInvoice and newSalesInvoice. After creating this class instance with these methods, you should use updateNow method for actual posting.
Example: inventUpd_Financial = InventUpd_Financial:: newPurchInvoice(purchLine, inventVoucherTransPost, number, lineValue, purchLine.currencyCode, purchParmLine); inventUpd_Financial.updateNow();
5-15
Using API
5.5 PRODUCTION SERIES There are several classes for handling production series as well. API’s in this module use the same structure as used in the Inventory module. There are two major classes in the Production series: ProdStatusType – this class and its hierarchy are used for receiving information about manipulating the production process, for a specific status. ProdTableType – this class and its hierarchy is used for handling information from Production status, planning, and so on.
5-16
Using API
5.6 NUMBER SEQUENCES There are a lot of places where automatic number sequences are used. All number sequences are set up in Main Menu, Basic, Setup, Number Sequences. Usually Number sequences are connected to some specific parts of program using references – fixed list of Axapta predefined functionality. Number sequences can be set up by using the setup wizard. Examples of existing references: •
Customer account
•
Sales Order – Quotation number
•
Ledger – Journal Voucher
There can only be one Number sequence assigned to a reference. Several references may be assigned to the same number sequence. In some cases, modules can use number sequence directly without the use of references:
Program element
Number sequence
NumberSeq class handles all number sequences in Axapta. This class is used to get new or to reserve number from specific number sequence. Class description follows:
NumberSeq This class is used for getting new numbers from a specific number sequence. Methods In order to get new number from a number sequence, you need to have an instance of class NumberSeq. There are several static methods that help to create a new instance:
5-17
Using API
newGetNum newGetNum (newGetNumFromCode) newGetNum(NumberSequenceReference _numberSequenceReference, boolean MakeDecisionLater = FALSE, boolean dontThrowOnMissingRefSetUp = FALSE)
Creates a new instance of NumberSeq class and generates a new number in a number sequence related to the number sequence type specified as a parameter. A new number could be accessed by calling a non-static method Num in the class instance: mySeq.Num() Note: In this and in all following methods, postfix “FromCode” to a method name means that instead of specifying a number sequence type, an exact number sequence code will be specified as a first parameter.
newGetVoucher newGetVoucher (newGetVoucherFromCode) static NumberSeq newGetVoucher(NumberSequenceReference _numberSequenceReference, boolean _makeDecisionLater = FALSE, boolean _dontThrowOnMissingRefSetUp = FALSE) Creates a new instance of NumberSeq class and generates a new voucher code for the number sequence type specified as a first parameter. A new voucher code could be accessed by calling the non-static method Voucher().
newGetNumAndVoucher newGetNumAndVoucher (newGetNumAndVoucherFromCode) static NumberSeq newGetNumAndVoucher( NumberSequenceReference _ _ _ _numberSequenceReference, NumberSequenceReference
_ _voucherSequenceReference,
5-18
Using API
boolean _makeDecisionLater = FALSE, boolean _dontThrowOnMissingRefSetUp = FALSE) Creates a new instance of NumberSeq class and generates a new number and voucher codes for the number sequences specified as the first and second parameters. A new number could be accessed by calling the nonstatic method Num(), and a new voucher by calling the non-static method Voucher().
NewReserveNum NewReserveNum (newReserveNumFromCode) and NewReserveVoucher (newReserveVoucherFromCode) static NumberSeq newReserveNum(NumberSequenceReference _numberSequenceReference, boolean _makeDecisionLater = FALSE, boolean _dontThrowOnMissingRefSetUp = FALSE) Creates a new instance of NumberSeq class, and reserves new number (voucher) for a future use. A reserved number could be released by calling the static method release(), (for details see below).
Non static methods Parameter methods:
parmMakeDecisionLater: sets or returns the MakeDecisionLater value. The makeDecisionLater parameter is used when suggesting numbers in a form that the user can use. An example of how to use number sequences in forms can be seen in the form CustTable. 1.
parmNumberSequenceCode: sets or returns the NumberSequenceCode value
2.
ParmVoucherSequenceCode: sets or returns the VoucherSequenceCode value.
5-19
Using API
Corresponding methods for vouchers 1.
Num: Returns a new number from an initialized number sequence.
2.
Voucher: Returns a new voucher from an initialized number sequence.
3.
Abort: Aborts the new number calculation. The number becomes available again.
4.
NumAndVoucher: Returns a container of a new number and new voucher from initialized sequences.
Additional static methods Release static boolean release(NumberSequenceCode _numberSequenceCode, Num _num) Releases a reserved number (_num) in a specified number sequence (_numSequenceCode). This number will be available to use as a new number (use methods newGetNum or newGetVoucher). Returns TRUE if the number was successfully released and FALSE otherwise. highest static Integer highest(NumberSequenceCode _numberSequenceCode) Returns the highest value in a number sequence specified as a parameter. lowest static Integer lowest(NumberSequenceCode _numberSequenceCode)
Returns the lowest value in a number sequence specified as a parameter.
numInsertFormat
5-20
Using API
public static client server num numInsertFormat(Integer num,
NumberSequenceFormat format) Returns a number inserted into a mask. For example: if the parameters are _num=1562 and mask=’SN#####L’, returns ‘SN01562L’. numRemoveFormat public static client server Integer numRemoveFormat(Num num,
NumberSequenceFormat
format )
Removes the mask from a number. The function is opposite to the numInserTemplate().
NumberSeqReference Number sequences cannot be used without references. A reference is a record in the table NumberSeqReference for each use of a number sequence. When, for instance, a number sequence is used for a sales order ID, a record exists specifically for that in the reference table. A class hierarchy for the number sequences exists, including the setup of references.
5-21
Using API
5.7 EXERCISES
Exercise 6
Automatic depreciation
You want to post the depreciation on hotel rooms depending on how often they are used. On this basis, ensure that whenever an invoice is posted, this will cause an automatic depreciation on the buildings. For example, a unit of currency for each day the room has been used. This should be done using LedgerVoucher.
Exercise 7
Purchase order
The hotel offers transport of guests (car rental and limo service). This service is not handled internally but is carried out by a vendor. When a line of the type ‘transport’ is created in HotelGuestExpenses, the user is prompted if they should create a purchase order. Make sure that if the answer is positive, a purchase order will be created automatically.
Exercise 8
Number Sequences
When a reservation is created in HotelBookingTable, the HotelBookingId field should be allocated an automatically generated number.
Lesson 6. Using the COM Interface
At the end of this lesson, you are expected to be able to: Know about the purpose of COM objects. Use a COM object from Axapta. Use the Axapta Business Connector.
AX-300-ILT-058-v01.00-ENUS
Using the COM Interface
6-1
6.1 WHAT ARE COM OBJECTS COM is short for Component Object Module. In short, that means an external application being used as an object. We have previously seen how classes in Axapta can be created and how these classes can be used to create objects. The use of COM objects can to a very large extent be compared with the use of objects from Axapta’s own classes. This applies even if a COM object is an external application. As with Dynamic Link Libraries, you also normally have special classes, serving the purpose of interface between Axapta and COM objects.
Using the COM Interface
6-2
6.2 MS-AGENT A good example of a COM Object, which is relatively easy to use and which we will use with the exercises of this lesson, is the Microsoft Agent, MS-Agent. MS-Agent is a small application, which can be used for user dialog in different scenarios. MS-Agent generates a cartoon like character at a specified location on the screen. The character can, through a speech bubble and speech synthesis, give the user the required information. The Interface to this COM Object is the class SysMicrosoftAgent and an example of how to use its methods can be seen in the form tutorial_COMAgent. Note that the application to be used as a COM object has to be installed before the code in the above example gives the expected result. This is irrelevant for newer versions of Windows.
6-3
Using the COM Interface
6.3 AXAPTA BUSINESS CONNECTOR Using the Axapta Business Connector third party products like Visual Basic, Java, or MS Office products, enables you to use Axapta as a COM object. This implies access to the data and business logic of Axapta. This enables the use of applications as front ends, other than Axapta. An example of the use of this could be a web page designed as an order form. The result is that the customer places his orders directly as an Axapta sales order. The business logic of Axapta then ensures that, for example, the correct discounts are given, or calculates backorders.
Example:
You can copy the code below into a job in Axapta. This example will open a Word session and write the text ‘Hello from Axapta’, save the text in a document called c:\Axapta COM Document1.doc, and finally close the Word session. COM COM COM COM ;
wordApplication; wordDocuments; wordDocument; wordRange;
wordApplication = new COM("word.application"); wordApplication.visible(TRUE); wordDocuments
= wordApplication.Documents();
wordDocument = wordDocuments.add(); wordDocument.saveas("c:\\Axapta COM Document1.doc"); wordDocument.activate(); wordRange = wordDocument.range(0,0); wordRange.insertafter("Hello from Axapta"); wordRange = wordDocument.range(6,19); wordRange.bold(true); wordRange = wordDocument.range(11,26); wordRange.italic(true); wordDocument.save(); wordDocument.close(); wordApplication.quit();
6-4
Using the COM Interface
6.4 EXERCISES
Exercise 9
Exercise 10
Use MS-Agent in a form
∙
Create a new form, MSAgentDemo, which uses the class SysMicrosoftAgent, so that ’Merlin’ is automatically displayed when the form is opened, and disappears when the form closes.
∙
Using buttons on the form, it must be possible to have Merlin say different sentences. Note that the tone can be changed using ! or ?
Launch MS Word from Axapta
Sometimes it is handy to use other applications for special purposes, such as writing letters in MS Word. It is then convenient to be able to bring over some information from the current record in Axapta. ∙
Add a new button with the text ’Word’ to the Customers form (CustTable). When the user presses the button, MS Word must be launched, using the necessary code to launch Word and inserting the name and address of the customer.
Hint: You can find some hints on how to control MS Word as a COM object in the class DocuActionCom_Word.
Exercise 11
Use the Axapta Business Connector
From MS Excel, it should be possible to get the names of all customers in Axapta having transactions. This should be possible by clicking a button in MS Excel.
6-5
Using the COM Interface
∙
Make sure that the password and other settings for the current active configuration in the Axapta Configuration Utility are valid.
∙
Create a new document in MS Excel and then create a button in the document.
∙
Open the Visual Basic Editor for the button method. Make sure that under Tools, References, that AxaptaComConnector is selected.
∙
Now add the following BASIC code to the button method and see the result when the code is activated (by pressing the button). Dim Axapta As AxaptaCOMConnector.Axapta2 Dim AxaptaQuery As AxaptaCOMConnector.IAxaptaObject
Dim AxaptaDataSource As AxaptaCOMConnector.IAxaptaObject Dim CustTableBuffer As AxaptaCOMConnector.IAxaptaRecord ' Log on to Axapta Set Axapta = CreateObject("AxaptaCOMConnector.Axapta2") Axapta.Logon "", "", "", "" 'Table ID CustTable = 77 Set AxaptaQuery = Axapta.CreateObject("Query") Set AxaptaDataSource = AxaptaQuery.Call("AddDataSource", CustTable) Set AxaptaQueryRun = Axapta.CreateObject("QueryRun", AxaptaQuery)
I = 1 While (AxaptaQueryRun.Call("Next")) Set CustTableBuffer = AxaptaQueryRun.Call("GetNo", 1)
Cells(I, 1).Value = CustTableBuffer.field("AccountNum")
6-6
Using the COM Interface
Cells(I, 2).Value = CustTableBuffer.field("Name")
I = I + 1 Wend
' Log off Axapta.Logoff Set Axapta = Nothing
Lesson 7. Active X
At the end of this lesson, you are expected to be able to: Know some of the possibilities of using ActiveX controls. Know how to use Active X in Axapta.
AX-300-ILT-059-v01.00-ENUS
7-1
Active X
7.1 WHAT IS ACTIVEX ActiveX controls are 3rd party programs like DLLs (Dynamic Link Libraries) and COM objects. They provide us with functionality not present in the standard Axapta product. What makes ActiveX controls special compared to DLLs and COM objects is that they can have a user interface and can be associated with controls in Axapta forms. When a control is inserted in a form, it is possible to select a control type of ActiveX. Then the developer must select the actual ActiveX control (the program) to be used. Note that the use of ActiveX controls requires that the ActiveX control is registered on all computers/clients using the ActiveX control.
7-2
Active X
7.2 ACTIVEX EXPLORER When an ActiveX control is inserted, the ActiveX Explorer can be activated from the right-hand mouse button menu.
This tool has 2 purposes: ∙
To show the developer which events and methods are present for the actual ActiveX control, and which parameters is received and returned.
∙
To give the developer an overview of the events occurred during execution of the ActiveX. It also allows the developer to add X++ to be executed on the events. For debugging purposes, a trace of the ActiveX events can be enabled from the user options form.
7-3
Active X
7.3 EXERCISES
Exercise 12
Use the ActiveXMovieControl Object
In this exercise we will use an ActiveX control. As an example we will use the ActiveMovieControl object. This object could be used to play assembly instructions for items if a field with the file path was added to the item master. ∙
Exercise 13
Create a form with an ActiveX control of the ActiveMovieObject type. Also add a string field allowing the user to specify the relevant file.
Try ActiveX trace
Enable the ActiveX trace and then open the form from exercise 1. Take a look at the events occurred.
Lesson 8. Editor Scripts
At the end of this lesson, you are expected to be able to: Create new editor scripts, And know about: The classes used with editor scripts.
AX-300-ILT-060-v01.00-ENUS
8-1
Editor Scripts
8.1 EDITOR SCRIPTS In the Axapta editor it is possible, using the toolbar or ALT+M, to execute a script. A script is an action, like having a comment inserted (similar functionality is also present in many word processors, often referred to as macros). In Axapta we can create our own new scripts if needed. The secret is in the class called EditorScripts. Every existing script is a method in this class. If you want to create a new script, you simply create a new method in this class. If the name of the method contains an underscore, the method will appear in a submenu, breaking the name with the underscores, when using the add-ins menu (ALT+M). Let’s take a look at one of the methods: void template_flow_if(Editor editor) { xppSource xppSource = new xppSource(editor.columnNo()); Source template = xppSource.if(); ; editor.insertLines(template); } All methods in the class have a void return data type (they never return a value), and always receive an object of the type Editor. This object is a system class and contains a number of methods available in the editor, like insertLines(), which makes it possible to insert text. Another method is columnNo(), which gives you the current horizontal position of the cursor in the editor. The remaining methods can be found in the AOT under System Documentation\Classes\Editor. Last but not least, a class called xppSource exists. This class contains methods returning templates that comply with the code standard for certain X++ statements, as for example, if, while, for.
8-2
Editor Scripts
8.2 EXERCISES
Exercise 14
Create a new script
Find the class EditorScripts and create a new script. The script should be a sub item of the sendTo menu when using ALT+M When using the script, the selected text should be displayed in the infolog. Optionally, it should be possible in the infolog to select an Edit button. This should reopen the editor in the same method, and be positioned on the same line and column (hint: use the SysInfoAction_Editor class when adding to the infolog).
Lesson 9. Dynamic Link Library
At the end of this lesson, you are expected to be able to: Learn the purpose of using DLL’s. Try to use a specific DLL.
AX-300-ILT-061-v01.00-ENUS
Dynamic Link Library
9-1
9.1 USE OF DYNAMIC LINK LIBRARIES This lesson deals with Dynamic Link Libraries (DLL), which are individual or whole groups of program parts that can be run in windows. A DLL can hence be associated with a specific application that uses program parts. Alternatively, a DLL could be independent of a particular application and may be, for example, installed from a CD or downloaded from Internet. The interface between Axapta and the various DLLs, takes the form of classes with methods, each of which can activate the program parts found in the different DLLs.
Dynamic Link Library
9-2
9.2 WINAPI Perhaps, without further thought, we have already used DLLs via the class WinAPI. If we go in and look at the code in WinAPI’s methods, we will see that each one calls a DLL that lies outside Axapta. In practice, these calls could be made independent of WinAPI’s methods if one wanted to call a particular DLL. This is however not a recommended procedure as the code will use more space and will be more difficult to read. Therefore, if you want to install new DLLs and use them in Axapta, you should create one or more classes with methods to be used as an interface.
Dynamic Link Library
9-3
9.3 VARCHART VarChart is a German product that generates graphics for administrative systems. Axapta contains several classes that function as an interface to this product. One of the classes that is relevant to this lesson is called Graphics_Period and can be used to make a graphical presentation of transactions over a given period.
9-4
Dynamic Link Library
9.4 EXERCISES
Exercise 15
Exercise 16
Check the WinAPI class
∙
Have a look at the code in some of the methods.
∙
Identify which DLLs WinAPI uses.
Use WinAPI
Make a count of the seconds spent when joining between ledgerTable and ledgerTrans tables. You have to use the GetTickCount Function of Kernel32.dll.
Lesson 10. The RunBase Class
At the end of this lesson, you are expected to be able to: Know about the RunBase Class Know about the methods used with the RunBase Class Know about the general recommendations used with the RunBase Class
lesson: AX-300-ILT-172-v01.00-ENUS
10-2
The RunBase Class
10.1 THE RUNBASE CLASS Axapta has a high-level programming interface for executing various processes and tasks. Every time when you need to collect information and then execute a task, use the RunBase class function. This class has dialog, last value saving, query range definitions and many more useful functions inside. RunBase class is a parent class. It can be used in all classes: class MyClass extends RunBase A more detailed description of each method in this class follows.
Methods used in new classes ClassDeclaration – in this section you should: 1.
Declare that your new class is a child-class to RunBase class. Example: class MyClass extends RunBase
2.
Declare the dialog object. Example: DialogRunbase dialogRunbase;
3.
Declare DialogField objects and variables where data form dialog will be saved. Example: DialogField dialogCustAccount; CustAccount custAccount;
4.
Declare QueryRun object if you specify ranges for a query in the dialog (Select button with all functionalities will appear automatically). Example: QueryRun queryRun;
5.
It is highly recommended that you declare two macros in ClassDeclaration. One of them specifying the version of data to be used (usually 1), and the other – a list of all variables that store information from the dialog. This should be saved for the next time users open the same dialog. Commas should separate variables.
10-3
The RunBase Class
The declaration looks as follows: #define.CurrentVersion(1) #localmacro.CurrentList series, caseNo, nameTemplate #endmacro public boolean canGoBatch() – This method is reserved for use with RunBaseBatch class. If you want to use the batch system you should extend RunBaseBatch class, and look for the method descriptions in the next chapter of this document. In RunBase class this method returns false. protected void cleanupDialog() – this method should be overridden if any cleanup is required after calling the dialog. protected Object dialog() – This method should be always overridden in order to specify what should be placed in the dialog. If you need to modify the query with, for example, ranges, in this method you should: 1.
Call super() method. super();
2.
Initialize DialogRunBase class object declared in ClassDeclaration section. dialogRunBase = new DialogRunBase(“My Dialog Caption”,this);
3.
Initialize the dialog field objects and define the values by calling value() method with the parameter value-storing variable. Example: dialogSeries = dialogRunBase.addField(typeID(SourceC oumnNum)); dialogSeries.value(series);
10-4
The RunBase Class
dialogCaseNo = dialogRunBase.addField(typeID(Case)); dialogCaseNo.value(caseNo); 4.
Add the “Select” button if a query will be used in the dialog. Example: dialogRunBase.addMenuItemButton(MenuItemTyp e::Action,IdentifierStr(RunBaseQueryDialog) ,false);
5.
Return initialized DialogRunBase object: Return dialogRunBase;
If you do not need to modify ranges you can just do the following instead: •
Declare the FormRun query and return it FormRun formRun = classFactory.createQueryForm(this); ; formRun.init(); return formRun;
public void getLast() – This method packs and unpacks last saved values. This method should not be overridden. If no last saved value is found, it calls initParmDefault() method described below. GetLast() should be called before prompt() method when using your own class. public void initParmDefault() – This method will be called if no last value is found in the system. It should be overridden if necessary and default dialog parameters should be specified. Example: series = 1; caseNo = 0; abstract public container pack() – This method should be overridden and packing to a container. If you have declared two macros in
10-5
The RunBase Class
ClassDeclaration then there is quite a simple way to implement it. If you are not using a query in your dialog, then the code should look like this: return [#CurrentVersion,#CurrentList]; If you are using a query, and queryRun is declared in the ClassDeclaration section as a QueryRun object, then your code should look like this: return [#CurrentVersion,#CurrentList,queryRun.Pack ()]; public RunbaseProgress parmProgress(RunbaseProgress _progress = progress) – Set/Get progress class instance, which will be used in your run() method, if needed. By default, progress will return a variable which is declared in the RunBase ClassDeclaration section. public void progressInit(str caption, int total, Filename animation, int updateInterval = 1) - method used for progress initialization. Here, caption – progress window caption, total – total number of steps in progress, animation – name of animation file (it is recommended that you take it as one of the descriptions in #AviFiles macro libraries), updateInterval – time interval in seconds, when progress should be updated. Example of usage progressInit and parmProgress methods: #Macrolib.AviFiles this.progressInit("My Progress", 10, #AviUpdate); for (i=1;i