Pages

Wednesday, November 13, 2013

AX Retail 2012 R2: Create New POS Form with Editable Quantity



Last blog, I explained about how to create new Retail POS transactions.  Now, I will show creating new POS form.  

Noted:  This customization is based on AX 2012 R2 + CU6 


Example from Tender Declaration 

With the requirement to have a new POS form for entering planned order quantity, It's been long time since I was .NET developer.  And because there's very short time, the only one way is, copying features from existing form. ;-)  

So, I found out that Tender Declaration is a good one having grid and editable quantity. 



This form is in "Retail SDK\POS Plug-ins\Services\Dialog\WinFormsTouch".    

Tip: How did I find this form?  Easily, search for "TenderDeclaration" in all files of entire solution.  That's the way I always use when develop POS.    



Noted:  I just mention this for guys who just get to know Retail POS development.  Not only install Retail POS SDK from AX Setup, you need to have DevExpress Winforms license. And once you first buy, you won't see the WinForms installer for MS Dynamics AX 2012 R2 (v2011.2.111) in the Download Manager, you need to request from the DevExpress Support Center.  


  

Where should the new form be?

Since only small form, I will simply create it in BlankOperations project.  You may decide to have a new project if there're too many objects and better have its default namespace under "Microsoft.Dynamics.Retail.Pos".  

Under BlankOperations, add new item "DevExpress Form v11.2"



In behind code, set the form to inherit from "LSRetailPosis.POSProcesses.frmTouchBase", to have a blank form as Retail POS pattern. 

namespace Microsoft.Dynamics.Retail.Pos.BlankOperations.WinFormsTouch
{
    public partial class POSTestForm : LSRetailPosis.POSProcesses.frmTouchBase
    {
        .....

Before design grid, you better drag TableLayoutPanel to form first, then you can have all object's size showing as percentage.  Set the Dock properties; Header = Top, TableLayoutPanel = Fill.     



Drag XtraGrid control to TableLayoutPanel, set position in the table by Column, ColumnSpan, Row, RowSpan as you want.  


     
I prefer to design grid columns by "Run Designer".  Reference field name is case-sensitive from Grid DataSource field.  




Grid DataSource

If grid is only for viewing, Grid DataSource can be a simple DataTable (System.Data.DataTable).   But this form is different because needs to be filled the quantity.  So, we will bind Grid DataSource using ViewModel sealed class.  See example in frmTenderCount.cs --> TenderViewModel: -

    /// <summary>
    /// Model of tender row for grid to bind to
    /// </summary>
    sealed internal class TenderViewModel
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TenderViewModel"/> class.
        /// </summary>
        public TenderViewModel()
        {
            this.Enabled = true;
        }

        /// <summary>
        /// Gets or sets the type of the tender operation.
        /// </summary>
        /// <value>
        /// The type of the tender operation.
        /// </value>
        public PosisOperations TenderOperationType
        {
            get;
            set;
        }
        ....... 

Declare variable for Grid DataSource as list of ViewModel.  Load data from DataTable to the ViewModel and add to the list.  Then, bind the ViewModel list to GridControl. 

    private System.Data.DataTable yourDataTable;
    System.Collections.Generic.List<YourViewModel> gridSource;

    private void loadData()
        {
            try
            {
                yourDataTable = <<Function to get DataTable>>
                gridSource = new System.Collections.Generic.List<YourViewModel>();

                foreach (DataRow row in yourDataTable.Rows)
                {
                    YourViewModel viewRow = new YourViewModel()
                    {
                        ITEMID = (string)row["ITEMID"],
                        ITEMNAME = (string)row["ITEMNAME"],
                        COLOR = (string)row["COLOR"],
                        CONFIG = (string)row["CONFIG"],
                        ORDEREDQTY = (decimal)row["ORDEREDQTY"]),
                        UNITID = (string)row["UNITID"]
                    };
                    gridSource.Add(viewRow); 
                }


                grResult.DataSource = gridSource;
                ...... 


Entering quantity in Grid

Because Retail POS is touchscreen based.  It's not convenience to input data using keyboard.  We need to draw Quantity cell using event handler "CustomDrawCell".  See example: -

        private void gvTenders_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e)
        {
            string column = e.Column.FieldName;

            if (column == COLQTY || column == COLTOTAL)
            {
                // Determine the tender type
                PosisOperations operationTenderType = gridSource[e.RowHandle].TenderOperationType;

                // Draw the calculator icon in the quantity column if the tender type is not cash or currency
                bool drawIcon = (column == COLQTY) && (operationTenderType != PosisOperations.PayCash) && (operationTenderType != PosisOperations.PayCurrency);

                e.Appearance.FillRectangle(e.Cache, e.Bounds);
                DrawButton(e.Cache, e.Bounds, gridTenders.LookAndFeel.ActiveLookAndFeel.ActiveStyle, e.Appearance, GetButtonState(e.RowHandle, column), e.DisplayText, drawIcon);

                e.Handled = true;
            }

        }

Create event handler; KeyUp, MouseDown for controlling grid column click: -

        private void gvTenders_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Space)
            {
                switch (gvTenders.FocusedColumn.FieldName)
                {
                    case COLQTY:
                        OnQtyButtonClick(gvTenders.FocusedRowHandle);
                        break;
                    case COLTOTAL:
                        OnTotalButtonClick(gvTenders.FocusedRowHandle);
                        break;
                    default:
                        break;
                }
            }

        }

        private void gvTenders_MouseUp(object sender, MouseEventArgs e)
        {
            if (QtyPressedRowHandle != GridControl.InvalidRowHandle)
            {
                OnQtyButtonClick(QtyPressedRowHandle);
                QtyPressedRowHandle = GridControl.InvalidRowHandle;
            }

            if (TotalPressedRowHandle != GridControl.InvalidRowHandle)
            {
                OnTotalButtonClick(TotalPressedRowHandle);
                TotalPressedRowHandle = GridControl.InvalidRowHandle;
            }
        }


Input the quantity using frmInputNumpad dialog.  Then, update inputted quantity to Grid DataSource (ViewModel).  You can also modify the dialog, e.g. Integer+Positive --> set dialog EntryTypes properties as NumpadEntryTypes.IntegerPositive. 



        private void OnTotalButtonClick(int rowHandle)
        {
            if (!gridSource[rowHandle].Enabled)
            {
                return;
            }

            using (frmInputNumpad inputDialog = new frmInputNumpad())
            {
                inputDialog.EntryTypes = NumpadEntryTypes.Price;
                inputDialog.PromptText = LSRetailPosis.ApplicationLocalizer.Language.Translate(1443);
                inputDialog.CurrencyCode = gridSource[rowHandle].Currency;

                // The input dialog should allow negative values if it is a tender declaration
                inputDialog.AllowNegativeValues = (this.transaction.TransactionType == TenderCountTransaction.TypeOfTransaction.TenderDeclaration);
                inputDialog.EntryTypes = NumpadEntryTypes.IntegerPositive;

                LSRetailPosis.POSProcesses.POSFormsManager.ShowPOSForm(inputDialog);

                if (inputDialog.DialogResult == DialogResult.OK)
                {
                    decimal subTotal;
                    if (decimal.TryParse(inputDialog.InputText, out subTotal))
                    {
                        gridSource[rowHandle].Total = subTotal;
                        UpdateTotalAmount();

                        //Reseting the data source of denomination grid since user has altered the total amount
                        denominationDataSources[rowHandle] = null;
                    }
                }
            }
        }

Save Data from ViewModel list

When save data from ViewModel List to Store DB, we will loop it to ViewModel variable using "FindAll".  
                    
          List<TenderViewModel> cashTenders = gridSource.FindAll(tender => tender.TenderOperationType == PosisOperations.PayCash);

          foreach (TenderViewModel cashCount in cashTenders)
          {
              .....

View form using Blank Operation button

Create a Blank Operation button for calling the form.  Giving Operation number as you want.      



        /// <summary>

        /// Displays an alert message according operation id passed.

        /// </summary>

        /// <param name="operationInfo"></param>

        /// <param name="posTransaction"></param>        

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Grandfather")]

        public void BlankOperation(IBlankOperationInfo operationInfo, IPosTransaction posTransaction)
        {
            // This country check can be removed when customizing the BlankOperations service.
            if (Functions.CountryRegion == SupportedCountryRegion.BR || Functions.CountryRegion == SupportedCountryRegion.HU)
            {
                return;
            }


            switch ((operationInfo.OperationId).ToUpperInvariant().Replace(" ", string.Empty))
            {
                #region Planned Order
                case "CREATEORDER":  //Create Planned Order
                    CreateOrder(operationInfo, true, Application);
                    break;
                default:
                    //default, just echo the operation number and parameter value 
                    break;
            }
        }

        private void CreateOrder(IBlankOperationInfo operationInfo, bool allowBlank, IApplication application)
        {
            using (WinFormsTouch.POSFormTest searchDialog = new WinFormsTouch.POSFormTest())
            {
                bool inputValid;
                do
                {
                    inputValid = true;

                    searchDialog.Application = application; 
                    application.ApplicationFramework.POSShowForm(searchDialog);

                    // Quit if cancel is pressed...
                    if (searchDialog.DialogResult == System.Windows.Forms.DialogResult.Cancel && allowBlank)
                    {
                        return;
                    }
                    else if (searchDialog.DialogResult == System.Windows.Forms.DialogResult.OK)
                    {
                        .....
                    }
                    else if (searchDialog.DialogResult == DialogResult.Cancel && !allowBlank)
                    {
                        inputValid = false;
                    }
                } while (!inputValid);
            }
        }

After compile BlankOperations.dll and replace it in Retail POS services directory (C:\Program Files (x86)\Microsoft Dynamics AX\60\Retail POS\Services).  Run Retail POS and click the new Blank Operation button.  You will see the new form with grid and editable quantity. 

  

31 comments:

  1. Thanks for giving this information. You have made it so easy to understand.

    ReplyDelete
  2. Really the best informative information about POS Form, its very helpful.

    Pos Solutions
    Cash Registers

    ReplyDelete
  3. Thank full , EPOS he was new Way to help to us to get the business running sucessfull.

    ReplyDelete
  4. It's interesting and knowlegable to read this post. epos systems for small retailers Thanks for the great post.

    ReplyDelete
  5. Thanks for sharing unique information, epos good post to share.

    ReplyDelete
  6. Its good and informative post, gives a lot of knowledge. retail epos i would like to see more from you....

    ReplyDelete
  7. It's been really good to see the blog epos system for small retailers which covers all the important points. The blog describes in detail about the various aspects about the industry.

    ReplyDelete
  8. It was very Interesting and useful information epos system you have shared and keep sharing the blogs....

    ReplyDelete
  9. excellent postbest pos system for retail keep sharing and updating thank you for posting

    ReplyDelete
  10. Thanks for sharing your post.epos systems for small retailers and it was awesome.i really like it

    ReplyDelete
  11. Really informative post epos system as well as helpful to us Thanks for more information

    ReplyDelete
  12. Thanks for posting epos software for retail your valuable thoughts with us & our readers. Thank You

    ReplyDelete
  13. This is nice post emperium epos software for retail for better understanding and thanks a lot for sharing keep it up...

    ReplyDelete
  14. This is an interesting blog that you have posted. epos suppilers I appreciate your blogs and look forward for your next blog

    ReplyDelete
  15. This is absolutely awesome Blog.. epos systems for small business Great stuff, will looking forward for some more postings

    ReplyDelete
  16. I finnally found nice blog, epos system Thanks for sharing wonderful information.

    ReplyDelete
  17. Thanks for great information you write it very clean. epos I am very lucky to get this tips from you.

    ReplyDelete
  18. Thanks for sharing such unique information epos software which are in actual fact as well as helpful for us.Keep it up.....

    ReplyDelete
  19. Thanks for sharing this useful information epos regarding There is a very good information on your blog.

    ReplyDelete
  20. Fantastic website. epos system Lots of useful information here. thank you in your effort!

    ReplyDelete
  21. This Site is very essential for me. compare epos systems Because I have got many information from here.Thank You..

    ReplyDelete
  22. The Blog is quite informative. epos systems for small business Thanks for sharing a wonderful Post.

    ReplyDelete
  23. So happy to be given a privilege to post. epos system for small business I really enjoyed reading your blog post.

    ReplyDelete
  24. Thanks for sharing such unique information epos software which are in actual fact as well as helpful for us.Keep it up.....

    ReplyDelete
  25. Thanks for sharing bioinformatic stuff and really enjoyed to read it. i saw a website related on Free POS, Ipod POS and hope that your reader will enjoyed to read it.

    ReplyDelete
  26. Boost Your Sales With Our Takeaway EPOS Software.Fast EPOS System for Takeaway Businesses takeaway epos
    takeaway epos software
    epos software for takeaway
    takeaway epos

    ReplyDelete
  27. EPOS all in one solution for your takeaway business. all about order management system.
    EPOS allowing you to take action quickly and effortlessly.
    takeaway epos
    epos software for takeaway delivery
    website: intelepos.com
    Email: info@intelepos.com

    ReplyDelete
  28. This is such an amazing article, the blogger have so much knowledge about this topic kindly write more about on point of sale system in Pakistanand point of sale in Pakistan

    ReplyDelete
  29. This is the Great Post. epos Thanks for this wonderful post share with us...

    ReplyDelete
  30. Skip Hire Nottingham is the best skip hire services provider in Nottingham. Skip Hire Nottingham offers cheap prices and all kinds of skip sizes as we value the needs of our customers. We provide our services all across at a competitive price. Book your order now and Get 20% instant discount.

    Visit our site for more details....

    ReplyDelete