using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using NLog; using POSV.Bean; using POSV.Card; using POSV.Entity; using POSV.Printer; using POSV.ShoppingCart; using POSV.Utils; using System.Threading; using POSV.ServiceCenter; using POS.Language.Language; namespace POSV.Helper { public class PrintHelper { private static Logger logger = NLog.LogManager.GetCurrentClassLogger(); private static object _lock = new object(); /// /// 获取系统配置的收银小票打印机 /// /// public static PrinterObject GetTicketPrinterObject(bool cutPager, bool openCashbox) { var pobject = new PrinterObject(); var json = Global.Instance.GlobalConfigStringValue(ConfigConstant.PERIPHERAL_CASHIER_TICKET); if (string.IsNullOrEmpty(json)) { json = JsonUtils.Serialize(ConfigConstant.PeripheralGroupDefaultValue()); } var printer = JsonUtils.Deserialize(json); pobject.Id = printer.Id; pobject.Name = printer.Name; pobject.PortType = (PortType)Enum.Parse(typeof(PortType), printer.Port); pobject.DynamicLibrary = (DynamicLibrary)Enum.Parse(typeof(DynamicLibrary), printer.DynamicLibrary); pobject.PageWidth = printer.PageWidth; pobject.CutPager = cutPager; pobject.OpenCashbox = openCashbox; pobject.Data[PrinterObject.COM_PORT_NAME] = printer.Data[Constant.COM_PORT_NAME]; pobject.Data[PrinterObject.COM_PORT_BAUD] = printer.Data[Constant.COM_PORT_BAUD]; pobject.Data[PrinterObject.LPT_NAME] = printer.Data[Constant.LPT_NAME]; pobject.Data[PrinterObject.DRIVE_NAME] = printer.Data[Constant.DRIVE_NAME]; pobject.Data[PrinterObject.NET_IP_ADDRESS] = printer.Data[Constant.NET_IP_ADDRESS]; pobject.Data[PrinterObject.USB_PID] = printer.Data[Constant.USB_PID]; pobject.Data[PrinterObject.USB_VID] = printer.Data[Constant.USB_VID]; pobject.EscPosCommand.InitCommand = printer.InitCommand; pobject.EscPosCommand.NormalCommand = printer.NormalCommand; pobject.EscPosCommand.DoubleHeightCommand = printer.DoubleHeightCommand; pobject.EscPosCommand.DoubleWidthCommand = printer.DoubleWidthCommand; pobject.EscPosCommand.DoubleWidthHeightCommand = printer.DoubleWidthHeightCommand; pobject.EscPosCommand.CutPageCommand = printer.CutPageCommand; pobject.EscPosCommand.CashboxCommand = printer.CashboxCommand; pobject.EscPosCommand.AlignCenterCommand = printer.AlignCenterCommand; pobject.EscPosCommand.AlignLeftCommand = printer.AlignLeftCommand; pobject.EscPosCommand.AlignRightCommand = printer.AlignRightCommand; pobject.EscPosCommand.BeepCommand = printer.BeepCommand; //回退行数 pobject.EscPosCommand.FeedBackCommand = printer.FeedBackCommand; //退纸行数 int feedBackRow = Global.Instance.GlobalConfigIntValue(ConfigConstant.CONFIG_CASHIER_FEEDBACK_ROW, 0); pobject.FeedBackRow = feedBackRow; return pobject; } /// /// 打印订单小票、标签、厨显、厨打、出品打印 /// /// public static void PrintOrderObject(OrderObject order) { //异步操作前,复制当前订单对象,防止外部更改后,影响打印 var orderObject = ObjectUtils.Copy(order); //收银小票打印 Task.Factory.StartNew(() => { PrintOrderObjectTicket(orderObject); }); //打印标签 Task.Factory.StartNew(() => { LabelPrintHelper.PrintOrderLabel(orderObject); }); //通知厨显 Task.Factory.StartNew(() => { UploadSCNewOrder.UploadNewOrder2SC4KDS(orderObject); }); //厨打小票打印 Task.Factory.StartNew(() => { ChuDaHelper.KitchenPrinter(orderObject); }); //厨打标签打印 Task.Factory.StartNew(() => { ChuDaHelper.KitchenLabelPrinter(orderObject); }); //出品小票打印 Task.Factory.StartNew(() => { ChuDaHelper.MadePrinter(orderObject); }); } /// /// 打印订单小票 /// /// /// public static bool PrintOrderObjectTicket(OrderObject orderObject) { bool isException = false; try { //20240330 subin 收银小票,打印外带和自提的小票,不打印堂食票 if (orderObject.BusMode == "堂食" || orderObject.OrderType == OrderType.堂食) { logger.Info($"订单类型<{orderObject.OrderType}>,不打印收银小票"); return true; } //构建收银小票模版参数 List vars = null; if (orderObject.OrderType == OrderType.电话外卖) { vars = BuilderDeliveryTicketVariable(orderObject); } else { vars = PrintHelper.BuilderTicketVariable(orderObject); } //自动切纸 bool cutPager = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_CUT_PAGER, false); //是否允许打开钱箱 bool openCashbox = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_OPEN_CASHBOX, false); //不允许现金和银行卡以外方式打开钱箱 bool notAllowOpenCashBox = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_CASH_OPEN_CASHBOX, true); if (orderObject.Pays.Exists(x => x.No == "01" || x.No == "03")) { notAllowOpenCashBox = false; } openCashbox = openCashbox && !notAllowOpenCashBox; //票头空白行 int headerLine = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_HEADER_EMPTY, 0); //票尾空白行 int footerLine = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_FOOTER_EMPTY, 0); //小票打印份数 int ticketCount = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_TICKET_COUNT, 1); //打印延迟 int delaySecond = Global.Instance.GlobalConfigIntValue(ConfigConstant.PERIPHERAL_CASHIER_PRINT_DELAY, 1); for (int i = 1; i <= ticketCount; i++) { if (openCashbox && (i != 1)) { openCashbox = false; } //执行收银小票打印 switch (orderObject.OrderType) { case OrderType.电话外卖: { logger.Info("开始打印电话外送小票<{0}>", orderObject.TradeNo); var prt = PrintHelper.PrinterTicket("电话外卖", vars, cutPager, false, headerLine, footerLine); logger.Info("电话外送小票打印结果<{0},{1},{2}>", orderObject.TradeNo, prt.Item1, prt.Item2); } break; default: { logger.Info("开始打印收银小票<{0}>", orderObject.TradeNo); var prt = PrintHelper.PrinterTicket("收银小票", vars, cutPager, openCashbox, headerLine, footerLine); logger.Info("收银第<{0}>次小票打印结果<{1},{2},{3}>", i, orderObject.TradeNo, prt.Item1, prt.Item2); } break; } if (delaySecond > 0) { Thread.Sleep(delaySecond * 1000); } } } catch (Exception ex) { isException = true; logger.Error(ex, "打印订单小票信息异常"); } return isException; } /// /// 构建收银小票的参数变量 /// /// /// public static List BuilderTicketVariable(OrderObject orderObject) { var vars = new List(); var v = new Printer.VariableValue(); v.Key = "默认数据源"; v.DataType = DataType.Simple; var data = new Dictionary(); if (Global.Instance.IsStudyMode() && string.IsNullOrEmpty(orderObject.OrderNo))//练习模式固定序号 { data.Add("@序号@", Constant.STUDYMODE_DEFAULT_ORDERNO); } else { data.Add("@序号@", orderObject.OrderNo); } data.Add("@营业模式@", LangProxy.ToLang(orderObject.OrderType.ToString())); var tradeNo = orderObject.TradeNo; //票号长度 int length = Global.Instance.GlobalConfigIntValue(ConfigConstant.CONFIG_CASHIER_TICKETNO_LENGTH, 0); bool isRandom = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CONFIG_CASHIER_RANDOM_TICKETNO, false); if (isRandom) { tradeNo = orderObject.ObjectId; } if (length > 0 && (tradeNo.Length - length > 0)) { data.Add("@票号@", tradeNo.Substring(tradeNo.Length - length)); } else { data.Add("@票号@", tradeNo); } //var storeName = string.IsNullOrEmpty(Global.Instance.Worker.StoreInfo.PrintName) ? orderObject.StoreName : Global.Instance.Worker.StoreInfo.PrintName; data.Add("@门店名称@", Global.Instance.Worker.StoreInfo.PrintName); data.Add("@门店编码@", orderObject.StoreNo); if (orderObject.PrintType == 0) { data.Add("@单据类型@", LangProxy.ToLang("结账单")); } if (orderObject.PrintType == 1) { data.Add("@单据类型@", LangProxy.ToLang("退单")); } data.Add("@重打标识@", string.Format("{0}", orderObject.RPrint)); data.Add("@门店地址@", Global.Instance.Worker.StoreInfo.Address); data.Add("@门店电话@", Global.Instance.Worker.StoreInfo.OrderTel); data.Add("@收银员编码@", orderObject.WorkerNo); data.Add("@收银员名称@", orderObject.WorkerName); data.Add("@POS编码@", orderObject.PosNo); data.Add("@桌号@", orderObject.TableName); data.Add("@消费金额@", StringUtils.GetString(orderObject.Amount)); data.Add("@优惠金额@", StringUtils.GetString(orderObject.DiscountAmount)); data.Add("@应收金额@", StringUtils.GetString(orderObject.ReceivableAmount)); data.Add("@实收金额@", StringUtils.GetString(orderObject.ReceivedAmount - orderObject.MalingAmount)); data.Add("@找零金额@", StringUtils.GetString(orderObject.ChangeAmount)); data.Add("@抹零金额@", StringUtils.GetString(orderObject.MalingAmount)); data.Add("@销项税@", StringUtils.GetString(orderObject.ItemsSaleTax.ToString("0.00"))); data.Add("@打印时间@", orderObject.FinishDate); data.Add("@条码内容@", orderObject.TradeNo); data.Add("@条码说明@", orderObject.TradeNo); data.Add("@二维码内容@", orderObject.TradeNo); data.Add("@二维码说明@", orderObject.TradeNo); var notAllowTitle = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_TITLE, false); data.Add("@是否打印标题@", (!notAllowTitle).ToString().ToLower()); var allowOrderNo = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_ORDERNO, false); data.Add("@是否打印序号@", allowOrderNo.ToString().ToLower()); var notAllowStoreAddress = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_STORE_ADDRESS, false); data.Add("@是否打印地址@", (!notAllowStoreAddress).ToString().ToLower()); var notAllowStoreTelphone = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_STORE_TELPHONE, false); data.Add("@是否打印电话@", (!notAllowStoreTelphone).ToString().ToLower()); var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"images" + Path.DirectorySeparatorChar + "bmp"); if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } List images = null; using (var db = Global.Instance.OpenDataBase) { images = db.Query().ToList(); } if (images != null && images.Count > 0) { var headerImage = images.FirstOrDefault(x => x.Type == 0); var allowHeaderBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_HEADER_BITMAP, false); if (headerImage != null && allowHeaderBitmap) { var fileName = string.Empty; if (!string.IsNullOrEmpty(headerImage.StorageFileName) && headerImage.StorageFileName.Contains("/")) { fileName = headerImage.StorageFileName.Substring(headerImage.StorageFileName.LastIndexOf('/') + 1); } string targetFileName = filePath + Path.DirectorySeparatorChar + fileName; if (File.Exists(targetFileName)) { data.Add("@是否票头图片@", "true"); data.Add("@票头图片@", targetFileName); data.Add("@票头图片说明@", headerImage.Description == null ? "" : headerImage.Description); } else { data.Add("@是否票头图片@", "false"); data.Add("@票头图片说明@", ""); } } else { data.Add("@是否票头图片@", "false"); data.Add("@票头图片说明@", ""); } var footerImage = images.FirstOrDefault(x => x.Type == 1); var allowFooterBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_FOOTER_BITMAP, false); if (footerImage != null && allowFooterBitmap) { var fileName = string.Empty; if (!string.IsNullOrEmpty(footerImage.StorageFileName) && footerImage.StorageFileName.Contains("/")) { fileName = footerImage.StorageFileName.Substring(footerImage.StorageFileName.LastIndexOf('/') + 1); } string targetFileName = filePath + Path.DirectorySeparatorChar + fileName; if (File.Exists(targetFileName)) { data.Add("@是否票尾图片@", "true"); data.Add("@票尾图片@", targetFileName); data.Add("@票尾图片说明@", footerImage.Description == null ? "" : footerImage.Description); } else { data.Add("@是否票尾图片@", "false"); data.Add("@票尾图片说明@", ""); } } else { data.Add("@是否票尾图片@", "false"); data.Add("@票尾图片说明@", ""); } } else { data.Add("@票头图片说明@", ""); data.Add("@是否票头图片@", "false"); data.Add("@票尾图片说明@", ""); data.Add("@是否票尾图片@", "false"); } var allowBarCodeBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_BARCODE, false); data.Add("@是否打印条码@", allowBarCodeBitmap.ToString().ToLower()); var allowQRCodeBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_QRCODE, false); data.Add("@是否打印二维码@", allowQRCodeBitmap.ToString().ToLower()); if (string.IsNullOrEmpty(orderObject.MemberNo) && !orderObject.Pays.Exists(x => x.No == "02")) { //不使用会员卡且没有使用储值卡支付的 data.Add("@是否打印会员分隔线@", "false"); } v.Value = JsonUtils.Serialize(data); vars.Add(v); v = new Printer.VariableValue(); v.Key = "点单列表"; v.DataType = DataType.List; var list = new List>(); decimal totalQuantity = 0; decimal totalAmount = 0; decimal totalDiscountAmount = 0; //练习模式 string studyName = string.Empty; if (Global.Instance.IsStudyMode()) { studyName = LangProxy.ToLang(Constant.STUDYMODE_PRINTSTR); } //排序,避免显示列表和打印列表不一致 var items = orderObject.Items.OrderBy(x => x.OrderNo); //禁止打印套餐明细 var notAllowPrintSuitDetail = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_SUIT_DETAIL, false); //列表是否显示折后价 bool showDiscountPrice = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_DISCOUNTPRICE, false); //是否打印规格 var notAllowSepc = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_SPEC, false); //判断参数配置中是否定义显示简称 var showShortName = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_SHORTNAME, false); //禁止打印做法 var notAllowFlavor = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_FLAVOR, false); //免费做法打印为一行 var isOneRow = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_TICKET_FREEMAKEINONEROW, false); foreach (var item in items) { var row = new Dictionary(); //销售界面名称的显示 string showName = (showShortName && !string.IsNullOrEmpty(item.ShortName)) ? item.ShortName : item.Name; //规格名称 string specName = (notAllowSepc || string.IsNullOrEmpty(item.SpecName)) ? "" : Global.Instance.Additional.Item1 + item.SpecName + Global.Instance.Additional.Item2; //附加规格到名称中 string displayName = studyName + showName + specName; if (item.RowState == OrderRowState.套餐明) { if (notAllowPrintSuitDetail) { continue; } displayName = " " + displayName; } if (item.RowState == OrderRowState.普通 || item.RowState == OrderRowState.套餐主) { if (item.Promotions != null) { //禁止收银前台赠送 bool notAllowShowGive = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_NOT_ALLOW_SHOW_GIVE, true); if (!notAllowShowGive && item.Promotions.Exists(x => x.PromotionType == PromotionType.赠送)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("赠") + Global.Instance.Additional.Item2 + displayName; } //禁止收银前台折扣 bool notAllowShowDiscount = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_NOT_ALLOW_SHOW_DISCOUNT, true); if (!notAllowShowDiscount && item.Promotions.Exists(x => x.PromotionType == PromotionType.折扣 || x.PromotionType == PromotionType.整单折扣)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("折") + Global.Instance.Additional.Item2 + displayName; } //禁止收银前台议价 bool notAllowShowBargain = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_NOT_ALLOW_SHOW_BARGAIN, true); if (!notAllowShowBargain && item.Promotions.Exists(x => x.PromotionType == PromotionType.议价 || x.PromotionType == PromotionType.整单议价)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("议") + Global.Instance.Additional.Item2 + displayName; } //双数特价 if (item.Promotions.Exists(x => x.PromotionType == PromotionType.双数特价优惠 || x.PromotionType == PromotionType.双数特价赠送)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("双") + Global.Instance.Additional.Item2 + displayName; } } } row.Add("@品名@", displayName); row.Add("@数量@", (item.Quantity - item.RefundQuantity) + ""); decimal _salePrice = item.Price; if (showDiscountPrice) { _salePrice = item.DiscountPrice; } decimal _amount = item.Amount; if (showDiscountPrice) { _amount = item.Amount - item.DiscountAmount; } if (item.RowState == OrderRowState.套餐明) { row.Add("@单价@", ""); row.Add("@小计@", ""); row.Add("@优惠@", ""); } else { row.Add("@单价@", _salePrice + ""); row.Add("@小计@", _amount + ""); row.Add("@优惠@", item.DiscountAmount + ""); } list.Add(row); //允许打印做法或者做法包含加价 bool existAddPriceFlavor = item.Flavors.Exists(x => x.Price != 0); if (!notAllowFlavor || existAddPriceFlavor) { if (isOneRow) { //零价格做法、加料单独一行 var zeroFlavors = item.Flavors.FindAll(x => x.Price == 0); var flavorStr = string.Join(",", zeroFlavors.ConvertAll(x => x.Name + ((x.Quantity - x.RefundQuantity) > 1 ? (x.Quantity - x.RefundQuantity).ToString() : "")).ToArray()); row = new Dictionary(); row.Add("@品名@", " " + flavorStr); row.Add("@数量@", string.Empty); row.Add("@单价@", string.Empty); row.Add("@小计@", string.Empty); row.Add("@优惠@", string.Empty); list.Add(row); //有价加料 var priceFlavors = item.Flavors.FindAll(x => x.Price != 0); foreach (var flavor in priceFlavors) { row = new Dictionary(); row.Add("@品名@", " " + flavor.Name + "X" + (flavor.Quantity - flavor.RefundQuantity)); row.Add("@数量@", string.Empty); row.Add("@单价@", flavor.Price + ""); row.Add("@小计@", flavor.Amount + ""); row.Add("@优惠@", flavor.DiscountAmount + ""); list.Add(row); //做法的合计的数据 //totalQuantity += (flavor.Quantity - flavor.RefundQuantity); totalAmount += flavor.Amount; totalDiscountAmount += flavor.DiscountAmount; } } else { foreach (var flavor in item.Flavors) { row = new Dictionary(); row.Add("@品名@", " " + flavor.Name); if (flavor.QtyFlag == 1) { row.Add("@数量@", (flavor.Quantity - flavor.RefundQuantity) + ""); } else { row.Add("@数量@", string.Empty); } if (flavor.Price != 0) { row.Add("@单价@", flavor.Price + ""); row.Add("@小计@", flavor.Amount + ""); row.Add("@优惠@", flavor.DiscountAmount + ""); } else { row.Add("@单价@", string.Empty); row.Add("@小计@", string.Empty); row.Add("@优惠@", string.Empty); } list.Add(row); //做法的合计的数据 if (flavor.QtyFlag == 1) { totalQuantity += (flavor.Quantity - flavor.RefundQuantity); } totalAmount += flavor.Amount; totalDiscountAmount += flavor.DiscountAmount; } } } //单品的合计的数据 if (item.RowState != OrderRowState.套餐明) { totalQuantity += (item.Quantity - item.RefundQuantity); totalAmount += item.Amount; totalDiscountAmount += item.DiscountAmount; } } var total = new Dictionary(); total.Add("@品名@", LangProxy.ToLang("合计")); total.Add("@数量@", totalQuantity + ""); total.Add("@单价@", ""); total.Add("@小计@", totalAmount + ""); total.Add("@优惠@", totalDiscountAmount + ""); list.Add(total); v.Value = JsonUtils.Serialize(list); vars.Add(v); v = new Printer.VariableValue(); v.Key = "支付方式列表"; v.DataType = DataType.List; list = new List>(); var malingPayMode = OrderUtils.GetMalingPayMode(); //禁止抹零打印支付列表 var notAllowMaling = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_MALING, true); foreach (var item in orderObject.Pays) { if (notAllowMaling && malingPayMode != null && malingPayMode.No.Equals(item.No)) { continue; } var row = new Dictionary(); row.Add("@支付名称@", LangProxy.ToLang(item.Name) + ""); row.Add("@支付金额@", item.Amount + ""); row.Add("@支付凭证@", item.TradeVoucherNo + ""); list.Add(row); } v.Value = JsonUtils.Serialize(list); vars.Add(v); //会员信息 var memberDic = new Dictionary(); if (!string.IsNullOrEmpty(orderObject.MemberNo)) { var cardNo = string.IsNullOrEmpty(orderObject.CardFaceNo) ? orderObject.MemberNo : orderObject.CardFaceNo; memberDic.Add("@会员号@", CardUtils.CardNoEncrypt(cardNo)); memberDic.Add("@消费前积分@", orderObject.PrePoint + ""); memberDic.Add("@本次积分@", orderObject.AddPoint + ""); memberDic.Add("@当前积分@", orderObject.AftPoint + ""); //memberDic.Add("@消费前积分@", orderObject.AddPoint + ""); } else { memberDic.Add("@是否打印会员信息@", "false"); } vars.Add(new VariableValue() { Key = "会员卡信息", DataType = DataType.Simple, Value = JsonUtils.Serialize(memberDic) }); //储值卡信息 list = new List>(); var memberPayList = orderObject.Pays.FindAll(x => x.No == "02"); if (memberPayList.Count > 0) { foreach (var item in memberPayList) { var cardNo = string.IsNullOrEmpty(item.CardFaceNo) ? item.CardNo : item.CardFaceNo; var row = new Dictionary(); row.Add("@卡号@", CardUtils.CardNoEncrypt(cardNo)); row.Add("@可用余额@", item.CardAftAmount + ""); list.Add(row); } } else { var row = new Dictionary(); row.Add("@是否打印储值卡信息@", "false"); list.Add(row); } vars.Add(new VariableValue() { Key = "储值卡列表", DataType = DataType.List, Value = JsonUtils.Serialize(list) }); //储值卡列表2 list = new List>(); var memberPayList2 = orderObject.Pays.FindAll(x => x.No == "02"); if (memberPayList2.Count > 0) { foreach (var item in memberPayList2) { var cardNo = string.IsNullOrEmpty(item.CardFaceNo) ? item.CardNo : item.CardFaceNo; var row = new Dictionary(); row.Add("@卡信息@", string.Format(LangProxy.ToLang("卡号:{0}"), CardUtils.CardNoEncrypt(cardNo))); list.Add(row); row = new Dictionary(); row.Add("@卡信息@", string.Format(LangProxy.ToLang("消费前余额:{0}"), item.CardBeforeBalance + "")); list.Add(row); row = new Dictionary(); row.Add("@卡信息@", string.Format(LangProxy.ToLang("本次消费:{0}"), item.PaidAmount + "")); list.Add(row); row = new Dictionary(); row.Add("@卡信息@", string.Format(LangProxy.ToLang("消费后余额:{0}"), item.CardAftAmount + "")); list.Add(row); } } vars.Add(new VariableValue() { Key = "储值卡列表2", DataType = DataType.List, Value = JsonUtils.Serialize(list) }); return vars; } /// /// 构建电话外卖小票的参数变量 /// /// /// public static List BuilderDeliveryTicketVariable(OrderObject orderObject) { var vars = new List(); var v = new Printer.VariableValue(); v.Key = "默认数据源"; v.DataType = DataType.Simple; var data = new Dictionary(); data.Add("@序号@", orderObject.OrderNo); data.Add("@营业模式@", orderObject.OrderType.ToString()); var tradeNo = orderObject.TradeNo; //票号长度 int length = Global.Instance.GlobalConfigIntValue(ConfigConstant.CONFIG_CASHIER_TICKETNO_LENGTH, 0); bool isRandom = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CONFIG_CASHIER_RANDOM_TICKETNO, false); if (isRandom) { tradeNo = orderObject.ObjectId; } if (length > 0 && (tradeNo.Length - length > 0)) { data.Add("@票号@", tradeNo.Substring(tradeNo.Length - length)); } else { data.Add("@票号@", tradeNo); } data.Add("@重打标识@", string.Format("{0}", orderObject.RPrint)); var storeName = string.IsNullOrEmpty(Global.Instance.Worker.StoreInfo.PrintName) ? orderObject.StoreName : Global.Instance.Worker.StoreInfo.PrintName; data.Add("@门店名称@", storeName); data.Add("@门店编码@", orderObject.StoreNo); data.Add("@门店地址@", Global.Instance.Worker.StoreInfo.Address); data.Add("@门店电话@", Global.Instance.Worker.StoreInfo.OrderTel); data.Add("@收银员编码@", orderObject.WorkerNo); data.Add("@收银员名称@", orderObject.WorkerName); data.Add("@POS编码@", orderObject.PosNo); data.Add("@桌号@", orderObject.TableName); data.Add("@单注@", ""); data.Add("@消费金额@", StringUtils.GetString(orderObject.Amount)); data.Add("@优惠金额@", StringUtils.GetString(orderObject.DiscountAmount)); data.Add("@应收金额@", StringUtils.GetString(orderObject.ReceivableAmount)); data.Add("@实收金额@", StringUtils.GetString(orderObject.ReceivedAmount - orderObject.MalingAmount)); data.Add("@找零金额@", StringUtils.GetString(orderObject.ChangeAmount)); data.Add("@抹零金额@", StringUtils.GetString(orderObject.MalingAmount)); data.Add("@打印时间@", orderObject.FinishDate); data.Add("@条码内容@", orderObject.TradeNo); data.Add("@条码说明@", orderObject.TradeNo); data.Add("@二维码内容@", orderObject.TradeNo); data.Add("@二维码说明@", orderObject.TradeNo); var notAllowTitle = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_TITLE, false); data.Add("@是否打印标题@", (!notAllowTitle).ToString().ToLower()); var allowOrderNo = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_ORDERNO, false); data.Add("@是否打印序号@", allowOrderNo.ToString().ToLower()); var notAllowStoreAddress = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_STORE_ADDRESS, false); data.Add("@是否打印地址@", (!notAllowStoreAddress).ToString().ToLower()); var notAllowStoreTelphone = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_STORE_TELPHONE, false); data.Add("@是否打印电话@", (!notAllowStoreTelphone).ToString().ToLower()); data.Add("@是否票头图片@", "false"); data.Add("@是否票尾图片@", "false"); var allowBarCodeBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_BARCODE, false); data.Add("@是否打印条码@", allowBarCodeBitmap.ToString().ToLower()); var allowQRCodeBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_QRCODE, false); data.Add("@是否打印二维码@", allowQRCodeBitmap.ToString().ToLower()); v.Value = JsonUtils.Serialize(data); vars.Add(v); v = new Printer.VariableValue(); v.Key = "点单列表"; v.DataType = DataType.List; var list = new List>(); decimal totalQuantity = 0; decimal totalAmount = 0; decimal totalDiscountAmount = 0; //排序,避免显示列表和打印列表不一致 var items = orderObject.Items.OrderBy(x => x.OrderNo); foreach (var item in items) { var row = new Dictionary(); //判断参数配置中是否定义显示简称 var showShortName = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_SHORTNAME, false); //销售界面名称的显示 string showName = (showShortName && !string.IsNullOrEmpty(item.ShortName)) ? item.ShortName : item.Name; //是否打印规格 var notAllowSepc = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_SPEC, false); //规格名称 string specName = (notAllowSepc || string.IsNullOrEmpty(item.SpecName)) ? "" : Global.Instance.Additional.Item1 + item.SpecName + Global.Instance.Additional.Item2; //附加规格到名称中 string displayName = showName + specName; if (item.RowState == OrderRowState.套餐明) { displayName = " " + displayName; } if (item.RowState == OrderRowState.普通 || item.RowState == OrderRowState.套餐主) { if (item.Promotions != null) { //禁止收银前台赠送 bool notAllowShowGive = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_NOT_ALLOW_SHOW_GIVE, true); if (!notAllowShowGive && item.Promotions.Exists(x => x.PromotionType == PromotionType.赠送)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("赠") + Global.Instance.Additional.Item2 + displayName; } //禁止收银前台折扣 bool notAllowShowDiscount = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_NOT_ALLOW_SHOW_DISCOUNT, true); if (!notAllowShowDiscount && item.Promotions.Exists(x => x.PromotionType == PromotionType.折扣 || x.PromotionType == PromotionType.整单折扣)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("折") + Global.Instance.Additional.Item2 + displayName; } //禁止收银前台议价 bool notAllowShowBargain = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_NOT_ALLOW_SHOW_BARGAIN, true); if (!notAllowShowBargain && item.Promotions.Exists(x => x.PromotionType == PromotionType.议价 || x.PromotionType == PromotionType.整单议价)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("议") + Global.Instance.Additional.Item2 + displayName; } //双数特价 if (item.Promotions.Exists(x => x.PromotionType == PromotionType.双数特价优惠 || x.PromotionType == PromotionType.双数特价赠送)) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("双") + Global.Instance.Additional.Item2 + displayName; } } } row.Add("@品名@", displayName); row.Add("@数量@", (item.Quantity - item.RefundQuantity) + ""); //列表是否显示折后价 bool showDiscountPrice = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_DISCOUNTPRICE, false); decimal _salePrice = item.Price; if (showDiscountPrice) { _salePrice = item.DiscountPrice; } decimal _amount = item.Amount; if (showDiscountPrice) { _amount = item.Amount - item.DiscountAmount; } if (item.RowState == OrderRowState.套餐明) { row.Add("@单价@", ""); row.Add("@小计@", ""); row.Add("@优惠@", ""); } else { row.Add("@单价@", _salePrice + ""); row.Add("@小计@", _amount + ""); row.Add("@优惠@", item.DiscountAmount + ""); } list.Add(row); //禁止打印做法 var notAllowFlavor = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_FLAVOR, false); //允许打印做法或者做法包含加价 if (!notAllowFlavor || item.Flavors.Count > 0) { foreach (var flavor in item.Flavors) { row = new Dictionary(); row.Add("@品名@", " " + flavor.Name); row.Add("@数量@", (flavor.Quantity - flavor.RefundQuantity) + ""); if (flavor.Price != 0) { row.Add("@单价@", flavor.Price + ""); row.Add("@小计@", flavor.Amount + ""); row.Add("@优惠@", flavor.DiscountAmount + ""); } else { row.Add("@单价@", string.Empty); row.Add("@小计@", string.Empty); row.Add("@优惠@", string.Empty); } list.Add(row); //做法的合计的数据 totalQuantity += (flavor.Quantity - flavor.RefundQuantity); totalAmount += flavor.Amount; totalDiscountAmount += flavor.DiscountAmount; } } //单品的合计的数据 if (item.RowState != OrderRowState.套餐明) { totalQuantity += (item.Quantity - item.RefundQuantity); totalAmount += item.Amount; totalDiscountAmount += item.DiscountAmount; } } var total = new Dictionary(); total.Add("@品名@", "合计"); total.Add("@数量@", totalQuantity + ""); total.Add("@单价@", ""); total.Add("@小计@", totalAmount + ""); total.Add("@优惠@", totalDiscountAmount + ""); list.Add(total); v.Value = JsonUtils.Serialize(list); vars.Add(v); if (orderObject.Delivery != null) { v = new Printer.VariableValue(); v.Key = "外送信息"; v.DataType = DataType.Simple; var delivery = new Dictionary(); delivery.Add("@订餐人称呼@", orderObject.Delivery.Customer); delivery.Add("@订餐人电话@", orderObject.Delivery.Telephone); delivery.Add("@订餐人地址@", orderObject.Delivery.Address); delivery.Add("@外送描述@", orderObject.Delivery.Description); v.Value = JsonUtils.Serialize(delivery); vars.Add(v); } return vars; } /// /// 获取系统配置的厨打打印机 /// /// public static PrinterObject GetKitchenPrinterObject(PrinterItem printer, bool cutPager) { var pobject = new PrinterObject(); pobject.Id = printer.Id; pobject.Name = printer.Name; pobject.PortType = (PortType)Enum.Parse(typeof(PortType), printer.Port); pobject.DynamicLibrary = (DynamicLibrary)Enum.Parse(typeof(DynamicLibrary), printer.DynamicLibrary); pobject.PageWidth = printer.PageWidth; pobject.CutPager = cutPager; pobject.OpenCashbox = false; pobject.Data[PrinterObject.COM_PORT_NAME] = printer.Data[Constant.COM_PORT_NAME]; pobject.Data[PrinterObject.COM_PORT_BAUD] = printer.Data[Constant.COM_PORT_BAUD]; pobject.Data[PrinterObject.LPT_NAME] = printer.Data[Constant.LPT_NAME]; pobject.Data[PrinterObject.DRIVE_NAME] = printer.Data[Constant.DRIVE_NAME]; pobject.Data[PrinterObject.NET_IP_ADDRESS] = printer.Data[Constant.NET_IP_ADDRESS]; pobject.Data[PrinterObject.USB_PID] = printer.Data[Constant.USB_PID]; pobject.Data[PrinterObject.USB_VID] = printer.Data[Constant.USB_VID]; pobject.EscPosCommand.InitCommand = printer.InitCommand; pobject.EscPosCommand.NormalCommand = printer.NormalCommand; pobject.EscPosCommand.DoubleHeightCommand = printer.DoubleHeightCommand; pobject.EscPosCommand.DoubleWidthCommand = printer.DoubleWidthCommand; pobject.EscPosCommand.DoubleWidthHeightCommand = printer.DoubleWidthHeightCommand; pobject.EscPosCommand.CutPageCommand = printer.CutPageCommand; pobject.EscPosCommand.CashboxCommand = printer.CashboxCommand; pobject.EscPosCommand.AlignCenterCommand = printer.AlignCenterCommand; pobject.EscPosCommand.AlignLeftCommand = printer.AlignLeftCommand; pobject.EscPosCommand.AlignRightCommand = printer.AlignRightCommand; return pobject; } /// /// 收银小票打印 /// /// /// /// /// /// /// /// /// public static Tuple PrinterTicket(string prefix, List args, bool cutPager, bool openCashbox, int headerLine, int footerLine) { var sw = new System.Diagnostics.Stopwatch(); sw.Start(); Tuple result = new Tuple(false, "小票打印异常"); try { var pobject = GetTicketPrinterObject(cutPager, openCashbox); if ("None".Equals(pobject.Name)) { logger.Warn("收银参数设置不启用小票打印"); result = new Tuple(false, "不启用小票打印"); return result; } string fileName = string.Format(@"template\printer\{0}_{1}_{2}.designer", prefix, Global.Instance.Authc.TenantId, pobject.PageWidth); string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); if (!File.Exists(filePath)) { fileName = string.Format(@"template\printer\{0}_通用模版_{1}.designer", prefix, pobject.PageWidth); } string template = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); if (File.Exists(template)) { string json = System.IO.File.ReadAllText(template); DesignerSurface surface = JSON.Deserialize(json); if (pobject.PortType == PortType.驱动 && pobject.Name.Contains("针式驱动打印")) { WinPrint.Print(pobject.Data.FirstOrDefault(f => f.Key == "drive").Value, surface, args); result = new Tuple(true, ""); } else { PrinterTemplate printer = surface.Parse(args); var pcontent = printer.Parse(pobject, args, headerLine, footerLine); result = PrinterUtils.PrintContent(pobject, pcontent); } } else { result = new Tuple(false, "打印模版没有配置"); } } catch (Exception ex) { result = new Tuple(false, "打印异常了"); } finally { sw.Stop(); logger.Info("收银小票打印耗时<{0}>", sw.ElapsedMilliseconds); } return result; } public static Tuple PrinterTicket(string prefix, List args, bool cutPager, bool openCashbox) { return PrinterTicket(prefix, args, cutPager, openCashbox, 0, 0); } public static Tuple> BuilderKitchenVariable(OrderObject orderObject, List items, KitchenPrinterItem printer, bool isChuda) { var vars = new List(); var v = new Printer.VariableValue(); v.Key = "默认数据源"; v.DataType = DataType.Simple; var data = new Dictionary(); if (Global.Instance.IsStudyMode() && string.IsNullOrEmpty(orderObject.OrderNo)) { data.Add("@序号@", Constant.STUDYMODE_DEFAULT_ORDERNO); } else { data.Add("@序号@", orderObject.OrderNo); } data.Add("@是否打印订单备注@", string.IsNullOrEmpty(orderObject.Ext1) ? "false" : "true"); data.Add("@订单备注@", string.IsNullOrEmpty(orderObject.Ext1) ? "" : orderObject.Ext1); //Yao 2023-06-23 增加微信点餐 中的微信堂食和微信外带 //orderObject.OrderNo = "D203"; logger.Info("当前序号:{0}|{1}", orderObject.OrderNo, orderObject.OrderType); //if (orderObject.OrderType == OrderType.微信点餐) //{ //if (orderObject.OrderNo[0] == 'T') // data.Add("@营业模式@", "微信堂食"); //微信堂食 // else if (orderObject.OrderNo[0] == 'D') // data.Add("@营业模式@", "微信外带"); //微信外带 // else data.Add("@营业模式@", LangProxy.ToLang(orderObject.OrderType.ToString())); if (printer.Length > 0) { var str = orderObject.TradeNo; if (str.Length < printer.Length) { str = str.PadLeft(printer.Length, '0'); } data.Add("@票号@", str.Substring(str.Length - printer.Length)); } else { data.Add("@票号@", orderObject.TradeNo); } var storeName = string.IsNullOrEmpty(Global.Instance.Worker.StoreInfo.PrintName) ? orderObject.StoreName : Global.Instance.Worker.StoreInfo.PrintName; data.Add("@门店名称@", storeName); data.Add("@门店编码@", orderObject.StoreNo); data.Add("@门店地址@", Global.Instance.Worker.StoreInfo.Address); data.Add("@门店电话@", Global.Instance.Worker.StoreInfo.OrderTel); data.Add("@收银员编码@", orderObject.WorkerNo); data.Add("@收银员名称@", orderObject.WorkerName); data.Add("@POS编码@", orderObject.PosNo); data.Add("@桌号@", orderObject.TableName); data.Add("@打印时间@", orderObject.FinishDate); data.Add("@重打标识@", string.Format("{0}", orderObject.RPrint)); data.Add("@方案名称@", orderObject.Ext3); //zhangy 2020-05-09 Add 厨打添加订餐人和手机号 data.Add("@订餐人@", string.IsNullOrEmpty(orderObject.Ext2) ? "" : orderObject.Ext2); if (orderObject.OrderStatus == OrderStatus.已取消 || orderObject.OrderStatus == OrderStatus.已退单) { data.Add("@是否打印退单标识@", "true"); data.Add("@退单@", "已退单"); } else { data.Add("@是否打印退单标识@", "false"); data.Add("@退单@", "已退单"); } decimal totalAmount = 0.00M; foreach (OrderItem orderItem in items) { totalAmount += orderItem.TotalReceivableAmount; } data.Add("@总金额@", string.Format("{0}", totalAmount)); if (orderObject.OrderStatus == OrderStatus.已退单) { data.Add("@退单标识@", "true"); } else { data.Add("@退单标识@", "false"); } v.Value = JsonUtils.Serialize(data); vars.Add(v); v = new Printer.VariableValue(); v.Key = "点单列表"; v.DataType = DataType.List; //练习模式 string studyName = string.Empty; if (Global.Instance.IsStudyMode()) { studyName = Constant.STUDYMODE_PRINTSTR; } var list = new List>(); int seq = 1; foreach (var item in items) { var seqStr = seq + "."; var row = new Dictionary(); //判断参数配置中是否定义显示简称 var showShortName = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_SHORTNAME, false); //销售界面名称的显示 string showName = (showShortName && !string.IsNullOrEmpty(item.ShortName)) ? item.ShortName : item.Name; //是否打印规格 var notAllowSepc = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_SPEC, false); //规格名称 string specName = (notAllowSepc || string.IsNullOrEmpty(item.SpecName)) ? "" : Global.Instance.Additional.Item1 + item.SpecName + Global.Instance.Additional.Item2; //附加规格到名称中 string displayName = showName + specName; if (item.RowState == OrderRowState.套餐明) { displayName = Global.Instance.Additional.Item1 + LangProxy.ToLang("套") + Global.Instance.Additional.Item2 + displayName; } row.Add("@品名@", studyName + displayName); decimal quantity = 0.00M; if (isChuda) { //厨打 if (orderObject.OrderStatus == OrderStatus.已退单) { quantity = 0 - item.RefundQuantity; } else { if (orderObject.RPrint) { //重打 quantity = item.Quantity; } else { if (item.Quantity > item.ChudaQty) { quantity = item.Quantity - item.ChudaQty; } else { continue; } } } } else { //出品 if (orderObject.OrderStatus == OrderStatus.已退单) { quantity = 0 - item.RefundQuantity; } else { if (orderObject.RPrint) { //重打 quantity = item.Quantity; } else { if (item.Quantity > item.ChupinQty) { quantity = item.Quantity - item.ChupinQty; } else { continue; } } } } row.Add("@数量@", quantity + ""); row.Add("@单位@", item.ProductUnitName == null ? "" : item.ProductUnitName); //列表是否显示折后价 bool showDiscountPrice = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_DISCOUNTPRICE, false); decimal _salePrice = item.Price; if (showDiscountPrice) { _salePrice = item.DiscountPrice; } decimal _amount = item.Amount; if (showDiscountPrice) { _amount = item.Amount - item.DiscountAmount; } if (item.RowState == OrderRowState.套餐明) { row.Add("@序号@", seqStr); row.Add("@单价@", ""); row.Add("@小计@", ""); row.Add("@优惠@", ""); } else { row.Add("@序号@", seqStr); row.Add("@单价@", _salePrice + ""); row.Add("@小计@", _amount + ""); row.Add("@优惠@", item.DiscountAmount + ""); } list.Add(row); //打印做法 if (item.Flavors.Count > 0) { foreach (var flavor in item.Flavors.Where(f => !f.Description.Equals("打包费") && !f.Description.Equals("配送费") && !f.Description.Equals("商家优惠"))) { row = new Dictionary(); row.Add("@序号@", ""); row.Add("@品名@", " " + flavor.Name); row.Add("@数量@", (flavor.Quantity - flavor.RefundQuantity) + ""); row.Add("@单位@", ""); if (flavor.Price != 0) { row.Add("@单价@", flavor.Price + ""); row.Add("@小计@", flavor.Amount + ""); row.Add("@优惠@", flavor.DiscountAmount + ""); } else { row.Add("@单价@", string.Empty); row.Add("@小计@", string.Empty); row.Add("@优惠@", string.Empty); } list.Add(row); } } seq++; } if (list.Count > 0) { v.Value = JsonUtils.Serialize(list); vars.Add(v); return new Tuple>(true, vars); } else { return new Tuple>(false, null); } } public static List BuilderKitchenVariable(OrderObject orderObject) { var vars = new List(); var v = new Printer.VariableValue(); v.Key = "默认数据源"; v.DataType = DataType.Simple; var data = new Dictionary(); data.Add("@序号@", orderObject.OrderNo); //Yao 2023-06-23 增加微信点餐 中的微信堂食和微信外带 logger.Info("当前序号:{0}", orderObject.OrderNo); //if (orderObject.OrderNo[0] == 'T') // data.Add("@营业模式@", "微信堂食"); //微信堂食 //else if (orderObject.OrderNo[0] == 'D') // data.Add("@营业模式@", "微信外带"); //微信外带 //else //data.Add("@营业模式@", LangProxy.ToLang(orderObject.OrderType.ToString())); data.Add("@票号@", orderObject.TradeNo); var storeName = string.IsNullOrEmpty(Global.Instance.Worker.StoreInfo.PrintName) ? orderObject.StoreName : Global.Instance.Worker.StoreInfo.PrintName; data.Add("@门店名称@", storeName); data.Add("@门店编码@", orderObject.StoreNo); data.Add("@门店地址@", Global.Instance.Worker.StoreInfo.Address); data.Add("@门店电话@", Global.Instance.Worker.StoreInfo.OrderTel); data.Add("@收银员编码@", orderObject.WorkerNo); data.Add("@收银员名称@", orderObject.WorkerName); data.Add("@POS编码@", orderObject.PosNo); data.Add("@桌号@", orderObject.TableName); data.Add("@打印时间@", orderObject.SaleDate); data.Add("@条码内容@", orderObject.TradeNo); data.Add("@条码说明@", orderObject.TradeNo); data.Add("@二维码内容@", orderObject.TradeNo); data.Add("@二维码说明@", orderObject.TradeNo); data.Add("@票头图片@", orderObject.TradeNo); data.Add("@票尾图片@", orderObject.TradeNo); var notAllowTitle = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_TITLE, false); data.Add("@是否打印标题@", (!notAllowTitle).ToString().ToLower()); var allowOrderNo = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_ORDERNO, false); data.Add("@是否打印序号@", allowOrderNo.ToString().ToLower()); var notAllowStoreAddress = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_STORE_ADDRESS, false); data.Add("@是否打印地址@", (!notAllowStoreAddress).ToString().ToLower()); var notAllowStoreTelphone = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_STORE_TELPHONE, false); data.Add("@是否打印电话@", (!notAllowStoreTelphone).ToString().ToLower()); var allowHeaderBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_HEADER_BITMAP, false); data.Add("@是否票头图片@", allowHeaderBitmap.ToString().ToLower()); var allowFooterBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_FOOTER_BITMAP, false); data.Add("@是否票尾图片@", allowFooterBitmap.ToString().ToLower()); var allowBarCodeBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_BARCODE, false); data.Add("@是否打印条码@", allowBarCodeBitmap.ToString().ToLower()); var allowQRCodeBitmap = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_ALLOW_QRCODE, false); data.Add("@是否打印二维码@", allowQRCodeBitmap.ToString().ToLower()); v.Value = JsonUtils.Serialize(data); vars.Add(v); v = new Printer.VariableValue(); v.Key = "点单列表"; v.DataType = DataType.List; var list = new List>(); decimal totalQuantity = 0; decimal totalAmount = 0; decimal totalDiscountAmount = 0; foreach (var item in orderObject.Items) { var row = new Dictionary(); //判断参数配置中是否定义显示简称 var showShortName = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_SHORTNAME, false); //销售界面名称的显示 string showName = (showShortName && !string.IsNullOrEmpty(item.ShortName)) ? item.ShortName : item.Name; //是否打印规格 var notAllowSepc = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_SPEC, false); //规格名称 string specName = (notAllowSepc || string.IsNullOrEmpty(item.SpecName)) ? "" : Global.Instance.Additional.Item1 + item.SpecName + Global.Instance.Additional.Item2; //附加规格到名称中 string displayName = showName + specName; if (item.RowState == OrderRowState.套餐明) { displayName = Global.Instance.Additional.Item1 + "套" + Global.Instance.Additional.Item2 + displayName; } row.Add("@品名@", displayName); row.Add("@数量@", (item.Quantity - item.RefundQuantity) + ""); //列表是否显示折后价 bool showDiscountPrice = Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_SHOW_DISCOUNTPRICE, false); decimal _salePrice = item.Price; if (showDiscountPrice) { _salePrice = item.DiscountPrice; } decimal _amount = item.Amount; if (showDiscountPrice) { _amount = item.Amount - item.DiscountAmount; } row.Add("@单价@", _salePrice + ""); row.Add("@小计@", _amount + ""); row.Add("@优惠@", item.DiscountAmount + ""); list.Add(row); //禁止打印做法 var notAllowFlavor = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_CASHIER_NOT_ALLOW_FLAVOR, false); //允许打印做法或者做法包含加价 if (!notAllowFlavor || item.Flavors.Count > 0) { foreach (var flavor in item.Flavors) { row = new Dictionary(); row.Add("@品名@", " " + flavor.Name); row.Add("@数量@", (flavor.Quantity - flavor.RefundQuantity) + ""); row.Add("@单价@", flavor.Price + ""); row.Add("@小计@", flavor.Amount + ""); row.Add("@优惠@", flavor.DiscountAmount + ""); list.Add(row); //做法的合计的数据 totalQuantity += (flavor.Quantity - flavor.RefundQuantity); totalAmount += flavor.Amount; totalDiscountAmount += flavor.DiscountAmount; } } //单品的合计的数据 totalQuantity += (item.Quantity - item.RefundQuantity); totalAmount += item.Amount; totalDiscountAmount += item.DiscountAmount; } var total = new Dictionary(); total.Add("@品名@", "合计"); total.Add("@数量@", totalQuantity + ""); total.Add("@单价@", ""); total.Add("@小计@", totalAmount + ""); total.Add("@优惠@", totalDiscountAmount + ""); list.Add(total); v.Value = JsonUtils.Serialize(list); vars.Add(v); return vars; } /// /// 厨打单打印 /// /// /// /// /// public static Tuple PrinterKitchen(KitchenPrinterItem kpi, string prefix, List args, bool cutPager, int headerLine, int footerLine) { var sw = new System.Diagnostics.Stopwatch(); sw.Start(); Tuple result = null; try { var pobject = GetKitchenPrinterObject(kpi.PrinterItem, cutPager); var beep = Global.Instance.GlobalConfigBoolValue(ConfigConstant.PERIPHERAL_KITCHEN_ALLOW_BEEP_CHUDA, false); //厨房单蜂鸣 pobject.Beep = beep; if ("None".Equals(pobject.Name)) { logger.Warn("没有配置厨打方案对应的打印机"); result = new Tuple(false, "厨打方案打印机未配置"); return result; } string fileName = string.Format(@"template\printer\{0}_{1}_{2}.designer", prefix, Global.Instance.Authc.TenantId, pobject.PageWidth); string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); if (!File.Exists(filePath)) { fileName = string.Format(@"template\printer\{0}_通用模版_{1}.designer", prefix, pobject.PageWidth); } string template = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); if (File.Exists(template)) { string json = System.IO.File.ReadAllText(template); DesignerSurface surface = JSON.Deserialize(json); PrinterTemplate printer = surface.Parse(args); var pcontent = printer.Parse(pobject, args); if (pobject.PortType == PortType.驱动 && pobject.Name.Contains("针式驱动打印")) { WinPrint.Print(pobject.Data.FirstOrDefault(f => f.Key == "drive").Value, surface, args); result = new Tuple(true, ""); } else { if (pcontent != null) { for (int i = 0; i < headerLine; i++) { var _header = new PrintContent(); _header.Format = RowFormat.Line; _header.Content = new StringBuilder(); _header.AlignStyle = AlignStyle.居左; _header.FontStyle = FontStyle.正常字体; _header.BitmapFile = string.Empty; pcontent.Insert(0, _header); } for (int i = 0; i < footerLine; i++) { var _footer = new PrintContent(); _footer.Format = RowFormat.Line; _footer.Content = new StringBuilder(); _footer.AlignStyle = AlignStyle.居左; _footer.FontStyle = FontStyle.正常字体; _footer.BitmapFile = string.Empty; pcontent.Add(_footer); } } result = PrinterUtils.PrintContent(pobject, pcontent); } } else { result = new Tuple(false, "厨打模版没有配置"); } } catch (Exception ex) { logger.Error(ex, "厨打异常"); result = new Tuple(false, "打印异常了"); } finally { sw.Stop(); logger.Info("厨打耗时<{0}>", sw.ElapsedMilliseconds); } return result; } public static List BuilderMemberRegisterVariable(string storeNo, string storeName, string workerNo, string workerName, string posNo, MemberInfoQueryResponse member) { var vars = new List(); var v = new Printer.VariableValue(); v.Key = "默认数据源"; v.DataType = DataType.Simple; var data = new Dictionary(); data.Add("@门店名称@", storeName); data.Add("@门店编码@", storeNo); data.Add("@收银员编码@", workerNo); data.Add("@收银员名称@", workerName); data.Add("@POS编码@", posNo); if (member.CardList != null && member.CardList.Count > 0) { var card = member.CardList[0]; //string cardNo = card.CardNo; //if (!string.IsNullOrEmpty(card.FaceNo)) //{ // cardNo = card.FaceNo; //} data.Add("@会员卡号@", card.CardNo); data.Add("@卡类型@", card.CardTypeName); } else { data.Add("@会员卡号@", ""); data.Add("@卡类型@", ""); } data.Add("@手机号码@", member.Mobile); data.Add("@打印时间@", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); data.Add("@会员姓名@", member.Name); data.Add("@会员类型@", member.MemberTypeName); data.Add("@备注@", member.Description); v.Value = JsonUtils.Serialize(data); vars.Add(v); return vars; } public static Tuple PrinterMemberRegister(string prefix, List args, bool cutPager) { var sw = new System.Diagnostics.Stopwatch(); sw.Start(); Tuple result = null; try { //采用收银打印机 var pobject = GetTicketPrinterObject(cutPager, false); if ("None".Equals(pobject.Name)) { logger.Warn("收银参数设置不启用会员登记打印"); result = new Tuple(false, "不启用会员登记打印"); return result; } string fileName = string.Format(@"template\printer\{0}_{1}_{2}.designer", prefix, Global.Instance.Authc.TenantId, pobject.PageWidth); string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); if (!File.Exists(filePath)) { fileName = string.Format(@"template\printer\{0}_通用模版_{1}.designer", prefix, pobject.PageWidth); } string template = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName); if (File.Exists(template)) { string json = System.IO.File.ReadAllText(template); DesignerSurface surface = JSON.Deserialize(json); PrinterTemplate printer = surface.Parse(args); var pcontent = printer.Parse(pobject, args); result = PrinterUtils.PrintContent(pobject, pcontent); } else { result = new Tuple(false, "会员登记模版没有配置"); } } catch (Exception ex) { result = new Tuple(false, "打印异常了"); } finally { sw.Stop(); logger.Info("会员登记小票打印耗时<{0}>", sw.ElapsedMilliseconds); } return result; } /// /// 开钱箱 /// /// public static Tuple OpenCashBox() { Tuple result = null; var pobject = GetTicketPrinterObject(false, true); if ("None".Equals(pobject.Name)) { logger.Warn("收银参数未设置小票打印机,无法开钱箱"); result = new Tuple(false, "未配置打印机,无法开钱箱"); return result; } logger.Info("工号[{0}]手动打开钱箱", Global.Instance.Worker.No); var content = new List(); PrinterTemplate printer = new PrinterTemplate(); content.Add(printer.OpenCashbox(pobject)); //启动新任务 Task.Factory.StartNew(() => { PrinterUtils.PrintContent(pobject, content); }); return new Tuple(true, "执行开钱箱成功!"); } } }