Marking Checklist Items as Complete

Microsoft Dynamics AX 2012 uses Checklist to accomplish certain tasks. One such task is the Redeployment Checklist for the Retail Channels and the Initialization Checklist. The whole idea is that you cannot continue with a task until you have not completed the previous task.

But let’s say you do want to mark a task as completed without actually running the Class. In case you know what you are doing, and you are sure you can skip a step here is a short job demonstrating how you can mark the Synchronization of the database as completed:

static void pcoMarkCheckListAsComplete(Args _args)
{
    //Marking Compile as completed
    SysCheckList::finished(classnum(SysCheckListItem_Compile));
 
    //Marking Syncronize database as completed
    SysCheckList::finished(className2Id(classStr(SysCheckListItem_Synchronize)));
 
 
    info('done');
}

Hope you enjoyed my post and in case you have a question don’t hesitate to leave a comment!

Autocomplete text in MorphX Editor

One useful tool in Dynamics AX MorphX Editor is the Autocomplete function. For example, if you type if and click the Tab Button the if statement autocompletes.

ifScript

Nifty! But what if you want to add your own Autocomplete function: let’s say if you type info and click the Tab Button you want info(StrFmt(“%1”, )); to be inserted.

 

Just add following method to class xppSource

Source info(Source _variable = '')
{
 
    source += @'info(StrFmt("%1", ));';
 
    source += '\n';
    return source;
}

 

Add the following method to class EditorScripts

 

public void template_flow_if(Editor editor)
{
    xppSource xppSource = new xppSource(editor.columnNo());
 
    int currentLine = editor.currentLineNo();
 
    int currentCol = editor.columnNo();
 
    Source template = xppSource.if();
 
 
 
    editor.insertLines(template);
 
    editor.gotoLine(currentLine+1);
 
    editor.gotoCol(currentCol+5);
 
}

 

 

The result will look like this:

infoScript

Hope this helped.

Customizing the Retail Transaction Service

Microsoft Dynamics AX 2012 for Retail came with a very powerful feature that I feel is a bit underrated: the possibility to customize the Retail Transaction Service.

The Retail Transaction Service is just a simple Windows Service that sends synchronous requests from the POS to the HQ .Net Business Connector for processing. After the AOS finishes the processing of the data, it returns some data back to the POS.

In Microsoft Dynamics AX 2012 for Retail there are two Classes for the customization: RetailTransactionService and RetailTransactionServiceEx.

The RetailTransactionService Class holds all the standard methods used by the POS like creating a new customer, updating an address or updating a transfer order. These methods represent the basic functionalities of the POS. Of course, if needed customization to these methods can be done.

The RetailTransactionServiceEx Class is there to add functionalities beyond the standard. Just add a new method to this class and you will be able to call this method from the POS. There are a few important notes to make about the methods:

  1. The methods have to be static.
  2. Pick simple parameters when calling the method like strings or integers. For structured data, use an XML.
  3. As return values use a container. Always have a flag to be able to check if the call was successful.

Use the Application.TransactionService.Invoke() method (with the X++ method name and parameters) from the POS side to invoke the newly written method.

Hope you enjoyed my post and in case you have a question don’t hesitate to leave a comment!

Distribution Scheduler for Retail Stores

Microsoft Dynamics AX 2012 for Retail has made a huge step forward in helping partners and clients deploy the AX POS in stores. But how do you keep the POS-DB up to date?

Here comes the Distribution schedule, found under /Retail/Periodic/Retail scheduler/Distribution schedule, in play.

There are 3 types of jobs in the scheduler: A-Jobs, N-Jobs and P-Job. The job number tells you what data the job will replicate on the POS-DB; for example N-1010 replicates everything that is related to Customers and N-1080 replicates everything that is related to Tax information. The different tables that are being replicated on the POS-DB you can see under /Retail/Setup/Retail scheduler/Scheduler job. 

Setup of Scheduler Jobs

Setup of Scheduler Jobs

As you can see from the screenshot, every job is made out of at least 1 subjob (tables) that can be replicated. Here you can create specific jobs, that transfer only the tables that you need. You can also edit existing jobs by enabling or disabling subjobs.

Important to note here is that there are a couple of jobs that seem to repeat, like A-1010 and N-1010. What is the difference between the different job types you might ask? Good question!

  • A-Jobs replicate only changes made to the data in the respective tables since the last time the A-Job has ran
  • N-Jobs replicate the whole table in the POS-DB
  • P-Job replicates the data from the POS-DB in AX (the oposite direction from the A and N-Jobs). Here are the POS transactions, transaction lines, tax information, reason codes etc.

Exactly these A-Jobs are used to keep the POS-DB up to date. Every time there is a new record (or an update) in a table that is relevant to the POS-DB (you can find a list of tables under /Retail/Setup/Retail scheduler/Scheduler subjob) there is a so called Preaction generated. This preaction logs the changes to the tables.  All preactions are saved under /Retail/Periodic/Retail scheduler/Preactions.

These preactions must be then converted into Actions (found at /Retail/Periodic/Retail scheduler/Actions).This can be achieved via a Job found at /Retail/Periodic/Retail scheduler/Create actions. These actions will then be processed by the A-Jobs.

These jobs can run directly or as a batchjob.

Here is a simplified standard walkthrough of the process:

  • A change is made to an existing address.
  • A preaction is automatically generated.
  • At the end of the day there is a batch job that converts the preactions into actions. These preactions are then marked as processed.
  • After that the A-1010 batch job starts and creates a XML file for each table with all the changes.
  • These XML files are created by the Retail Store Connect (RSC) Service. The RSC also packs the files together and sends them to the POS-DB.
  • On the POS-DB the RSC unpacks the file in the respective XML files and writes the changes in the db.

Of course, these jobs can be planned and run multiple times a  day, depending on the needs of the customer.

Hope you enjoyed my post and in case you have a question don’t hesitate to leave a comment!

Debugging Batch Jobs

Show me the developer who doesn’t love breakpoints? They are the best thing since sliced bread and double monitors.

So how can one set a breakpoint in managed code? It’s actually not that hard.

The problem here is that the standard AX debugger can only debug interpreted code. But since we have CLR code we can use our trusty Visual Studio.

Here are the steps:

1.  Be sure breakpoints are enabled on AOS configuration
2.  Start Microsoft Visual Studio with admin rights
3.  Go to Debug and choose Attach to process

Attach to process

Attach to process

4.  Select the AX32Serv.exe process (make sure Show processes for all users and Show processes in all sessions are checked) and click Attach.

AX32Serv.exe

AX32Serv.exe

5.  A warning will pop up about a “suspicious” process. This is our process so just select Attach again.

6.  Now just go to the batch job you want to run and set a breakpoint.

Breakpoint

Breakpoint

7.  From Dynamics AX run the Job in batch

In case you get a breakpoint that is not red and when the cursor is on top of it it displays a message

“The breakpoint will not currently be hit. No symbols have been loaded for this document.”

don’t worry. If the xpps are loaded correctly and the xppil lib exists you will hit the breakpoint.

If not, just generate a fll CIL and/or restart the AX service.

Empty Breakpoint

Empty Breakpoint

 

Hope you enjoyed my post and in case you have a question don’t hesitate to leave a comment!

Exporting CSV Files in Dynamics AX

One thing that really comes in handy (more often than you would think) is writing files from X++ code.

There are multiple reasons for doing this: exporting data, writing log files, saving records etc.

For example, I like writing data in CSV files because it’s fast, simple and best of all you can open the file using Excel and you have the format you want.

Let’s say you want a list of  all open sales orders from today.

Here is the code:

static void PCO_CSVFile(Args _args)
{
	SalesTable              	salesTable;
	System.IO.StreamWriter  	streamWriter;
	FileName                	fileName;
	utcDateTime             	todaysDate;
	TimeOfDay               	midnight;
	str                     	inputLine;
 
	//setting the date for today at midnight
	midnight = str2time('00:00:00');
	todaysDate = DateTimeUtil::newDateTime(today(), midnight);
 
	//setting the path and file name
	fileName	= WINAPI::getTempPath() + "TodaysOpenOrders" + ".csv";
 
	//initializing the streamWriter
	//nice part here is we can choose encoding (come in handy more often than not)
	streamWriter = new System.IO.StreamWriter(fileName, 
                                                  false, 
                                                  System.Text.Encoding::GetEncoding(28591));
 
	//creating the heading and inserting it in the file
	inputLine = 'SalesID;Customer Account;Payment Mode;Created At';
	streamWriter.WriteLine(inputLine,true);
 
	while select * from salesTable where salesTable.createdDateTime >= todaysDate
        	&& salesTable.SalesStatus == SalesStatus::Backorder
	{
 
    	inputLine = strFmt('%1;%2;%3;%4',
            	salesTable.SalesId,
            	salesTable.CustAccount,
            	salesTable.PaymMode,
            	salesTable.createdDateTime);
 
    	//inserting a new line every time
    	streamWriter.WriteLine(inputLine,true);
	}
 
	//don't forget to close the file
	streamWriter.Close();
 
	info("You are done!");
}

Of course there are other classes too that you can use to write a CSV file. One example is the CommaTextIo Class. I would recommend using this Class if you are not sure what Encoding you should use.

Hope this helped.

 

Create a new Job using EditorScripts Class

One thing that I like to do is copy a segment of code in a Job and debug it there. It’s like a safe place, where you can test/debug the code, without worrying that some unknown variables might influence the process. And since I use it quite often, I wrote a nifty function, to automate it a bit by adding this small method to the EditorScripts Class. In case you don’t know what the EditorSpripts does and how it works here is a previous post explaining the Class

 

Here is what it does: Let’s say you found a select statement that you would like to run, without the rest of the code in the method. You just select the code you are interested in, click on the createNewJob under Scripts -> WorkFlow, add a new for the new Job and voila! your new Job is ready.

newJobTool

 

Here is the code

 

public void WorkFlow_createNewJob(Editor editor)
{
    //dialog variables
    Dialog dialog;
    DialogField jobName;
    Str20 strJobName;
    //editor variables needed for selection
    Editor newJobEditor;
    str selectedText;
    //variables needed to create the new Job
    TreeNode treeNode;
    xInfo xInfo = new xInfo();
    //creating the dialog for the name of the job
    dialog = new Dialog("WorkFlow - Create Job");
    jobName = dialog.addField("str20");
 
    if (dialog.run())
    {
        strJobName = jobName.Value();
    }
 
    //getting the selected text from the editor
    selectedText += EditorScripts::getSelectedText(editor);
 
    //creating the job
    treeNode = xInfo.rootNode();
    treeNode = treeNode.AOTfindChild("Jobs");
    treeNode.AOTadd(strJobName);
 
    //treeNode holds our freshly made Job
    treeNode = treeNode.AOTfindChild(strJobName);
    //opens the job
    treeNode.AOTedit(3,1);
 
    //newJobEditor is the editor of the created Job
    newJobEditor = Editor::open('\Jobs\\' + strJobName);
 
    //inserting the selected text in the new Job
    newJobEditor.insertString(selectedText);
}

Hope you enjoyed my post and in case you have a question don’t hesitate to leave a comment.

Reducing Repetitive Typing with the EditorScripts Class

One thing I really hate is repetitive typing, especially when I am trying to test something via a Job or debugging. One easy way to debug your code is by displaying the information you want on the screen via an infolog.

So imagine this scenario: you’ve just finished writing that nasty SQL statement, with 2-3 joints thrown in there (you know, for good measure), and all you want to do is look at the values it returns from the database.

If you are anything like me, you will write something like this

 info(StrFmt(‘%1, ‘%2, %3’, variable1, variable2, variable3));

It’s not that bad, writing that statement out every time, but if you use this method EVERY DAY (like I do), you will get sick of it.

So I wrote this small method to add to the EditorScripts Class. In case you don’t know what the EditorSpripts does and how it works here is a previous post explaining the Class.

Here is what it does: just write the variables one after another, highlight the text, right click, select the function and voila! ready to debug!

infoMethodExample

Here is the code

void WorkFlow_infoStrFmt(Editor e)
{
    str             beginingText, selectedText, endingText, finalText;
    int             i, j;
    container       cont;
    ;
 
    //the beginning and ending of each info statement
    beginingText = 'info(strFmt(\'';
    endingText ='));';
    j = 1;
 
    //getting the highlighted text (as a string)
    //and saving it in a container
    selectedText = EditorScripts::getSelectedText(e);
    cont = str2con(selectedText, ' ');
 
    //for each value in the container
    for(i = 1; i <= conLen(cont); i++)
    {
        if(conPeek(cont,i) !='')
        {
            //we add a %1 or %2 or %3 etc.
            beginingText +=  strFmt('%%1 ', j);
            //variable j keeps track of how many variables we have in the container
            j++;
        }
    }
 
    //here we add the comma between the string and the values in the StrFmt method
    beginingText += '\', ';
    j = 1;
 
    //for each value in the container
    for(i = 1; i <= conLen(cont); i++)
    {
        if(conPeek(cont,i) !='')
        {
            //we add all the variables in the StrFmt method
            beginingText +=  strFmt('%1, ', conPeek(cont, i));
        }
    }
 
    //deleting the last 3 characters from the string (a comma, a space and a return)
    beginingText = strDel(beginingText, strLen(beginingText)-3, strLen(beginingText));
 
    //putting the 2 strings together
    finalText = beginingText + endingText;
 
    //positioning the cursor in the editor
    //adding the final string in the editor
    //and deselecting the text
    e.gotoCol(strlen(e.currentLine()) + 2);
    e.insertString(strFmt('%1', finalText));
    e.unmark();
}

Hope you enjoyed my post and in case you have a question don’t hesitate to leave a comment.

Customizing MorphX using EditorScripts Class

Most IDEs have some cool build-in tools to help you write faster and more efficient code, and MorphX is no different. In case you hate repetitive typing as much as I do, here is a quick tweak that can help.

There are a couple of ways to add functionality to the MorphX Editor, and the easiest and fastest way is by adding a new method to the Class EditorScripts in the AOT.

Every new Method in the class can be called from the Editor by Right Click > Scripts.

MSDYNAX EditorScripts Comment

So let’s write a very basic Method, just to get an idea of what we can do with this Class. This method will comment the line in which the cursor is, or the highlighted lines in the code.

In the AOT go to Classes-EditorScripts and create a new Method which will look something like this:

private void method1()
{
}

Please note the name convention: pcoNewNode is the new node under the Scripts menu and everything after the underscore is the node under pcoNewNode. The parameter _editor is just our Editor instance.

First we want to get where the line number where the code highlighting starts and where it ends. Next, we deselect the highlighted text and for each line we write in the first position the string “//”.

public void pcoNewNode_CommentScript(Editor _editor)
{
    //getting the line number of the start and end of the highlithing
    int startLine = _editor.selectionStartLine();
    int endLine   = _editor.selectionEndLine();
    int i;
 
    //unmark the highlighted text
    _editor.unmark();
 
    //for every line
    for (i = startLine; i <= endLine; i++)
    {
        //put the cursor on that line number
        _editor.gotoLine(i);
        //put it in the first position (column) of that line
        _editor.gotoCol(1);
        //insert the string
        _editor.insertString('//');
    }
}

This is a very easy and fun way of customizing MorphX, because all you have to do is write good old  X++ code.