Knowledge Transfer Wave 2 Dynamics AX TAP 4/22/2017 12:11 AM ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Application Integration Framework (AIF) Document/Interface Development Søren Vagn Andersen Program Manager Microsoft Dynamics AX ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Agenda Extensibility Model XML Document Structure Key Concepts Implementing New Documents Sending Documents Advanced Topics
Supported XML Documents Trade Price List [out] Price/Discount Agreement [in] Purchase Order [out] Sales Order [in] Picking List [out] Packing Slip [in] Advance Ship Notice [out] Sales Invoice [out] Purchase Invoice [in] Free Text Invoice [in] Finance Exchange Rates [out,in] GL Chart of Accounts [out,in] GL Dimensions [out,in] Inventory Inventory Counting Journal [in] Inventory Transfer Journal [in] Inventory Balances [out] Inventory Transactions [out] Inventory Profit/Loss Journal [in]
XML Document Development Model driven approach Focus on data and business logic Customizations handled (almost) automatically Generalized framework Tools support Wizard for generating class skeletons Best practice check to detect data model changes
HOW ? Model Driven Approach XML DB Axd<Document> query defines XML structure and content Axd<Document> class performs serialization and de-serialization SalesTable HOW ? SalesLine ... ... DB Ax<Table> classes manage data access
Configure and generate Inventory Balance Web Service 4/22/2017 12:11 AM Configure and generate Inventory Balance Web Service Fill in key TO DO’s adding some business logic "Browse" Web Service in IIS Admin to see what has been generated ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Agenda Extensibility Model XML Document Structure Key Concepts Implementing New Documents Sending Documents Advanced Topics
XML Schema Structure Empty Hidden <?xml version="1.0" encoding="utf-16"?> <SalesOrder xmlns="http://schemas.microsoft.com/dynamics/"> <DocPurpose>Original</DocPurpose> <SenderId>dmo</SenderId> <SalesTable class="entity"> <CaseTagging>No</CaseTagging> <CovStatus>1</CovStatus> <CurrencyCode>EUR</CurrencyCode> <CustAccount>4020</CustAccount> <SalesLine class="entity"> <Blocked>No</Blocked> <Complete>No</Complete> ... <InventDim class="entity">…</InventDim> </SalesLine> <DocuRefHeader class="entity">…</DocuRefHeader> </SalesTable> </SalesOrder> Parm<Property>() methods on Axd<Document> class Empty Hidden
Serialization Strategy Serialize parm<Property>() methods on the Axd<Document> class Read data using Ax<Table> class, if present Read directly from table, if no Ax<Table> class Field list on Axd<Document> query controls what fields are serialized If Ax<Table> exists, only fields with parm<Field>() method on Ax<Table> class Calculated fields (display fields) are always serialized
Mapping Simple Datatypes X++ Datatype XSD Type String xsd:string, maxLength=StringSize (maxLength=max(StringSize,50) in case of value mapping) Integer xsd:int xsd:time, ISO format: HH:MM:SS (Time stamp if global::isTypeTime is true) Int64 xsd:long Real xsd:decimal, fractionDigits=NoOfDecimals Date xsd:date, ISO format: YYYY-MM-DD Enum xsd:string, enumeration=<EnumName>, ... GUID xsd:string, pattern=’[0-9A-Fa-f]{8}-...’ BLOB xsd:string, Base64 encoded
Arrays All elements are serialized <Dimension> <element>Department</element> <element>Cost Center</element> <element>Purpose</element> </Dimension>
Null Values Outbound Inbound Null values are not serialized Arrays may contain empty elements Inbound Empty string elements interpreted as zero-length string, not null Use <element xsi:nil=”true”/> to specify null value
Security Respects Microsoft Dynamics AX security Security keys Record level security MaxAccessMode property AllowEditOnCreate property Visible property No access to system tables SystemTable=Yes TableType≠Table
Agenda Extensibility Model XML Document Structure Key Concepts Implementing New Documents Sending Documents Advanced Topics
Axd<Document> Query Describes structure of XML document Controls amount of data retrieved from Microsoft Dynamics AX Disabled fields and data sources are excluded from Schema Only one (1) ”root” data source allowed Same name as Axd class
Work Tables and Journals Posting XML PurchTable VendPurchOrderJour Read from journals Insert into work tables PurchLine VendPurchOrderTrans XML
Documents With Header/Lines Header = ”Root” data source SalesTable Lines SalesLine Notes at both header and lines
Axd<Document> Classes Service classes Implement AifServiceable interface Expose document actions Validation of entire document, e.g. Cross-table dependencies Document life-cycle constraints May invoke business logic Posting
Ax<Table> Classes 1-to-1 relationship with tables Name derived from table, e.g. AxSalesLine parm<Field>() method for each field Defaulting of fields with no values Validation of fields with respect to, e.g. Referential integrity Number sequences Business logic Value mapping of specific fields Also used by other modules Enterprise Portal ...
Class Hierarchy ? Action Axd<Document> Method AifServiceable 4/22/2017 12:11 AM Class Hierarchy AifServiceable AxdBase Axd<Document> Axd<Document> ? +getActionList() Explain which of these can be generated by the Wizard, and what remains to be done. Action Axd<Document> Method SendDocument XML read(entityKey, ...) ReceiveDocument entityKey create(XML, ...) ... AxInternalBase Ax<Table> Table ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Axd<Document> Method Action Axd<Document> Method SendDocument Generate XML document identified by entity key XML read(entityKey, ...) SendDocumentList Generate list of XML documents each identified by entity key XML readList(entityKeyList, ...) QueryDocuments Generate list of XML documents matching query criteria XML findList(queryCriteria, ...) QueryEntityKeys Generate list of entity keys for XML documents matching query criteria entityKeyList findEntityKeyList(queryCriteria, ...) ReceiveDocument Parse XML document and write data to database entityKey create(XML, ...) ReceiveDocumentList Parse list of XML documents and write data to database entityKeyList createList(XML, ...)
Entity Keys Identify specific document instance Table (Field, Value) pairs for primary keys Use entity keys returned by AIF Must be ”root” data source in query Use ID in X++ Not needed in XML / Web Client Field Use Field Name in XML / Web Client
Using Entity Keys XML Action Entity Key <?xml version="1.0" encoding="utf-8" ?> <Envelope xmlns="http://schemas.microsoft.com/dynamics/2005/12/documents"> <Header> … <Action>readInventSum</action> </Header> <Body> <EntityKey> <KeyData> <KeyField> <Field>ItemId</Field> <Value>B-R12</Value> </KeyField> <Field>InventDimId</Field> <Value>00001_060</Value> </KeyData> </EntityKey> </Body> </Envelope> Action Entity Key
Using Entity Keys Web Services Create entity key object //Set the Enity Key EntityKey entityKey = new EntityKey(); entityKey.KeyData = new KeyField[2] { new KeyField(), new KeyField() }; entityKey.KeyData[0].Field = "ItemId"; entityKey.KeyData[0].Value = "B-R12"; entityKey.KeyData[1].Field = "InventDimId"; entityKey.KeyData[1].Value = "00001_060"; Populate entity key
Query Criteria Similar to entity keys Criteria for identifying range of documents List of Table Field Operator Operand1 Operand2 (optional; operator dependent) Table must be ”root” data source or inner-joined with ”root” data source Query must not contain hidden or locked range for <Table>.<Field>
Valid Operators X++ Operator XML Enumeration # of Operands == Equals 1 != NotEquals > GreaterThan >= GreaterThanEquals < LessThan <= LessThanEquals .. Range 2
Using Query Criteria Action Query criteria <?xml version="1.0" encoding="utf-8" ?> <Envelope xmlns="http://schemas.microsoft.com/dynamics/2005/12/documents"> <Header> … <Action>findListSalesOrder</action> </Header> <Body> <QueryCriteria> <CriteriaElement> <DataSourceName>SalesTable</DataSourceName> <FieldName>CustAccount</FieldName> <Operator>Range</Operator> <Value1>4000</Value1> <Value2>4020</Value2> </CriteriaElement> <FieldName>CurrencyCode</FieldName> <Operator>Equals</Operator> <Value1>USD</Value1> </QueryCriteria> </Body> </Envelope> Action Query criteria
Constraints Enables the AIF to make decisions based on document contents Routing Security (to prevent spoofing) Constraint types Customer Vendor Warehouse
Constraint Based Routing EndpointA [3001] Microsoft Dynamics AX XML PurchaseOrder1 [3001] PurchaseOrder2 [3004] EndpointB [3001,3004] EndpointC [3000,3001] EndpointD [3001,3002,3004] EndpointE [No Constraints]
Constraint Based Security EndpointA [4000] Microsoft Dynamics AX XML SalesOrder1 [4000] SalesOrder2 [4002] EndpointB [4000,4002] EndpointC [4000,4012] EndpointD [4000,4002,4012] EndpointE [No Constraints]
Agenda Extensibility Model XML Document Structure Key Concepts Implementing New Documents Sending Documents Advanced Topics
Axd<Document> TO DO’s ... in code generated by the Axd Wizard getLabel() getActionList() initQueryFromEntityKey(), initQueryFromQuery() Validate entity key contents Update query based on configuration settings prepareForSave() Validate data across tables Provide defaults for document getConstraintList() Identify document constraints
Update Query Example: AxdSalesInvoice public void initQueryFromEntityKey(AifEntityKey _aifEntityKey = null, boolean _validateEntityKey = false) { QueryBuildDataSource qbdsFormLetterRem; ... //Disable FormLetterRemarks if no remarks for sales invoice. if (!(select formLetterRemarks where formLetterRemarks.FormLetter == FormTextType::SalesInvoice).RecId) qbdsFormLetterRem = query.dataSourceTable(tablenum(formLetterRemarks),1); qbdsFormLetterRem.enabled(false); query.dataSourceTable(tablenum(formLetterRemarks),2); if (qbdsFormLetterRem) } Disable data sources not needed
Document Validation/Defaulting Example: AxdSalesOrder public boolean prepareForSave(AxdStack _axdStack, str _dataSourceName) { AxSalesTable axSalesTable; ... ; switch (classidget(_axdStack.top())) case classnum(AxSalesTable) : axSalesTable = _axdStack.top(); this.checkSalesTable(axSalesTable); axSalesTable.parmSalesType(this.salesType()); } Verify that elements required by document are provided Set default order type Set default order type
Document Validation Logic Example: AxdSalesOrder private void checkSalesTable(AxSalesTable _axSalesTable) { ; if (!_axSalesTable.parmDeliveryDate()) error(strfmt("@SYS88971")); } if (!_axSalesTable.parmCustAccount()) error(strfmt("@SYS88972")); if (!_axSalesTable.parmPurchOrderFormNum()) error(strfmt("@SYS88973")); Verify that values are provide
Document Defaults As Parameters Example: AxdSalesOrder protected SalesType salesType() { ; switch (AxdDocumentParameters::find().SalesType) case AxdSalesType::Journal : return SalesType::Journal; case AxdSalesType::Sales : return SalesType::Sales; }
Identifying Constraints Example: AxdSalesOrder public void getConstraintList(Common _curRec, AifConstraintList _constraintList) { AifConstraint aifConstraint = new AifConstraint(); SalesTable salesTable; ; if (_curRec.TableId != tablenum(SalesTable)) throw error(strfmt("@SYS23396",funcname())); } salesTable = _curRec ; aifConstraint.parmId(salesTable.CustAccount); aifConstraint.parmType(AIFConstraintType::Customer); _constraintList.addConstraint(aifConstraint) ; Most documents will only have one constraint but there could be more so it’s a list Constraint = Customer ID Add constraint to list ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Ax<Table> TO DO’s ... in code generated by the Axd Wizard 4/22/2017 12:11 AM Ax<Table> TO DO’s ... in code generated by the Axd Wizard Implement defaulting logic Add to set<Field>() methods Add parm<Field>() methods for calculated fields (display fields) Implement caching as appropriate Use cacheObject() as skeleton for objects Use cacheRecordRecord() as skeleton for records NOTE – AIF Wizard uses extensive use of the Cross Reference!!!! So Cross Reference will have to be enabled on development boxes. More and More AXbc classes will be provided – TAP2 has about 50 completed. The rest you will have to do yourself until they come with subsequent versions of Ax. ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Resolving Defaulting Logic Example: SalesTable.CashDisc void initInvoiceAccount() { CustTable custTable; ; custTable = this.custTable_InvoiceAccount(); this.NumberSequenceGroup = custTable.NumberSequenceGroup; this.Payment = custTable.PaymTermId; this.initFromPayment(); if (custTable.PaymSched) this.PaymentSched = custTable.PaymSched; } this.PaymMode = custTable.PaymMode; this.PaymSpec = custTable.PaymSpec; this.CashDisc = custTable.CashDisc; this.setListCode(); CashDisc is defaulted from CustTable
Ax<Table> Defaulting Logic Example: AxSalesTable.setCashDisc() protected void setCashDisc() { if (this.isMethodExecuted(funcname(), fieldnum(SalesTable, CashDisc))) return; } this.setInvoiceAccount(); if (this.isFieldSet(fieldnum(SalesTable, InvoiceAccount))) this.parmCashDisc(this.invoiceAccount_CustTableRecord().CashDisc); Make sure the invoice account is set Default CashDisc from (cached) customer record associated with the invoice account See inline with previous slide. See one of the existing AXBC classes for good examples of defaulting logic for any new tables that you want to do ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Calculated (Display) Fields Typically method on table parm<Field>() method on Ax<Table> class Always included in XML schema Always serialized Read-only Can not be mandatory
Ax<Table> Class Performance Caching Frequently Used Data Avoid duplicate database lookups Cache table variables Cache Ax<Table> classes Axd Wizard generates code templates Copy for each table variable/Ax<Table> class Search/replace table variable/class name Use cache for data lookup
Caching Table Variables Example: AxSalesLine public InventTable inventTableRecord(InventTable _inventTable = null) { InventTable inventTable; if (!inventTableIdx) inventTableIdx = this.nextCacheIdx(); } if (!prmisdefault(_inventTable)) this.tableCacheInsert(inventTableIdx, _inventTable); inventTable = _inventTable; else if (this.tableCacheExist(inventTableIdx)) inventTable = this.tableCacheLookup(inventTableIdx); this.setInventTableRecordFields(); inventTable = InventTable::find(this.parmItemId()); this.tableCacheInsert(inventTableIdx, inventTable); return inventTable; Insert in cache Lookup record in cache Lookup record and insert in cache
Using Cached Table Variables Example: AxSalesLine protected void setSalesUnit() { if (this.isMethodExecuted(funcname(), fieldnum(SalesLine, SalesUnit))) return; } this.setInventTableRecordFields(); if (this.isInventTableRecordFieldsSet()) this.parmSalesUnit(this.inventTableRecord().salesUnitId()); Lookup inventTable in cache
Best Practices Don’t override AxdBase.getName() Be careful with inner joins Use FetchMode=1:n for outer joins Watch out for display fields Inner joins – if no data in secondary table then no results will be passed Outer Joins – use fetchmode=1:n to sequence results properly ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Agenda Extensibility Model XML Document Structure Key Concepts Implementing New Documents Sending Documents Advanced Topics
Enabling The Application Send Electronically Calling the AIF Send Service Using the Send Framework Integrating with exising business logic, e.g. posting routines
”Send Electronically” Button Example: VendPurchOrderJour form void clicked() { VendPurchOrderJour vendPurchOrderJourLocal; ; for (vendPurchOrderJourLocal = vendPurchOrderJour_ds.getFirst(true) ? vendPurchOrderJour_ds.getFirst(true) : vendPurchOrderJour; vendPurchOrderJourLocal; vendPurchOrderJourLocal = vendPurchOrderJour_ds.getNext()) vendPurchOrderJourLocal.sendElectronically(XMLDocPurpose::Original); } super(); Original
Calling The AIF Send Service 4/22/2017 12:11 AM void sendElectronically(XMLDocPurpose _xMLDocPurpose, AifSendMode _aifSendMode = AifSendMode::Async) { AxdSendContext axdSendContext = AxdSendContext::construct(); AifEntityKey aifEntityKey = AifEntityKey::construct(); Map keyData; AifConstraintList aifConstraintList = new AifConstraintList(); AifConstraint aifConstraint = new AifConstraint(); ; keyData = SysDictTable::getKeyData(this); aifEntityKey.parmTableId(this.TableId); aifEntityKey.parmRecId(this.RecId); aifEntityKey.parmKeyDataMap(keyData); axdSendContext.parmXMLDocPurpose(_xMLDocPurpose); axdSendContext.parmSecurity(false); aifConstraint.parmType(AifConstraintType::Vendor) ; aifConstraint.parmId(this.OrderAccount) ; aifConstraintList.addConstraint(aifConstraint) ; AifSendService::submitDefault( classnum(AxdPurchaseRequisition), aifEntityKey, aifConstraintList, _aifSendMode, axdSendContext.pack()); } Create entity key Establish document context Security should not be overriden (i.e. RLS / Table / Field level). BUT you can do it in the case that you want a user to be able to send more data than they are privelaged to see. “Send and Forget” is via batch (ASYNCH). You can do a SYNCH send (for example on Pro-Forma Invoices) where the original document may not exist by the time an ASYNCH send was sent. Identify constraints Call AIF Send Service (”send and forget”) ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Send Framework Example: General Ledger > Chart of Accounts Select which documents (here: accounts) to send Select target endpoints
Using the Send Framework Example: AxdSendChartofAccounts class AxdSendChartofAccounts extends AxdSend { } static public void main(Args args) { AxdSendChartofAccounts axdSendChartofAccounts ; AifConstraintList aifConstraintList; AifConstraint aifConstraint; ; axdSendChartofAccounts = new AxdSendChartofAccounts(); aifConstraintList = new AifConstraintList(); aifConstraint = new AifConstraint(); aifConstraint.parmType(AifConstraintType::NoConstraint); aifConstraintList.addConstraint(aifConstraint); axdSendChartofAccounts.parmShowDocPurpose(true) ; axdSendChartofAccounts.sendMultipleDocuments(classnum(AxdChartOfAccounts), AifSendMode::Async, aifConstraintList); } Configure form Invoke Send Framework
Sending As Part Of Posting Example: PurchFormLetter_PurchOrder void printJournal() { if (journalList.len() > 0) if (printFormletter) this.sendAsXML(); vendPurchOrderJour.printJournal(this, journalList); } if (this.proforma()) this.removeProforma(); Send document before printing
Sending As Part Of Posting Example: PurchFormLetter_PurchOrder protected void sendAsXML() { boolean newLine; if (new PrintJobSettings(printerSettingsFormletter, true).getTarget() != PrintMedium::Screen && !this.proforma()) newLine = journalList.first(vendPurchOrderJour); while (newLine) vendPurchOrderJour.sendElectronically(XMLDocPurpose::Original); newLine = journalList.next(vendPurchOrderJour); } Same method as invoked from ”Send Electronically” Button
Agenda Extensibility Model XML Document Structure Key Concepts 4/22/2017 12:11 AM Agenda Extensibility Model XML Document Structure Key Concepts Implementing New Documents Sending Documents Advanced Topics Note – 1 COM license for AIF and 1 Axapta User License for each EndPoint. You could use the same user but probably better to have one per endpoint for security reasons ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Mandatory Fields ... or Required Elements? Field that must contain a value when a record is inserted into the Microsoft Dynamics AX database, e.g. SalesTable.SalesId Required Element Element required to be present in the XML document to satisfy the schema, e.g. <DeliveryDate> on a Sales Order
Required Elements An XML element is required when Element is required by Axd<Document> class OR Field is mandatory on table AND Field value can not be defaulted
Mandatory Fields Example: Sales Order SalesTable CurrencyCode CustAccount CustGroup InvoiceAccount LanguageId SalesId ShippingDateRequested SalesLine CurrencyCode CustAccount CustGroup ItemId ShippingDateRequested
Defaulting Mandatory Fields Example: AxSalesTable protected void initMandatoryFieldsExemptionList() { super(); this.setParmMethodAsNotMandatory(methodstr(AxSalesTable, parmSalesId)); parmInvoiceAccount)); parmCustGroup)); parmLanguageId)); parmShippingDateRequested)); } Register field as not required Override Benefit: Compile-time verification of table/field names. ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Required By Axd<Document> Class Example: AxdSalesOrder protected void initMandatoryFieldsMap() { super(); this.setParmMethodAsMandatory(classnum(AxSalesLine), methodstr(AxSalesLine,parmSalesQty)); methodstr(AxSalesLine,parmSalesUnit)); this.setParmMethodAsMandatory(classnum(AxSalesTable), methodstr(AxSalesTable,parmPurchOrderFormNum)); methodstr(AxSalesTable,parmDeliveryDate)); } Override Register field as required
Inventory Dimensions InventDim.inventDimId = 00003_060 <SalesLine class=”entity”> ... <ItemId>CL-100B</ItemId> <InventDim class="entity"> <inventColorId>Gold</inventColorId> <inventSizeId>30</inventSizeId> </InventDim> </SalesLine> InventDim.inventDimId = 00003_060
AxInventDim_<ParentTable> Example: AxInventDim_SalesLine class AxInventDim_SalesLine extends AxInventDim { AxSalesLine axSalesLine; } Class is specific to SalesLine public static AxInventDim_SalesLine newAxSalesLine(AxSalesLine _axSalesLine) { AxInventDim_SalesLine axInventDim_SalesLine; ; axInventDim_SalesLine = new AxInventDim_SalesLine(); axInventDim_SalesLine.axSalesLine(_axSalesLine); return axInventDim_SalesLine; } These are special classes whose sole purpose is to update their parent class. Parent in this case is SalesLine Register parent SalesLine public void save() { ; axSalesLine.updateFromInventDim(); } Update SalesLine instead of saving InventDim record ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
AxInventDim_<ParentTable> Example: AxSalesLine AxInventDim_<ParentTable> Example: AxSalesLine.updateFromInventDim public void updateFromInventDim() { ttsbegin; runState = AxBCRunState::Save; fieldModified = new Set(Types::Integer); this.initRecord(); this.inputStatus(InternalExternal::Internal); this.setInventDimId(); inventDimIdDirtySaved = false; this.validateFields(); this.validateWrite(); this.write(); this.resetInternalValues(); ttscommit; } Invoke defaulting logic for SalesLine.InventDimId Re-validate data Update SalesLine SalesLine.InventDimId
Document References (Notes) Accounts Receivable > Setup > Forms > Form Setup Control whether document references are included in XML document
Configuring Document References Example: AxdSalesOrder Disable data sources depending on value of ”Include documents on sheet” Select configured document type Allow only ”external” notes public void initQueryFromEntityKey(AifEntityKey _aifEntityKey, boolean _validateEntityKey) { super(_aifEntityKey, _validateEntityKey); this.docuRefEnabling(); } Internal Docs will be flagged as “internal” so if the same order is sent out somewhere that the notes will not be sent. ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
Disabling DocuRef Data Sources Example: AxdSalesOrder protected void docuRefEnabling() { CustFormLetterDocument custFormLetterDocument; void disableDocuRef(tableId _tableId) { ... } ; custFormLetterDocument = CustFormLetterDocument::find(); switch (custFormLetterDocument.DocuOnConfirm) case DocuOnFormular::Head: disableDocuRef(tablenum(SalesLine)); break; case DocuOnFormular::Line: disableDocuRef(tablenum(SalesTable)); case DocuOnFormular::None: } ...
Selecting Correct DocuRef Type Example: AxdSalesOrder protected void docuRefEnabling() { CustFormLetterDocument custFormLetterDocument; void disableDocuRef(tableId _tableId) { ... } ; custFormLetterDocument = CustFormLetterDocument::find(); switch (custFormLetterDocument.DocuOnConfirm) ... } query.dataSourceTable(tablenum(DocuRef),1). findRange(fieldnum(DocuRef,TypeId)). value(custFormLetterDocument.DocuTypeConfirm); query.dataSourceTable(tablenum(DocuRef),2).
Allow Only External DocuRef Notes Example: AxdSalesOrder Only external notes Place restriction on data source in query Make sure the range is locked!
EndpointE [No Constraints] Multiple Constraints EndpointA [WH1] Microsoft Dynamics AX XML PickingList1 [WH1,WH2] PickingList2 [WH1] EndpointB [WH1,WH2] EndpointC [WH2,WH3] EndpointD [WH1,WH2,WH4] EndpointE [No Constraints]
Multiple Constraints Example: AxdPickingList class AxdPickingList extends AxdBase { AifConstraintList aifConstraintList; } public void getConstraintList(Common _common, AifConstraintList _constraintList) { int i ; int noOfConstraints ; ; noOfConstraints = aifConstraintList.getConstraintCount() ; for(i=1 ;i <= noOfConstraints; i++) { _constraintList.addConstraint(aifConstraintList.getConstraint(i); } Copy constraints identified while processing document
Multiple Constraints Example: AxdPickingList public void processingRecord(Common common) { AIFConstraint AIFConstraint ; InventDim inventDim ; ; if (common.TableId == tablenum(InventDim)) inventDim = common ; AIFConstraint = new AIFConstraint(); if (inventDim.InventLocationId) AIFConstraint.parmType(AifConstraintType::Warehouse) ; AIFConstraint.parmId(inventDim.InventLocationId) ; } else AIFConstraint.parmType(AifConstraintType::NotSet ) ; aifConstraintList.addConstraint(AIFConstraint) ; Called for every data source Identify constraint Add constraint to list
Exposing Calculated Data Problem: The data to be read is not readily available in Microsoft Dynamics AX Solution Create Axd<Document> query with temporary table as data source Make Axd<Document> class generate data in temporary table
Generating Data In Temporary Table Example: AxdPriceList class AxdPricelist extends AxdBase { ... PriceDiscTmpPrintout priceDiscTmpPrintout; } void prepareForQuery(QueryRun _queryRun) { ; select firstonly priceDiscTmpPrintout; if(!priceDiscTmpPrintout) this.insertPriceDiscTmpPrintout(); _queryRun.setCursor(priceDiscTmpPrintout); } Run before seriallization and after de-serialization Generate data ”Connect” query to temporary table
Invoking Business Logic Problem Want to invoke business logic, such as a posting routine without reading or creating data Solution Create Axd<Document> class with no query Add properties to Axd<Document> class for holding results Add parm<Property>() method per property Override read() method to invoke business logic before serializing data
Axd<Document> Class With No Query class AxdOperation extends AxdBase { str result; } Property will be serialized public Str parmResult(str _result = result) { ; result = _result; return result; } public QueryName getQueryName() { return ''; } No query!
Invoking Business Logic public AifDocumentXml read(AifEntityKey _entityKey, AifSchemaInfo _xsdInfo, AifEndpointActionPolicyInfo _actionPolicyInfo, AifConstraintList _constraintList, AifPropertyBag _aifPropertyBag) { AifDocumentXml xml; ; // Call business logic here using data in _entityKey as // parameters. Save result in ’result’ property. xml = super(_entityKey, _xsdInfo, _actionPolicyInfo, _constraintList, _aifPropertyBag); return xml; }
4/22/2017 12:11 AM questions? ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.
© 2006 Microsoft Corporation. All rights reserved. 4/22/2017 12:11 AM © 2006 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary. ©2004 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.