Dynamics AX TAP Knowledge Transfer Wave 2. Application Integration Framework (AIF)...
-
Upload
matthew-mcdaniel -
Category
Documents
-
view
250 -
download
3
Transcript of Dynamics AX TAP Knowledge Transfer Wave 2. Application Integration Framework (AIF)...
Dynamics AX TAP
Knowledge Transfer Wave 2
Application Integration Framework (AIF)Document/Interface Development
Søren Vagn AndersenProgram ManagerMicrosoft Dynamics AX
Agenda
Extensibility Model
XML Document Structure
Key Concepts
Implementing New Documents
Sending Documents
Advanced Topics
Supported XML DocumentsTrade
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]
FinanceExchange Rates [out,in]GL Chart of Accounts [out,in]GL Dimensions [out,in]
InventoryInventory Counting Journal [in]Inventory Transfer Journal [in]Inventory Balances [out]Inventory Transactions [out]Inventory Profit/Loss Journal [in]
XML Document Development
Model driven approachFocus on data and business logicCustomizations handled (almost) automatically
Generalized framework
Tools supportWizard for generating class skeletonsBest practice check to detect data model changes
Model Driven Approach
SalesTableSalesTable
SalesLineSalesLine
DBDB
XMLXML
HOW ?HOW ?...
...
Axd<Axd<DocumentDocument> query defines> query definesXML structure and contentXML structure and content
Ax<Ax<TableTable> classes manage data access> classes manage data access
Axd<Axd<DocumentDocument> > class performsclass performsserialization and serialization and de-serializationde-serialization
Agenda
Extensibility Model
XML Document Structure
Key Concepts
Implementing New Documents
Sending Documents
Advanced Topics
XML Schema Structure<?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> <CaseTagging>No</CaseTagging> <Complete>No</Complete> <CurrencyCode>EUR</CurrencyCode> ...
<InventDim class="entity">…</InventDim>
</SalesLine>
<DocuRefHeader class="entity">…</DocuRefHeader> <DocuRefHeader class="entity">…</DocuRefHeader>
</SalesTable></SalesOrder>
HiddenEmpty
Parm<Property>()methods onAxd<Document>class
Serialization Strategy
Serialize parm<Property>() methods on the Axd<Document> classRead data using Ax<Table> class, if presentRead directly from table, if no Ax<Table> classField 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 DatatypesX++ Datatype
XSD Type
String xsd:string, maxLength=StringSize
(maxLength=max(StringSize,50) in case of value mapping)
Integer xsd:intInteger xsd:time, ISO format: HH:MM:SS
(Time stamp if global::isTypeTimeglobal::isTypeTime is true)
Int64 xsd:longReal xsd:decimal,
fractionDigits=NoOfDecimalsDate xsd:date, ISO format: YYYY-MM-DDEnum 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
OutboundNull values are not serializedArrays may contain empty elements
InboundEmpty string elements interpreted aszero-length string, not nullUse <element xsi:nil=”true”/> to specify null value
SecurityRespects Microsoft Dynamics AX security
Security keysRecord level securityMaxAccessMode propertyAllowEditOnCreate propertyVisible property
No access to system tablesSystemTable=YesTableType≠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
XMLXML
Insert into Insert into work tableswork tables
XMLXML
Read fromRead fromjournalsjournals
PurchTablePurchTable
PurchLinePurchLine
VendPurchOrderJourVendPurchOrderJour
VendPurchOrderTransVendPurchOrderTrans
PostingPosting
Documents With Header/Lines
SalesTableSalesTable
SalesLineSalesLine
Header = ”Root” data sourceHeader = ”Root” data source
LinesLines
Notes at both header and linesNotes at both header and lines
Axd<Document> Classes
Service classesImplement AifServiceable interfaceExpose document actions
Validation of entire document, e.g.Cross-table dependenciesDocument life-cycle constraints
May invoke business logicPosting
Ax<Table> Classes1-to-1 relationship with tablesName derived from table, e.g. AxSalesLineparm<Field>() method for each fieldDefaulting of fields with no valuesValidation of fields with respect to, e.g.
Referential integrityNumber sequencesBusiness logic
Value mapping of specific fieldsAlso used by other modules
Enterprise Portal...
Class Hierarchy
TableTable
Axd<Axd<DocumentDocument>>AxdBaseAxdBase
AxInternalBaseAxInternalBase Ax<Ax<TableTable>>
AifServiceableAifServiceable
Axd<Axd<DocumentDocument>>
??+getActionList()+getActionList()
Action Axd<Document> Method
SendDocument XML read(entityKey, ...)
ReceiveDocument entityKey create(XML, ...)
... ...
Action Axd<Document> Method
SendDocumentGenerate XML document identified by entity key
XML read(entityKey, ...)
SendDocumentListGenerate list of XML documents each identified by entity key
XML readList(entityKeyList, ...)
QueryDocumentsGenerate list of XML documents matching query criteria
XML findList(queryCriteria, ...)
QueryEntityKeysGenerate list of entity keys for XML documents matching query criteria
entityKeyList findEntityKeyList(queryCriteria, ...)
ReceiveDocumentParse XML document and write data to database
entityKey create(XML, ...)
ReceiveDocumentListParse list of XML documents and write data to database
entityKeyList createList(XML, ...)
Entity KeysIdentify specific document instance
Table
(Field, Value) pairs for primary keys
Use entity keys returned by AIFTable
Must be ”root” data source in query
Use ID in X++
Not needed in XML / Web Client
FieldUse ID in X++
Use Field Name in XML / Web Client
Using Entity KeysXML<?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> <KeyField> <Field>InventDimId</Field> <Value>00001_060</Value> </KeyField> </KeyData> </EntityKey> </Body></Envelope>
Action
Entity Key
Using Entity KeysWeb Services
//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";
Create entity key object
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 1> GreaterThan 1
>= GreaterThanEquals
1
< LessThan 1<= LessThanEquals 1.. Range 2
Using 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> <CriteriaElement> <DataSourceName>SalesTable</DataSourceName> <FieldName>CurrencyCode</FieldName> <Operator>Equals</Operator> <Value1>USD</Value1> </CriteriaElement> </QueryCriteria> </Body></Envelope>
Action
Querycriteria
Constraints
Enables the AIF to make decisions based on document contents
RoutingSecurity (to prevent spoofing)
Constraint typesCustomerVendorWarehouse
Constraint Based Routing
Micro
soft D
ynam
ics AX
EndpointA
[3001]
EndpointB
[3001,3004]
EndpointC
[3000,3001]
EndpointD
[3001,3002,3004]
EndpointE
[No Constraints]
XML
PurchaseOrder1
[3001]
PurchaseOrder2
[3004]
Constraint Based Security
Micro
soft D
ynam
ics AX
EndpointA
[4000]
EndpointB
[4000,4002]
EndpointC
[4000,4012]
EndpointD
[4000,4002,4012]
EndpointE
[No Constraints]
XML
SalesOrder1
[4000]
SalesOrder2
[4002]
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 QueryExample: AxdSalesInvoicepublic 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); qbdsFormLetterRem = query.dataSourceTable(tablenum(formLetterRemarks),2); if (qbdsFormLetterRem) { qbdsFormLetterRem.enabled(false); } }} Disable data sources not needed
Document Validation/DefaultingExample: AxdSalesOrderpublic 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 elementsrequired by documentare provided
Set default order type
Document Validation LogicExample: AxdSalesOrderprivate void checkSalesTable(AxSalesTable _axSalesTable){ ; if (!_axSalesTable.parmDeliveryDate()) { error(strfmt("@SYS88971")); }
if (!_axSalesTable.parmCustAccount()) { error(strfmt("@SYS88972")); }
if (!_axSalesTable.parmPurchOrderFormNum()) { error(strfmt("@SYS88973")); }}
Verify that valuesare provide
Document Defaults As ParametersExample: AxdSalesOrderprotected SalesType salesType(){ ; switch (AxdDocumentParameters::find().SalesType) { case AxdSalesType::Journal : return SalesType::Journal; case AxdSalesType::Sales : return SalesType::Sales; } return SalesType::Journal;}
Identifying ConstraintsExample: 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) ;}
Constraint = Customer ID
Add constraint to list
Ax<Table> TO DO’s... in code generated by the Axd Wizard
Implement defaulting logicAdd to set<Field>() methods
Add parm<Field>() methods for calculated fields (display fields)
Implement caching as appropriateUse cacheObject() as skeleton for objectsUse cacheRecordRecord() as skeleton for records
Resolving Defaulting LogicExample: 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 LogicExample: 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); }}
Default CashDisc from (cached) customerrecord associated with the invoice account
Make sure the invoice account is set
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 PerformanceCaching Frequently Used DataAvoid duplicate database lookups
Cache table variablesCache Ax<Table> classes
Axd Wizard generates code templatesCopy for each table variable/Ax<Table> classSearch/replace table variable/class name
Use cache for data lookup
Caching Table VariablesExample: AxSalesLinepublic 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); } else { this.setInventTableRecordFields(); inventTable = InventTable::find(this.parmItemId()); this.tableCacheInsert(inventTableIdx, inventTable); } } return inventTable;}
Insertin cache
Lookup recordin cache
Lookup record and insert in cache
Using Cached Table VariablesExample: AxSalesLineprotected 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
Agenda
Extensibility Model
XML Document Structure
Key Concepts
Implementing New Documents
Sending Documents
Advanced Topics
Enabling The ApplicationSend Electronically
Calling the AIF Send Service
Using the Send Framework
Integrating with exising business logic, e.g. posting routines
”Send Electronically” ButtonExample: 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 Servicevoid 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 contextIdentify constraints
Call AIF Send Service(”send and forget”)
Send FrameworkExample: General Ledger > Chart of Accounts
Select target endpointsSelect which documents (here: accounts) to send
Using the Send FrameworkExample: AxdSendChartofAccountsclass 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 PostingExample: 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 PostingExample: 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
Implementing New Documents
Sending Documents
Advanced Topics
Mandatory Fields... or Required Elements?
Mandatory FieldField that must contain a value when a record is inserted into the Microsoft Dynamics AX database, e.g. SalesTable.SalesId
Required ElementElement 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>
classOR
Field is mandatory on tableANDField value can not be defaulted
Mandatory FieldsExample: Sales Order
SalesTableCurrencyCode
CustAccount
CustGroup
InvoiceAccount
LanguageId
SalesId
ShippingDateRequested
SalesLineCurrencyCode
CustAccount
CustGroup
ItemId
ShippingDateRequested
Defaulting Mandatory FieldsExample: AxSalesTableprotected void initMandatoryFieldsExemptionList(){ super();
this.setParmMethodAsNotMandatory(methodstr(AxSalesTable,
parmSalesId));this.setParmMethodAsNotMandatory(methodstr(AxSalesTable,
parmInvoiceAccount));this.setParmMethodAsNotMandatory(methodstr(AxSalesTable,
parmCustGroup));
this.setParmMethodAsNotMandatory(methodstr(AxSalesTable,
parmLanguageId)); this.setParmMethodAsNotMandatory(methodstr(AxSalesTable,
parmShippingDateRequested));}
Override
Register field as not required
Required By Axd<Document> ClassExample: AxdSalesOrderprotected void initMandatoryFieldsMap(){ super();
this.setParmMethodAsMandatory(classnum(AxSalesLine),
methodstr(AxSalesLine,parmSalesQty));
this.setParmMethodAsMandatory(classnum(AxSalesLine),
methodstr(AxSalesLine,parmSalesUnit));
this.setParmMethodAsMandatory(classnum(AxSalesTable),
methodstr(AxSalesTable,parmPurchOrderFormNum));
this.setParmMethodAsMandatory(classnum(AxSalesTable),
methodstr(AxSalesTable,parmDeliveryDate));}
Override
Register field as required
Inventory Dimensions<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_SalesLineclass AxInventDim_SalesLine extends AxInventDim{ AxSalesLine axSalesLine;}
public static AxInventDim_SalesLine
newAxSalesLine(AxSalesLine _axSalesLine)
{
AxInventDim_SalesLine axInventDim_SalesLine;
;
axInventDim_SalesLine = new AxInventDim_SalesLine();
axInventDim_SalesLine.axSalesLine(_axSalesLine);
return axInventDim_SalesLine;
}public void save()
{
;
axSalesLine.updateFromInventDim();
}
Register parent SalesLine
Update SalesLine instead of saving InventDim record
Class is specific to SalesLine
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.InventDimIdRe-validate data
Update SalesLine SalesLine.InventDimId
Document References (Notes)Accounts Receivable > Setup > Forms > Form Setup
Control whetherdocument referencesare included in XML document
Configuring Document ReferencesExample: AxdSalesOrder
Disable data sources depending on value of ”Include documents on sheet”
Select configured document type
Allow only ”external” notespublic void initQueryFromEntityKey(AifEntityKey _aifEntityKey,
boolean _validateEntityKey)
{
super(_aifEntityKey, _validateEntityKey);
this.docuRefEnabling();
}
Disabling DocuRef Data SourcesExample: AxdSalesOrderprotected 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)); break; case DocuOnFormular::None: disableDocuRef(tablenum(SalesTable)); disableDocuRef(tablenum(SalesLine)); } ...}
Selecting Correct DocuRef TypeExample: AxdSalesOrderprotected 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). findRange(fieldnum(DocuRef,TypeId)). value(custFormLetterDocument.DocuTypeConfirm);
}
Allow Only External DocuRef NotesExample: AxdSalesOrder
Place restrictionon data sourcein query
Make sure therange is locked!
Only external notes
Multiple Constraints
Micro
soft D
ynam
ics AX
EndpointA
[WH1]
EndpointB
[WH1,WH2]
EndpointC
[WH2,WH3]
EndpointD
[WH1,WH2,WH4]
EndpointE
[No Constraints]
XML
PickingList1
[WH1,WH2]
PickingList2
[WH1]
Multiple ConstraintsExample: 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 ConstraintsExample: AxdPickingListpublic 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
SolutionCreate Axd<Document> query with temporary table as data source Make Axd<Document> class generate data in temporary table
Generating Data In Temporary TableExample: AxdPriceList
class AxdPricelist extends AxdBase{ ... PriceDiscTmpPrintout priceDiscTmpPrintout;}
void prepareForQuery(QueryRun _queryRun){ ;
select firstonly priceDiscTmpPrintout;
if(!priceDiscTmpPrintout) this.insertPriceDiscTmpPrintout();
_queryRun.setCursor(priceDiscTmpPrintout);}
Run before seriallizationand after de-serialization
Generate data
”Connect” query totemporary table
Invoking Business Logic
ProblemWant to invoke business logic, such as a posting routine without reading or creating data
SolutionCreate Axd<Document> class with no queryAdd properties to Axd<Document> class for holding resultsAdd parm<Property>() method per propertyOverride read() method to invoke business logic before serializing data
Axd<Document> Class With No Queryclass AxdOperation extends AxdBase{ str result;}
public Str parmResult(str _result = result){ ;
result = _result;
return result;}
public QueryName getQueryName(){
return '';
}No query!
Property will be serialized
Invoking Business Logicpublic 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;}
questions?questions?
© 2006 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only.
Microsoft makes no warranties, express or implied, in this summary.