
Author: tw
-
Find Datatypes
I like reusing/extending data types that already exist, however it is not always easy to find them. The following job lets you search the existing data types for a keyword:
static void findEDT(Args _args) { #AOT Dialog dialog = new Dialog('Find EDT'); SearchString searchString; DialogField dialogField = dialog.addField('SearchString'); boolean stopAfterFound; void searchNodes(boolean _extendedDataTypes) { TreeNode treeNode; TreeNodeIterator treeNodeIterator; SysDictType sysDictType; SysDictEnum sysDictEnum; Boolean found; ; if(_extendedDataTypes) { treeNode = TreeNode::findNode(#ExtendedDataTypesPath); } else { treeNode = TreeNode::findNode(#BaseEnumsPath); } treeNodeIterator = treenode.AOTiterator(); treeNode = treeNode.AOTfirstChild(); treeNode = treeNodeIterator.next(); while(treeNode) { if(treeNode.treeNodeName() like "*" + searchString + "*") { if(_extendedDataTypes) { sysDictType = sysDictType::newTreeNode(treeNode); } if(sysDictType) { if (sysDictType.extend() && sysDictType.enumId()) { info(strfmt("%1 (%2 - %3 -> %4)",treeNode.treeNodeName(), sysDictType.baseType(), extendedTypeId2name(sysDictType.extend()), enumId2Name(sysDictType.enumId()) )); } if(sysDictType.extend()) { info(strfmt("%1 (%2 - %3)",treeNode.treeNodeName(), sysDictType.baseType(), extendedTypeId2name(sysDictType.extend()) )); } else if (sysDictType.enumId()) { info(strfmt("%1 (%2 - %3)",treeNode.treeNodeName(), sysDictType.baseType(), enumId2Name(sysDictType.enumId()) )); } else { info(strfmt("%1 (%2)",treeNode.treeNodeName(), sysDictType.baseType())); } } else { info(strfmt("%1",treeNode.treeNodeName())); } found = true; } else if(stopAfterFound && found) { return; } treeNode = treeNodeIterator.next(); } } ; if(dialog.run()) { searchString = dialogField.value(); if(!strScan(searchString, "*", 1, 999)) //no "*" { searchString = "*" + searchString + "*"; } else if(strKeep(searchString,"*") == "*" && subStr(searchString,strLen(searchString),1)=="*") //just one final "*": beginns with { stopAfterFound = true; } info(strfmt("Find %1",searchString)); if(searchString) { setPrefix('Extended Data Types'); searchNodes(true); setPrefix('Base Enums'); searchNodes(false); } } }Update: slight improvement “stopAfterFound”
-
Identify country specific functionality
Add the following to SysCountryRegionCode::isLegalEntityInCountryRegion
Idea by Kim Steffensen (Microsoft Escalation engineer)
public static boolean isLegalEntityInCountryRegion(container _isoCountryCodes, selectableDataArea _selectableDataArea = curext()) { #Define.DEBUG_ALL(true) //set true to get infolog for every country evaluated #Define.DEBUG_SINGLECOUNTRY(false) //set true to get infolog when active country is evaluated int i; str callingPath; int line; if(#DEBUG_ALL || #DEBUG_SINGLECOUNTRY) { //initialize context callingPath = subStr(conPeek(xSession::xppCallStack(),3),4,999); line = conPeek(xSession::xppCallStack(),4); } if(#DEBUG_ALL && ! #DEBUG_SINGLECOUNTRY) { //print context of every country evaluated for(i=1; i <= conLen(_isoCountryCodes); i++) { info(strFmt("%1 %2 %3",conPeek(_isoCountryCodes,i),callingPath,line),"",SysInfoAction_Editor::newLineColumn(callingPath,line)); } } if (conFind(_isoCountryCodes, SysCountryRegionCode::countryInfo(_selectableDataArea))) { if(#DEBUG_SINGLECOUNTRY) { //print context of active country evaluated info(strFmt("%1 %2 %3",SysCountryRegionCode::countryInfo(_selectableDataArea),callingPath,line),"",SysInfoAction_Editor::newLineColumn(callingPath,line)); } return true; } return false; } -
List of predefined AX 2012 Workflows
Category Workflow Description Accounts payable Vendor bank remittance journal workflow Use this type to create approval workflows for vendor bank remittance journals Accounts payable Vendor disbursement journal workflow Use this type to create approval workflows for vendor disbursement journals Accounts payable Vendor draw promissory note journal workflow Use this type to create approval workflows for vendor draw promissory note journals Accounts payable Vendor invoice approval journal workflow Use this type to create approval workflows for vendor invoice approval journals Accounts payable Vendor invoice journal workflow Use this type to create approval workflows for vendor invoice recording journals Accounts payable Vendor invoice line workflow Use this type to create review workflows for vendor invoice lines Accounts payable Vendor invoice register journal workflow Use this type to create approval workflows for vendor invoice register journals Accounts payable Vendor invoice workflow Use this type to create review workflows for vendor invoices Accounts payable Vendor redraw promissory note journal workflow Use this type to create approval workflows for vendor redraw promissory note journals Accounts payable Vendor settle promissory note journal workflow Use this type to create approval workflows for vendor settle promissory note journals Accounts receivable Customer bank remittance workflow Use this type to create approval workflows for customer bank remittance journals Accounts receivable Customer draw bill of exchange workflow Use this type to create approval workflows for customer draw bill of exchange journals Accounts receivable Customer free text invoice workflow Use this type to create approval workflows for free text invoices Accounts receivable Customer payment workflow Use this type to create approval workflows for customer payment journals Accounts receivable Customer protest bill of exchange workflow Use this type to create approval workflows for customer protest bill of exchange journals Accounts receivable Customer recurring invoice workflow Use this type to create approval workflows for recurring invoices Accounts receivable Customer redraw bill of exchange workflow Use this type to create approval workflows for customer redraw bill of exchange journals Accounts receivable Customer settle bill of exchange workflow Use this type to create approval workflows for customer settle bill of exchange journals Advanced ledger entry Advanced ledger entry workflow Use this type to create approval workflows for advance ledger entries Bank Bank reconciliation journal approval workflow Use this type to create approval workflows for Bank Reconciliation journals Budget plan Budget plan workflows Use this type to create and review workflows for budget plans Budget register entries Budget account entry workflow Use this type to create review workflows for budget account entries Budget register entries Budget register entry workflow Use this type to create review workflows for budget register entries Budget register entries Commitments approval Use this template to create approval workflows for commitment documents Case management Case management workflow Use this type to create a workflow for cases Case management Document handling Workflow type for document handling Fixed assets Ledger fixed assets budget journal workflow Use this type to create approval workflows for fixed asset budget journals Fixed assets Ledger post fixed assets journal workflow Use this type to create approval workflows for post fixed asset journals General ledger Ledger allocations journal workflow Use this type to create approval workflows for allocation journals General ledger Ledger daily journal workflow Use this type to create approval workflows for daily journals General ledger Ledger eliminations journal workflow Use this type to create approval workflows for eliminations journal Procurement and sourcing Catalog import approval Use this type to create review workflows for imported catalogs Procurement and sourcing Catalog import product approval Use this type to create review workflows for imported catalog products Procurement and sourcing Delivery due date notification workflow Use this type to create delivery due date notification workflows for unconfirmed product receipts Procurement and sourcing Invoice received notification workflow Use this type to create invoice received notification workflows for unconfirmed product receipts Procurement and sourcing Product receipt failed notification workflow Use this type to create notifications workflows for failed product receipts Procurement and sourcing Purchase order line workflow Use this type to create review- and approval workflows for purchase order lines Procurement and sourcing Purchase order workflow Use this type to create review- and approval workflows for purchase orders Procurement and sourcing Purchase requisition line review Use this type to create review workflows for purchase requisition lines Procurement and sourcing Purchase requisition review Use this type to create review workflows for purchase requisitions Procurement and sourcing Unconfirmed product receipt rejection notification workflow Use this type to create notification workflows for rejected unconfirmed product receipts Project Review budget revision workflow Use this type to review a budget revision Project Review original budget workflow Use this type to review an original budget Project Review project invoice proposals Use this type to review project invoice proposals Project Review project quotations Use this type to review project quotations Purchase agreement approval workflow Purchase agreement approval workflow Use this type to create approval workflows for purchase agreements Retail catalog workflow category Retail catalog approval workflow Retail catalog approval workflow type Signing limits Signing limits workflow Use this template to create a workflow for review of signing limit requests Time and attendance Time and attendance days total workflow Use this type to create approval workflows for time and attendance days total records Time and attendance Time and attendance journal registration workflow Use this type to create approval workflows for time and attendance journal registration records Timesheet Review timesheet line workflow Use this type to review a timesheet line Timesheet Review timesheet workflow Use this type to review a timesheet Travel and expense Cash advance request Use this type to create approval workflows for cash advance requests Travel and expense Dispute management Use this type to create workflows for credit card dispute management Travel and expense Expense line item Use this type to create line item approvals for expense reports Travel and expense Expense line item auto posting Use this type to create line item automatic posting workflows for expense reports Travel and expense Expense report Use this type to create document approvals for expense reports Travel and expense Expense report auto posting Use this type to create document automatic posting workflows for expense reports Travel and expense Travel requisition Use this type to create approval workflows for travel requisitions Travel and expense VAT tax recovery Use this type to create approval workflows for VAT tax recovery User management Inactivate user request workflow Use this type to create user inactivation workflows for inactivate user requests User management User request workflow Use this type to create user provisioning workflows for user requests Vendor request management Vendor add application workflow Use this type to create approval workflows for vendor add application requests Vendor request management Vendor add justification workflow Use this type to create approval workflows for vendor add justification requests Vendor request management Vendor category application workflow Use this type to create approval workflows for vendor category application requests Vendor request management Vendor category justification workflow Use this type to create approval workflows for vendor category justification requests Vendor request management Vendor status change request workflow Use this type to create approval workflows for vendor status change requests This list was exported using the following job:
static void workFlowDescription(Args _args) { #AOT Treenode workflowTypesNode, workFlowNode; int i; int nodeCount; str workflowName; SysDictWorkflowType sysDictWorkflowType; SysDictWorkflowCategory sysDictWorkflowCategory; ; workflowTypesNode = treenode::findNode(#WorkflowTypesPath); nodeCount = workflowTypesNode.AOTchildNodeCount(); workFlowNode = workflowTypesNode.AOTfirstChild(); for (i=1; i<=nodeCount; ++i) { workflowName = workFlowNode.AOTgetProperty("Name"); try { sysDictWorkflowType = SysDictWorkflowType::newTypeName(workflowName); sysDictWorkflowCategory = new SysDictWorkflowCategory(sysDictWorkflowType.category()); info(sysDictWorkflowCategory.label() + ";" + sysDictWorkflowType.label() + ";" + sysDictWorkflowType.help()); } catch ( Exception::Error) { exceptionTextFallThrough(); } workFlowNode = workFlowNode.AOTnextSibling(); } } -
AX 2012 CU7 – Send documents to e-mail addresses defined on the customer.
Probably every AX consultancy has programmed a module to send customer documents by email using addresses defined on the customer. With CU7 you can finally can do this in Standard AX:
Define a primary e-mail on the customer

In the print dialog select “Customer primary contact”

Result: The e-mail is sent to the primary e-mail address defined on the customer.
The settings are now saved in the print destinations and do not need to be changed anymore. When the primary e-mail address is changed, the next e-mail will automatically be sent to the new address.
Even better, once the print settings have been saved, all sales orders will pick up their respective customer emails without further settings needed.
Follow the instructions here http://blogs.msdn.com/b/axsupport/archive/2013/02/05/emailing-customer-invoices-from-a-batch.aspx, you will be able to automatically send you confirmations and invoices by email using email addresses defined on the customer.
Even better: Define e-mail addresses for different documents by applying customizable purposes:

Select purpose in the print dialog:
Final Note: If the defined e-mail is missing you will get the following error.
![clip_image002[5] clip_image002[5]](http://thwidmer.wordpress.com/wp-content/uploads/2013/11/clip_image0025_thumb.png)
-
Deduplication on my Windows 8 Notebook with AX Demo Hyper-V
[Update 6.8.2015]: Caution, at the moment there is no way to activate Deduplication on Windows 10
After reading http://www.expta.com/2013/04/updated-blistering-fast-hyper-v-2012.html, http://www.expta.com/2013/02/windows-server-2012-deduplication-is.html and http://weikingteh.wordpress.com/2013/01/15/how-to-enable-data-deduplication-in-windows-8/ I enabled deduplication on my notebook, saving me lots of space on my precious SSD.
It’s a pity that you cannot enable it on your boot drive, as this happens to be my largest SSD, but my secondary SSD with just 128 GB also benefited from the deduplication. I might reorganize my drives at some later stage.
Here a short summary of the steps required for enabling deduplication on a windows 8.1 Notebook:
- Download Windows Server 2012 deduplication package (e.g. here)
- In powershell run the following to install the package files that have been extracted into the current directory
dism /online /add-package /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~~6.3.9600.16384.cab /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~en-US~6.3.9600.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~~6.3.9600.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~en-US~6.3.9600.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~~6.3.9600.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~en-US~6.3.9600.16384.cab - The to enable deduplication run this powershell command
dism /online /enable-feature /featurename:Dedup-Core /all - Disable Periodic Processing because our main focus will be the deduplication of VHDs
Set-DedupSchedule -Name "BackgroundOptimization" -Enabled $false - Enable Dedup on your volume of choice
Enable-DedupVolume D: - Set minimum age to zero as VHD Files will always have recent modifications. (Maybe wait a moment for the previous command to complete.)
Set-Dedupvolume D: -MinimumFileAgeDays 0 - Run Deduplication only when Hyper-V stopped
Start-DedupJob –Volume D: –Type OptimizationResult:

- Disable (e.g. before installing Windows 10)
Start-DedupJob-VolumeD:-TypeUnoptimization
Disable-DedupVolume -Volume D:
[Update 6.8.2015 – Removed Windows 8 commands; Add Disable Command; Warning Windows 10]
-
Pattern: Job to delete many records
Pattern for efficient (i.e. use transaction for multiple deletes and use doDelete), stable (i.e. don’t make one huge transaction but commit and restart transaction periodically) and verbose (count down the number of remaining records) job to delete many records in a table.
static void deleteJob(Args _args) { #define.TABLE(myTable) //set #define.CONDITION(true) //set #define.TRANSACTIONSIZE(100) //set #TABLE #TABLE; int i = 1; ; while (i>0) { i=0; info(strfmt("%1",(select count(RecId) from #TABLE where #CONDITION).RecId)); infolog.viewUpdate(); ttsbegin; while select forupdate #TABLE where #CONDITION { #TABLE .dodelete(); i++; if(i>=#TRANSACTIONSIZE) break; } ttscommit; } } -
Functions to use in Queries, Filters
Joris on Dynamics AX Musings wrote this Blog Entry: Custom Query Range Functions using SysQueryRangeUtil
The following functions can be used in any query or filter. Note that the functions are case sensitive and need to be put in brackets e.g. (currentUserId()).
Current user (or roles thereof)
- currentUserId()
- currentEmployeeId()
- currentBusinessRelationsAccount()
- currentContactPersonId()
- currentCustomerAccount()
- currentVendorAccount()
Dates (all but dateRange are relate to the current date and time)
- currentSessionDate()
- currentSessionDateTime()
- day(int relativeDays = 0)
- dayRange(int relativeDaysFrom = 0, int relativeDaysTo = 0)
- greaterThanDate(int relativeDays = 0)
- lessThanDate(int relativeDays = 0)
- monthRange(int relativeMonthsFrom = 0, int relativeMonthsTo = 0)
- yearRange(int relativeYearsFrom = 0, int relativeYearsTo = 0)
- dateRange(date startDate, date endDate)
Constants
- currentStaticMasterPlan()
AX2012 only
- currentDate()
- currentLanguageId()
- currentUserLanguage();
- currentWorker()
- currentWorkerRecId()
- currentLegalEntity()
- currentParty()
- advancedLedgerEntryCurrentUserFilter(boolean _createdBy)
- advancedLedgerEntryTxtOpenDraftAll(anytype _advancedLedgerEntryTransactionStatus)
- currentRoleHasAccessToPrivate(boolean _useCache = true)
- currentStaticMasterPlanVersion()
- dateRange(date startDate, date endDate)
- lessThanUtcDate(int relativeDays = 0)
- lessThanUtcNow()
- greaterThanUtcDate(int relativeDays = 0)
- greaterThanUtcNow()
- documentStatusPurchOrderOrGreater()
- getActiveMasterPlanVersionByPlanId(ReqPlanId _planId)
- isDirAddressPolicyOff()
- isPrivate()
- pmfInventTableIsBOM()
- pmfInventTableIsBOMFormula()
- projActiveAll(ProjActiveAll _projActiveAll)
- projActiveAllWIPEliminated(anytype _ProjTableActiveAll)
- projLevels(ProjLevels _projLevels)
- projPostedTransType(ProjPostTransViewType _projPostedTransViewType)
- projUnpostedTransType(ProjUnpostedTransViewType _projUnpostedTransViewType)
- salesQuotationTemplateGroupFilter(SalesQuotationFilter _salesQuotationFilter)
- salesQuotationTypeListPageFilter(SalesQuotationTypeListPage _salesQuotationTypeListPage)
- sessionGuid()
- workflowDelegationFilter(WorkflowDelegationView _filter)
As you see AX 2012 has many more predefined special ranges, many of which are not very self explanatory, as they are not really intended for general use, but are used in the filters of the pre-filtered list pages.
And remember: as Joris showed, you can easily extend the list.


