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.
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.
Thanks for giving this information. You have made it so easy to understand.
ReplyDeleteReally the best informative information about POS Form, its very helpful.
ReplyDeletePos Solutions
Cash Registers
Klink pos offers customer based products as Barcode scanners, Cash drawers, Customer display, Card readers, Receipt printers, POS Essential hardware, POS Let’s Get Online Ordering.
ReplyDeleteIts good and informative post, gives a lot of knowledge. retail epos i would like to see more from you....
ReplyDeleteThanks for great information you write it very clean. epos I am very lucky to get this tips from you.
ReplyDeleteThanks for sharing this useful information epos regarding There is a very good information on your blog.
ReplyDeleteFantastic website. epos system Lots of useful information here. thank you in your effort!
ReplyDeleteThanks 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.
ReplyDeleteBoost Your Sales With Our Takeaway EPOS Software.Fast EPOS System for Takeaway Businesses takeaway epos
ReplyDeletetakeaway epos software
epos software for takeaway
takeaway epos
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
ReplyDeleteThis is the Great Post. epos Thanks for this wonderful post share with us...
ReplyDelete