Skip to main content

Posts

Showing posts from March, 2012

Inventory Journal Import

1. Create a Movement Journal and go into the Lines screen. 2. Select Functions, Import Lines 3. Select a csv file with the columns: ItemId, Warehouse, Location, Batch, Qty, Cost. (you can mod the code to expand this) 4. The lines are added to the journal. You can download the xpo below, and here are some of the key bits of code. Create a class (mine is called inventJournalImport) extending runbase. Create a menu item (action) for the class and drop it on the InventJournalMovement form. The main method of the class is as follows: client static void main(Args args) { inventJournalImport inventJournalImport; Object formRunObject; JournalForm journalForm; InventJournalId inventJournalId; FormDataSource journalTrans_ds; ; inventJournalImport = new inventJournalImport(); inventJournalImport.getLast(); if (!args || !args.caller() || args.caller().name() != fo

Inventory Turns Report

static void InventoryTurns(Args _args) { itemId itemId; inventTrans inventTrans; inventSum inventSum; qty thisQty, qtyOnHand, totalDailyQtyOnHand, avgDailyQtyOnHand, usageQty; Amount thisValue, valueOnHand, totalDailyValueOnHand, avgDailyValueOnHand, usageValue; Real turnsByQty, turnsByValue; date lastDate, fromDate, toDate; ; //set the itemID and date range itemId = '00001'; fromDate = mkDate(1,1,2010); toDate = mkDate(31,12,2010); //****average daily on-hand lastDate = systemDateGet(); //initialize with today. //inventSum contains today's values for qty and value while select inventSum where inventSum.ItemId == itemId && inventSum.Closed == NoYes::No { qtyOnHand += inventSum.PhysicalInvent; valueOnHand += (inventSum.PhysicalValue + inventSum.PostedValue); } //starting with today, we work backward to the from

Mark All for Open Cust Trans and Open Vend Trans

We have situations where there are lots of open transactions that need to be settled against each other. This can be the case if auto settlement is turned off. One solution is to add a "Mark All" button to the custOpenTrans or vendOpenTrans forms. This button "checks" the mark checkbox on every line. The user can then uncheck several lines if needed and Update to settle the lines. The code below is an example of what we used on the open vendor transaction screen. The code is very similar on the AR side. One note: I used vendTable.AccountNum in the code below. That should be generalized to work with any buffer that is passed into the open trans form. void customMarkAll() { VendTransOpen localVendTransOpen; VendTrans localVendTrans; container conSum; int linesProcessed; ; //show wait cursor startLengthyOperation(); element.lock(); //remove all prior markings specOffsetVoucher.deleteSpe

Find TableName from TableId

static void NDPToolsShowTableNameFromId(Args _args) { SysDictTable sysDictTable;       int id = 40015;   //enter your ID here       ;       sysDictTable = new SysDictTable(id);       info (sysDictTable.name()); }

Common Prefixes in AX 2009

Please see the common prefixes used in AX 2009 : Prefix Description Ax        Dynamics AX Typed Data Source Axd      Dynamics AX business Document BOM    Bill of Material COS     Cost Accounting Cust      Customer HRM    Human Resources management Invent   Inventory Management JMG     Shop floor management KM       Knowledge Management Ledger  General Ledger PBA     Product Builder Prod     Production Proj      Project Purch   Purchase Req      Requirements Sales    Sales SMA    Service Management SMM   Sales and Marketting Management Sys       Application Framework and development tools Tax      Tax Engine Vend    Vendor Web     Web Framework WMS   Warehouse Management

Sayfaya sığdırmak için, Test – Rapor raporu yüzde XX küçültüldü

Dizaynı neden ile büyük olan ve her seferinde Sayfaya sığdırmak için, Test – Rapor raporu yüzde XX küçültüldü şeklinde uyarı veren raporunuz varsa, raporunuzun init() metodunda alttaki değişikliği yaparak bu mesajı görmeyi engelleyebilirsiniz.     //kucukltum mesajini kapatir     this.printJobSettings().suppressScalingMessage(true);    //

Read and alter registry settings in Axapta

Here is a sample code of increasing max. open cursors during run-time. But, please note that its purpose is only to show you how to read and write registry. If you encounter any open cursors problem, it is recommended to optimize the SQL statement rather than changing the setting for maximum open cursors. static void IncreaseMaxOpenCursors(Args _args) { #winapi container regRet; int readReg; int writeReg; str keyValue, keyPath, configName; int maxOpenCursors; ; //Specify your Axapta configuration utility name here configName = " LocalMachine "; //New maximum open cursor, default is 90 maxOpenCursors = 120; keyPath = @"SOFTWARENavisionAxapta3.0" + configName; readReg = WinAPI:: regOpenKey ( #HKEY_CURRENT_USER , keyPath, #KEY_READ ); if (readReg) { regRet = WinAPI::regGetValue(readReg, ‘opencursors’); keyValue = conpeek(regRet,1); info(keyValue); if (str2int(keyValue) < maxOpenCursors) { writeReg = WinAPI:

X++ code to remove identical copy

Our client asked for a job to remove the identical copy from VAR layer. For some unknown reason, some AOT objects are touched in VAR layer but actually are identical copy. When the developer compared the VAR layer object with the one in lower layer (BUS, SYS etc.), AX showed it was an identical copy. Here is the example on how you can remove the identical copy in X++ code: static void FindAndDeleteIdenticalObjects(Args _args) { SysTreeNode comparable1, comparable2; TreeNode curLevelTreeNode, upperLevelTreeNode; UtilIdElements utilElements, joinUtilElements; ; while select UtilElements where UtilElements.utilLevel == UtilEntryLevel::var && ( UtilElements.recordType == UtilElementType::Form || Utilelements.recordType == UtilElementType::Report || Utilelements.recordType == UtilElementType::Table || Utilelements.recordType == UtilElementType::Class || Utilelements.recordTyp

Dynamics AX 2009: Write to eventlog entry

Our client requested to keep track of all Dynamics AX system errors during the User Acceptance Testing. I use the application event logs to store the information. The following code shows you how to write event log entry with X++: Create a new class AX_EventLog with a static method WriteEventLog : static void WriteEventLog(Exception _exception, str _event) { str eventSource = " AX event "; str logType = " Application "; System.Diagnostics.EventLogEntryType eventLogEntryType; int eventCategory = 9999; ; switch (_exception) { case Exception::Info: eventLogEntryType = System.Diagnostics.EventLogEntryType::Information; break ; case Exception::Warning: eventLogEntryType = System.Diagnostics.EventLogEntryType::Warning; break ; default : eventLogEntryType = System.Diagnostics.EventLogEntryType::Error; } if (!System.Diagnostics.EventLog::Exists(eventSource)) { System.Diagnostics.EventLog::CreateEventSource(eventSource, logType); } System.Diagnostics.EventLog::Writ

Not Like’ in Dynamics AX

In X++, we can use Like ‘*someIdentifier’ to implement the Like keyword. e.g. select firstonly purchTable where purchTable.purchId like ‘ 00007* ‘; However if you want to use ‘Not Like’ in X++ SQL statement, you have three options: The first option, using ‘!’ as ‘not’, e.g. select firstonly purchTable where !(purchTable.purchId like ‘ 00007* ‘); The second option, using notExists join e.g. PurchTable purchTable, refPurchTable; ; select firstonly purchTable notExists join refPurchTable where purchTable.purchId == ‘ 00007* ‘; Please make sure that you do put purchTable.purchId in condition statement, otherwise the SQL statement will retrieve an empty result set. The last option, using Query e.g. Query query = new Query(); QueryRun queryRun; ; query.addDataSource(tableNum(PurchTable)).addRange(fieldNum(PurchTable, PurchId)).value(‘ !00007* ‘); queryRun = new QueryRun(query); if(queryRun.next()) { purchTable = queryRun.get( tableNum (PurchTable))

Self diagnostics

this Script will check if all tables have Primary index Cluster index Caching //NOTE: temp tables are skipped static void TableTuningTest(Args _args) { boolean skipEmptyTables = true; boolean result; treeNode treeNode; SysDictTable sdt; str TableAndCound; int recordCount; boolean skipEmptyrecordCount = false; treeNodeIterator treeNodeIterator =TreeNode::findNode(" \\Data Dictionary\\Tables").AOTiterator(); ; treeNode = treeNodeIterator.next(); setPrefix("Tuning"); while (treeNode) { sdt = new SysDictTable(tablename2id(treeNode.AOTname())); recordCount = sdt.recordCount(); if(!sdt.isTmp() && (!skipEmptyTables || (recordCount != 0)) ) { TableAndCound = treeNode.AOTname()+ ' ('+ int2str(sdt.recordCount())+')'; setPrefix(TableAndCound); result = false; result = result || sdt.treeNode().AOTgetProperty("CreatedDateTime") == "yes" ? true : fa

How to install Xpo’s

Most companies have 3 different Dynamics AX environments: - Development environment - Test/Acceptation environment - Production/live environment. When a customer wants to have changes to their production/live environment, the describe some kind of document with requirements. A developer will implement the requirements in their Development environment. When he is finished someone has to copy the changes to the test/acceptation environment. The customer will test the changes and when he accepts them, the changes have to be copied to the production environment.   This coping of changed code can be done in 2 ways: - Xpo file (with label files). - A var layer files (with label files). 1 Copy the delivered Xpo or layer and label files to your delivery archive directory. (Note use the delivery date in the folder name) 2 Create in the archive directory a directory backup. 3 Stop all batch servers. 4

What can go wrong with number sequences?

Very low performance of the application Data base blocking on the number sequence table so al user get stocked when the need a sequence number. Let’s start with the worst performance setup related to a number sequence. We set the customer account number on continues. The below table shows the queries that are executed. Continues = true, pre allocation = false First time (8 database calls) SQL statement: (SysRecordTemplateTable) SQL statement: (CustFormletterParameters) SQL statement: (NumberSequenceReference) SQL statement: (NumberSequenceTable) SQL statement: (NumberSequenceTable) SQL statement: (NumberSequenceList) SQL statement: (NumberSequenceList) SQL statement: (NumberSequenceTable) Second time (5 database calls) SQL statement: (NumberSequenceTable) SQL statement: (NumberSequenceTable) SQL statement: (NumberSequenceList) SQL statement: (NumberSequenceList) SQL statement: (NumberSequenceTable ) Now we remove the Continues option and create a new custom

Debug queries and show sql

Sometimes you want to see the query with has been executed to the database. Solution: Try to find the query in the code, and add info(query.dataSourceNo(1).toString()); The word query has to be replaced with the object name of the query at that time. This will result in this kind of message in the info log: SELECT * FROM LedgerTrans ORDER BY LedgerTrans.TransDate ASC, LedgerTrans.Voucher ASC WHERE ((AccountNum = 21240 OR AccountNum = 21240 OR AccountNum = 21230 OR AccountNum = 21230 OR AccountNum = 21205 OR AccountNum = 21205)) AND ((TransDate>=12/01/2002 AND TransDate<=12/31/2002)) AND ((PeriodCode = Normal))

Where is my code running

Sometime you are not for sure if your code is running on the AOS or on the client. By adding below line in your code. AX will tell you where the code is running. info(strfmt("%1",xGlobal::clientKind()));

Mass update on table properties

We all have run in trouble in the past when for a lot of tables the same update needs to be done: Below script can help you out. It will look in all tables that are in the database (SQLDictionary) Next it will find the related AOT Tree node. static void ChangeTableProperties(Args _args) { SQLDictionary dictionary; TreeNode treeNode; str properties; ; while select dictionary where dictionary.fieldId == 0 && dictionary.name like("Proj*") { treeNode = TreeNode::findNode('\\data dictionary\\tables\\'+dictionary.name); if (treeNode) { properties = treeNode.AOTgetProperties(); properties = setProperty(properties, 'CreatedDateTime', 'Yes'); properties = setProperty(properties, 'CreatedBy', 'Yes'); treeNode.AOTsetProperties(properties); treeNode.AOTsave(); } } }

table & field ID conflicts

Some months ago, I posted an article about SQLDictionary ID conflicts. It was a x++ job that scans and solves at once. Last month I have to do this in a use live environment. The customer preferred detailed information about the ID conflicts and solving it was the next step. The keyword in this process is: Don’t lose customer data on the Database! Let’s look at next example Tablename AOT ID SQL ID A 50003 40001 B 40025 40013 C 40026 40025 So I created a script that checks: Difference in Table ID Difference in Field ID Difference in String size Changed field properties Check if documents in document management are attached to tables with an ID conflict. (or amy other table). From the results I created small jobs that solved the ID conflicts on a structural way. Solve any difference in the field Properties In your AOT (string size, Created date, etc) Solve the Table ID conflicts Process the tables in an order that the change to a non existing ID in th