|
|
|
|
using DevComponents.DotNetBar;
|
|
|
|
|
using DevComponents.DotNetBar.Rendering;
|
|
|
|
|
using DevComponents.DotNetBar.SuperGrid;
|
|
|
|
|
using DevComponents.DotNetBar.SuperGrid.Style;
|
|
|
|
|
using POSV.Bean;
|
|
|
|
|
using POSV.Business;
|
|
|
|
|
using POSV.Card;
|
|
|
|
|
using POSV.Component;
|
|
|
|
|
using POSV.Entity;
|
|
|
|
|
using POSV.Helper;
|
|
|
|
|
using POSV.MessageEvent;
|
|
|
|
|
using POSV.MsgCenter;
|
|
|
|
|
using POSV.Proxy.GuoPan;
|
|
|
|
|
using POSV.Shift;
|
|
|
|
|
using POSV.ShoppingCart;
|
|
|
|
|
using POSV.Utils;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
|
|
|
|
namespace POSV
|
|
|
|
|
{
|
|
|
|
|
public partial class FastTemplate : BaseForm
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 计时器
|
|
|
|
|
/// </summary>
|
|
|
|
|
private System.Timers.Timer timer;
|
|
|
|
|
|
|
|
|
|
//当前订单对象
|
|
|
|
|
private OrderObject _orderObject = null;
|
|
|
|
|
|
|
|
|
|
//当前选中的单品行记录
|
|
|
|
|
private OrderItem _orderItem = null;
|
|
|
|
|
|
|
|
|
|
private object _promLock = new object();
|
|
|
|
|
|
|
|
|
|
//是否正在计算促销,防止操作过快
|
|
|
|
|
private bool _PromCalculateIng = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public FastTemplate()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
|
|
|
|
InitializeGrid();
|
|
|
|
|
|
|
|
|
|
this.txtCash.Multiline = false;
|
|
|
|
|
this.txtCash.GotFocus += this.OnInputGotFocus;
|
|
|
|
|
|
|
|
|
|
this.categoryControl.CategoryXCheckedChanged += OnCategoryXCheckedChanged;
|
|
|
|
|
|
|
|
|
|
this.productControl.ProductXClick += OnProductXClick;
|
|
|
|
|
|
|
|
|
|
//注册结算支付事件通知
|
|
|
|
|
MsgEvent.RemoveListener(Constant.ORDER_PAYMENT_NOTIFY, this.OrderPaymentEventNotify);
|
|
|
|
|
MsgEvent.Receive(Constant.ORDER_PAYMENT_NOTIFY, this.OrderPaymentEventNotify);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 结账通知事件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="args"></param>
|
|
|
|
|
protected virtual void OrderPaymentEventNotify(object sender, MsgEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
if (args.Data is OrderObject)
|
|
|
|
|
{
|
|
|
|
|
var oldMember = this._orderObject.Member;
|
|
|
|
|
var newOrderObject = args.Data as OrderObject;
|
|
|
|
|
|
|
|
|
|
if (newOrderObject.Member != null && oldMember == null)
|
|
|
|
|
{
|
|
|
|
|
//复制出来之前的gridrow
|
|
|
|
|
foreach (var item in newOrderObject.Items)
|
|
|
|
|
{
|
|
|
|
|
var oldItem = this._orderObject.Items.FirstOrDefault(x => x.Id == item.Id);
|
|
|
|
|
if (oldItem != null)
|
|
|
|
|
{
|
|
|
|
|
item.GridRow = oldItem.GridRow;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._orderObject = newOrderObject;
|
|
|
|
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
//修改会员卡号显示
|
|
|
|
|
string showCardNo = string.IsNullOrEmpty(this._orderObject.Member.CurrentCard.FaceNo) ? this._orderObject.Member.CurrentCard.CardNo : newOrderObject.Member.CurrentCard.FaceNo;
|
|
|
|
|
|
|
|
|
|
//会员卡号
|
|
|
|
|
//this.lblMemberCardNo.Text = string.Format(this.lblMemberCardNo.Tag.ToString(), CardUtils.CardNoEncrypt(showCardNo));
|
|
|
|
|
//会员姓名
|
|
|
|
|
//this.lblMemberName.Text = string.Format(this.lblMemberName.Tag.ToString(), this._orderObject.Member.Name);
|
|
|
|
|
//会员余额
|
|
|
|
|
//this.lblMemberAmount.Text = string.Format(this.lblMemberAmount.Tag.ToString(), this._orderObject.Member.CurrentCard.AvailableAmount);
|
|
|
|
|
//会员积分
|
|
|
|
|
//this.lblMemberPoint.Text = string.Format(this.lblMemberPoint.Tag.ToString(), this._orderObject.Member.CurrentCard.TotalPoint);
|
|
|
|
|
|
|
|
|
|
foreach (var item in this._orderObject.Items)
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(item);
|
|
|
|
|
}
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this._orderObject = newOrderObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
var result = BusinessUtils.Instance.OrderFinished(_orderObject);
|
|
|
|
|
if (result.Item1)
|
|
|
|
|
{
|
|
|
|
|
this.DestoryOrderObject(false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ShowToastNotify(this, result.Item2);
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializeGrid()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
|
|
|
|
|
gridControl.GetDetailRowHeight -= GridControlRowGetDetailHeight;
|
|
|
|
|
gridControl.GetDetailRowHeight += GridControlRowGetDetailHeight;
|
|
|
|
|
|
|
|
|
|
gridControl.PostRenderRow -= GridControlPostRenderRow;
|
|
|
|
|
gridControl.PostRenderRow += GridControlPostRenderRow;
|
|
|
|
|
|
|
|
|
|
gridControl.RowActivated -= GridControlRowActivated;
|
|
|
|
|
gridControl.RowActivated += GridControlRowActivated;
|
|
|
|
|
|
|
|
|
|
gridControl.CellClick -= GridControlCellClick;
|
|
|
|
|
gridControl.CellClick += GridControlCellClick;
|
|
|
|
|
|
|
|
|
|
//行最小高度
|
|
|
|
|
panel.MinRowHeight = 40;
|
|
|
|
|
panel.DefaultRowHeight = 0;
|
|
|
|
|
|
|
|
|
|
panel.Footer.Visible = false;
|
|
|
|
|
panel.Footer.RowHeight = 0;
|
|
|
|
|
|
|
|
|
|
panel.InitialSelection = RelativeSelection.None;
|
|
|
|
|
panel.InitialActiveRow = RelativeRow.None;
|
|
|
|
|
|
|
|
|
|
//滚动条
|
|
|
|
|
//this.gridControl.Width = this.leftContainer.Width + 16;
|
|
|
|
|
this.gridControl.HScrollBarVisible = false;
|
|
|
|
|
this.gridControl.VScrollBarVisible = true;
|
|
|
|
|
this.gridControl.VScrollBar.Width = 0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "初始化购物车界面异常");
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
this.leftContainer.Invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridControlRowGetDetailHeight(object sender, GridGetDetailRowHeightEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
GridRow row = e.GridRow;
|
|
|
|
|
if (row != null)
|
|
|
|
|
{
|
|
|
|
|
OrderItem item = row.Tag as OrderItem;
|
|
|
|
|
|
|
|
|
|
int isFlavor = (int)row["flavor"].Value;
|
|
|
|
|
|
|
|
|
|
if (isFlavor == 1)
|
|
|
|
|
{
|
|
|
|
|
string text = item.FlavorNames;
|
|
|
|
|
|
|
|
|
|
Rectangle r = row.FirstVisibleCell.ContentBounds;
|
|
|
|
|
Rectangle t = row.LastVisibleCell.ContentBounds;
|
|
|
|
|
|
|
|
|
|
Size rsize = e.SizeNeeded;
|
|
|
|
|
rsize.Height = 0;
|
|
|
|
|
rsize.Width = (t.Right - r.Left);
|
|
|
|
|
|
|
|
|
|
var sf = TextFormatFlags.Left | TextFormatFlags.NoPadding | TextFormatFlags.WordBreak;
|
|
|
|
|
Size size = TextRenderer.MeasureText(text, Constant.DEFAULT_FONT, rsize, sf);
|
|
|
|
|
|
|
|
|
|
e.PostDetailHeight = size.Height;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GridControlPostRenderRow(object sender, GridPostRenderRowEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
GridRow row = e.GridRow as GridRow;
|
|
|
|
|
if (row != null)
|
|
|
|
|
{
|
|
|
|
|
OrderItem item = row.Tag as OrderItem;
|
|
|
|
|
|
|
|
|
|
//是否下划线
|
|
|
|
|
int isUnderline = (int)row["underline"].Value;
|
|
|
|
|
//是否包含口味
|
|
|
|
|
int isFlavor = (int)row["flavor"].Value;
|
|
|
|
|
|
|
|
|
|
Rectangle r = row.FirstVisibleCell.ContentBounds;
|
|
|
|
|
Rectangle t = row.LastVisibleCell.ContentBounds;
|
|
|
|
|
|
|
|
|
|
string text = item.FlavorNames;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r.Width = t.Right - r.X;// - Dpi.Width5;
|
|
|
|
|
r.Y = e.Bounds.Bottom - row.EffectivePostDetailRowHeight;// - Dpi.Height5;
|
|
|
|
|
r.Height = row.EffectivePostDetailRowHeight;
|
|
|
|
|
|
|
|
|
|
if (isFlavor == 1)
|
|
|
|
|
{
|
|
|
|
|
//e.Graphics.FillRectangle(Brushes.LightPink , r);
|
|
|
|
|
//e.Graphics.DrawRectangle(Pens.RosyBrown , r);
|
|
|
|
|
|
|
|
|
|
r.Inflate(-2, 1);
|
|
|
|
|
|
|
|
|
|
var sf = TextFormatFlags.Left | TextFormatFlags.NoPadding | TextFormatFlags.WordBreak;
|
|
|
|
|
|
|
|
|
|
TextRenderer.DrawText(e.Graphics, text, Constant.DEFAULT_FONT, r,
|
|
|
|
|
row.IsSelected ? Color.DimGray : Color.DimGray, sf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//绘制下边线
|
|
|
|
|
if (isUnderline == 1)
|
|
|
|
|
{
|
|
|
|
|
System.Drawing.Pen pen1 = new System.Drawing.Pen(System.Drawing.Color.DarkGray);//画笔
|
|
|
|
|
e.Graphics.DrawLine(pen1, new Point(r.Left, t.Bottom + row.EffectivePostDetailRowHeight), new Point(t.Right, t.Bottom + row.EffectivePostDetailRowHeight));
|
|
|
|
|
pen1.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//绘制右边线
|
|
|
|
|
System.Drawing.Pen pen = new System.Drawing.Pen(SystemColors.ControlDark);//画笔
|
|
|
|
|
e.Graphics.DrawLine(pen, new Point(t.Right, t.Top - 1), new Point(t.Right, row.EffectivePostDetailRowHeight + t.Bottom));
|
|
|
|
|
pen.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void GridControlRowActivated(object sender, GridRowActivatedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.NewActiveRow != null)
|
|
|
|
|
{
|
|
|
|
|
GridPanel panel = e.GridPanel;
|
|
|
|
|
panel.SetSelected(e.OldActiveRow, false);
|
|
|
|
|
panel.SetSelected(e.NewActiveRow, true);
|
|
|
|
|
panel.SetActiveRow(e.NewActiveRow);
|
|
|
|
|
|
|
|
|
|
//当前行的对象
|
|
|
|
|
OrderItem orderItem = e.NewActiveRow.Tag as OrderItem;
|
|
|
|
|
|
|
|
|
|
//设置当前活跃行
|
|
|
|
|
this._orderItem = orderItem;
|
|
|
|
|
|
|
|
|
|
//通知副屏,选中指定行
|
|
|
|
|
if (Global.Instance.EnableVice)
|
|
|
|
|
{
|
|
|
|
|
MsgEvent.Send(Constant.VICE_ORDER_NOTIFY, new Tuple<ViceNotifyType, object>(ViceNotifyType.UPDATEORDERITEM, orderItem));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 点击点单列表中任意单元格事件
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
private void GridControlCellClick(object sender, GridCellClickEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (e.MouseEventArgs.Button == MouseButtons.Left)
|
|
|
|
|
{
|
|
|
|
|
OrderItem orderItem = e.GridCell.GridRow.Tag as OrderItem;
|
|
|
|
|
//设置当前活跃行
|
|
|
|
|
this._orderItem = orderItem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 更新购物车列表当前活跃行
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void UpdateGridRow()
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
if (this._orderItem == null) return;
|
|
|
|
|
|
|
|
|
|
RefreshRow(this._orderItem);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RefreshRow(OrderItem orderItem)
|
|
|
|
|
{
|
|
|
|
|
GridRow row = orderItem.GridRow;
|
|
|
|
|
|
|
|
|
|
//删除订单项时,判空
|
|
|
|
|
if (row == null || row["name"] == null)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//商品名称显示规格
|
|
|
|
|
string _productName = orderItem.DisplayName;
|
|
|
|
|
decimal _quantity = orderItem.Quantity;
|
|
|
|
|
string _unit = orderItem.ProductUnitName;
|
|
|
|
|
|
|
|
|
|
//列表是否显示折后价
|
|
|
|
|
bool showDiscountPrice = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_DISCOUNTPRICE, false);
|
|
|
|
|
decimal _salePrice = orderItem.Price;
|
|
|
|
|
if (showDiscountPrice)
|
|
|
|
|
{
|
|
|
|
|
_salePrice = orderItem.DiscountPrice;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decimal _amount = orderItem.Amount;
|
|
|
|
|
decimal _detailMain = 0.00M;
|
|
|
|
|
//if (orderItem.RowState == OrderRowState.套餐主)
|
|
|
|
|
//{
|
|
|
|
|
// _detailMain = this._orderObject.Items.FindAll(x=>x.RowState == OrderRowState.套餐明 && orderItem.Id.Equals(x.ParentId)).Sum(m => m.FlavorDiscountAmount); ;
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
if (showDiscountPrice)
|
|
|
|
|
{
|
|
|
|
|
_amount = orderItem.Amount - (orderItem.TotalDiscountAmount + _detailMain);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decimal _promotion = orderItem.TotalDiscountAmount + _detailMain;
|
|
|
|
|
|
|
|
|
|
row["name"].Value = _productName;
|
|
|
|
|
row["quantity"].Value = _quantity;
|
|
|
|
|
row["price"].Value = OrderUtils.ToRound(_salePrice);
|
|
|
|
|
row["unit"].Value = _unit;
|
|
|
|
|
row["amount"].Value = OrderUtils.ToRound(_amount);
|
|
|
|
|
|
|
|
|
|
row["discount"].Value = _promotion;
|
|
|
|
|
|
|
|
|
|
this._orderItem.Discount = _promotion;
|
|
|
|
|
|
|
|
|
|
if (orderItem.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
row["quantity"].Value = orderItem.Quantity;
|
|
|
|
|
row["price"].Value = "";
|
|
|
|
|
row["amount"].Value = orderItem.SuitAmount > 0 ? ("+" + orderItem.SuitAmount) : "";
|
|
|
|
|
row["discount"].Value = "";
|
|
|
|
|
|
|
|
|
|
this._orderItem.Discount = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (orderItem.Flavors.Count() > 0)
|
|
|
|
|
{
|
|
|
|
|
row["flavor"].Value = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
row["flavor"].Value = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
row.InvalidateRender();
|
|
|
|
|
|
|
|
|
|
row.InvalidateLayout();
|
|
|
|
|
|
|
|
|
|
//通知副屏
|
|
|
|
|
if (Global.Instance.EnableVice)
|
|
|
|
|
{
|
|
|
|
|
MsgEvent.Send(Constant.VICE_ORDER_NOTIFY, new Tuple<ViceNotifyType, object>(ViceNotifyType.UPDATEORDERITEM, orderItem));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 更新套餐主信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
private void UpdateSuitMain(OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
if (item.RowState == OrderRowState.套餐主 || item.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
var mainItem = this._orderObject.Items.Find(x => x.Group == item.Group && x.RowState == OrderRowState.套餐主);
|
|
|
|
|
var subItems = this._orderObject.Items.FindAll(x => x.Group == item.Group && x.RowState == OrderRowState.套餐明);
|
|
|
|
|
if (mainItem != null && subItems != null)
|
|
|
|
|
{
|
|
|
|
|
mainItem.FlavorCount = subItems.Sum(x => x.FlavorCount);
|
|
|
|
|
mainItem.FlavorAmount = subItems.Sum(x => x.FlavorAmount);
|
|
|
|
|
mainItem.FlavorDiscountAmount = subItems.Sum(x => x.FlavorDiscountAmount);
|
|
|
|
|
mainItem.FlavorReceivableAmount = subItems.Sum(x => x.FlavorReceivableAmount);
|
|
|
|
|
//刷新购物车
|
|
|
|
|
this.RefreshRow(mainItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 刷新整个点单列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void UpdateGrid()
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in this._orderObject.Items)
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(item);
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 刷新点单列表指定行
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
private void UpdateGridRow(OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
//设置当前活跃行
|
|
|
|
|
this._orderItem = item;
|
|
|
|
|
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
panel.SetSelected(panel.ActiveRow, false);
|
|
|
|
|
|
|
|
|
|
if (this._orderItem != null)
|
|
|
|
|
{
|
|
|
|
|
panel.SetSelected(this._orderItem.GridRow, true);
|
|
|
|
|
panel.SetActiveRow(this._orderItem.GridRow);
|
|
|
|
|
|
|
|
|
|
//刷新购物车
|
|
|
|
|
this.RefreshRow(this._orderItem);
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BuildGridRow(ProductExt product, OrderRowState rowState = OrderRowState.None)
|
|
|
|
|
{
|
|
|
|
|
//0、添加点单过快提示
|
|
|
|
|
if (_PromCalculateIng)
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, "操作过快,请重新操作");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isGo = true;
|
|
|
|
|
|
|
|
|
|
//1、先判断是否已经完成
|
|
|
|
|
if (isGo && (this._orderObject.OrderType == OrderType.电话外卖 && this._orderObject.OrderStatus == OrderStatus.等待付款) || this._orderObject.OrderStatus == OrderStatus.已完成)
|
|
|
|
|
{
|
|
|
|
|
this.DestoryOrderObject(true);
|
|
|
|
|
|
|
|
|
|
isGo = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//2、判断订单号是否正常
|
|
|
|
|
if (isGo && string.IsNullOrEmpty(this._orderObject.TradeNo))
|
|
|
|
|
{
|
|
|
|
|
//尝试重新获取一次单号
|
|
|
|
|
var ticket = OrderUtils.Instance.GenerateTicketNoEx();
|
|
|
|
|
if (ticket.Item1)
|
|
|
|
|
{
|
|
|
|
|
this._orderObject.TradeNo = ticket.Item3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//重新判断是否获取到单号
|
|
|
|
|
if (string.IsNullOrEmpty(this._orderObject.TradeNo))
|
|
|
|
|
{
|
|
|
|
|
//是否提醒收银员
|
|
|
|
|
var isNofity = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_TICKET_NO_NOFITY, true);
|
|
|
|
|
//是否采用本机单号
|
|
|
|
|
var isLocalTicketNo = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_LOCAL_TICKET_NO, false);
|
|
|
|
|
|
|
|
|
|
string notifyMessage = "获取全局单号失败,收银参数禁止使用本机单号,请重新操作";
|
|
|
|
|
if (isNofity)
|
|
|
|
|
{
|
|
|
|
|
MDialogForm dialog = null;
|
|
|
|
|
//采用本机单号
|
|
|
|
|
if (isLocalTicketNo)
|
|
|
|
|
{
|
|
|
|
|
notifyMessage = "获取全局单号失败,采用本机单号可能出现重复,是否继续?";
|
|
|
|
|
dialog = new MDialogForm("提示信息", notifyMessage, MessageBoxIcon.Warning, MessageBoxButtons.YesNo);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dialog = new MDialogForm("提示信息", notifyMessage, MessageBoxIcon.Warning, MessageBoxButtons.OK);
|
|
|
|
|
}
|
|
|
|
|
//操作员选择了 是
|
|
|
|
|
if (DialogResult.Yes == dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
this._orderObject.TradeNo = OrderUtils.Instance.GenerateTicketNo();
|
|
|
|
|
|
|
|
|
|
isGo = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isGo = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (isLocalTicketNo)
|
|
|
|
|
{
|
|
|
|
|
this._orderObject.TradeNo = OrderUtils.Instance.GenerateTicketNo();
|
|
|
|
|
|
|
|
|
|
isGo = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isGo = false;
|
|
|
|
|
|
|
|
|
|
this.ShowToastNotify(this, "获取全局单号失败,设置禁止使用本机单号,请重试");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isGo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//3、如果有整单优惠,禁止点单操作
|
|
|
|
|
if (isGo && this._orderObject.Promotions != null && this._orderObject.Promotions.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, "享受整单优惠,不允许继续点单");
|
|
|
|
|
|
|
|
|
|
isGo = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//4、允许销售售价为零的商品
|
|
|
|
|
var allowPriceZero = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ALLOW_PRICE_ZERO, false);
|
|
|
|
|
if (isGo && product.Price <= 0 && !allowPriceZero)
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, "不允许售卖价格为零的商品");
|
|
|
|
|
|
|
|
|
|
isGo = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//5、售价为零的商品时提示
|
|
|
|
|
var priceZeroNotify = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_PRICE_ZERO_NOTIFY, false);
|
|
|
|
|
if (isGo && product.Price <= 0 && priceZeroNotify)
|
|
|
|
|
{
|
|
|
|
|
var dialog = new MDialogForm("提示信息", "您是否要售卖零售价的单品", MessageBoxIcon.Warning, MessageBoxButtons.YesNo);
|
|
|
|
|
//操作员选择了 是
|
|
|
|
|
if (DialogResult.Yes == dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
isGo = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isGo = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//**********************开始点单*******************************
|
|
|
|
|
if (isGo)
|
|
|
|
|
{
|
|
|
|
|
var newProduct = ObjectUtils.Copy<ProductExt>(product);
|
|
|
|
|
AddGridRow(newProduct, rowState);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnProductXClick(object sender, ProductXEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var product = e.Product;
|
|
|
|
|
|
|
|
|
|
this.BuildGridRow(product);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnLoad(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnLoad(e);
|
|
|
|
|
if (this.DesignMode) return;
|
|
|
|
|
|
|
|
|
|
//网络状态
|
|
|
|
|
ChangNetworkStatus();
|
|
|
|
|
|
|
|
|
|
//加载副屏
|
|
|
|
|
LoadingViceScreen();
|
|
|
|
|
|
|
|
|
|
//登录班次
|
|
|
|
|
BusinessUtils.Instance.WorkerLogin();
|
|
|
|
|
|
|
|
|
|
//初始化收银员权限
|
|
|
|
|
BusinessUtils.Instance.InitPermission();
|
|
|
|
|
|
|
|
|
|
//刷练习模式
|
|
|
|
|
StudyModeChangedNotify(this, null);
|
|
|
|
|
|
|
|
|
|
//创建默认订单
|
|
|
|
|
NewOrderObject();
|
|
|
|
|
|
|
|
|
|
//刷新界面
|
|
|
|
|
this.RefreshUi();
|
|
|
|
|
|
|
|
|
|
//定时器
|
|
|
|
|
this.timer = new System.Timers.Timer(60000);//定时周期2秒
|
|
|
|
|
this.timer.Elapsed += TimerElapsed;//到60秒了做的事件
|
|
|
|
|
this.timer.AutoReset = true; //是否不断重复定时器操作
|
|
|
|
|
this.timer.Start();
|
|
|
|
|
|
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var lists = Global.Product._productList;
|
|
|
|
|
this.productControl.PageNumber = 1;
|
|
|
|
|
this.productControl.BindDataSource(lists, PriceTypeEnum.零售价);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "加载商品信息异常");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
//当前未登录状态
|
|
|
|
|
Global.Instance.IsLogin = true;
|
|
|
|
|
//门店名称
|
|
|
|
|
this.lblStoreName.Text = string.Format(this.lblStoreName.Tag.ToString(), Global.Instance.Authc.TenantId, Global.Instance.Authc.StoreNo, Global.Instance.Worker.StoreInfo.Name);
|
|
|
|
|
//POS编号
|
|
|
|
|
this.lblPosNo.Text = string.Format(this.lblPosNo.Tag.ToString(), Global.Instance.Authc.PosNo);
|
|
|
|
|
//操作员工号
|
|
|
|
|
this.lblWorkerNo.Text = string.Format(this.lblWorkerNo.Tag.ToString(), Global.Instance.Worker.No);
|
|
|
|
|
//登录日期
|
|
|
|
|
this.lblLoginDate.Text = string.Format(this.lblLoginDate.Tag.ToString(), Global.Instance.Worker.LastDate);
|
|
|
|
|
//系统日期
|
|
|
|
|
this.lblSystemDate.Text = string.Format(this.lblSystemDate.Tag.ToString(), DateTime.Now.ToString("yyyy-MM-dd HH:mm"));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 创建一个订单对象,本单交易完成前,对象唯一存在
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private OrderObject NewOrderObject()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (this._orderObject == null)
|
|
|
|
|
{
|
|
|
|
|
this._orderObject = BusinessUtils.Instance.NewOrderObject();
|
|
|
|
|
|
|
|
|
|
//订单商品明细
|
|
|
|
|
var observableCollection = new ObservableCollection<OrderItem>();
|
|
|
|
|
observableCollection.CollectionChanged += OrderItemCollectionChanged;
|
|
|
|
|
|
|
|
|
|
this._orderObject.Maps = observableCollection;
|
|
|
|
|
|
|
|
|
|
//会员卡号
|
|
|
|
|
//this.lblMemberCardNo.Text = string.Format(this.lblMemberCardNo.Tag.ToString(), string.Empty);
|
|
|
|
|
//会员余额
|
|
|
|
|
//this.lblMemberAmount.Text = string.Format(this.lblMemberAmount.Tag.ToString(), string.Empty);
|
|
|
|
|
//会员积分
|
|
|
|
|
//this.lblMemberPoint.Text = string.Format(this.lblMemberPoint.Tag.ToString(), string.Empty);
|
|
|
|
|
|
|
|
|
|
//刷新桌号
|
|
|
|
|
MsgEvent.Send(Constant.MSGCENTER_NOTIFY, new MsgEntity() { Subject = Constant.MENU_TITLE_CHANGED_NOTIFY, SubSubject = ModuleKeyCode.桌号.ToString(), Operate = MsgEntityOperate.发布, Data = new Tuple<ModuleKeyCode, MenuTileNotifyType, string>(ModuleKeyCode.桌号, MenuTileNotifyType.数量, _orderObject.TableName) });
|
|
|
|
|
|
|
|
|
|
//默认营业模式
|
|
|
|
|
bool ts = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ORDERTYPEDEFAULTTS, true);
|
|
|
|
|
if (ts)
|
|
|
|
|
{
|
|
|
|
|
this._orderObject.OrderType = OrderType.堂食;
|
|
|
|
|
MsgEvent.Send(Constant.MSGCENTER_NOTIFY, new MsgEntity() { Subject = Constant.MENU_TITLE_CHANGED_NOTIFY, SubSubject = ModuleKeyCode.外带.ToString(), Operate = MsgEntityOperate.发布, Data = new Tuple<ModuleKeyCode, MenuTileNotifyType, string>(ModuleKeyCode.外带, MenuTileNotifyType.名称, OrderType.堂食.ToString()) });
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this._orderObject.OrderType = OrderType.外带;
|
|
|
|
|
MsgEvent.Send(Constant.MSGCENTER_NOTIFY, new MsgEntity() { Subject = Constant.MENU_TITLE_CHANGED_NOTIFY, SubSubject = ModuleKeyCode.外带.ToString(), Operate = MsgEntityOperate.发布, Data = new Tuple<ModuleKeyCode, MenuTileNotifyType, string>(ModuleKeyCode.外带, MenuTileNotifyType.名称, OrderType.外带.ToString()) });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._orderItem = null;
|
|
|
|
|
|
|
|
|
|
return this._orderObject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OrderItemCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
foreach (var item in this._orderObject.Maps)
|
|
|
|
|
{
|
|
|
|
|
GridRow row = (GridRow)panel.Rows[i];
|
|
|
|
|
|
|
|
|
|
item.OrderNo = (++i);
|
|
|
|
|
|
|
|
|
|
//修改行序号
|
|
|
|
|
row["order"].Value = item.OrderNo;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private OrderObject DestoryOrderObject(bool forced, bool newOrder = true)
|
|
|
|
|
{
|
|
|
|
|
//关闭会员优惠提醒
|
|
|
|
|
MsgEvent.Send(Constant.HISTORY_CHANGED_NOTIFY, new Tuple<HistoryMsgType, object>(HistoryMsgType.会员优惠, 0));
|
|
|
|
|
|
|
|
|
|
//禁止交易完成后立即清除单据信息,显示已结账
|
|
|
|
|
bool allowShowPreOrder = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_NOT_ALLOW_SHOW_PREORDER);
|
|
|
|
|
|
|
|
|
|
if (forced || !allowShowPreOrder)
|
|
|
|
|
{
|
|
|
|
|
//清理GridPanel
|
|
|
|
|
GridPanel panel = this.gridControl.PrimaryGrid;
|
|
|
|
|
panel.Rows.Clear();
|
|
|
|
|
|
|
|
|
|
this.checkoutControl.Visible = false;
|
|
|
|
|
this.txtCash.Text = "0";
|
|
|
|
|
|
|
|
|
|
this._orderObject = null;
|
|
|
|
|
|
|
|
|
|
//通知副屏
|
|
|
|
|
if (Global.Instance.EnableVice)
|
|
|
|
|
{
|
|
|
|
|
MsgEvent.Send(Constant.VICE_ORDER_NOTIFY, new Tuple<ViceNotifyType, object>(ViceNotifyType.CLEARALLITEMS, null));
|
|
|
|
|
}
|
|
|
|
|
if (newOrder)
|
|
|
|
|
{
|
|
|
|
|
return NewOrderObject();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.checkoutControl.Visible = true;
|
|
|
|
|
|
|
|
|
|
//重置会员信息,默认情况下,支付完成后支持刷卡
|
|
|
|
|
this._orderObject.Member = null;
|
|
|
|
|
|
|
|
|
|
//通知副屏
|
|
|
|
|
if (Global.Instance.EnableVice)
|
|
|
|
|
{
|
|
|
|
|
MsgEvent.Send(Constant.VICE_ORDER_NOTIFY, new Tuple<ViceNotifyType, object>(ViceNotifyType.FINISHEDORDER, null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this._orderObject;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 刷新点单列表,更新界面元素
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void RefreshUi()
|
|
|
|
|
{
|
|
|
|
|
this.BeginInvoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_PromCalculateIng = true;
|
|
|
|
|
|
|
|
|
|
lock (this._promLock)
|
|
|
|
|
{
|
|
|
|
|
this.CalPromotion();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "计算优惠发生异常");
|
|
|
|
|
Global.Instance.BugReport(ex, "计算优惠发生异常");
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
_PromCalculateIng = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RefreshUiEx()
|
|
|
|
|
{
|
|
|
|
|
//数量合计
|
|
|
|
|
this.lblTotalQuantity.Text = string.Format(this.lblTotalQuantity.Tag.ToString(), this._orderObject.TotalQuantity.ToString());
|
|
|
|
|
|
|
|
|
|
//优惠合计
|
|
|
|
|
this.lblTotalDiscount.Text = string.Format(this.lblTotalDiscount.Tag.ToString(), this._orderObject.DiscountAmount.ToString());
|
|
|
|
|
|
|
|
|
|
//应收金额
|
|
|
|
|
this.lblReceivableAmount.Text = string.Format(this.lblReceivableAmount.Tag.ToString(), this._orderObject.ReceivableAmount.ToString());
|
|
|
|
|
|
|
|
|
|
//客显
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
GuestShowUtils.Instance.DisplayData(CustomerDisplayType.Total, this._orderObject.ReceivableAmount.ToString("f2"));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "客显异常");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CalPromotion()
|
|
|
|
|
{
|
|
|
|
|
//套餐,自动找到套餐主菜进行优惠计算
|
|
|
|
|
if (this._orderItem != null && this._orderItem.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
//套餐明细,找到套餐主菜进行优惠计算
|
|
|
|
|
var mainItem = this._orderObject.Items.Find(x => x.Group == this._orderItem.Group && x.RowState == OrderRowState.套餐主);
|
|
|
|
|
if (mainItem != null)
|
|
|
|
|
{
|
|
|
|
|
CalItemPromEngine(mainItem);
|
|
|
|
|
|
|
|
|
|
//套餐道菜分摊
|
|
|
|
|
PromotionUtils.CalculateSuitShare(this._orderObject, mainItem);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CalItemPromEngine(this._orderItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CalOrderPromEngine();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CalItemPromEngine(OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
//先计算当前单品优惠,取最优
|
|
|
|
|
if (item != null)
|
|
|
|
|
{
|
|
|
|
|
if (item.Promotions != null && item.Promotions.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
//有优惠,不计算单品优惠
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var promResult = PromotionEngine.Instance.CalItemPromotion(this._orderObject, item);
|
|
|
|
|
if (promResult.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
if (promResult.Exists(x => x.Type == PromotionType.双数特价优惠 || x.Type == PromotionType.双数特价赠送))
|
|
|
|
|
{
|
|
|
|
|
ApplyDoublePromMain(promResult, item);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var fineProm = promResult.OrderByDescending(x => x.DiscountAmount).ToList()[0];
|
|
|
|
|
var needUpdate = BusinessUtils.Instance.ApplyItemFinePromotion(this._orderObject, item, fineProm);
|
|
|
|
|
if (needUpdate)
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(item);
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 双数特价
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 双数特价优惠入口
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="promResult"></param>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
private void ApplyDoublePromMain(List<PromotionEntity> promResult, OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
var fineProm = promResult.FirstOrDefault(x => x.Type == PromotionType.双数特价优惠 || x.Type == PromotionType.双数特价赠送);
|
|
|
|
|
//优先处理双数促销
|
|
|
|
|
if (fineProm.Type == PromotionType.双数特价赠送)
|
|
|
|
|
{
|
|
|
|
|
ApplyDoublePromGive(fineProm, item);
|
|
|
|
|
}
|
|
|
|
|
else if (fineProm.Type == PromotionType.双数特价优惠)
|
|
|
|
|
{
|
|
|
|
|
ApplyDoublePromDiscount(fineProm, item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 双数特价优惠处理
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fineProm"></param>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
private void ApplyDoublePromDiscount(PromotionEntity fineProm, OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
//优惠商品
|
|
|
|
|
var product = fineProm.Products[0];
|
|
|
|
|
//满足双数特价的主商品数量
|
|
|
|
|
var masterList = this._orderObject.Items.FindAll(x => x.SpecId == product.SpecId && x.Promotions.Count == 0 && string.IsNullOrEmpty(x.ParentId));
|
|
|
|
|
//已参与满足双数特价的子商品数量
|
|
|
|
|
var subList = this._orderObject.Items.FindAll(x => x.SpecId == product.SpecId && x.Promotions.Count == 1
|
|
|
|
|
&& x.Promotions[0].PromotionType == PromotionType.双数特价优惠
|
|
|
|
|
&& x.Promotions[0].PlanNo == fineProm.PromotionId);
|
|
|
|
|
//主商品数量
|
|
|
|
|
var totalMasterQuantity = masterList.Sum(x => x.Quantity);
|
|
|
|
|
//子商品数量
|
|
|
|
|
var totalSubQuantity = subList.Sum(x => x.Quantity);
|
|
|
|
|
//应优惠商品数量
|
|
|
|
|
var shouldQuantity = product.Quantity;
|
|
|
|
|
|
|
|
|
|
if (shouldQuantity > totalSubQuantity)
|
|
|
|
|
{
|
|
|
|
|
//新增优惠商品
|
|
|
|
|
var dQuantity = (shouldQuantity - totalSubQuantity);
|
|
|
|
|
bool isSucc = false;
|
|
|
|
|
//假如是子商品
|
|
|
|
|
if (item.Quantity == dQuantity)
|
|
|
|
|
{
|
|
|
|
|
isSucc = DoublePromPart3(item, masterList, subList, dQuantity, fineProm);
|
|
|
|
|
}
|
|
|
|
|
if (!isSucc)
|
|
|
|
|
{
|
|
|
|
|
//假如是主商品
|
|
|
|
|
isSucc = DoublePromPart2(item, masterList, subList, dQuantity, fineProm);
|
|
|
|
|
if (!isSucc)
|
|
|
|
|
{
|
|
|
|
|
//主商品需要拆行
|
|
|
|
|
if (item.Quantity > dQuantity)
|
|
|
|
|
{
|
|
|
|
|
item.Quantity -= dQuantity;
|
|
|
|
|
//套餐主数量变更,同步更新子商品数量
|
|
|
|
|
UpdateSuitSubQuantity(item);
|
|
|
|
|
//沽清
|
|
|
|
|
//创建新的OrderItem
|
|
|
|
|
var newItem = BusinessUtils.Instance.NewOrderItem(_orderObject, ObjectUtils.Copy(item.ProductExt));
|
|
|
|
|
newItem.Quantity = dQuantity;
|
|
|
|
|
newItem.ParentId = item.Id;
|
|
|
|
|
//新Item加入促销
|
|
|
|
|
BusinessUtils.Instance.ApplyPromotionEntity(this._orderObject, newItem, fineProm);
|
|
|
|
|
//新数据定位
|
|
|
|
|
int orderNo = BusinessUtils.Instance.AppendItemPosition(this._orderObject, item);
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
AddGridRowExt(newItem.ProductExt, newItem, orderNo);
|
|
|
|
|
RefreshRow(item);
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error("未能成功处理双数特价优惠的UI商品调整");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (shouldQuantity < totalSubQuantity)
|
|
|
|
|
{
|
|
|
|
|
//减少商品
|
|
|
|
|
var specs = _orderObject.Items.FindAll(x => x.SpecId == product.SpecId);
|
|
|
|
|
if (specs.Count > 1)
|
|
|
|
|
{
|
|
|
|
|
var quantity = (totalSubQuantity - shouldQuantity);
|
|
|
|
|
List<OrderItem> updateItems = new List<OrderItem>();
|
|
|
|
|
List<OrderItem> deleteItems = new List<OrderItem>();
|
|
|
|
|
foreach (var sub in subList)
|
|
|
|
|
{
|
|
|
|
|
if (quantity > 0)
|
|
|
|
|
{
|
|
|
|
|
if (sub.ParentId == item.Id)
|
|
|
|
|
{
|
|
|
|
|
if (sub.Quantity > quantity)
|
|
|
|
|
{
|
|
|
|
|
sub.Quantity -= quantity;
|
|
|
|
|
quantity = 0;
|
|
|
|
|
updateItems.Add(sub);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (sub.Quantity <= quantity)
|
|
|
|
|
{
|
|
|
|
|
quantity -= sub.Quantity;
|
|
|
|
|
deleteItems.Add(sub);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (quantity > 0)
|
|
|
|
|
{
|
|
|
|
|
//计算异常
|
|
|
|
|
this.ShowToastNotify(this, "双数促销执行错误,请消单后重新点单!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var del in deleteItems)
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
DoRemoveOrderItem(del);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var up in updateItems)
|
|
|
|
|
{
|
|
|
|
|
//更新促销
|
|
|
|
|
RefreshPromotionEntityItem(up, fineProm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 双数特价赠送处理
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="fineProm"></param>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
private void ApplyDoublePromGive(PromotionEntity fineProm, OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
var p = fineProm.Products[0];
|
|
|
|
|
//已赠送商品集
|
|
|
|
|
var giveItems = _orderObject.Items.FindAll(x => x.SpecId == p.SpecId && x.Promotions.Count == 1
|
|
|
|
|
&& x.Promotions[0].PromotionType == PromotionType.双数特价赠送
|
|
|
|
|
&& x.Promotions[0].PlanNo == fineProm.PromotionId);
|
|
|
|
|
//已赠送商品总数
|
|
|
|
|
var giveQuantity = giveItems.Sum(x => x.Quantity);
|
|
|
|
|
//差值
|
|
|
|
|
var dQuantity = p.Quantity - giveQuantity;
|
|
|
|
|
|
|
|
|
|
if (dQuantity > 0)
|
|
|
|
|
{
|
|
|
|
|
var childItem = _orderObject.Items.FirstOrDefault(x => x.SpecId == p.SpecId && x.ParentId == item.Id && x.Promotions.Count == 1 && x.Promotions[0].PromotionType == PromotionType.双数特价赠送 && x.Promotions[0].PlanNo == fineProm.PromotionId);
|
|
|
|
|
if (childItem != null)
|
|
|
|
|
{
|
|
|
|
|
//已经存在双数特价赠送的商品,直接将赠送的商品数量置为当前商品数量,适用于操作数量增加
|
|
|
|
|
childItem.Quantity += dQuantity;
|
|
|
|
|
|
|
|
|
|
RefreshPromotionEntityItem(childItem, fineProm);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//新增一行商品
|
|
|
|
|
//沽清
|
|
|
|
|
//创建新的OrderItem
|
|
|
|
|
var newItem = BusinessUtils.Instance.NewOrderItem(_orderObject, ObjectUtils.Copy(item.ProductExt));
|
|
|
|
|
newItem.Quantity = dQuantity;
|
|
|
|
|
//新Item加入促销
|
|
|
|
|
newItem.ParentId = item.Id;
|
|
|
|
|
BusinessUtils.Instance.ApplyPromotionEntity(this._orderObject, newItem, fineProm);
|
|
|
|
|
|
|
|
|
|
var orderNo = BusinessUtils.Instance.AppendItemPosition(this._orderObject, item);
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
AddGridRowExt(newItem.ProductExt, newItem, orderNo);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (dQuantity < 0)
|
|
|
|
|
{
|
|
|
|
|
//减少赠送
|
|
|
|
|
decimal delQuantity = dQuantity * -1;
|
|
|
|
|
if (delQuantity > 0)
|
|
|
|
|
{
|
|
|
|
|
var childItem = this._orderObject.Items.FirstOrDefault(x => x.ParentId == item.Id && x.RowState != OrderRowState.套餐明);
|
|
|
|
|
if (childItem.Quantity > delQuantity)
|
|
|
|
|
{
|
|
|
|
|
childItem.Quantity -= delQuantity;
|
|
|
|
|
RefreshPromotionEntityItem(childItem, fineProm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 双数特价,判定当前商品为主商品,寻找子商品
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="masterItem"></param>
|
|
|
|
|
/// <param name="masterList"></param>
|
|
|
|
|
/// <param name="subList"></param>
|
|
|
|
|
/// <param name="dQuantity"></param>
|
|
|
|
|
/// <param name="fineProm"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private bool DoublePromPart2(OrderItem masterItem, List<OrderItem> masterList, List<OrderItem> subList, decimal dQuantity, PromotionEntity fineProm)
|
|
|
|
|
{
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
|
|
var currItemSub = subList.FindAll(x => x.ParentId == masterItem.Id);
|
|
|
|
|
|
|
|
|
|
//当前主菜对应的子菜数量,判断是否饱和,饱和找其他主
|
|
|
|
|
var currItemQuantity = currItemSub.Sum(x => x.Quantity);
|
|
|
|
|
if (currItemSub.Count > 0 && (currItemQuantity + dQuantity) < masterItem.Quantity)
|
|
|
|
|
{
|
|
|
|
|
//不饱和,可以接受
|
|
|
|
|
var tempItem = currItemSub[0];
|
|
|
|
|
|
|
|
|
|
tempItem.Quantity += dQuantity;
|
|
|
|
|
masterItem.Quantity -= dQuantity;
|
|
|
|
|
|
|
|
|
|
//套餐主数量变更,同步更新子商品数量
|
|
|
|
|
UpdateSuitSubQuantity(masterItem);
|
|
|
|
|
|
|
|
|
|
RefreshPromotionEntityItem(tempItem, fineProm);
|
|
|
|
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(masterItem);
|
|
|
|
|
RefreshRow(tempItem);
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
result = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//查找正好符合数量的未被使用的商品作为子商品
|
|
|
|
|
var subItem = masterList.FirstOrDefault(x => x.Id != masterItem.Id && x.Quantity == dQuantity && (!_orderObject.Items.Exists(y => y.ParentId == x.Id) || (x.RowState == OrderRowState.套餐主 && !_orderObject.Items.Exists(y => y.ParentId == x.Id && y.RowState != OrderRowState.套餐明))));
|
|
|
|
|
if (subItem != null)
|
|
|
|
|
{
|
|
|
|
|
//应用优惠
|
|
|
|
|
BusinessUtils.Instance.ApplyPromotionEntity(this._orderObject, subItem, fineProm);
|
|
|
|
|
|
|
|
|
|
subItem.ParentId = masterItem.Id;
|
|
|
|
|
BusinessUtils.Instance.ApplyPromotionEntity(this._orderObject, subItem, fineProm);
|
|
|
|
|
|
|
|
|
|
//移动至主商品下方
|
|
|
|
|
int orderNo = BusinessUtils.Instance.AppendItemPosition(this._orderObject, masterItem);
|
|
|
|
|
MoveItemPosition(subItem, orderNo);
|
|
|
|
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(subItem);
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
result = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 双数特价,判断当前商品为子商品,寻找主商品
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
/// <param name="masterList"></param>
|
|
|
|
|
/// <param name="subList"></param>
|
|
|
|
|
/// <param name="dQuantity"></param>
|
|
|
|
|
/// <param name="fineProm"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private bool DoublePromPart3(OrderItem item, List<OrderItem> masterList, List<OrderItem> subList, decimal dQuantity, PromotionEntity fineProm)
|
|
|
|
|
{
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
|
|
//查找正好符合数量的未被使用的商品作为主商品
|
|
|
|
|
//符合数量有两种,1、一个主商品下已有子商品,但是该主商品还可以接纳当前数量的商品
|
|
|
|
|
OrderItem masterItem = null;
|
|
|
|
|
foreach (var tmp in masterList)
|
|
|
|
|
{
|
|
|
|
|
if (tmp.Id != item.Id)
|
|
|
|
|
{
|
|
|
|
|
if (tmp.RowState == OrderRowState.普通)
|
|
|
|
|
{
|
|
|
|
|
var currItemSub = subList.FindAll(x => x.ParentId == tmp.Id);
|
|
|
|
|
var currItemQuantity = currItemSub.Sum(x => x.Quantity);
|
|
|
|
|
if (tmp.Quantity - currItemQuantity >= dQuantity)
|
|
|
|
|
{
|
|
|
|
|
masterItem = tmp;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (tmp.RowState == OrderRowState.套餐主)
|
|
|
|
|
{
|
|
|
|
|
var currItemSub = subList.FindAll(x => x.ParentId == tmp.Id && x.RowState == OrderRowState.套餐主);
|
|
|
|
|
var currItemQuantity = currItemSub.Sum(x => x.Quantity);
|
|
|
|
|
if (tmp.Quantity - currItemQuantity >= dQuantity)
|
|
|
|
|
{
|
|
|
|
|
masterItem = tmp;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (masterItem != null)
|
|
|
|
|
{
|
|
|
|
|
//应用优惠
|
|
|
|
|
item.ParentId = masterItem.Id;
|
|
|
|
|
BusinessUtils.Instance.ApplyPromotionEntity(this._orderObject, item, fineProm);
|
|
|
|
|
//移动至主商品下方
|
|
|
|
|
int orderNo = BusinessUtils.Instance.AppendItemPosition(this._orderObject, masterItem);
|
|
|
|
|
MoveItemPosition(item, orderNo);
|
|
|
|
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(item);
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
result = true;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private void MoveItemPosition(OrderItem item, int orderNo)
|
|
|
|
|
{
|
|
|
|
|
if (item.RowState == OrderRowState.普通)
|
|
|
|
|
{
|
|
|
|
|
//移动到父商品下方
|
|
|
|
|
this._orderObject.Maps.Move(item.OrderNo - 1, orderNo);
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
this.gridControl.PrimaryGrid.Rows.Remove(item.GridRow);
|
|
|
|
|
this.gridControl.PrimaryGrid.Rows.Insert(orderNo, item.GridRow);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
else if (item.RowState == OrderRowState.套餐主)
|
|
|
|
|
{
|
|
|
|
|
//套餐整体移动到父商品下方
|
|
|
|
|
this._orderObject.Maps.Move(item.OrderNo - 1, orderNo);
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
this.gridControl.PrimaryGrid.Rows.Remove(item.GridRow);
|
|
|
|
|
this.gridControl.PrimaryGrid.Rows.Insert(orderNo, item.GridRow);
|
|
|
|
|
}));
|
|
|
|
|
var subItems = this._orderObject.Items.FindAll(x => x.RowState == OrderRowState.套餐明 && x.ParentId == item.Id);
|
|
|
|
|
foreach (var sub in subItems)
|
|
|
|
|
{
|
|
|
|
|
var targetCount = ++orderNo;
|
|
|
|
|
this._orderObject.Maps.Move(sub.OrderNo - 1, targetCount);
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
this.gridControl.PrimaryGrid.Rows.Remove(sub.GridRow);
|
|
|
|
|
this.gridControl.PrimaryGrid.Rows.Insert(targetCount, sub.GridRow);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 更新促销信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
/// <param name="fineProm"></param>
|
|
|
|
|
private void RefreshPromotionEntityItem(OrderItem item, PromotionEntity fineProm)
|
|
|
|
|
{
|
|
|
|
|
var p = fineProm.Products[0];
|
|
|
|
|
var promotion = item.Promotions[0];
|
|
|
|
|
//优惠金额
|
|
|
|
|
promotion.DiscountAmount = OrderUtils.ToRound(fineProm.DiscountAmount / p.Quantity * item.Quantity);
|
|
|
|
|
//折扣率
|
|
|
|
|
if (item.Amount != 0)
|
|
|
|
|
{
|
|
|
|
|
promotion.DiscountRate = OrderUtils.ToRound((item.Amount - promotion.DiscountAmount) / item.Amount);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
promotion.DiscountRate = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PromotionUtils.Calculate(this._orderObject, item, promotion);
|
|
|
|
|
|
|
|
|
|
if (item.RowState == OrderRowState.套餐主)
|
|
|
|
|
{
|
|
|
|
|
//同步更改套餐明细数量
|
|
|
|
|
UpdateSuitSubQuantity(item);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(item);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 套餐主数量变更,同步更新子商品数量变更
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
private void UpdateSuitSubQuantity(OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
if (item.RowState == OrderRowState.套餐主)
|
|
|
|
|
{
|
|
|
|
|
var details = this._orderObject.Items.FindAll(x => x.ParentId == item.Id && x.Group == item.Group);
|
|
|
|
|
foreach (var detail in details)
|
|
|
|
|
{
|
|
|
|
|
//道菜加价金额
|
|
|
|
|
detail.SuitAmount = item.Quantity * detail.SuitAddPrice;
|
|
|
|
|
|
|
|
|
|
//道菜数量随主菜变化而增加
|
|
|
|
|
detail.Quantity = item.Quantity * detail.SuitQuantity;
|
|
|
|
|
|
|
|
|
|
//将更改后的行数据同步到订单列表
|
|
|
|
|
var inx = this._orderObject.Maps.IndexOf(detail);
|
|
|
|
|
this._orderObject.Maps[inx] = detail;
|
|
|
|
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshRow(detail);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//套餐道菜分摊
|
|
|
|
|
PromotionUtils.CalculateSuitShare(this._orderObject, item);
|
|
|
|
|
|
|
|
|
|
//套餐主特殊处理
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
UpdateSuitMain(item);
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CalOrderPromEngine()
|
|
|
|
|
{
|
|
|
|
|
//计算整单优惠
|
|
|
|
|
var orderPromResult = PromotionEngine.Instance.CalOrderPromotion(this._orderObject);
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
MsgEvent.Send(Constant.HISTORY_CHANGED_NOTIFY, new Tuple<HistoryMsgType, object>(HistoryMsgType.优惠列表, orderPromResult));
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void AddGridRow(ProductExt product, OrderRowState rowState = OrderRowState.None)
|
|
|
|
|
{
|
|
|
|
|
//添加沽清业务规则
|
|
|
|
|
SaleClear saleClear = null;
|
|
|
|
|
if (SaleClearUtils.Instance.Maps.ContainsKey(product.Id))
|
|
|
|
|
{
|
|
|
|
|
saleClear = SaleClearUtils.Instance.Maps[product.Id];
|
|
|
|
|
}
|
|
|
|
|
//是否参与沽清
|
|
|
|
|
bool isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
if (isSaleClear && saleClear.Quantity <= 0)
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, "已经销售完了!");
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//创建新的OrderItem
|
|
|
|
|
var master = BusinessUtils.Instance.NewOrderItem(this._orderObject, product, rowState);
|
|
|
|
|
//多规格选择
|
|
|
|
|
if (product.SpecCount > 1)
|
|
|
|
|
{
|
|
|
|
|
//规格权限控制码 10007
|
|
|
|
|
string permissionCode = "10007";
|
|
|
|
|
|
|
|
|
|
bool isGo = true;
|
|
|
|
|
|
|
|
|
|
//是否启用授权窗口
|
|
|
|
|
var isAuthz = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_AUTO_LOCK_DISABLE, false);
|
|
|
|
|
|
|
|
|
|
//没有按钮权限
|
|
|
|
|
if (isGo && !isAuthz)
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, "您没有多规格选择权限!");
|
|
|
|
|
isGo = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isGo)
|
|
|
|
|
{
|
|
|
|
|
var autoSelectSpec = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CONFIG_CASHIER_AUTO_SELECT_SPEC, true);
|
|
|
|
|
//有规格操作权限
|
|
|
|
|
if (Global.Instance.HasPermission(permissionCode))
|
|
|
|
|
{
|
|
|
|
|
if (autoSelectSpec)
|
|
|
|
|
{
|
|
|
|
|
SelectSpecDialog(master, product, permissionCode, saleClear);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AddGridRow(product, master, saleClear);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var authForm = new AuthDialogForm("规格", permissionCode, this._orderObject);
|
|
|
|
|
authForm.ExpectValidate(permissionCode);
|
|
|
|
|
|
|
|
|
|
authForm.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (args.Data is Tuple<decimal, decimal, List<string>, Worker>)
|
|
|
|
|
{
|
|
|
|
|
if (autoSelectSpec)
|
|
|
|
|
{
|
|
|
|
|
this.SelectSpecDialog(master, product, permissionCode, saleClear);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AddGridRow(product, master, saleClear);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
authForm.CancelButtonClick += (o, args) => { };
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, authForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AddGridRow(product, master, saleClear);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SelectSpecDialog(OrderItem master, ProductExt product, string permissionCode, SaleClear saleClear = null)
|
|
|
|
|
{
|
|
|
|
|
var dialogForm = new MSpecDialogForm(master, permissionCode);
|
|
|
|
|
dialogForm.AcceptButtonClick += (sender, args) =>
|
|
|
|
|
{
|
|
|
|
|
AddGridRow(product, master, saleClear);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dialogForm.CancelButtonClick += (sender, args) => { };
|
|
|
|
|
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.01, dialogForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddGridRow(ProductExt product, OrderItem master, SaleClear saleClear = null)
|
|
|
|
|
{
|
|
|
|
|
//判断是否需要输入售价
|
|
|
|
|
var priceZeroInput = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_PRICE_ZERO_INPUT, false);
|
|
|
|
|
if (priceZeroInput && product.Price <= 0)
|
|
|
|
|
{
|
|
|
|
|
var dialogForm = new InputPriceDialogForm(product);
|
|
|
|
|
dialogForm.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
var inputValue = Convert.ToDecimal(args.Data);
|
|
|
|
|
|
|
|
|
|
product.Price = inputValue;
|
|
|
|
|
product.MemberPrice = inputValue;
|
|
|
|
|
product.OtherPrice = inputValue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//售价
|
|
|
|
|
master.SalePrice = product.Price;
|
|
|
|
|
//单品最低售价
|
|
|
|
|
master.MinPrice = product.MinPrice;
|
|
|
|
|
//会员价
|
|
|
|
|
master.MemberPrice = product.MemberPrice;
|
|
|
|
|
//会员价(元)
|
|
|
|
|
master.MemberSalePrice = product.MemberPrice;
|
|
|
|
|
//批发价
|
|
|
|
|
master.DispatchPrice = product.DispatchPrice;
|
|
|
|
|
//第三方价
|
|
|
|
|
master.OtherPrice = product.OtherPrice;
|
|
|
|
|
|
|
|
|
|
//默认情况下,零售价和售价一样,零售价主要解决前台售价为0的商品,需要录入的售价
|
|
|
|
|
master.Price = product.Price;
|
|
|
|
|
//默认情况下,折后单价和零售价一样
|
|
|
|
|
master.DiscountPrice = master.Price;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AddGridRowEx(product, master, true, saleClear);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dialogForm.CancelButtonClick += (o, args) => { };
|
|
|
|
|
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.01, dialogForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AddGridRowEx(product, master, true, saleClear);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddGridRowEx(ProductExt product, OrderItem master, bool refUI, SaleClear saleClear = null)
|
|
|
|
|
{
|
|
|
|
|
bool isException = false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
List<OrderItem> rows = BusinessUtils.Instance.BuildGridRow(_orderObject, product, master);
|
|
|
|
|
|
|
|
|
|
foreach (var item in rows)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(item.ProductId))
|
|
|
|
|
{
|
|
|
|
|
isException = true;
|
|
|
|
|
MDialogForm errDialog = new MDialogForm("错误提示", "套餐中的商品当前门店不存在,请联系管理员!", MessageBoxIcon.Error, MessageBoxButtons.OK);
|
|
|
|
|
errDialog.ShowDialog();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
|
|
|
|
|
foreach (var r in rows)
|
|
|
|
|
{
|
|
|
|
|
GridRow gridRow = null;
|
|
|
|
|
|
|
|
|
|
switch (r.RowState)
|
|
|
|
|
{
|
|
|
|
|
case OrderRowState.套餐明:
|
|
|
|
|
{
|
|
|
|
|
//套餐明细不显示售价和优惠
|
|
|
|
|
gridRow = new GridRow(r.OrderNo, r.DisplayName, r.Quantity, r.ProductUnitName, /*r.Price*/"", r.SuitAddPrice > 0 ? ("+" + r.SuitAddPrice) : "", /*r.Discount*/"", r.Underline, r.Flavor, r.Group, r.ParentId, r.Scheme);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
gridRow = new GridRow(r.OrderNo, r.DisplayName, r.Quantity, r.ProductUnitName, r.Price, r.Amount, r.Discount, r.Underline, r.Flavor, r.Group, r.ParentId, r.Scheme);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gridRow.RowHeight = 0;
|
|
|
|
|
gridRow.Tag = r;
|
|
|
|
|
|
|
|
|
|
//将RowIndex映射
|
|
|
|
|
r.GridRow = gridRow;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
panel.Rows.Add(gridRow);
|
|
|
|
|
|
|
|
|
|
if (panel.ActiveRow != null)
|
|
|
|
|
{
|
|
|
|
|
panel.SetSelected(panel.ActiveRow, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
panel.SetSelected(gridRow, true);
|
|
|
|
|
panel.SetActiveRow(gridRow);
|
|
|
|
|
|
|
|
|
|
//压入集合对象
|
|
|
|
|
this._orderObject.Maps.Add(r);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//通知副屏
|
|
|
|
|
if (Global.Instance.EnableVice)
|
|
|
|
|
{
|
|
|
|
|
var rowVice = new GridRow(r.DisplayName, r.Quantity, r.SalePrice, r.Amount, r.FlavorNames);
|
|
|
|
|
rowVice.Tag = r;
|
|
|
|
|
MsgEvent.Send(Constant.VICE_ORDER_NOTIFY, new Tuple<ViceNotifyType, object>(ViceNotifyType.ADDORDERITEM, rowVice));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (refUI)
|
|
|
|
|
{
|
|
|
|
|
this.RefreshUi();
|
|
|
|
|
}
|
|
|
|
|
Application.DoEvents();
|
|
|
|
|
int h = panel.Rows.Sum(p => p.Size.Height);
|
|
|
|
|
this.gridControl.VScrollOffset = h;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
isException = true;
|
|
|
|
|
|
|
|
|
|
LOGGER.Error(ex, "单品加入购物车异常");
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
if (!isException)
|
|
|
|
|
{
|
|
|
|
|
var isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
//沽清处理
|
|
|
|
|
if (isSaleClear)
|
|
|
|
|
{
|
|
|
|
|
saleClear.SaleQuantity += 1;
|
|
|
|
|
|
|
|
|
|
SaleClearUtils.Instance.Maps[product.Id] = saleClear;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//套餐自动打开换菜窗口
|
|
|
|
|
if (product.SuitFlag == 1)
|
|
|
|
|
{
|
|
|
|
|
var showRes = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CONFIG_CASHIER_ADDSUITAUTOOPENCHANGEFORM, false);
|
|
|
|
|
if (showRes)
|
|
|
|
|
{
|
|
|
|
|
//OnShortcutMouseDown(null, new MenuEventArgs("换菜", null, new ModuleMenu() { PermissionCode = "10008" }));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AddGridRowExt(ProductExt product, OrderItem master, int row, SaleClear saleClear = null)
|
|
|
|
|
{
|
|
|
|
|
bool isException = false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
List<OrderItem> rows = BusinessUtils.Instance.BuildGridRow(_orderObject, product, master);
|
|
|
|
|
|
|
|
|
|
foreach (var item in rows)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(item.ProductId))
|
|
|
|
|
{
|
|
|
|
|
isException = true;
|
|
|
|
|
MDialogForm errDialog = new MDialogForm("错误提示", "套餐中的商品当前门店不存在,请联系管理员!", MessageBoxIcon.Error, MessageBoxButtons.OK);
|
|
|
|
|
errDialog.ShowDialog();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
|
|
|
|
|
foreach (var r in rows)
|
|
|
|
|
{
|
|
|
|
|
GridRow gridRow = null;
|
|
|
|
|
|
|
|
|
|
switch (r.RowState)
|
|
|
|
|
{
|
|
|
|
|
case OrderRowState.套餐明:
|
|
|
|
|
{
|
|
|
|
|
//套餐明细不显示售价和优惠
|
|
|
|
|
gridRow = new GridRow(r.OrderNo, r.DisplayName, r.Quantity, r.ProductUnitName, /*r.Price*/"", r.SuitAddPrice > 0 ? ("+" + r.SuitAddPrice) : "", /*r.Discount*/"", r.Underline, r.Flavor, r.Group, r.ParentId, r.Scheme);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
gridRow = new GridRow(r.OrderNo, r.DisplayName, r.Quantity, r.ProductUnitName, r.Price, r.Amount, r.Discount, r.Underline, r.Flavor, r.Group, r.ParentId, r.Scheme);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gridRow.RowHeight = 0;
|
|
|
|
|
gridRow.Tag = r;
|
|
|
|
|
|
|
|
|
|
//将RowIndex映射
|
|
|
|
|
r.GridRow = gridRow;
|
|
|
|
|
|
|
|
|
|
panel.Rows.Insert(row, gridRow);
|
|
|
|
|
panel.SetSelected(gridRow, true);
|
|
|
|
|
panel.SetActiveRow(gridRow);
|
|
|
|
|
|
|
|
|
|
//压入集合对象
|
|
|
|
|
this._orderObject.Maps.Insert(row, r);
|
|
|
|
|
//套餐一次增加多行,++处理
|
|
|
|
|
row++;
|
|
|
|
|
|
|
|
|
|
//通知副屏
|
|
|
|
|
if (Global.Instance.EnableVice)
|
|
|
|
|
{
|
|
|
|
|
var rowVice = new GridRow(r.DisplayName, r.Quantity, r.SalePrice, r.Amount, r.FlavorNames);
|
|
|
|
|
rowVice.Tag = r;
|
|
|
|
|
MsgEvent.Send(Constant.VICE_ORDER_NOTIFY, new Tuple<ViceNotifyType, object>(ViceNotifyType.ADDORDERITEM, rowVice));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this.RefreshUi();
|
|
|
|
|
|
|
|
|
|
Application.DoEvents();
|
|
|
|
|
int h = panel.Rows.Sum(p => p.Size.Height);
|
|
|
|
|
this.gridControl.VScrollOffset = h;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
isException = true;
|
|
|
|
|
|
|
|
|
|
LOGGER.Error(ex, "单品加入购物车异常");
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
if (!isException)
|
|
|
|
|
{
|
|
|
|
|
var isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
//沽清处理
|
|
|
|
|
if (isSaleClear)
|
|
|
|
|
{
|
|
|
|
|
saleClear.SaleQuantity += 1;
|
|
|
|
|
|
|
|
|
|
SaleClearUtils.Instance.Maps[product.Id] = saleClear;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 删除指定订单项
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="item"></param>
|
|
|
|
|
private void DoRemoveOrderItem(OrderItem item)
|
|
|
|
|
{
|
|
|
|
|
if (item != null)
|
|
|
|
|
{
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
List<OrderItem> rows = new List<OrderItem>();
|
|
|
|
|
rows.Add(item);
|
|
|
|
|
//依赖
|
|
|
|
|
var subRows = this._orderObject.Items.FindAll(x => x.ParentId == item.Id);
|
|
|
|
|
rows.AddRange(subRows);
|
|
|
|
|
//买一送一套餐时,需要将送的套餐明细同步删除
|
|
|
|
|
foreach (var subRow in subRows)
|
|
|
|
|
{
|
|
|
|
|
if (subRow.RowState == OrderRowState.套餐主)
|
|
|
|
|
{
|
|
|
|
|
var subsubRows = this._orderObject.Items.FindAll(x => x.ParentId == subRow.Id);
|
|
|
|
|
rows.AddRange(subsubRows);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var activeRow = panel.ActiveRow;
|
|
|
|
|
if (rows.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var row in rows)
|
|
|
|
|
{
|
|
|
|
|
if (row.GridRow != null)
|
|
|
|
|
{
|
|
|
|
|
//删除一条记录前 获取当前记录的下一个可用行记录
|
|
|
|
|
activeRow = row.GridRow.NextVisibleRow;
|
|
|
|
|
if (activeRow == null)
|
|
|
|
|
{
|
|
|
|
|
activeRow = row.GridRow.PrevVisibleRow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//删除当前行
|
|
|
|
|
panel.Rows.Remove(row.GridRow);
|
|
|
|
|
|
|
|
|
|
//移除数据存储
|
|
|
|
|
this._orderObject.Maps.Remove(row);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//通知副屏
|
|
|
|
|
if (Global.Instance.EnableVice)
|
|
|
|
|
{
|
|
|
|
|
MsgEvent.Send(Constant.VICE_ORDER_NOTIFY, new Tuple<ViceNotifyType, object>(ViceNotifyType.DELETESINGLEITEM, row.GridRow.RowIndex));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thread.Sleep(5);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//选择当前活动行
|
|
|
|
|
if (activeRow != null)
|
|
|
|
|
{
|
|
|
|
|
panel.SetSelected(activeRow, true);
|
|
|
|
|
panel.SetActiveRow(activeRow);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this._orderItem = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.RefreshUi();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 删除单品
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void RemoveOrderItem()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
bool isSuccess = true;
|
|
|
|
|
|
|
|
|
|
OrderItem item = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
if (panel.ActiveRow != null)
|
|
|
|
|
{
|
|
|
|
|
item = panel.ActiveRow.Tag as OrderItem;
|
|
|
|
|
|
|
|
|
|
if (item.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
isSuccess = false;
|
|
|
|
|
|
|
|
|
|
this.ShowToastNotify(this, "请选择套餐删除!");
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DoRemoveOrderItem(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
if (isSuccess && item != null)
|
|
|
|
|
{
|
|
|
|
|
//添加沽清业务规则
|
|
|
|
|
SaleClear saleClear = null;
|
|
|
|
|
if (SaleClearUtils.Instance.Maps.ContainsKey(item.ProductId))
|
|
|
|
|
{
|
|
|
|
|
saleClear = SaleClearUtils.Instance.Maps[item.ProductId];
|
|
|
|
|
}
|
|
|
|
|
//是否参与沽清
|
|
|
|
|
bool isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
if (isSaleClear)
|
|
|
|
|
{
|
|
|
|
|
saleClear.SaleQuantity -= item.Quantity;
|
|
|
|
|
|
|
|
|
|
SaleClearUtils.Instance.Maps[item.ProductId] = saleClear;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 取消全单
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void CleanOrderObject()
|
|
|
|
|
{
|
|
|
|
|
bool isSuccess = true;
|
|
|
|
|
//消单是否提醒
|
|
|
|
|
if (Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ORDER_CANCEL_NOTIFY))
|
|
|
|
|
{
|
|
|
|
|
MDialogForm dialog = new MDialogForm("操作提醒", "您确定是要进行取消全单操作吗?", MessageBoxIcon.Warning, MessageBoxButtons.OKCancel);
|
|
|
|
|
if (DialogResult.OK != dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
isSuccess = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isSuccess)
|
|
|
|
|
{
|
|
|
|
|
//处理参与沽清的业务
|
|
|
|
|
var rows = this._orderObject.Items;
|
|
|
|
|
if (rows.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var row in rows)
|
|
|
|
|
{
|
|
|
|
|
//套餐明细不处理沽清业务
|
|
|
|
|
if (row.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//添加沽清业务规则
|
|
|
|
|
SaleClear saleClear = null;
|
|
|
|
|
if (SaleClearUtils.Instance.Maps.ContainsKey(row.ProductId))
|
|
|
|
|
{
|
|
|
|
|
saleClear = SaleClearUtils.Instance.Maps[row.ProductId];
|
|
|
|
|
}
|
|
|
|
|
//是否参与沽清
|
|
|
|
|
bool isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
if (isSaleClear)
|
|
|
|
|
{
|
|
|
|
|
saleClear.SaleQuantity -= row.Quantity;
|
|
|
|
|
|
|
|
|
|
SaleClearUtils.Instance.Maps[row.ProductId] = saleClear;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//发送消单操作,清理表格数据
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
panel.Rows.Clear();
|
|
|
|
|
|
|
|
|
|
//消单后,清理订单对象
|
|
|
|
|
DestoryOrderObject(true);
|
|
|
|
|
|
|
|
|
|
this.txtCash.Text = string.Empty;
|
|
|
|
|
//刷新界面
|
|
|
|
|
this.RefreshUi();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 确保点击完成后继续,避免连击统一个按钮
|
|
|
|
|
/// </summary>
|
|
|
|
|
bool isDoubleHit = false;
|
|
|
|
|
|
|
|
|
|
private void OnMenuClick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var button = sender as ButtonXExt;
|
|
|
|
|
|
|
|
|
|
if (!Global.Instance.AuthLogin)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Info("客户端到期禁止使用");
|
|
|
|
|
var dialog = new MDialogForm("特别提示", "您的POS使用权限已过期,请联系代理商续费!", MessageBoxIcon.Warning, MessageBoxButtons.OK);
|
|
|
|
|
if (DialogResult.OK != dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Info("到期自动退出系统");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (isDoubleHit)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Info("<{0}>连击事件,忽略本次点击", button.Text);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//校验是否继续
|
|
|
|
|
var result = BusinessUtils.Instance.STB_MenuOperateValidate(this._orderObject, this._orderItem, button.Text.Trim());
|
|
|
|
|
if (!result.Item1)
|
|
|
|
|
{
|
|
|
|
|
ShowToastNotify(this, result.Item2);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isDoubleHit = true;
|
|
|
|
|
|
|
|
|
|
//是否启用授权窗口
|
|
|
|
|
var isAuthz = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_AUTO_LOCK_DISABLE, false);
|
|
|
|
|
|
|
|
|
|
//模块授权控制
|
|
|
|
|
if (!this.IsAccredit(button.Text.Trim()))
|
|
|
|
|
{
|
|
|
|
|
isDoubleHit = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
switch (button.Text.Trim())
|
|
|
|
|
{
|
|
|
|
|
case "速结":
|
|
|
|
|
{
|
|
|
|
|
QuickPay();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "现金找零":
|
|
|
|
|
{
|
|
|
|
|
var dialogForm = new CashDialogForm(this._orderObject);
|
|
|
|
|
dialogForm.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
decimal inputMoney = Convert.ToDecimal(args.Data);
|
|
|
|
|
|
|
|
|
|
QuickPay(inputMoney);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dialogForm.CancelButtonClick += (o, args) => { };
|
|
|
|
|
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.08, dialogForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "会员卡":
|
|
|
|
|
{
|
|
|
|
|
var dialogForm = new MCardDialogForm(this._orderObject);
|
|
|
|
|
dialogForm.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dialogForm.CancelButtonClick += (o, args) => { };
|
|
|
|
|
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.08, dialogForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "扫码支付":
|
|
|
|
|
{
|
|
|
|
|
var dialogForm = new MPayDialogForm(this._orderObject);
|
|
|
|
|
dialogForm.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dialogForm.CancelButtonClick += (o, args) => { };
|
|
|
|
|
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.08, dialogForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "离线支付":
|
|
|
|
|
{
|
|
|
|
|
OfflinePay();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "功能":
|
|
|
|
|
{
|
|
|
|
|
var form = Application.OpenForms["MoreDialogForm"];
|
|
|
|
|
if (form == null)
|
|
|
|
|
{
|
|
|
|
|
form = new MoreDialogForm();
|
|
|
|
|
}
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.30, form as BusinessForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "交班":
|
|
|
|
|
{
|
|
|
|
|
//是否是盲交模式
|
|
|
|
|
bool ShiftMode = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CONFIG_CASHIER_SHIFTMODE, false);
|
|
|
|
|
if (ShiftMode)
|
|
|
|
|
{
|
|
|
|
|
var dialogForm = new FastShitBlindForm();
|
|
|
|
|
dialogForm.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
dialogForm.CancelButtonClick += (o, args) => { };
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.30, dialogForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var dialogForm = new FastShitForm();
|
|
|
|
|
dialogForm.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
dialogForm.CancelButtonClick += (o, args) => { };
|
|
|
|
|
TransparentForm trans = new TransparentForm(this, 0.30, dialogForm);
|
|
|
|
|
trans.Show(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "注销":
|
|
|
|
|
{
|
|
|
|
|
//重启收银程序
|
|
|
|
|
Global.Instance.Restart = true;
|
|
|
|
|
Application.ExitThread();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "锁屏":
|
|
|
|
|
{
|
|
|
|
|
var locked = new LockForm();
|
|
|
|
|
locked.ShowDialog();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "最小化":
|
|
|
|
|
{
|
|
|
|
|
this.WindowState = FormWindowState.Minimized;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "退出":
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Info("手动退出系统");
|
|
|
|
|
this.Close();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "OnMenuClick异常");
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
isDoubleHit = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 离线支付结账
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void OfflinePay()
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Info("操作离线支付");
|
|
|
|
|
|
|
|
|
|
//自动弹出桌号
|
|
|
|
|
if (!ProcessAutoDeskNo())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//食堂版本的离线支付
|
|
|
|
|
decimal inputMoney = _orderObject.ReceivableAmount;
|
|
|
|
|
|
|
|
|
|
var result = BusinessUtils.Instance.OfflinePay(_orderObject, inputMoney);
|
|
|
|
|
|
|
|
|
|
if (result.Item1)
|
|
|
|
|
{
|
|
|
|
|
this.DestoryOrderObject(false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, result.Item2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 现金结账
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void QuickPay(decimal inputMoney = -9999)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Info("操作现金结账");
|
|
|
|
|
|
|
|
|
|
//自动弹出桌号
|
|
|
|
|
if (!ProcessAutoDeskNo())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//食堂版本的速结不采用数据金额模式,直接按单结账
|
|
|
|
|
if (inputMoney == -9999)
|
|
|
|
|
{
|
|
|
|
|
inputMoney = _orderObject.ReceivableAmount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var result = BusinessUtils.Instance.QuickPay(_orderObject, inputMoney);
|
|
|
|
|
|
|
|
|
|
if (result.Item1)
|
|
|
|
|
{
|
|
|
|
|
this.DestoryOrderObject(false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, result.Item2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 自动弹出桌号
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private bool ProcessAutoDeskNo()
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(this._orderObject.TableNo))
|
|
|
|
|
{
|
|
|
|
|
//有桌号,不弹
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
///自动弹出桌号
|
|
|
|
|
var autoDeskNo = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_CHECKAUTOOPENDESKNO, false);
|
|
|
|
|
if (autoDeskNo)
|
|
|
|
|
{
|
|
|
|
|
var result = SetDeskNo();
|
|
|
|
|
if (result == DialogResult.OK)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private DialogResult SetDeskNo()
|
|
|
|
|
{
|
|
|
|
|
var form = new DeskNoForm(this._orderObject);
|
|
|
|
|
form.AcceptButtonClick += (o, args) =>
|
|
|
|
|
{
|
|
|
|
|
var desk = args.Data as Tuple<string, string, string>;
|
|
|
|
|
this._orderObject.TableNo = desk.Item1;
|
|
|
|
|
this._orderObject.TableName = desk.Item2;
|
|
|
|
|
this._orderObject.Ext1 = desk.Item3;
|
|
|
|
|
if (this._orderObject.TableNo != null)
|
|
|
|
|
{
|
|
|
|
|
//显示桌号
|
|
|
|
|
MsgEvent.Send(Constant.MSGCENTER_NOTIFY, new MsgEntity() { Subject = Constant.MENU_TITLE_CHANGED_NOTIFY, SubSubject = ModuleKeyCode.桌号.ToString(), Operate = MsgEntityOperate.发布, Data = new Tuple<ModuleKeyCode, MenuTileNotifyType, string>(ModuleKeyCode.桌号, MenuTileNotifyType.数量, _orderObject.TableName) });
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
return form.ShowDialog(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnFormClosing(FormClosingEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
bool isSuccess = false;
|
|
|
|
|
|
|
|
|
|
bool isGo = true;
|
|
|
|
|
//允许有未结账单据(含挂单)存在时退出系统
|
|
|
|
|
if (!Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ACCOUNT_EN_ROUTE, false) && this._orderObject != null && this._orderObject.OrderStatus == OrderStatus.新建单 && this._orderObject.Items.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
var dialog = new MDialogForm("操作提醒", "有正在操作的单据,不允许退出系统", MessageBoxIcon.Warning, MessageBoxButtons.OK);
|
|
|
|
|
dialog.ShowDialog();
|
|
|
|
|
isGo = false;
|
|
|
|
|
|
|
|
|
|
isSuccess = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isGo && !Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ACCOUNT_EN_ROUTE_NOTIFY, false))
|
|
|
|
|
{
|
|
|
|
|
var dialog = new MDialogForm("操作提醒", "您确定是要退出系统吗?", MessageBoxIcon.Warning, MessageBoxButtons.OKCancel);
|
|
|
|
|
if (DialogResult.OK != dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
isSuccess = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
isSuccess = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.Cancel = isSuccess;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnFormClosed(FormClosedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnFormClosed(e);
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 练习模式切换图标显示
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="args"></param>
|
|
|
|
|
protected virtual void StudyModeChangedNotify(object sender, MsgEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
this.studyModeControl.Text = "练习模式";
|
|
|
|
|
this.studyModeControl.Visible = Global.Instance.IsStudyMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnCategoryXCheckedChanged(object sender, CategoryXEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var productType = e.Data;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var lists = Global.Product._productList;
|
|
|
|
|
var selectProduct = new List<ProductExt>();
|
|
|
|
|
if (!Constant.ALL_PRODUCT_TAG.Equals(productType.No))
|
|
|
|
|
{
|
|
|
|
|
selectProduct = lists.FindAll(x => !string.IsNullOrEmpty(x.TypePath) && x.TypePath.StartsWith(productType.Path));
|
|
|
|
|
}
|
|
|
|
|
this.productControl.PageNumber = 1;
|
|
|
|
|
this.productControl.BindDataSource(selectProduct, PriceTypeEnum.零售价);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "加载商品信息异常");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
//每分钟检查一次到期时间
|
|
|
|
|
StoreInfo storeInfo = Global.StoreInfo.StoreInfoMessage;
|
|
|
|
|
if (storeInfo != null && storeInfo.CostMode == 0)
|
|
|
|
|
{
|
|
|
|
|
int authDays = DateTimeUtils.DifferentDaysByMillisecond(storeInfo.DueDate, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
//租赁模式剩余时间小于0天,禁止登陆系统
|
|
|
|
|
if (authDays < 0)
|
|
|
|
|
{
|
|
|
|
|
Global.Instance.AuthLogin = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
|
|
{
|
|
|
|
|
//清理内存
|
|
|
|
|
Global.ClearMemory();
|
|
|
|
|
//更新系统日期
|
|
|
|
|
this.lblSystemDate.Text = string.Format(this.lblSystemDate.Tag.ToString(), DateTime.Now.ToString("yyyy-MM-dd HH:mm"));
|
|
|
|
|
//发送收银机工作状态
|
|
|
|
|
if (DateTime.Now.Minute % 5 == 0)
|
|
|
|
|
{
|
|
|
|
|
HttpClientUtils.PosMonitor();
|
|
|
|
|
}
|
|
|
|
|
//清理过期的沽清数据
|
|
|
|
|
SaleClearUtils.Instance.Expired();
|
|
|
|
|
}));
|
|
|
|
|
});
|
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
var status = ServiceHelper.CheckServiceStatus();
|
|
|
|
|
|
|
|
|
|
LOGGER.Debug("服务中心运行状态:" + status.ToString());
|
|
|
|
|
|
|
|
|
|
ServiceHelper.StartService();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 网络连接状态
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
/// <param name="args"></param>
|
|
|
|
|
protected override void NetworkEventNotify(object sender, MsgEventArgs args)
|
|
|
|
|
{
|
|
|
|
|
base.NetworkEventNotify(sender, args);
|
|
|
|
|
|
|
|
|
|
if (IsDisposed || !this.IsHandleCreated) return;
|
|
|
|
|
|
|
|
|
|
//呈现联机更新状态
|
|
|
|
|
this.BeginInvoke(new MethodInvoker(() =>
|
|
|
|
|
{
|
|
|
|
|
ChangNetworkStatus();
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ChangNetworkStatus()
|
|
|
|
|
{
|
|
|
|
|
this.lblNetworkStatus.Text = Global.Instance.Online ? "网络正常" : "网络异常";
|
|
|
|
|
this.lblNetworkStatus.ForeColor = Global.Instance.Online ? Color.FromArgb(68, 68, 68) : Color.FromArgb(244, 91, 99);
|
|
|
|
|
this.lblNetworkStatus.Invalidate();
|
|
|
|
|
|
|
|
|
|
Color status = Global.Instance.Online ? Color.FromArgb(0, 199, 186) : Color.FromArgb(244, 91, 99);
|
|
|
|
|
this.lblDot1.SymbolColor = this.lblDot2.SymbolColor = this.lblDot3.SymbolColor = this.lblDot4.SymbolColor = this.lblDot5.SymbolColor = status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 加载副屏
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void LoadingViceScreen()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//Global.Instance.EnableVice = true;
|
|
|
|
|
//ViceScreenForm vice2 = new ViceScreenForm();
|
|
|
|
|
//vice2.Show();
|
|
|
|
|
//return;
|
|
|
|
|
var enableVice = Global.Instance.GlobalConfigBoolValue(ConfigConstant.DEVICE_VICE_ENABLE);
|
|
|
|
|
if (enableVice)
|
|
|
|
|
{
|
|
|
|
|
//启用副屏
|
|
|
|
|
Screen[] sc = Screen.AllScreens;
|
|
|
|
|
if (sc.Count() > 1)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < sc.Count(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (!sc[i].Primary)
|
|
|
|
|
{
|
|
|
|
|
ViceScreenForm vice = new ViceScreenForm();
|
|
|
|
|
vice.FormBorderStyle = FormBorderStyle.None;
|
|
|
|
|
vice.StartPosition = FormStartPosition.Manual;
|
|
|
|
|
Point p = new Point(sc[i].Bounds.Location.X, sc[i].Bounds.Location.Y);
|
|
|
|
|
vice.Location = p;
|
|
|
|
|
vice.WindowState = FormWindowState.Maximized;
|
|
|
|
|
vice.Show();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
enableVice = false;
|
|
|
|
|
LOGGER.Info("设置启用了副屏,但是当前机器只有一块屏幕,不能启动副屏显示");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Info("未启用副屏");
|
|
|
|
|
}
|
|
|
|
|
Global.Instance.EnableVice = enableVice;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "副屏显示异常");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnKeyboardClick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
//先判断是否已经完成
|
|
|
|
|
if (this._orderObject.OrderStatus == OrderStatus.已完成)
|
|
|
|
|
{
|
|
|
|
|
this.DestoryOrderObject(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var button = sender as ButtonXExt;
|
|
|
|
|
var keyCode = button.Tag.ToString().Trim();
|
|
|
|
|
if (string.IsNullOrEmpty(keyCode)) return;
|
|
|
|
|
|
|
|
|
|
this.ActiveControl = this.txtCash;
|
|
|
|
|
this.txtCash.Focus();
|
|
|
|
|
|
|
|
|
|
switch (keyCode)
|
|
|
|
|
{
|
|
|
|
|
case "clear":
|
|
|
|
|
{
|
|
|
|
|
bool isSuccess = true;
|
|
|
|
|
|
|
|
|
|
OrderItem item = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
if (panel.ActiveRow != null)
|
|
|
|
|
{
|
|
|
|
|
item = panel.ActiveRow.Tag as OrderItem;
|
|
|
|
|
|
|
|
|
|
if (item.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
isSuccess = false;
|
|
|
|
|
|
|
|
|
|
this.ShowToastNotify(this, "请选择套餐删除!");
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DoRemoveOrderItem(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
if (isSuccess && item != null)
|
|
|
|
|
{
|
|
|
|
|
//添加沽清业务规则
|
|
|
|
|
SaleClear saleClear = null;
|
|
|
|
|
if (SaleClearUtils.Instance.Maps.ContainsKey(item.ProductId))
|
|
|
|
|
{
|
|
|
|
|
saleClear = SaleClearUtils.Instance.Maps[item.ProductId];
|
|
|
|
|
}
|
|
|
|
|
//是否参与沽清
|
|
|
|
|
bool isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
if (isSaleClear)
|
|
|
|
|
{
|
|
|
|
|
saleClear.SaleQuantity -= item.Quantity;
|
|
|
|
|
|
|
|
|
|
SaleClearUtils.Instance.Maps[item.ProductId] = saleClear;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.txtCash.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "accept":
|
|
|
|
|
{
|
|
|
|
|
this.UpdateGridRow(null);
|
|
|
|
|
|
|
|
|
|
this.txtCash.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map[keyCode]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ProductExt builderProductExt(decimal price, OrderItem orderItem = null)
|
|
|
|
|
{
|
|
|
|
|
var json = "{\"typeName\":\"自选快餐\",\"unitName\":\"份\",\"specName\":\"\",\"specId\":\"999999\",\"chuda\":\"\",\"chudaFlag\":\"1\",\"chupin\":\"\",\"chupinFlag\":\"0\",\"chuDaLabelFlag\":\"0\",\"chuDaLabel\":\"\",\"chuxianTime\":0,\"kdsChupinTime\":0,\"tenantId\":\"\",\"brandId\":\"\",\"typeId\":\"999999\",\"typePath\":\"999999\",\"no\":\"999999\",\"name\":\"自选快餐\",\"shortName\":\"自选快餐\",\"spell\":\"ZXKC\",\"assistNo\":\"\",\"otherNo\":\"\",\"barCode\":\"999999\",\"english\":\"\",\"unitId\":\"\",\"description\":\"\",\"commissionType\":0,\"commissionValue\":0.0,\"discountFlag\":1,\"suitFlag\":0,\"tapleFlag\":1,\"weighFlag\":1,\"currentFlag\":0,\"mebDiscountFlag\":0,\"giveFlag\":1,\"labelPrintFlag\":1,\"promotionFlag\":0,\"type\":0,\"stockFlag\":1,\"pointType\":0,\"pointValue\":0.0,\"purchaseTax\":17.0,\"saleTax\":0.0,\"lyRate\":0.0,\"stopFlag\":0,\"groupName\":\"\",\"picture\":\"\",\"price\":12.0,\"memberPrice\":11.0,\"costPrice\":8.0,\"otherPrice\":0.0,\"purchasePrice\":8.0,\"minPrice\":11.0,\"dispatchPrice\":8.0,\"specCount\":1,\"kdsFlag\":1,\"ext1\":\"\",\"ext2\":\"\",\"ext3\":\"\",\"id\":\"999999\",\"createUser\":\"sync\",\"createDate\":\"2019-01-25 09:41:12\",\"modifyUser\":\"sync\",\"modifyDate\":\"2019-01-25 09:41:17\"}";
|
|
|
|
|
|
|
|
|
|
var product = JsonUtils.Deserialize<ProductExt>(json);
|
|
|
|
|
|
|
|
|
|
product.TenantId = Global.Instance.Worker.TenantId;
|
|
|
|
|
|
|
|
|
|
product.Price = price;
|
|
|
|
|
|
|
|
|
|
product.MemberPrice = price;
|
|
|
|
|
|
|
|
|
|
return product;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnInputValueChanged(object sender, EnterEventArg e)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(this.txtCash.Text.Trim()))
|
|
|
|
|
{
|
|
|
|
|
if (this._orderItem != null && this._orderItem.RowState == OrderRowState.自选快餐)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
this._orderItem.Price = this.txtCash.DecimalValue;
|
|
|
|
|
this._orderItem.MemberPrice = this.txtCash.DecimalValue;
|
|
|
|
|
|
|
|
|
|
//食堂自动加菜逻辑
|
|
|
|
|
if (!this.MaxSaleMoney(_orderItem))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.RefreshRow(this._orderItem);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (this.txtCash.DecimalValue > 0)
|
|
|
|
|
{
|
|
|
|
|
var product = this.builderProductExt(this.txtCash.DecimalValue);
|
|
|
|
|
|
|
|
|
|
this.BuildGridRow(product, OrderRowState.自选快餐);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
//更新表格全部
|
|
|
|
|
UpdateGridRow();
|
|
|
|
|
RefreshUiEx();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnShortcutClick(object sender, TouchEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var button = sender as TouchButtonX;
|
|
|
|
|
//校验是否继续
|
|
|
|
|
var result = BusinessUtils.Instance.STB_MenuOperateValidate(this._orderObject, this._orderItem, button.Text.Trim());
|
|
|
|
|
if (!result.Item1)
|
|
|
|
|
{
|
|
|
|
|
ShowToastNotify(this, result.Item2);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
switch (button.Text.Trim())
|
|
|
|
|
{
|
|
|
|
|
case "上一页":
|
|
|
|
|
{
|
|
|
|
|
this.gridControl.Focus();
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["pgup"]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "下一页":
|
|
|
|
|
{
|
|
|
|
|
this.gridControl.Focus();
|
|
|
|
|
InputSimulatorUtils.SendKey(KeyCodes.Map["pgdn"]);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "删菜":
|
|
|
|
|
{
|
|
|
|
|
if (!this.IsAccredit("删菜"))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
bool isSuccess = true;
|
|
|
|
|
|
|
|
|
|
OrderItem item = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
if (panel.ActiveRow != null)
|
|
|
|
|
{
|
|
|
|
|
item = panel.ActiveRow.Tag as OrderItem;
|
|
|
|
|
|
|
|
|
|
if (item.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
isSuccess = false;
|
|
|
|
|
|
|
|
|
|
this.ShowToastNotify(this, "请选择套餐删除!");
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DoRemoveOrderItem(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
if (isSuccess && item != null)
|
|
|
|
|
{
|
|
|
|
|
//添加沽清业务规则
|
|
|
|
|
SaleClear saleClear = null;
|
|
|
|
|
if (SaleClearUtils.Instance.Maps.ContainsKey(item.ProductId))
|
|
|
|
|
{
|
|
|
|
|
saleClear = SaleClearUtils.Instance.Maps[item.ProductId];
|
|
|
|
|
}
|
|
|
|
|
//是否参与沽清
|
|
|
|
|
bool isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
if (isSaleClear)
|
|
|
|
|
{
|
|
|
|
|
saleClear.SaleQuantity -= item.Quantity;
|
|
|
|
|
|
|
|
|
|
SaleClearUtils.Instance.Maps[item.ProductId] = saleClear;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.txtCash.Text = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "消单":
|
|
|
|
|
{
|
|
|
|
|
if (!this.IsAccredit("消单"))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
bool isSuccess = true;
|
|
|
|
|
//消单是否提醒
|
|
|
|
|
if (Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ORDER_CANCEL_NOTIFY))
|
|
|
|
|
{
|
|
|
|
|
MDialogForm dialog = new MDialogForm("操作提醒", "您确定是要进行取消全单操作吗?", MessageBoxIcon.Warning, MessageBoxButtons.OKCancel);
|
|
|
|
|
//var trans = Application.OpenForms["TransparentFormExt"];
|
|
|
|
|
//if (trans == null)
|
|
|
|
|
//{
|
|
|
|
|
// trans = new TransparentFormExt(this, dialog);
|
|
|
|
|
//}
|
|
|
|
|
//trans.Visible = false;
|
|
|
|
|
//((TransparentFormExt)trans).Show(this);
|
|
|
|
|
|
|
|
|
|
if (DialogResult.OK != dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
isSuccess = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isSuccess)
|
|
|
|
|
{
|
|
|
|
|
//处理参与沽清的业务
|
|
|
|
|
var rows = this._orderObject.Items;
|
|
|
|
|
if (rows.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var row in rows)
|
|
|
|
|
{
|
|
|
|
|
//套餐明细不处理沽清业务
|
|
|
|
|
if (row.RowState == OrderRowState.套餐明)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//添加沽清业务规则
|
|
|
|
|
SaleClear saleClear = null;
|
|
|
|
|
if (SaleClearUtils.Instance.Maps.ContainsKey(row.ProductId))
|
|
|
|
|
{
|
|
|
|
|
saleClear = SaleClearUtils.Instance.Maps[row.ProductId];
|
|
|
|
|
}
|
|
|
|
|
//是否参与沽清
|
|
|
|
|
bool isSaleClear = SaleClearUtils.Instance.CheckSaleClear(saleClear);
|
|
|
|
|
|
|
|
|
|
if (isSaleClear)
|
|
|
|
|
{
|
|
|
|
|
saleClear.SaleQuantity -= row.Quantity;
|
|
|
|
|
|
|
|
|
|
SaleClearUtils.Instance.Maps[row.ProductId] = saleClear;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//发送消单操作,清理表格数据
|
|
|
|
|
GridPanel panel = gridControl.PrimaryGrid;
|
|
|
|
|
panel.Rows.Clear();
|
|
|
|
|
|
|
|
|
|
//消单后,清理订单对象
|
|
|
|
|
DestoryOrderObject(true);
|
|
|
|
|
|
|
|
|
|
//刷新界面
|
|
|
|
|
this.RefreshUi();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region IsAccredit
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 模块授权控制
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool IsAccredit(string permissionName)
|
|
|
|
|
{
|
|
|
|
|
var permissionCode = this.ToPermissionCode(permissionName);
|
|
|
|
|
if (Global.Instance.HasPermission(permissionCode))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var authForm = new AuthDialogForm(permissionName, permissionCode, this._orderObject);
|
|
|
|
|
authForm.ExpectValidate(permissionCode);
|
|
|
|
|
authForm.ShowDialog();
|
|
|
|
|
|
|
|
|
|
if (authForm.IsAccredit)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ToPermissionCode
|
|
|
|
|
private string ToPermissionCode(string permissionName)
|
|
|
|
|
{
|
|
|
|
|
switch (permissionName)
|
|
|
|
|
{
|
|
|
|
|
case "现在找零":
|
|
|
|
|
return "10019";
|
|
|
|
|
case "速结":
|
|
|
|
|
return "10019";
|
|
|
|
|
case "会员卡":
|
|
|
|
|
return "10023";//会员卡查询
|
|
|
|
|
case "营业单据":
|
|
|
|
|
return "30001";//销售流水
|
|
|
|
|
case "销售汇总":
|
|
|
|
|
return "30002";
|
|
|
|
|
case "收银报表":
|
|
|
|
|
return "30003";
|
|
|
|
|
case "营业日报":
|
|
|
|
|
return "30005";
|
|
|
|
|
case "时段报表":
|
|
|
|
|
return "30004";
|
|
|
|
|
case "交班查询":
|
|
|
|
|
return "30008";
|
|
|
|
|
case "会员开户":
|
|
|
|
|
return "20001";
|
|
|
|
|
case "会员充值":
|
|
|
|
|
return "20002";
|
|
|
|
|
case "会员信息":
|
|
|
|
|
return "20005";
|
|
|
|
|
case "会员换卡":
|
|
|
|
|
return "20004";
|
|
|
|
|
case "开钱箱":
|
|
|
|
|
return "10020";
|
|
|
|
|
case "设置":
|
|
|
|
|
return "40001";
|
|
|
|
|
case "交班":
|
|
|
|
|
return "10036";
|
|
|
|
|
case "消单":
|
|
|
|
|
return "10001";
|
|
|
|
|
case "删菜":
|
|
|
|
|
return "10002";
|
|
|
|
|
default:
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region MaxSaleMoney
|
|
|
|
|
private bool MaxSaleMoney(OrderItem _orderItem)
|
|
|
|
|
{
|
|
|
|
|
var _maxMoney = Global.Instance.GlobalConfigStringValue(ConfigConstant.CONFIG_CASHIER_MAXSALEMONEY);
|
|
|
|
|
|
|
|
|
|
decimal Money = 0.00M;
|
|
|
|
|
if (string.IsNullOrEmpty(_maxMoney))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
decimal.TryParse(_maxMoney, out Money);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Money == 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_orderItem.Price > Money)
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, "已超出最大金额,当前设置的最大金额数是:["+ Money.ToString("0.00")+ "]");
|
|
|
|
|
this.txtCash.Text = Money.ToString();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void InfoGuoPanDll()
|
|
|
|
|
{
|
|
|
|
|
var _msid = Global.Instance.GlobalConfigStringValue(ConfigConstant.CONFIG_CASHIER_GUOPANMSID, "");
|
|
|
|
|
var _key = Global.Instance.GlobalConfigStringValue(ConfigConstant.CONFIG_CASHIER_GUOPANKEY, "");
|
|
|
|
|
if (Global.Instance.Worker.TenantId.Equals("771200"))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var _ParenthWnd = FindWindow(null, this.Text);
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(_msid) || string.IsNullOrEmpty(_key))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _data = GuoPanProxy.ApiInit(_msid, _key, _ParenthWnd.ToInt32());
|
|
|
|
|
|
|
|
|
|
if (!_data.Item1)
|
|
|
|
|
{
|
|
|
|
|
this.ShowToastNotify(this, _data.Item2, 5000);
|
|
|
|
|
return;
|
|
|
|
|
DialogForm dialog = new DialogForm("操作提醒", "初始化果盘参数异常,是否继续请求初始化?", MessageBoxIcon.Warning, MessageBoxButtons.OKCancel);
|
|
|
|
|
if (DialogResult.OK == dialog.ShowDialog())
|
|
|
|
|
{
|
|
|
|
|
InfoGuoPanDll();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[DllImport("User32.dll", EntryPoint = "FindWindow")]
|
|
|
|
|
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
|
|
|
|
|
|
|
|
|
protected override void DefWndProc(ref Message m)
|
|
|
|
|
{
|
|
|
|
|
base.DefWndProc(ref m);
|
|
|
|
|
|
|
|
|
|
switch (m.Msg)
|
|
|
|
|
{
|
|
|
|
|
case 2907:
|
|
|
|
|
int _LParam = m.LParam.ToInt32();
|
|
|
|
|
if (_LParam == 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var _id = _LParam;
|
|
|
|
|
bool openConfirm = Global.Instance.GlobalConfigBoolValue(ConfigConstant.WEIXIN_CONFIRM_PARAMETER, true);
|
|
|
|
|
if (openConfirm)
|
|
|
|
|
{
|
|
|
|
|
GuoPanProxy.AutoConfirmOrder(_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
LOGGER.Error(ex, "自动接单失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MsgEvent.Send(Constant.GuoPan_WEIXIN_UI_UPDATA, _LParam);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|