Microsoft Dynamics AX Support

This blog contains posts by the Microsoft Dynamics AX Support teams Worldwide

AX for Retail: Managing and Maintaining POS Customizations

AX for Retail: Managing and Maintaining POS Customizations

  • Comments 9

[Update: 2013-09-26]  See new functionality in AX for Retail 2012 R2 that makes maintaining customizations a bit easier: AX for Retail 2012 R2: Using the Extensions folder for POS Customizations

One of the most challenging aspects of an AX for Retail deployment that we in Support help out with is dealing with ongoing maintenance of POS customizations.

The AX for Retail POS application was designed to be easily customized:  many of the components are shipped with full source code and a developer can simply modify, compile, and deploy their version of that component.  For example, if your deployment has a unique requirement for custom pricing, you would load the Price Service C# project (which contains the source code for Microsoft’s version of the component), make your code changes, compile to the Price.dll and then copy the DLL into your Retail POS folder.  The next time you launch the POS application your customized version will automatically be used instead of the stock version.   This is a bit simplified;  for more details you can see the product documentation for this topic.

Very simple and very powerful.  To steal an over-used superhero movie cliché, though, with great power comes great responsibility.  And that responsibility is to have a plan to manage the source code for your POS customizations.

The Problem

The problem is pretty easy to describe.  By my estimate, almost half of the POS in AX for Retail 2012 R2 is customizable.  This includes some very important core areas of the product:  the price/discount/tax engine, receipt printing, end of day processing, sales order processing, and most of the UI elements (Dialog and Interaction services).

Because the sample source code that we ship for services and triggers is actually the same source code that is used to compile the shipped version of those DLLs, it is very likely that a hotfix we ship will affect that same code.  By my rough count, about a third of all AX for Retail hotfixes that we have shipped in 2012 R1 (“6.1”) include changes to plug-ins. 

If one of these hotfixes is for a component that you customized, you will need to update your customization to merge in this code change. 

In addition, when you install a POS hotfix, the installer does not know about any customizations.  This means at the very least you will have to re-copy your customized DLLs back into the Retail POS directory after installing the hotfix.

The concept of a “three-way code merge” is not a new one.  Most source code repository solutions have tools built-in for this problem and there are many standalone text compare utilities that can be used to work around the issue.  However, the biggest issue that I’ve seen with POS customizations is simply the awareness of the issue.  Once the awareness is there, coming up with a system to handle the issue isn’t too difficult.  Walking through a simple example should help.

Initial Development

Consider that there are two developers at work on the code:  you (the Partner) and Microsoft.  Developer “Partner” is tasked with making a customization to the price engine (Price service) and the receipt printing engine (Printing service).  Let’s say that Partner started development on version 6.0.1108.2423 of the POS (AX 2012 CU4).

This means that Partner used the AX Installer to install the POS application and POS Plug-ins (source code which gets installed to the “my documents” folder) on a development machine and then later ran the CU4 installer (KB 2765124) to get both the binaries and plug-ins up to 6.0.1108.2423.  We will call this the baseline that was used for customizations.

Suggestion:  Make a copy of the baseline directory and store it in a safe place.  In this screenshot you can see I just made a copy of the entire directory and named it “Retail POS Plug-ins 2423”:

2013-07-08 13_54_44-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

To keep things even more segregated, I also made a copy of the directory to use for the actual development work:

2013-07-08 13_57_16-AX for Retail_  Managing and Maintaining POS Customizations - Windows Live Write

The customizations to the Printing and Price services should then be done in this development directory:

2013-07-08 14_05_08-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

2013-07-08 14_17_31-c# decimal constant - Google Search

Deploying the customizations is as simple as compiling the projects and then copying the resulting DLLs to the Retail POS\Services directory:

2013-07-08 14_23_35-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

Installing the Hotfix

This customization is pretty simple and was coded and thoroughly tested before deploying to production.  However, after a couple of months the client has discovered a bug in the receipt printing process (totally unrelated to your rock-solid code, of course) and Microsoft delivered a hotfix to address the issue (KB 2804675, version 6.0.1108.3631).  Because the fix was targeted at receipt printing, it should be no surprise that the Printing customization may be affected.  However, because POS hotfixes are always cumulative, there is a possibility that a previous hotfix also affected the Price plug-in.   Because of the way we set up the source code directories, we can quickly determine what plug-ins are affected.

A POS machine will typically only have a few components installed so we will only select those components during the update:

2013-07-08 15_12_26-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

Inspecting the Retail POS\Services directory we can confirm that the customized DLLs have indeed been clobbered (as expected):

2013-07-08 15_14_56-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

We can use a compare utility to confirm that source code has been updated in the Retail Plug-ins directory by comparing it against our 2423 directory:

2013-07-08 15_17_37-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection 2013-07-08 15_18_41-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

This shows us every change that was made to any service or trigger between builds 2423 and 3631:

2013-07-08 15_38_03-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

As you can see, the Price project does not show up in this list.  This means that no changes to the Price service have been made since the previous baseline.  Partner only needs to worry about updating the Printing project.

The Manual Three-way Merge

Unless a three-way merge tool is being used, the developer needs to make a choice:  a) merge Microsoft’s changes into the customization or b) re-merge the customization into the new baseline.  The general rule of thumb is to figure out who did the most changes.  If Partner’s customization is huge and Microsoft only made a small change, copy and paste Microsoft’s changes into the customization.  If the Microsoft changes are larger, copy the new baseline version of the files into the customization directory and re-do the customizations.  Since this example only changed a couple of lines in the FormModulation.cs file, this is the choice to make.

[Side Note:  A third scenario is possible but unlikely:  if you analyze the code changes between the two baselines you may decide that the changes Microsoft made will never be applicable to your customer.  For example, maybe a fix was made to pricing with respect to trade agreements.  If your customer doesn’t use trade agreements you might not even bother merging them into your customization.  In general, though, this is bad practice as it is too easy skim over changes that you may not understand or have interdependencies you may not be aware of.]

To do the merge using option b) we will copy the new baseline versions of the Printing.cs and FormModulation.cs files to the development directory using Windows Explorer (after first copying the text of the customization):

2013-07-08 15_57_56-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

2013-07-08 15_55_36-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

2013-07-08 16_00_07-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

At this point Visual Studio should prompt you to re-load the file.  This will blow away your customization so be careful here!

2013-07-08 16_01_29-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

And then we will simply copy and paste the customization again:

2013-07-08 16_02_55-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

And now we can re-compile and re-deploy the DLL and start testing.

 

Wrap-up and Tips

After testing is complete, make sure to make another copy of the Microsoft-provided source code to match the hotfix that was installed.  This will be the next baseline that will be used for the next hotfix that requires a code merge:

2013-07-08 16_09_23-SERSTAD21 - 10.10.80.86 - Remote Desktop Connection

Obviously this can be a pretty convoluted process and even small customizations can quickly become very difficult to manage.  A couple of tips that may help you out:

  • If you made the mistake of just doing your development directly in the “Retail POS Plug-ins” directory before making a backup of it, you can always find a different machine and run an AX installer for that version.  Remember that we’re only dealing with text files here (.CS files) so you can make copies of them anywhere you want.
  • Be liberal in your use of code comments of your customizations.  Anything you can do to help another developer with comparing lines of code will make things a lot easier down the road.
  • When possible, create separate methods or even separate .CS files for your code.  The fewer “touches” in the actual code the better.
  • As mentioned, this is not a new problem and there are lots of tools out there to help with this type of code merge.  At the very least, make sure you are storing your development branch in some sort of version control system.

Installing POS hotfixes is a very important part of your deployment maintenance and remembering about customizations is something that sometimes slips through the cracks.  You never know when a critical hotfix will need to be rapidly deployed; make sure you have this process down solid beforehand and make sure to budget time for this important step.

Leave a Comment
  • Please add 2 and 7 and type the answer here:
  • Post
  • Hello Shane! Thank you very much for your post!

    I have the following requirement :

    A customer wants to ensure that the cashier never sells a product with less than a specified margin.

    The calculation is simple. The sales price should never be less than the cost price + % margin.

    From the Ax side, I added a new parameter to the tables RetailPositionPosPermission and RetailPosPermissionGroup

    I used cross-references in the field maxTotalDiscountPct and made all the customizations following the pattern.

    Here comes the problem!

    From POS application the right place to edit seems to be the classes representing those tables PositionPosPermission and PosPermissionGroup.

    The issue is than I cannot edit nor extend these classes because they are compiled and marked as sealed.

    Is the source code available?

    Is there any workaround?

    For almost every requirement, I have the same kind of problems.

    Thanks in advance,

    Alejandro.

  • interesting article. Unfortunately the article stops at the critical point of deployment of the hot fixed DLL to remote POS devices. How would this be installed on PC in remote locations ?

  • Hi B,

    Deploying the actual DLL is relatively straightforward:  you just need to copy the new DLL to the file system on the POS machine.

    We don't currently have an automated solution to remotely do this - but you could set something up with System Center or other computer management tool to do the automated copy.

    Usually deploying a custom DLL to a POS is done in conjunction with deploying the hotfix - many customer come up with a manual process to do the copy of the custom DLL directly after deploying the hotfix.

  • Hi Shane,

    AX 2012 Retail POS facilitates Time Clock entry functionality. But I was not able to see required setup. Kindly send me if you have any details to sudhykg@gmail.com

    Tks

    Sudhy  

  • Hello Shane!

    I have a couple of issues, well basically is one, we have a machine with AX 2012 and the CU6, we have some customization for the POS that used to work fine before the CU6, when we copy into the Extensions folder our custom dll's we get the error message: Could not load all external service modules, the first time I received this message i was able to fix it  copying "Microsoft.Dynamics.Retail.TestConnector.dll" from "C:\Program Files (x86)\Microsoft Dynamics AX\60\Client\Bin\Connectors" to "C:\Program Files (x86)\Microsoft Dynamics AX\60\Retail POS\Connectors".... But after that and after copy our custom Dll's POS keep displaying the same error: Could not load all external service modules.

    Do you any idea where I should start to look?

    I tried to open a clear Solution, the one that comes with the Pos installation and I tried to copy my code from my customization, piece by piece but it is not helping.

    I really appreciate any help.

  • Hi Shane.

    I have a question. I need to get the selected line of sale in a blank operation. I can get the last line, but i need the selected line. Is that possible?

    Thanks.

  • Hi shane,

    I need get the selected line from the main window of the pos and then use it in a blank operation. Is that possible?

    Thanks

  • Mack:  thanks for the question.  The blank operation actually sends in the currently-selected line of the transaction in the operationInfo.ItemLineId parameter.

    See this line of code in the sample you can download from blogs.msdn.com/.../ax-for-retail-the-blank-operation-explained.aspx

    SaleLineItem saleItem = myTransaction.GetItem(operationInfo.ItemLineId);

  • Marcos:  please see my other comment (same question - are you and Mack working on the same project?).

    Sudhy K.G:  I don't have any specifics on that functionality.  Please open a support case and a support engineer will point you to the documentation.

Page 1 of 1 (9 items)