Monday, June 4, 2012

AX 2012 for Retail - An Introduction to Application Settings



Hi there!

I hope everyone had a good weekend and that you are ready for another challenging week ahead of you.

In this post I’m going to write about using the AX 2012 for Retail Application Settings. This is a dll that exists within the AX 2012 for Retail application folder, and that can be used to retrieve important and useful in-memory information such as the POS operator Id, Terminal ID, Store ID, Data Area ID, Store ID, among others.

If we think about it, by using this dynamic library, we can minimize numerous trips to the database and therefore improve performance at run time. On this thought, this post will focus on a sample project that will retrieve some POS information through a windows form that will be opened when the PostLogon() event is fired. This means that when the Windows form opens, we’ll know who is logged in, the terminal and the store they logged in to.

So, let’s start by setting up our project. Please note that I made a copy of my POS application folder to play around, as our exercise will overwrite the Application Triggers dll and it will create a new dll that for our new form project.

If you haven’t read my post on AX 2012 POS development - Application triggers I would recommend to read it before moving forward.

1-Create a new project, select Class Library and name it Application Triggers.




2-Add the Microsoft.Dynamics.Retail.POS.Contract.dll reference to the above project.



3-Add the System.ComponentModel.Composition.dll to the above project.



4-Open your code file and implement the IApplicationtrigger interface as shown below.



5-Make sure it looks like the following picture, and then delete the throw statements to avoid firing an exception at run time.



6-On top of the ApplicationStart() Method add the following:



7-Add a new project to the solution, select Class Library, and give it a name (i.e. AppSettingFormExample) . Then in your new project add a new form and a new class.  In the form add 4 buttons that will have the following caption:

 a.Show Current User
 b.Show Current Store
 c.Shoe Current Terminal
 d.Show Current Connection


NOTE: You can see a sample of this form below.






8-Build the solution so our AppSettingFormExample dll is created in the AX 2012 POS folder as shown in my post AX 2012 POS development - Application triggers

9-In order to launch the form we created above from the ApplicationTriggers PostLogon() method, we need to add our Form project as a reference to the ApplicationTriggers Project.  When you are done, then add the namespace to your code as shown below:





 
10-Build the solution.

11-In your ApplicationTriggers Project, reference the System.Settings.Dll.

12-Add the namespace to your code (LSRetailPosis.Settings).



 

13-Add the following code to the class you created along with the form. Here we are using the ApplicationSettings dll to retrieve the information each button says it will retrieve. If you note, this is a really good and simplified design. Each of these calls does not fire up a trip to the Database and it just takes the data from memory, which makes the AX 2012 POS application really responsive.



14-In order to call our class and retrieve the information we need, we have to write some events for each button.

Now, I like to write one event handler for all the buttons in my form and then use a switch statement to identify which is which, and then route their operations. For me this works better as I just create one method instead of 4 for each button. Neither is better than the other, unless you think the same way I do : - )

So, write the following code in tour designer:



Now, we need to go to each button properties’ Click() method and add the name of our button event handler in order for the event to work.



15-Run the solution and the AX 2012 POS application should be opened (Check my post AX 2012 POS development - Application triggers). Input your credentials.



you should see the form you created. Click each button and you should see the following results.

_______________________________________________________________
NOTE: In order to launch the form after the PostLogon() method, you will have to instantiate the Form you created as shown below:
Form1myform = new Form1();
myform.ShowDialog();
_________________________________________________________________________________











There is much more to cover on the AX 2012 POS System Settings, and I certainly encourage you to dive deeper into it as it is really cool and make writing code really easy and scalable.

That’s all for now and keep checking back for my next post on Blank Operations and much more!

 


26 comments:

  1. Very good article, thank you very much, i have juste a remarque, you have miss to put the code to lauche the form.
    its working for me , tank you.

    ReplyDelete
    Replies
    1. Hi!

      Thanks for reading my blog. I did include the code to open the form, it's right above the last portion of the blog :-)

      NOTE: In order to launch the form after the PostLogon() method, you will have to instantiate the Form you created as shown below:

      Form1myform = new Form1();

      myform.ShowDialog();

      Delete
  2. yes yes i have'nt seen it, i have add this portion of code in my programme and it's working very nice, otherwise, i'm no trying to get à price list and to show it in a form. have you any idea about the function i have to call?

    ReplyDelete
    Replies
    1. There are different ways to do this. You can write a method in AX and call it from your POS as a dataset or something. The other method would be to use the DataAccess.dll that it is within the POS app folder. With this dll you can query the POS DB directly. ANd you can just use LINQ and/or in-line sql statements.

      If you get it going, I would greatly appreciate you sharing this with us :-)

      Let me know.

      Delete
  3. OKEY !! i'm gonna try it today and i will share the result with you !! thanks a lot !!

    ReplyDelete
  4. Hi Edward,

    today i succufly implement the function to get the PriceList of a product, and i have put the result in a forme, so when i select a product in the POS, the forme is shown and you get all the discount and the rules parametred on the product.

    i have used the ITEM Service with a function i desined to get information from The retail database.

    Now i'm gonna try to change the behave of the POS, so the OPERATOR would have the choice to use a SPECIFIQUE PRICELIST Or a DISCOUNT FORMULA from the form i have shown to him.

    ReplyDelete
    Replies
    1. That's nice work man! I would love to see the code you wrote to post it in my blog and share it with others if that's ok with you.

      Delete
  5. Here is my Code !!

    in item.cs file i added this function !!

    public List GetPromotion(string selectedItemId)
    {
    List benjid=new List();

    SqlConnection connection = Application.Settings.Database.Connection;

    try
    {
    if (!string.IsNullOrEmpty(selectedItemId))
    {

    string queryString = "SELECT DISTINCT RETAILPERIODICDISCOUNT.NAME AS NOMPROMO "+
    "FROM RETAILPERIODICDISCOUNTLINE INNER JOIN "+
    "RETAILGROUPMEMBERLINE ON RETAILPERIODICDISCOUNTLINE.RETAILGROUPMEMBERLINE = RETAILGROUPMEMBERLINE.RECID INNER JOIN "+
    "ECORESPRODUCT ON RETAILGROUPMEMBERLINE.PRODUCT = ECORESPRODUCT.RECID INNER JOIN "+
    "RETAILPERIODICDISCOUNT ON RETAILPERIODICDISCOUNTLINE.OFFERID = RETAILPERIODICDISCOUNT.OFFERID "+
    "WHERE (RETAILPERIODICDISCOUNT.DATAAREAID = 'CERW') AND (ECORESPRODUCT.DISPLAYPRODUCTNUMBER = @ITEMID)";
    using (SqlCommand command = new SqlCommand(queryString, connection))
    {
    command.Parameters.Add("@ITEMID", SqlDbType.NVarChar, 30).Value = selectedItemId.ToString();

    if (connection.State != ConnectionState.Open)
    {
    connection.Open();
    }

    using (SqlDataReader reader = command.ExecuteReader())
    {
    if (reader.HasRows.Equals(true))
    {
    while (reader.Read())
    {
    benjid.Add(reader["NOMPROMO"].ToString());
    }
    }
    }
    }

    }

    }
    catch (Exception ex)
    {
    LSRetailPosis.ApplicationExceptionHandler.HandleException(this.ToString(), ex);
    throw;
    }
    finally
    {
    if (connection.State != ConnectionState.Closed)
    {
    connection.Close();
    }
    }

    return benjid;
    }


    And to use it i added this portion of code in The "ProcessItem" Function


    public void ProcessItem(ISaleLineItem iSaleLineItem, bool bypassSerialNumberEntry)
    {
    SaleLineItem saleLineItem = (SaleLineItem)iSaleLineItem;

    ////////////////////////////////////////////////////////////////////////////////////
    /////////// Je vais créer mon ecran ou j'affice l'image de l'article ///////////////
    ////////////////////////////////////////////////////////////////////////////////////
    //MessageBox.Show("Article :::: "+saleLineItem.ItemId.ToString()+" ::::");
    List promo = new List(GetPromotion(saleLineItem.ItemId.ToString()));
    if (promo.Count > 0)
    {
    Form1 ecran = new Form1();

    for (int i = 0; i < promo.Count; i++)
    {
    ecran.AjouterMenu(promo[i].ToString());
    }
    ecran.Show();
    }///////////////////////////////////////////////////////////////////////////////////



    And in my Form i have create a listbox with a public function that take in argument a string in order to add my promotion in The list

    ReplyDelete
    Replies
    1. Super Mohamed, thanks so much for sharing your code with us. Have a great weekend and I hope to hear soon from you!

      Send me your email!

      Delete
    2. here is my email : benjid.irisi@gmail.com
      send me yours too :), have a nice day !!

      Delete
  6. Hi guys.

    I am having some problems and I want to know if you can help me.

    I need to save the SalesPersonId for each transaction on the POS, I see that the saleLineItem already has the SalesPersonId. I want to use that field but something is missing.

    When the Operator introduces the first item, it displays a form with a numpad to enter the salesperson code, so what I want is to save that value on the RetailTransactionTable but it will not insert the transaction into the Table until the operator(cashier) close the sale.

    I do not know if you understand what I am trying to say.

    Here is part of my code:

    SaleLineItem saleLineItem = (SaleLineItem)iSaleLineItem;

    LSRetailPosis.Transaction.RetailTransaction retailTrans = (LSRetailPosis.Transaction.RetailTransaction)saleLineItem.RetailTransaction;

    if (saleLineItem.SalesPersonId == null)
    {
    Dialog.Dialog dialog = new Dialog.Dialog();

    if (dialog.SalesPersonCode(out strSalesPersonCode) == DialogResult.OK)
    {
    saleLineItem.SalesPersonId = strSalesPersonCode;

    retailTrans.Save();
    }
    }

    Thank in advanced.

    ReplyDelete
    Replies
    1. Hi Camilo,

      You will have to use a custom database operation for this. You can use the DataAccess.Dll and write data to this line at the time you want to and not when the transaction is done.

      You already know the line number and the Sales Person Code.

      You can do something like the following:

      DBUtil dbUtil = new DBUtil(ApplicationSettings.Database.LocalConnection);

      StoreId = ApplicationSettings.Terminal.StoreId;

      var update = new SqlUpdate("Name of Table you want to update");
      update.Where("Name of Column", lineNum);
      update.Set("Name of Column", Minutes());
      dbUtil.Execute(update);

      I hope this helps. Let us know if you got it working and if thism post helped you, I would appreciated if you could share your solution with us.

      Delete
  7. Great job.

    I'm working on POS customization and I'm trying to customize the Barcode Service, because we need to read several specific barcodes with their own barcode masks and we need to extract different information, so I want to add this new information as a new fields on the BarcodeInfo datatype, in order to use it on different methods on the service.

    Is there any way to override the BarcodeInfo datatype to do it?

    Thanks



    ReplyDelete
    Replies
    1. Angel,

      The only thing that comes to mind is that you would create as many as barcode masks as you need to fulfill your need. I'm not sure and I haven't worked with the barcode service and/or dll yet.

      I hope this helps.

      Delete
  8. Thanks for your sharing,

    Follow your articles about Retail, I almost control the POS, but I'm still stuck in the pull the transaction from Store back to Headquarter. It could get the transaction but not for my custom field in that table.
    My custom field showed in "Distribution locations" and match with Headquarter in "Transfer field list" of "Scheduler subjob".
    Is there any place for us to set up or define what field will pull back to the Headquarter?

    Appreciate for your help.

    ReplyDelete
  9. thanks for sharing but where Should I found the system.settings.dll or LSRetailposis ????

    ReplyDelete
  10. Hi,

    It is located in your POS directory (Located either under the Microsoft Dynamics AX folder, or the place that your admin put it). There should be a system dll there. Then you just add a reference to Visual Studio and also create a using statement.

    ReplyDelete
  11. Hi, I was wondering if you know if there is documentation related to the "digital signing" for Ax 2012?

    Regards.

    ReplyDelete
    Replies
    1. Hi Camilo,

      I don't know about anything on that topic. Can you elaborate a bit more on what it is, so perhaps I know it by a different name?

      Delete
  12. Hi, I am trying to insert data into RetailperiodicDiscount through code, Can you help me with the tables which i need to insert , as its an abstract table.

    ReplyDelete
    Replies
    1. I don't think this is an abstract table. There is no such thing as abstract tables in AX. Only classes can be abstract. The Table you mentioned is a real table and therefore to insert data look at the relationships, specially RetailDiscountValidationPeriod and PriceDIscGroup tables.

      I don't have any code that does this, but I would assume that AX provides a class to do so. The other alternative is for you to follow the logic on how AX does this if you insert a record manually. Just set a breakpoint.

      I hope this helps.

      Delete
  13. Hi AxWonders,
    It has been fun following your blog. It would be great if you could help me in solving this issue we are having.

    We have added a few custom fields to the customer object in AX retail. We are trying to add these fields to the POS application and update the Transaction services accordingly. In the Transaction Services, we are planning to add code to update the new fields value with teh user input. But we are not able to see the new fields that were added to AX in the Customer object. We also observe that the Transaction.dll and the Contract.dll are still not updated with the changes on the AX side. Is there a way we can update this DLL?

    Thanks for your help in advance.

    Regards,
    Ram

    ReplyDelete
    Replies
    1. Hi,

      Thanks for following my blog! What you want to achieve is actually simple.

      The following link will help you achieve adding custom fields to the customer object and I used this post for what I did in the past.

      http://blogs.msdn.com/b/axsupport/archive/2012/08/06/retail-2012-working-with-custom-fields.aspx

      I hope this helps!

      Delete
    2. We have tried the custom fields approach, but as I understand it, it can be created only for four specific areas - Totals Area, Billing, Receipts etc. It did not give an option to create a custom field for Customer. So how would you add a custom field for Customer record and update the transaction service to set the values for the correct customer field.

      After adding the custom fields, the Transaction DLL's were not updated and hence we are not able to set the values to the new fields. I am new to this and any directions from you would be of great help.

      Thanks,
      Ram

      Delete
    3. Hi,

      In that case, shouldn't you modified the transaction DLL manually then? AX 2012 Retail has the SDK with all the dll's necessary to modify. In this SDK you'll find the Transaction project that you can map to both the retail app and AX.

      Not sure how to actually do what you are asking, I did modified the customer DLL following the approach on the link, and for what I have seen, any other modification must be done directly into the SDK projects and then be redeployed back to the retail folder.

      Delete

Thank you for your thoughts. Your comment will appear in my blog shortly after review.

Have a great day!