From 45fbdd514efc6e08e3f71bdf66ad77d4ced591ad Mon Sep 17 00:00:00 2001 From: wangw <1594593906@qq.com> Date: Wed, 15 Apr 2026 18:17:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=8D=B0=20=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/HandoverRecordController.java | 6 +- .../admin/PrintMachineController.java | 25 +- .../main/java/com/czg/mq/PrintMqListener.java | 27 +- .../java/com/czg/config/RabbitConfig.java | 22 +- .../java/com/czg/config/RabbitConstants.java | 5 +- .../java/com/czg/config/RabbitPublisher.java | 55 +- .../main/java/com/czg/config/RedisCst.java | 39 +- .../com/czg/account/entity/PrintMachine.java | 134 +-- .../service/HandoverRecordService.java | 8 +- .../account/service/PrintMachineService.java | 10 +- .../com/czg/order/dto/OrderInfoPrintDTO.java | 3 - .../order/service/OrderInfoRpcService.java | 4 +- .../java/com/czg/print/DayReportPrintDTO.java | 158 ++++ .../java/com/czg/print/OrderPrintDTO.java | 44 + .../com/czg/print/ProductReportPrintDTO.java | 94 ++ .../java/com/czg/print/RechargePrintDTO.java | 44 + .../com/czg/print/StockCheckPrintDTO.java | 87 ++ .../java/com/czg/print/StockPrintDTO.java | 101 +++ .../product/param/ConsCheckStockParam.java | 3 + .../param/ConsInOutStockHeadParam.java | 5 + .../service/impl/CallTableServiceImpl.java | 3 +- .../impl/HandoverRecordServiceImpl.java | 9 +- .../service/impl/PrintMachineServiceImpl.java | 32 +- .../czg/service/order/print/FeiPrinter.java | 138 +-- .../czg/service/order/print/PrintConfig.java | 52 +- .../service/order/print/PrinterHandler.java | 825 ++++++++---------- .../czg/service/order/print/PrinterImpl.java | 779 ++++++++++------- .../czg/service/order/print/YxyPrinter.java | 243 ++++-- .../impl/OrderInfoCustomServiceImpl.java | 7 +- .../service/impl/OrderInfoRpcServiceImpl.java | 9 +- .../service/impl/OrderPayServiceImpl.java | 17 +- .../impl/PrintMachineLogServiceImpl.java | 8 +- .../impl/ConsStockFlowServiceImpl.java | 46 +- 33 files changed, 1887 insertions(+), 1155 deletions(-) create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/print/DayReportPrintDTO.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/print/OrderPrintDTO.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/print/ProductReportPrintDTO.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/print/RechargePrintDTO.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/print/StockCheckPrintDTO.java create mode 100644 cash-common/cash-common-service/src/main/java/com/czg/print/StockPrintDTO.java diff --git a/cash-api/account-server/src/main/java/com/czg/controller/admin/HandoverRecordController.java b/cash-api/account-server/src/main/java/com/czg/controller/admin/HandoverRecordController.java index be6615d29..c9a9bf65f 100644 --- a/cash-api/account-server/src/main/java/com/czg/controller/admin/HandoverRecordController.java +++ b/cash-api/account-server/src/main/java/com/czg/controller/admin/HandoverRecordController.java @@ -102,8 +102,8 @@ public class HandoverRecordController { @OperationLog("收银机-交班/关班") @SaAdminCheckPermission(parentName = "交班记录", value = "handoverRecord:handover", name = "收银机-交班/关班") public CzgResult handover(@RequestParam Integer isPrint) { - Long id = handoverRecordService.handover(); - handoverRecordService.printHandoverReceipt(id, isPrint); - return CzgResult.success(id); + HandoverRecord handoverRecord = handoverRecordService.handover(); + handoverRecordService.printHandoverReceipt(handoverRecord, isPrint); + return CzgResult.success(handoverRecord.getId()); } } diff --git a/cash-api/account-server/src/main/java/com/czg/controller/admin/PrintMachineController.java b/cash-api/account-server/src/main/java/com/czg/controller/admin/PrintMachineController.java index c7eafb8b7..05357909a 100644 --- a/cash-api/account-server/src/main/java/com/czg/controller/admin/PrintMachineController.java +++ b/cash-api/account-server/src/main/java/com/czg/controller/admin/PrintMachineController.java @@ -1,11 +1,7 @@ package com.czg.controller.admin; import cn.hutool.core.util.StrUtil; -import com.alibaba.fastjson2.JSONArray; -import com.czg.account.dto.print.PrinterAddDTO; import com.czg.account.dto.print.PrinterDelDTO; -import com.czg.account.dto.print.PrinterEditDTO; -import com.czg.account.dto.print.PrinterOrderDTO; import com.czg.account.entity.PrintMachine; import com.czg.account.service.PrintMachineService; import com.czg.annotation.SaAdminCheckPermission; @@ -48,15 +44,10 @@ public class PrintMachineController { } if (StrUtil.isNotBlank(subType)) { - queryWrapper.eq(PrintMachine::getSubType, subType); + queryWrapper.eq(PrintMachine::getPrintType, subType); } queryWrapper.orderBy(PrintMachine::getSort, true).orderBy(PrintMachine::getId, false); Page page = printMachineService.page(PageUtil.buildPage(), queryWrapper); - page.getRecords().forEach(item -> { - if (StrUtil.isNotBlank(item.getCategoryIds())) { - item.setCategoryList(JSONArray.parse(item.getCategoryIds())); - } - }); return CzgResult.success(page); } @@ -73,15 +64,10 @@ public class PrintMachineController { } queryWrapper.in(PrintMachine::getConnectionType, "USB", "局域网"); if (StrUtil.isNotBlank(subType)) { - queryWrapper.eq(PrintMachine::getSubType, subType); + queryWrapper.eq(PrintMachine::getPrintType, subType); } queryWrapper.orderBy(PrintMachine::getSort, true).orderBy(PrintMachine::getId, false); Page page = printMachineService.page(PageUtil.buildPage(), queryWrapper); - page.getRecords().forEach(item -> { - if (StrUtil.isNotBlank(item.getCategoryIds())) { - item.setCategoryList(JSONArray.parse(item.getCategoryIds())); - } - }); return CzgResult.success(page); } @@ -94,9 +80,6 @@ public class PrintMachineController { @GetMapping("/detail") public CzgResult detail(@RequestParam Integer id) { PrintMachine printMachine = printMachineService.getOne(new QueryWrapper().eq(PrintMachine::getId, id).eq(PrintMachine::getShopId, StpKit.USER.getShopId())); - if (printMachine != null && StrUtil.isNotBlank(printMachine.getCategoryIds())) { - printMachine.setCategoryList(JSONArray.parse(printMachine.getCategoryIds())); - } return CzgResult.success(printMachine); } @@ -107,7 +90,7 @@ public class PrintMachineController { */ @SaAdminCheckPermission(parentName = "打印机管理", value = "printer:add", name = "打印机新增") @PostMapping - public CzgResult add(@RequestBody @Validated PrinterAddDTO printerAddDTO) { + public CzgResult add(@RequestBody @Validated PrintMachine printerAddDTO) { return CzgResult.success(printMachineService.add(StpKit.USER.getShopId(), printerAddDTO)); } @@ -117,7 +100,7 @@ public class PrintMachineController { */ @SaAdminCheckPermission(parentName = "打印机管理", value = "printer:edit", name = "打印机编辑") @PutMapping - public CzgResult edit(@RequestBody @Validated PrinterEditDTO printerEditDTO) { + public CzgResult edit(@RequestBody @Validated PrintMachine printerEditDTO) { return CzgResult.success(printMachineService.edit(StpKit.USER.getShopId(), printerEditDTO)); } diff --git a/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java b/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java index bfa6f7dd1..41fa4c1e2 100644 --- a/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java +++ b/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java @@ -57,29 +57,24 @@ public class PrintMqListener { if (orderId == null) { throw new RuntimeException("订单打印失败,未传递orderId"); } + //该字段表示 网络打印机是否打印订单 本地传参来的 Boolean printOrder = jsonObject.getBoolean("printOrder"); redisService.runFunAndCheckKey(() -> { - printerHandler.orderHandler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER, null); + if (printOrder) { + printerHandler.orderHandler(orderId, PrinterHandler.PrintTypeEnum.ORDER, null); + } + //菜品打印 全是后端 + printerHandler.orderHandler(orderId, PrinterHandler.PrintTypeEnum.ONLY_KITCHEN, null); + printerHandler.orderHandler(orderId, PrinterHandler.PrintTypeEnum.ALL_KITCHEN, null); return null; }, RedisCst.getLockKey("orderPrint", orderId)); }); } - /** - * 交班打印 - */ - @RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE}) - public void handoverPrint(String id) { - invokeFun(RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE, "handoverPrint", "java.order", id, (data) -> - printerHandler.handoverHandler(data)); - } - /** - * 叫号打印 - */ - @RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.CALL_TABLE_QUEUE}) - public void callTablePrint(String id) { - invokeFun(RabbitConstants.Queue.CALL_TABLE_QUEUE, "callTable", "java.order", id, (data) -> - printerHandler.callHandler(data)); + @RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.OTHER_PRINT_QUEUE}) + public void otherPrint(Long shopId, Object o, String printTypeEnum) { + PrinterHandler.PrintTypeEnum typeEnum = PrinterHandler.PrintTypeEnum.valueOf(printTypeEnum); + printerHandler.otherHandler(shopId, o, typeEnum); } } diff --git a/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConfig.java b/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConfig.java index 5ef28b588..4f023a041 100644 --- a/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConfig.java +++ b/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConfig.java @@ -70,26 +70,16 @@ public class RabbitConfig { return BindingBuilder.bind(orderMachinePrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE); } - //------------------------------------------------------交班打票 + + //------------------------------------------------------其它打印消息打票 @Bean - public Queue handoverPrintQueue() { - return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE, true, false, false); + public Queue otherPrintQueue() { + return new Queue(activeProfile + "-" + RabbitConstants.Queue.OTHER_PRINT_QUEUE, true, false, false); } @Bean - public Binding bindingHandoverPrintExchange(Queue handoverPrintQueue, DirectExchange exchange) { - return BindingBuilder.bind(handoverPrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE); - } - - //------------------------------------------------------叫号 打票 - @Bean - public Queue callTablePrintQueue() { - return new Queue(activeProfile + "-" + RabbitConstants.Queue.CALL_TABLE_QUEUE, true, false, false); - } - - @Bean - public Binding bindingCallTablePrintExchange(Queue callTablePrintQueue, DirectExchange exchange) { - return BindingBuilder.bind(callTablePrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.CALL_TABLE_QUEUE); + public Binding bindingOtherPrintExchange(Queue otherPrintQueue, DirectExchange exchange) { + return BindingBuilder.bind(otherPrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.OTHER_PRINT_QUEUE); } //------------------------------------------------------订单取消 diff --git a/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConstants.java b/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConstants.java index 852d607aa..4e6c5b3ab 100644 --- a/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConstants.java +++ b/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitConstants.java @@ -14,10 +14,11 @@ public interface RabbitConstants { public static final String ORDER_STOCK_QUEUE = "order.stock.queue"; public static final String ORDER_REFUND_QUEUE = "order.refund.queue"; public static final String ORDER_CANCEL_QUEUE = "order.cancel.queue"; + public static final String ORDER_PRINT_QUEUE = "order.print.queue"; public static final String ORDER_MACHINE_PRINT_QUEUE = "order.machine.print.queue"; - public static final String ORDER_HANDOVER_PRINT_QUEUE = "order.handover.print.queue"; - public static final String CALL_TABLE_QUEUE = "call.table.print.queue"; + + public static final String OTHER_PRINT_QUEUE = "other.print.queue"; public static final String PRODUCT_INFO_CHANGE_QUEUE = "product.info.change.queue"; public static final String CONS_INFO_CHANGE_QUEUE = "cons.info.change.queue"; diff --git a/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitPublisher.java b/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitPublisher.java index 870254de4..7577d0a49 100644 --- a/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitPublisher.java +++ b/cash-common/cash-common-mq/src/main/java/com/czg/config/RabbitPublisher.java @@ -7,6 +7,7 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import java.util.HashMap; import java.util.Map; /** @@ -62,37 +63,19 @@ public class RabbitPublisher { sendMsg(RabbitConstants.Queue.ORDER_PRINT_QUEUE, orderId); } } + /** - * 订单打印消息 + * 厨房票打印消息 * * @param orderId 订单id * @param printOrder 是否打印结算单 */ public void sendKitchenOrderPrintMsg(String orderId, boolean printOrder, String source) { - log.info("厨房打印消息, orderId: {}, printOrder: {}, source: {}", orderId, printOrder, source); + log.info("厨房菜品单打印消息, orderId: {}, printOrder: {}, source: {}", orderId, printOrder, source); //厨房票 sendMsg(RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE, new JSONObject().fluentPut("orderId", orderId).fluentPut("printOrder", printOrder).toString()); } - /** - * 退款订单打印消息 - * - * @param orderId 订单id - */ - public void sendOrderReturnPrintMsg(String orderId) { - //厨房票 - sendMsg(RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE, new JSONObject().fluentPut("orderId", orderId).fluentPut("printOrder", true).toString()); - } - - /** - * 交班小票打印消息 - * - * @param handoverRecordId 交班记录id - */ - public void sendHandoverPrintMsg(String handoverRecordId) { - sendMsg(RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE, handoverRecordId); - } - /** * 商品信息变动消息 * @@ -111,15 +94,6 @@ public class RabbitPublisher { sendMsg(RabbitConstants.Queue.CONS_INFO_CHANGE_QUEUE, shopId); } - /** - * 排队叫号小票打印 - * - * @param id 叫号队列id - */ - public void printCallNumTicket(Long id) { - sendMsg(RabbitConstants.Queue.CALL_TABLE_QUEUE, id.toString()); - } - /** * 1,2,applySmsTemp 模版审核 shop_id,sms_shop_template.id,applySmsTemp * 1,2,sendMarkSms 发送营销短信 shop_id,sms_push_event.id,sendMarkSms @@ -172,4 +146,25 @@ public class RabbitPublisher { rabbitTemplate.convertAndSend(activeProfile + "-" + RabbitConstants.Exchange.CASH_EXCHANGE, activeProfile + "-" + queue, msg); } + /** + * 其它类型 打印消息 + * STOCK 出入库 + * DAY_REPORT 经营日报 + * PRODUCT_REPORT 商品报表 + * RECHARGE 储值单 + * STOCK_CHECK 库存盘点 + * HANDOVER 交班单 + * CALL 排队取号 + * @param printType {@link com.czg.service.order.print.PrinterHandler.PrintTypeEnum} + */ + public void sendOtherPrintMsg(Long shopId, Object data, String printType) { + String exchange = activeProfile + "-" + RabbitConstants.Exchange.CASH_EXCHANGE; + String queueName = activeProfile + "-" + RabbitConstants.Queue.OTHER_PRINT_QUEUE; + Map msg = new HashMap<>(); + msg.put("shopId", shopId); + msg.put("data", data); + msg.put("printTypeEnum", printType); + rabbitTemplate.convertAndSend(exchange, queueName, msg); + } + } diff --git a/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java b/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java index e915eb0f0..165e5632e 100644 --- a/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java +++ b/cash-common/cash-common-redis/src/main/java/com/czg/config/RedisCst.java @@ -3,6 +3,7 @@ package com.czg.config; /** * * key常量 + * * @author Administrator */ public interface RedisCst { @@ -12,7 +13,6 @@ public interface RedisCst { String SYS_LOG_KEY = "sys:log:"; - /** * key过期监听 */ @@ -50,11 +50,18 @@ public interface RedisCst { // 排队取号全局号码 String TABLE_CALL_NUMBER = "table:call:number:"; - String PRINT_ORDER_DETAIL = "print:order:detail:"; - // 点歌地址url String SONG_URL = "song:"; + class kitchen { + //后厨总单 + public static final String ALL = "print:kitchen:all"; + //菜品单 + public static final String NORMAL = "print:kitchen:normal"; + //退菜单 + public static final String REFUND_ALL = "print:kitchen:refundAll"; + } + static String getLockKey(String sign, Object... args) { StringBuilder key = new StringBuilder(LOCK_KEY + ":" + sign + ":"); @@ -70,9 +77,31 @@ public interface RedisCst { return TABLE_CALL_NUMBER + shopId + ":" + callTableId; } + /** + * 后厨总单 + * + * @param machineId 打印机设备id + */ + static String kitchenAll(Long orderId, Long machineId) { + return kitchen.ALL + orderId + ":" + machineId; + } - static String getPrintOrderDetailKey(Long orderId, Long detailId) { - return PRINT_ORDER_DETAIL + orderId + ":" + detailId; + /** + * 后厨单个菜品单 + * + * @param machineId 打印机设备id + */ + static String kitchenNormal(Long orderId, Long machineId, Long detailId) { + return kitchen.NORMAL + orderId + ":" + machineId + ":" + detailId; + } + + /** + * 后厨总单 + * + * @param machineId 打印机设备id + */ + static String kitchenRefundAll(Long orderId, Long machineId) { + return kitchen.REFUND_ALL + orderId + ":" + machineId; } static String getSongUrlKey(Long shopId) { diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/entity/PrintMachine.java b/cash-common/cash-common-service/src/main/java/com/czg/account/entity/PrintMachine.java index ff7502cb6..fac856276 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/entity/PrintMachine.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/entity/PrintMachine.java @@ -4,16 +4,15 @@ import com.mybatisflex.annotation.Column; import com.mybatisflex.annotation.Id; import com.mybatisflex.annotation.KeyType; import com.mybatisflex.annotation.Table; -import java.io.Serializable; -import java.time.LocalDateTime; - -import java.io.Serial; -import java.util.List; - import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + /** * 打印机设备 实体类。 * @@ -21,7 +20,7 @@ import lombok.NoArgsConstructor; * @since 2025-02-20 */ @Data - +@Builder @NoArgsConstructor @AllArgsConstructor @Table("tb_print_machine") @@ -30,8 +29,16 @@ public class PrintMachine implements Serializable { @Serial private static final long serialVersionUID = 1L; + /** + * 主键ID + */ @Id(keyType = KeyType.Auto) - private Integer id; + private Long id; + + /** + * 店铺Id + */ + private Long shopId; /** * 设备名称 @@ -39,12 +46,22 @@ public class PrintMachine implements Serializable { private String name; /** - * 现在打印机支持USB 和 网络、蓝牙 + * 连接方式 USB、云打印、局域网 */ private String connectionType; /** - * ip地址 + * 打印类型 label标签 cash小票 + */ + private String printType; + + /** + * 打印机品牌 飞鹅/云想印 + */ + private String brand; + + /** + * ip地址/MAC地址 */ private String address; @@ -53,46 +70,6 @@ public class PrintMachine implements Serializable { */ private String port; - /** - * 打印类型(分类)label标签cash小票kitchen出品 - */ - private String subType; - - /** - * 状态 online - */ - private Integer status; - - /** - * 店铺Id - */ - private Long shopId; - - /** - * 分类Id - */ - private String categoryIds; - - /** - * 现在打印机支持USB 和 网络两种 - */ - private String contentType; - - @Column(onInsertValue = "now()") - private LocalDateTime createTime; - - @Column(onInsertValue = "now()", onUpdateValue = "now()") - private LocalDateTime updateTime; - - /** - * 分类 - */ - private List categoryList; - - /** - * 排序 - */ - private Integer sort; /** * 小票尺寸 58mm 80mm @@ -100,31 +77,58 @@ public class PrintMachine implements Serializable { private String receiptSize; /** - * 分类打印 0-所有 1-部分分类 2-部分商品 + * 打印数量 + */ + private Integer printNum; + + /** + * 打印内容 数组 + * GUEST_ORDER("客看单"),PRE_ORDER("预结算单"),ORDER("订单结算单"),RETURN_ORDER("退菜单"),REFUND_ORDER("退款单"), + * ALL_KITCHEN("后厨整单"),ONLY_KITCHEN("后厨分单"),REFUND_KITCHEN("后厨退菜单"), + * HANDOVER("交班单"),CALL("排队取号"),RECHARGE("储值单"),STOCK("出入库单"),STOCK_CHECK("盘点单"), + * PRODUCT_REPORT("商品报表"),DAY_REPORT("经营日报"),DAY_ORDER("日结单") + */ + private String printContentType; + + /** + * 打印模式(厨房打印菜品) all整单 /only单个 + */ + private String kitchenPrintMode; + + /** + * 分类打印 0-所有 1-部分分类 */ private String classifyPrint; /** - * 打印数量 c1m1^2=顾客+商家[2张] m1^1=商家[1张] c1^1顾客[1张] c2m1^3顾客2+商家1[3张] + * 分类Id */ - private String printQty; + private String categoryIds; /** - * 打印方式 all-全部打印 normal-仅打印结账单「前台」one-仅打印制作单「厨房」 + * 0 禁用 1启用 */ - private String printMethod; + private Integer status; /** - * 打印类型,JSON数组 refund-确认退款单 handover-交班单 queue-排队取号 - */ - private String printType; - /** - * 媒体音开关 0-关 1-开 + * 媒体声音开关 0关1开 */ private Integer volumeSwitch; - /** - * 交班打印机开关 0-关 1-开 - */ - private Integer handoverSwitch; -} + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @Column(onUpdateValue = "now()") + private LocalDateTime updateTime; + + /** + * 排序 + */ + private Integer sort; +} \ No newline at end of file diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/service/HandoverRecordService.java b/cash-common/cash-common-service/src/main/java/com/czg/account/service/HandoverRecordService.java index 8fddb8204..d7ed9d6f8 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/service/HandoverRecordService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/service/HandoverRecordService.java @@ -51,14 +51,14 @@ public interface HandoverRecordService extends IService { * * @return 交班记录ID */ - Long handover(); + HandoverRecord handover(); /** * 交班打印小票 * - * @param handoverRecordId 交班记录id - * @param isPrint 是否打印 1-是 0-否 + * @param record 交班记录 + * @param isPrint 是否打印 1-是 0-否 */ - void printHandoverReceipt(Long handoverRecordId, Integer isPrint); + void printHandoverReceipt(HandoverRecord record, Integer isPrint); } \ No newline at end of file diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/service/PrintMachineService.java b/cash-common/cash-common-service/src/main/java/com/czg/account/service/PrintMachineService.java index 4e2f8023b..55f6dc2d2 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/service/PrintMachineService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/service/PrintMachineService.java @@ -1,11 +1,7 @@ package com.czg.account.service; -import com.czg.account.dto.print.PrinterAddDTO; -import com.czg.account.dto.print.PrinterEditDTO; -import com.czg.account.dto.print.PrinterOrderDTO; -import com.mybatisflex.core.paginate.Page; -import com.mybatisflex.core.service.IService; import com.czg.account.entity.PrintMachine; +import com.mybatisflex.core.service.IService; /** * 打印机设备 服务层。 @@ -15,9 +11,9 @@ import com.czg.account.entity.PrintMachine; */ public interface PrintMachineService extends IService { - boolean add(Long shopId, PrinterAddDTO printerAddDTO); + boolean add(Long shopId, PrintMachine printMachine); - Boolean edit(Long shopId, PrinterEditDTO printerEditDTO); + Boolean edit(Long shopId, PrintMachine printMachine); } diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/dto/OrderInfoPrintDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/order/dto/OrderInfoPrintDTO.java index 171c10242..50f551a48 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/order/dto/OrderInfoPrintDTO.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/order/dto/OrderInfoPrintDTO.java @@ -20,11 +20,8 @@ public class OrderInfoPrintDTO implements Serializable { @NotNull(message = "id不为空") private Long id; /** - * 0 菜品和结算单同时打印 * 1 预结算单 * 2 结算单 - * 3 退菜/退款 - * 4 交班 */ @NotNull(message = "打印类型不为空") private Integer type; diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/service/OrderInfoRpcService.java b/cash-common/cash-common-service/src/main/java/com/czg/order/service/OrderInfoRpcService.java index 91d85c2e8..73652f5db 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/order/service/OrderInfoRpcService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/order/service/OrderInfoRpcService.java @@ -40,9 +40,9 @@ public interface OrderInfoRpcService { /** * 订单交班回调 发送答应交班小票消息至MQ * - * @param handoverRecordId 交班记录id + * @param record 交班记录id */ - void sendHandoverReceiptPrintMsgToMq(Long handoverRecordId); + void sendHandoverReceiptPrintMsgToMq(Long shopId, HandoverRecord record); /** * 交班售出商品明细 diff --git a/cash-common/cash-common-service/src/main/java/com/czg/print/DayReportPrintDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/print/DayReportPrintDTO.java new file mode 100644 index 000000000..722beee3c --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/print/DayReportPrintDTO.java @@ -0,0 +1,158 @@ +package com.czg.print; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +/** + * 经营日报 + * @author Administrator + */ +@Data +@Accessors(chain = true) +public class DayReportPrintDTO { + + /** + * 店铺名称 + */ + private String shopName; + + /** + * 操作人 + */ + private String operator; + + /** + * 统计时间 + */ + private String statisticsTime; + + /** + * 退款金额 + */ + private BigDecimal refundAmount; + /** + * 退菜数量 + */ + private Long returnDishCount; + /** + * 营业额 + */ + private TurnoverSts turnover; + + /** + * 订单 + */ + private OrderSts order; + + /** + * 数据统计 + */ + private Sts sts; + + + + /** + * 营业额 类 + */ + @Data + @Accessors(chain = true) + public static class TurnoverSts { + + /** + * 营业额 + */ + private BigDecimal turnover; + + /** + * 微信支付金额 + */ + private BigDecimal wechat; + + /** + * 支付宝支付金额 + */ + private BigDecimal alipay; + + /** + * 二维码收款 + */ + private BigDecimal selfScan; + /** + * 扫码收款 + */ + private BigDecimal barScan; + + /** + * 现金收款 + */ + private BigDecimal cash; + + /** + * 充值 + */ + private BigDecimal recharge; + + /** + * 挂账 + */ + private BigDecimal owed; + + /** + * 余额支付 + */ + private BigDecimal balance; + } + + /** + * 订单 类 + */ + @Data + @Accessors(chain = true) + public static class OrderSts { + /** + * 订单金额 + */ + private BigDecimal orderAmount; + + /** + * 订单总数 + */ + private Long orderCount; + } + + + /** + * 数据统计 类 + */ + @Data + @Accessors(chain = true) + public static class Sts { + /** + * 就餐人数 + */ + private Long customerCount; + /** + * 客单价 + * 实付金额(包含现金支付 包含会员支付 包含挂账)/就餐人数 + * 没有具体人数时,默认一桌按照1人计算 + */ + private BigDecimal avgPayAmount; + /** + * 翻台率 + * (订单数-桌台数)/桌台数*100% + */ + private BigDecimal turnoverRate; + /** + * 商品成本 + */ + private BigDecimal productCostAmount; + /** + * 毛利率(订单实付金额-商品成本)/订单实付金额*100% + */ + private BigDecimal profitRate; + } + + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/print/OrderPrintDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/print/OrderPrintDTO.java new file mode 100644 index 000000000..fe4af54d8 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/print/OrderPrintDTO.java @@ -0,0 +1,44 @@ +package com.czg.print; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 订单打印实体 + * @author ww + */ +@Data +@Accessors(chain = true) +public class OrderPrintDTO { + // 打印标题 结算单/客看单/预结算单 退菜单/退款单 + private String printTitle; + private String shopName; + //打印类型 收银-堂食 + private String printType; + //台桌区域-台桌号 + private String pickupNum; + private String orderNo; + //结账时间 + private String tradeDate; + //操作人名称 + private String operator; + private String payAmount; + private String originalAmount; + private String payType; + private String remark; + //取餐码 + private String outNumber; + private String discountAmount; + private String seatNum; + private String seatAmount; + private String packFee; + // 是否退款单 + private boolean isReturn; + //退款单用 + private String refundAmount; + //退款方式 现金退款/原路退回 + private String refundType; + //退款原因 + private String refundReason; + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/print/ProductReportPrintDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/print/ProductReportPrintDTO.java new file mode 100644 index 000000000..c6603fa01 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/print/ProductReportPrintDTO.java @@ -0,0 +1,94 @@ +package com.czg.print; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * 商品报表打印实体 + * + * @author ww + */ +@Data +@Accessors(chain = true) +public class ProductReportPrintDTO { + + /** + * 店铺名称 + */ + private String shopName; + + /** + * 打印时间 + */ + private String printTime; + + /** + * 操作人 + */ + private String operator; + + /** + * 统计时间 + */ + private String statisticsTime; + + /** + * 总计商品数量 + */ + private BigDecimal totalProductCount; + + /** + * 总计实收金额 + */ + private BigDecimal totalActualAmount; + + /** + * 商品明细列表 + * 分类名称,商品集合 + */ + private Map> items; + + + public ProductItem createProductItem(String productName, BigDecimal number, BigDecimal actualAmount, BigDecimal salesAmount) { + ProductItem item = new ProductItem(); + item.setProductName(productName); + item.setNumber(number); + item.setActualAmount(actualAmount); + item.setSalesAmount(salesAmount); + return item; + } + + /** + * 商品明细项 + * + * @author ww + */ + @Data + @Accessors(chain = true) + public static class ProductItem { + + /** + * 商品名称(第二列商品名称) + */ + private String productName; + + /** + * 数量(第三列数量) + */ + private BigDecimal number; + + /** + * 实收(第四列) + */ + private BigDecimal actualAmount; + + /** + * 销售额(第五列) + */ + private BigDecimal salesAmount; + } +} \ No newline at end of file diff --git a/cash-common/cash-common-service/src/main/java/com/czg/print/RechargePrintDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/print/RechargePrintDTO.java new file mode 100644 index 000000000..ced9d5f03 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/print/RechargePrintDTO.java @@ -0,0 +1,44 @@ +package com.czg.print; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 储值单 + * @author ww + */ +@Data +@Accessors(chain = true) +public class RechargePrintDTO { + //店铺名称 + private String shopName; + private String userId; + private String userName; + private String userPhone; + //支付时间 + private LocalDateTime payTime; + + //充值金额 + private BigDecimal rechargeAmount; + //赠送金额 + private BigDecimal giftAmount; + //赠送积分 + private BigDecimal giftPoints; + //赠送优惠券 张 + private Integer giftCoupon; + //充值后余额 + private BigDecimal balance; + //已付金额 + private BigDecimal payAmount; + //支付方式 + private String payType; + //操作员 + private String operator; + //充值编号 + private String rechargeId; + + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/print/StockCheckPrintDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/print/StockCheckPrintDTO.java new file mode 100644 index 000000000..0176af79b --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/print/StockCheckPrintDTO.java @@ -0,0 +1,87 @@ +package com.czg.print; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.experimental.Accessors; +import java.math.BigDecimal; +import java.util.List; + +/** + * 盘点单打印实体 + * @author ww + */ +@Data +@Accessors(chain = true) +public class StockCheckPrintDTO { + + /** + * 店铺名称 + */ + private String shopName; + + /** + * 耗材明细列表 + */ + private List items; + + /** + * 账存数量 + */ + private Integer winLossNumberCount; + + /** + * 盈亏金额 + */ + private BigDecimal winLossAmount; + + /** + * 备注 + */ + private String remark; + + /** + * 操作员 + */ + private String operator; + + public StockCheckItem createStockCheckItem(String consName, BigDecimal price, String unit, BigDecimal actualNumber, BigDecimal winLossNumber) { + return new StockCheckItem(consName, price, unit, actualNumber, winLossNumber); + } + + + /** + * 入库耗材明细 + * + * @author ww + */ + @Data + @Accessors(chain = true) + @AllArgsConstructor + public static class StockCheckItem { + /** + * 耗材名称 + */ + private String consName; + + /** + * 单价 + */ + private BigDecimal price; + + /** + * 单位 + */ + private String unit; + + /** + * 实际数 + */ + private BigDecimal actualNumber; + + /** + * 盈亏数 + */ + private BigDecimal winLossNumber; + } +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/print/StockPrintDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/print/StockPrintDTO.java new file mode 100644 index 000000000..bf757ac88 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/print/StockPrintDTO.java @@ -0,0 +1,101 @@ +package com.czg.print; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 入库打印单 + * + * @author ww + */ +@Data +@Accessors(chain = true) +public class StockPrintDTO { + //IN OUT + private String type; + /** + * 店铺名称 + */ + private String shopName; + + /** + * 出入库时间 + */ + private LocalDateTime inStockTime; + + /** + * 出入库耗材明细列表 + */ + private List items; + + /** + * 耗材总种类数 + */ + private Integer consCount; + + /** + * 出入库总数量 + */ + private BigDecimal stockNumberCount; + + /** + * 总金额 + */ + private BigDecimal amountCount; + + /** + * 操作员 + */ + private String operator; + + /** + * 打印时间 + */ + private LocalDateTime printTime; + + + public InStockItem createInStockItem(String consName, String unit, BigDecimal stockNumber, BigDecimal amount) { + InStockItem item = new InStockItem(); + item.setConsName(consName); + item.setUnit(unit); + item.setStockNumber(stockNumber); + item.setAmount(amount); + return item; + } + + + /** + * 入库耗材明细 + * + * @author ww + */ + @Data + @Accessors(chain = true) + public static class InStockItem { + /** + * 耗材名称 + */ + private String consName; + + /** + * 库存单位 + */ + private String unit; + + /** + * 出入数量 + */ + private BigDecimal stockNumber; + + /** + * 金额 + */ + private BigDecimal amount; + } + + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsCheckStockParam.java b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsCheckStockParam.java index b02ee4640..754ea3b30 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsCheckStockParam.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsCheckStockParam.java @@ -31,6 +31,9 @@ public class ConsCheckStockParam implements Serializable { */ @NotBlank(message = "耗材名称不能为空", groups = DefaultGroup.class) private String conName; + @NotBlank(message = "操作员不能为空", groups = DefaultGroup.class) + private String operator; + /** * 账存数量 */ diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java index 50c6d80de..d00909cc4 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ConsInOutStockHeadParam.java @@ -69,4 +69,9 @@ public class ConsInOutStockHeadParam implements Serializable { * 未入库信息 */ private List unInCons; + + /** + * 操作员 + */ + private String operator; } diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java index 0ddc5e49e..a7fd4636b 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java @@ -221,7 +221,7 @@ public class CallTableServiceImpl extends ServiceImpl "已取消"; diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/HandoverRecordServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/HandoverRecordServiceImpl.java index bd6fa3b02..11e965605 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/HandoverRecordServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/HandoverRecordServiceImpl.java @@ -11,7 +11,6 @@ import com.alibaba.fastjson2.JSONWriter; import com.czg.account.dto.HandoverRecordDTO; import com.czg.account.entity.HandoverRecord; import com.czg.account.service.HandoverRecordService; -import com.czg.account.vo.HandoverCategoryListVo; import com.czg.account.vo.HandoverProductListVo; import com.czg.account.vo.HandoverTotalVo; import com.czg.constants.SystemConstants; @@ -117,20 +116,20 @@ public class HandoverRecordServiceImpl extends ServiceImpl productData = data.getDetailList(); entity.setProductData(JSON.toJSONString(productData, JSONWriter.Feature.WriteMapNullValue)); super.updateById(entity); - return entity.getId(); + return entity; } @Override - public void printHandoverReceipt(Long handoverRecordId, Integer isPrint) { + public void printHandoverReceipt(HandoverRecord record, Integer isPrint) { if (isPrint == SystemConstants.OneZero.ONE) { - orderInfoRpcService.sendHandoverReceiptPrintMsgToMq(handoverRecordId); + orderInfoRpcService.sendHandoverReceiptPrintMsgToMq(record.getShopId(), record); } } } \ No newline at end of file diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/PrintMachineServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/PrintMachineServiceImpl.java index 8eed6b5ce..159fdc152 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/PrintMachineServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/PrintMachineServiceImpl.java @@ -3,8 +3,6 @@ package com.czg.service.account.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; -import com.czg.account.dto.print.PrinterAddDTO; -import com.czg.account.dto.print.PrinterEditDTO; import com.czg.account.entity.PrintMachine; import com.czg.account.service.PrintMachineService; import com.czg.exception.CzgException; @@ -20,32 +18,36 @@ import org.apache.dubbo.config.annotation.DubboService; * @since 2025-02-20 */ @DubboService -public class PrintMachineServiceImpl extends ServiceImpl implements PrintMachineService{ +public class PrintMachineServiceImpl extends ServiceImpl implements PrintMachineService { @Override - public boolean add(Long shopId, PrinterAddDTO dto) { + public boolean add(Long shopId, PrintMachine dto) { //分类打印选择部分打印时必传,JsonArray字符串数据 如:[{"id":125,"name":"意式咖啡"},{"id":127,"name":"饮品"}] - if ("1".equals(dto.getClassifyPrint()) || "2".equals(dto.getClassifyPrint())) { - if (StrUtil.isBlank(dto.getCategoryList())) { + if ("1".equals(dto.getClassifyPrint())) { + if (StrUtil.isBlank(dto.getCategoryIds()) || dto.getCategoryIds().length() < 3) { throw new CzgException("分类打印选择部分打印时,必须勾选需要部分打印的菜品"); } - if (!JSONUtil.isTypeJSONArray(dto.getCategoryList())) { + if (!JSONUtil.isTypeJSONArray(dto.getCategoryIds())) { throw new CzgException("传递的部分打印菜品数据不合法"); } - if (StrUtil.isBlank(dto.getCategoryIds())) { - throw new CzgException("分类打印选择部分打印时,传递的部分打印菜品id数据不能为空"); - } } else { dto.setCategoryIds(null); - dto.setCategoryList(null); } - PrintMachine entity = BeanUtil.copyProperties(dto, PrintMachine.class); - entity.setShopId(shopId); - return save(entity); + return save(dto); } @Override - public Boolean edit(Long shopId, PrinterEditDTO printerEditDTO) { + public Boolean edit(Long shopId, PrintMachine printerEditDTO) { + if ("1".equals(printerEditDTO.getClassifyPrint())) { + if (StrUtil.isBlank(printerEditDTO.getCategoryIds()) || printerEditDTO.getCategoryIds().length() < 3) { + throw new CzgException("分类打印选择部分打印时,必须勾选需要部分打印的菜品"); + } + if (!JSONUtil.isTypeJSONArray(printerEditDTO.getCategoryIds())) { + throw new CzgException("传递的部分打印菜品数据不合法"); + } + } else { + printerEditDTO.setCategoryIds(null); + } PrintMachine printMachine = getOne(new QueryWrapper().eq(PrintMachine::getShopId, shopId).eq(PrintMachine::getId, printerEditDTO.getId())); if (printMachine == null) { throw new CzgException("打印机不存在"); diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java index 68ab6ebbc..ce14e31cd 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java @@ -1,18 +1,14 @@ package com.czg.service.order.print; -import cn.hutool.core.date.DateUtil; import cn.hutool.core.text.UnicodeUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.czg.account.dto.HandoverRecordDTO; import com.czg.account.entity.PrintMachine; -import com.czg.account.entity.ShopInfo; import com.czg.order.entity.OrderDetail; import com.czg.order.entity.OrderInfo; -import com.czg.service.order.enums.OrderStatusEnums; +import com.czg.print.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.http.HttpEntity; @@ -22,9 +18,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import java.math.BigDecimal; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -67,57 +61,71 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl { } @Override - protected void normalDishesPrint(String operator, OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) { - String buildDishPrintData = buildDishPrintData(false, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(), - orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent()); + protected void onlyKitchenPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) { + String buildDishPrintData = buildOnlyKitchenPrintData(getPickupNum(orderInfo), orderDetail); String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; if (1 == machine.getVolumeSwitch()) { voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; } - String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1"); - printMachineLogService.save(orderInfo.getId(), machine, "新订单", buildDishPrintData, resp); - + String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(orderInfo.getId(), machine, "后厨商品单", buildDishPrintData, resp); } @Override - protected void returnDishesPrint(String operator, OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) { - String buildDishPrintData = buildDishPrintData(true, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(), - orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent()); + public OrderPrintDTO allKitchenPrint(OrderInfo orderInfo, List orderDetails, PrintMachine machine) { + OrderPrintDTO orderPrintDTO = super.allKitchenPrint(orderInfo, orderDetails, machine); + String buildDishPrintData = buildAllKitchenPrintData(orderPrintDTO, orderDetails); String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; - String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1"); - printMachineLogService.save(orderInfo.getId(), machine, "厨房退菜", buildDishPrintData, resp); - + if (1 == machine.getVolumeSwitch()) { + voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; + } + String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(orderInfo.getId(), machine, "后厨总单", buildDishPrintData, resp); + return null; } @Override - public PrintInfoDTO returnOrderPrint(String printTitle,String operator, String refundAmount, String refundReason, String refundType, - OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.returnOrderPrint(printTitle,operator, refundAmount, refundReason, refundType, orderInfo, machine, detailList); - String data = buildRefundOrderPrintData(printInfoDTO, detailList); + public OrderPrintDTO returnKitchenPrint(String operator, OrderInfo orderInfo, List orderDetail, PrintMachine machine) { + OrderPrintDTO orderPrintDTO = super.returnKitchenPrint(operator, orderInfo, orderDetail, machine); + String buildDishPrintData = buildAllKitchenPrintData(orderPrintDTO, orderDetail); + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + if (1 == machine.getVolumeSwitch()) { + voiceJson = "{\"bizType\":\"2\",\"content\":\"退菜消息,请及时处理\"}"; + } + String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(orderInfo.getId(), machine, "后厨退菜", buildDishPrintData, resp); + return null; + } + + @Override + public OrderPrintDTO returnOrderPrint(String printTitle, String operator, String refundAmount, String refundReason, String refundType, + OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.returnOrderPrint(printTitle, operator, refundAmount, refundReason, refundType, orderInfo, machine, detailList); + String data = buildRefundOrderPrintData(orderPrintDTO, detailList); sendOrderPrint(data, orderInfo.getId(), machine, "退款单"); return null; } @Override - public PrintInfoDTO guestOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.guestOrderPrint(orderInfo, machine, detailList); - String data = buildGuestOrderPrintData(printInfoDTO, detailList); + public OrderPrintDTO guestOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.guestOrderPrint(orderInfo, machine, detailList); + String data = buildGuestOrderPrintData(orderPrintDTO, detailList); sendOrderPrint(data, orderInfo.getId(), machine, "客看单"); return null; } @Override - public PrintInfoDTO preOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.preOrderPrint(orderInfo, machine, detailList); - String data = buildOrderPrintData(printInfoDTO, detailList); + public OrderPrintDTO preOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.preOrderPrint(orderInfo, machine, detailList); + String data = buildOrderPrintData(orderPrintDTO, detailList); sendOrderPrint(data, orderInfo.getId(), machine, "预结算单"); return null; } @Override - public PrintInfoDTO orderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.orderPrint(orderInfo, machine, detailList); - String data = buildOrderPrintData(printInfoDTO, detailList); + public OrderPrintDTO orderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.orderPrint(orderInfo, machine, detailList); + String data = buildOrderPrintData(orderPrintDTO, detailList); sendOrderPrint(data, orderInfo.getId(), machine, "结算单"); return null; @@ -130,15 +138,55 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl { voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一条新的排号记录\"}"; } String data = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime); - String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, "1"); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); printMachineLogService.save(machine, "叫号单", data, resp); } + @Override + protected void stockPrint(PrintMachine machine, StockPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildStockData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "IN".equals(record.getType()) ? "入库单" : "出库单", data, resp); + } + + @Override + protected void dayReportPrint(PrintMachine machine, DayReportPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildDayReportData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "经营日报单", data, resp); + } + + @Override + protected void productReportPrint(PrintMachine machine, ProductReportPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildProductReportData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "商品报表单", data, resp); + } + + @Override + protected void rechargePrint(PrintMachine machine, RechargePrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildRechargeData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "储值单", data, resp); + } + + @Override + protected void stockCheckPrint(PrintMachine machine, StockCheckPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildStockCheckData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "盘点单", data, resp); + } + @Override protected void handoverPrint(PrintMachine machine, HandoverRecordDTO record) { String string = buildHandoverData(record); String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; - sendPrintRequest(machine.getAddress(), string, voiceJson, "1"); + sendPrintRequest(machine.getAddress(), string, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); } /** @@ -153,11 +201,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl { if (1 == machine.getVolumeSwitch()) { voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; } - String printerNum = "1"; - if (StrUtil.isNotBlank(machine.getPrintQty())) { - printerNum = machine.getPrintQty().split("\\^")[1]; - } - String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); printMachineLogService.save(orderId, machine, bizType, data, resp); } @@ -244,20 +288,4 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl { } return msg; } - - /** - * 计算优惠金额:优先使用 discountAllAmount,如果为 null 则用原价 - 实付计算 - */ - private String calculateDiscountAmount(OrderInfo orderInfo) { - if (orderInfo.getDiscountAllAmount() != null) { - return orderInfo.getDiscountAllAmount().toPlainString(); - } - // 兜底计算:原价 + 餐位费 + 打包费 - 实付 - BigDecimal originalTotal = orderInfo.getOriginAmount() - .add(orderInfo.getSeatAmount() != null ? orderInfo.getSeatAmount() : BigDecimal.ZERO) - .add(orderInfo.getPackFee() != null ? orderInfo.getPackFee() : BigDecimal.ZERO); - BigDecimal discount = originalTotal.subtract(orderInfo.getPayAmount()); - return discount.compareTo(BigDecimal.ZERO) >= 0 ? discount.toPlainString() : "0.00"; - } - } diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrintConfig.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrintConfig.java index cf48443fa..15bce48e3 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrintConfig.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrintConfig.java @@ -1,42 +1,56 @@ package com.czg.service.order.print; -import org.springframework.context.annotation.Bean; +import com.czg.exception.CzgException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; import javax.annotation.PostConstruct; import javax.annotation.Resource; -import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * 打印机责任链初始化 + * * @author Administrator */ +@Slf4j @Configuration public class PrintConfig { @Resource - private List printers; + private ApplicationContext applicationContext; + + // 直接使用实例变量,不需要静态 + private Map printerMap; - // 初始化责任链 @PostConstruct - public void initChain() { - // 检查打印处理器列表是否为空 - if (printers != null && !printers.isEmpty()) { - for (int i = 0; i < printers.size() - 1; i++) { - // 设置当前处理器的下一个处理器 - printers.get(i).setNextPrinter(printers.get(i + 1)); + public void init() { + Map printers = applicationContext.getBeansOfType(PrinterHandler.class); + printerMap = new ConcurrentHashMap<>(); + + printers.forEach((beanName, printer) -> { + String brand = printer.printerBrand; + if (brand != null && !brand.trim().isEmpty()) { + printerMap.put(brand, printer); } + }); + + log.info("已注册打印机: {}", printerMap.keySet()); + } + + + /** + * 获取打印机 + */ + public PrinterHandler getPrinter(String key) { + PrinterHandler printer = printerMap.get(key); + if (printer == null) { + throw new CzgException("未找到打印机: " + key); } + return printer; } - - @Bean - @Primary - public PrinterHandler printerHandler() { - // 返回责任链的起始处理器 - return printers.getFirst(); - } - } diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java index 84877ec77..25b22274d 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java @@ -1,6 +1,6 @@ package com.czg.service.order.print; -import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -9,6 +9,8 @@ import com.czg.account.dto.HandoverRecordDTO; import com.czg.account.dto.PrintOrderDetailDTO; import com.czg.account.entity.*; import com.czg.account.service.*; +import com.czg.exception.CzgException; +import com.czg.print.*; import com.czg.config.RedisCst; import com.czg.constants.ParamCodeCst; import com.czg.market.service.OrderInfoService; @@ -25,13 +27,11 @@ import com.czg.service.RedisService; import com.czg.service.order.enums.OrderStatusEnums; import com.czg.system.dto.SysParamsDTO; import com.czg.system.service.SysParamsService; +import com.czg.utils.FunUtils; import com.mybatisflex.core.query.QueryWrapper; import jakarta.annotation.Resource; -import lombok.Data; import lombok.Getter; -import lombok.Setter; import lombok.ToString; -import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.web.client.RestTemplate; @@ -48,10 +48,9 @@ import java.util.stream.Collectors; @Slf4j @ToString public abstract class PrinterHandler { - @Setter - protected PrinterHandler nextPrinter; - protected String printerBrand; - + public String printerBrand; + @Resource + protected PrintConfig printConfig; @Resource protected RestTemplate restTemplate; @Resource @@ -88,157 +87,206 @@ public abstract class PrinterHandler { @Getter public enum PrintTypeEnum { - HANDOVER("交班", "handover"), + GUEST_ORDER("客看单"), + PRE_ORDER("预结算单"), + ORDER("订单结算单"), + RETURN_ORDER("退菜单"), + REFUND_ORDER("退款单"), - ONE_AND_ORDER("菜品和结算单同时打印", "oneAndOrder"), - PRE_ORDER("预结算单", "preOrder"), - ORDER("订单结算单", "order"), - GUEST_ORDER("客看单", "guestOrder"), + ALL_KITCHEN("后厨整单"), + ONLY_KITCHEN("后厨分单"), + REFUND_KITCHEN("后厨退菜单"), - RETURN_FOOD("退菜", "returnFood"), - RETURN_ORDER("退单", "returnOrder"), + HANDOVER("交班单"), + CALL("排队取号"), + RECHARGE("储值单"), + STOCK("出入库单"), + STOCK_CHECK("盘点单"), + PRODUCT_REPORT("商品报表"), + DAY_REPORT("经营日报"), + DAY_ORDER("日结单"); - ONE("菜品", "one"), - CALL("叫号", "call"); private final String name; - private final String code; - PrintTypeEnum(String name, String code) { + PrintTypeEnum(String name) { this.name = name; - this.code = code; } } - @Data - @Accessors(chain = true) - public static class PrintDetailInfo { - private boolean isPrint; - // private boolean isReturn; - private long orderId; - private long detailId; - private BigDecimal printNum; - private BigDecimal printReturnNum; - } - - @Data - @Accessors(chain = true) - public static class PrintInfoDTO { - private long count; - // 打印标题 结算单/客看单/预结算单 退菜单/退款单 - private String printTitle; - private String shopName; - //打印类型 收银-堂食 - private String printType; - //台桌区域-台桌号 - private String pickupNum; - private String orderNo; - //结账时间 - private String tradeDate; - //操作人名称 - private String operator; - private String payAmount; - private String originalAmount; - //余额 -// private String balance; - private String payType; - private String remark; - //取餐码 - private String outNumber; - private String discountAmount; - // private String discountRadio; -// private String orderNum; - private String seatNum; - private String seatAmount; - private String packFee; - // 是否退款单 - private boolean isReturn; - //退款单用 - private String refundAmount; - //退款方式 现金退款/原路退回 - private String refundType; - //退款原因 - private String refundReason; - - } public PrinterHandler(String printerBrand) { this.printerBrand = printerBrand; } + /** + * 处理订单打印 + * + * @param data 传递的数据 + * @param printTypeEnum GUEST_ORDER ORDER PRE_ORDER ONLY_KITCHEN ALL_KITCHEN + */ + public void orderHandler(String data, PrintTypeEnum printTypeEnum, Integer placeNum) { + OrderInfo orderInfo = orderInfoService.getById(data); + if (orderInfo == null) { + throw new RuntimeException("订单打印失败,订单不存在"); + } + List orderDetailList = new ArrayList<>(); + orderDetailList = switch (printTypeEnum) { + case PrintTypeEnum.GUEST_ORDER -> { + orderInfo.setPlaceNum(placeNum); + yield orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()).eq(OrderDetail::getPlaceNum, placeNum)); + } + case PrintTypeEnum.ORDER, PrintTypeEnum.PRE_ORDER, PrintTypeEnum.ONLY_KITCHEN, PrintTypeEnum.ALL_KITCHEN -> + orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId())); + default -> orderDetailList; + }; + for (PrintMachine machine : getPrintMachine(orderInfo.getShopId(), printTypeEnum)) { + PrinterHandler printer = printConfig.getPrinter(machine.getBrand()); + redisService.set("order:print:" + orderInfo.getId(), "", 180); + switch (printTypeEnum) { + case PrintTypeEnum.GUEST_ORDER: + log.info("准备开始打印客看订单"); + printer.guestOrderPrint(orderInfo, machine, orderDetailList); + break; + case PrintTypeEnum.ORDER: + log.info("准备开始打印订单"); + printer.orderPrint(machine, orderInfo, orderDetailList); + + break; + case PrintTypeEnum.PRE_ORDER: + log.info("准备开始打印预结算订单"); + printer.preOrderPrint(machine, orderInfo, orderDetailList); + break; + case PrintTypeEnum.ONLY_KITCHEN: + // 判断订单是否是先付费或者已结算 + if (!"after-pay".equals(orderInfo.getPayMode()) && (OrderStatusEnums.UNPAID.getCode().equals(orderInfo.getStatus()) || OrderStatusEnums.CANCELLED.getCode().equals(orderInfo.getStatus()))) { + log.warn("此订单未支付, 订单信息: {}", orderInfo.getId()); + } + List tbOrderDetailList = getCanPrintOrderDetails(machine, orderInfo.getId(), orderDetailList); + if (CollUtil.isEmpty(tbOrderDetailList)) { + log.info("此订单无打印菜品, 订单信息: {}", orderInfo.getId()); + break; + } + log.info("准备开始打印菜品单"); + //后厨单菜品 + tbOrderDetailList.forEach(item -> { + Boolean b = redisService.hasKey(RedisCst.kitchenNormal(orderInfo.getId(), machine.getId(), item.getId())); + if (!b) { + FunUtils.safeRunVoid(() -> onlyKitchenPrint(orderInfo, item, machine), + "订单id:{} ,后厨分单打印失败", orderInfo.getId()); + // 保存已打印信息 + redisService.set(RedisCst.kitchenNormal(orderInfo.getId(), machine.getId(), item.getId()), "", 180); + } + }); + break; + case PrintTypeEnum.ALL_KITCHEN: + Boolean exit = redisService.hasKey(RedisCst.kitchenAll(orderInfo.getId(), machine.getId())); + if (exit) { + break; + } + // 判断订单是否是先付费或者已结算 + if (!"after-pay".equals(orderInfo.getPayMode()) && (OrderStatusEnums.UNPAID.getCode().equals(orderInfo.getStatus()) || OrderStatusEnums.CANCELLED.getCode().equals(orderInfo.getStatus()))) { + log.warn("此订单未支付, 订单信息: {}", orderInfo.getId()); + } + List allOrderDetailList = getCanPrintOrderDetails(machine, orderInfo.getId(), orderDetailList); + if (CollUtil.isEmpty(allOrderDetailList)) { + log.info("此订单无打印菜品, 订单信息: {}", orderInfo.getId()); + break; + } + log.info("准备开始打印后厨整单"); + printer.allKitchenPrint(orderInfo, allOrderDetailList, machine); + redisService.set(RedisCst.kitchenAll(orderInfo.getId(), machine.getId()), "", 180); + break; + } + } + } + + /** + * 处理其它打印 + * + * @param data 传递的数据 + * @param printTypeEnum IN_STOCK DAY_REPORT PRODUCT_REPORT RECHARGE STOCK_CHECK + */ + public void otherHandler(Long shopId, Object data, PrintTypeEnum printTypeEnum) { + if (shopId == null || Objects.isNull(data)) { + log.info("otherHandler 打印数据为空, shopId: {}, data: {}", shopId, data); + return; + } + switch (printTypeEnum) { + case PrintTypeEnum.STOCK: + getPrintMachine(shopId, printTypeEnum) + .forEach(machine -> printConfig.getPrinter(machine.getBrand()).stockPrint(machine, (StockPrintDTO) data)); + break; + case PrintTypeEnum.DAY_REPORT: + getPrintMachine(shopId, printTypeEnum) + .forEach(machine -> printConfig.getPrinter(machine.getBrand()).dayReportPrint(machine, (DayReportPrintDTO) data)); + break; + case PrintTypeEnum.PRODUCT_REPORT: + getPrintMachine(shopId, printTypeEnum) + .forEach(machine -> printConfig.getPrinter(machine.getBrand()).productReportPrint(machine, (ProductReportPrintDTO) data)); + break; + case PrintTypeEnum.RECHARGE: + getPrintMachine(shopId, printTypeEnum) + .forEach(machine -> printConfig.getPrinter(machine.getBrand()).rechargePrint(machine, (RechargePrintDTO) data)); + break; + case PrintTypeEnum.STOCK_CHECK: + getPrintMachine(shopId, printTypeEnum) + .forEach(machine -> printConfig.getPrinter(machine.getBrand()).stockCheckPrint(machine, (StockCheckPrintDTO) data)); + break; + case PrintTypeEnum.HANDOVER: + log.info("准备开始打印交班"); + getPrintMachine(shopId, printTypeEnum) + .forEach(machine -> printConfig.getPrinter(machine.getBrand()).handoverPrint(machine, (HandoverRecordDTO) data)); + break; + case PrintTypeEnum.CALL: + log.info("准备开始打印叫号单"); + getPrintMachine(shopId, printTypeEnum) + .forEach(machine -> printConfig.getPrinter(machine.getBrand()).callNumPrintBefore(machine, (CallQueue) data)); + break; + default: + throw new CzgException("otherHandler 未知打印类型"); + } + } + /** * 获取可用打印机 * * @param shopId 店铺id - * @param subType 打印类型(分类)label标签 cash小票 kitchen出品 - * @param printMethod 打印方式 all-全部打印 normal-仅打印结账单「前台」one-仅打印制作单「厨房」 - * @param printType 打印类型,JSON数组 refund-确认退款单 handover-交班单 queue-排队取号 + * @param contentType GUEST_ORDER("客看单"), + * PRE_ORDER("预结算单"), + * ORDER("订单结算单"), + * RETURN_ORDER("退菜单"), + * REFUND_ORDER("退款单"), + *

+ * ALL_KITCHEN("后厨整单"), + * ONLY_KITCHEN("后厨分单"), + * REFUND_KITCHEN("后厨退菜单"), + *

+ * HANDOVER("交班单"), + * CALL("排队取号"), + * RECHARGE("储值单"), + * STOCK("出入库单"), + * STOCK_CHECK("盘点单"), + * PRODUCT_REPORT("商品报表"), + * DAY_REPORT("经营日报"), + * DAY_ORDER("日结单"); * @return 打印机列表 */ - private List getPrintMachine(Long shopId, String subType, String printMethod, String printType) { + private List getPrintMachine(Long shopId, PrintTypeEnum contentType) { QueryWrapper wrapper = new QueryWrapper() .eq(PrintMachine::getStatus, 1) .eq(PrintMachine::getShopId, shopId) - .eq(PrintMachine::getSubType, subType) - .eq(PrintMachine::getConnectionType, "网络"); - - if (StrUtil.isNotEmpty(printMethod)) { - List arrayList = switch (printMethod) { - case "all" -> Arrays.asList("one", "normal", "all"); - case "one" -> Arrays.asList("one", "all"); - case "normal" -> Arrays.asList("normal", "all"); - default -> new ArrayList<>(); - }; - if (!arrayList.isEmpty()) { - wrapper.in(PrintMachine::getPrintMethod, arrayList); - } - } - if ("callTicket".equals(printType)) { - printType = "queue"; - } - if (StrUtil.isNotEmpty(printType)) { - wrapper.like(PrintMachine::getPrintType, printType); - } + .eq(PrintMachine::getPrintType, "cash") + .like(PrintMachine::getPrintContentType, contentType) + .eq(PrintMachine::getConnectionType, "云打印"); List list = printMachineService.list(wrapper); if (list.isEmpty()) { log.error("店铺未配置打印机,店铺id: {}", shopId); return list; } - log.info("打印机列表: {}", list); return list; } - /** - * 处理订单打印 - * - * @param data 传递的数据 - * @param printTypeEnum order preOrder one - */ - public void orderHandler(String data, PrintTypeEnum printTypeEnum, Integer placeNum) { - String printMethod; - OrderInfo orderInfo = orderInfoService.getById(data); - if (orderInfo == null) { - throw new RuntimeException("订单打印失败,订单不存在"); - } - switch (printTypeEnum) { - case PrintTypeEnum.GUEST_ORDER: - case PrintTypeEnum.PRE_ORDER: - case PrintTypeEnum.ORDER: - printMethod = "normal"; - break; - case PrintTypeEnum.ONE: - printMethod = "one"; - break; - case PrintTypeEnum.ONE_AND_ORDER: - printMethod = "all"; - break; - default: - throw new RuntimeException("未知打印类型"); - } - getPrintMachine(orderInfo.getShopId(), "cash", printMethod, "").forEach(machine -> { - handleRequest(machine, placeNum, orderInfo, printTypeEnum); - }); - } /** * 处理退菜退款订单打印 @@ -253,269 +301,69 @@ public abstract class PrinterHandler { */ public void refundOrderHandler(String printTitle, String operator, String refundAmount, String refundReason, String refundType, OrderInfo orderInfo, List detailList) { - getPrintMachine(orderInfo.getShopId(), "cash", "normal", "").forEach(machine -> { - refundHandleRequest(machine, printTitle, operator, refundAmount, refundReason, refundType, orderInfo, detailList); + //前台退菜单 + if ("退菜单".equals(printTitle)) { + getPrintMachine(orderInfo.getShopId(), PrintTypeEnum.RETURN_ORDER).forEach(machine -> + printConfig.getPrinter(machine.getBrand()).returnOrderPrint(printTitle, operator, refundAmount, refundReason, refundType, orderInfo, machine, detailList)); + } else if ("退款单".equals(printTitle)) { + getPrintMachine(orderInfo.getShopId(), PrintTypeEnum.REFUND_ORDER).forEach(machine -> + printConfig.getPrinter(machine.getBrand()).returnOrderPrint(printTitle, operator, refundAmount, refundReason, refundType, orderInfo, machine, detailList)); + } else { + log.error("未知的前台退款打印类型: {}", printTitle); + } + } + + /** + * 处理退菜退款订单打印 + */ + public void kitchenRefundAllHandler(String operator, OrderInfo orderInfo, List detailList) { + //后厨退菜单 + getPrintMachine(orderInfo.getShopId(), PrintTypeEnum.REFUND_KITCHEN).forEach(machine -> { + Boolean isPrint = redisService.hasKey(RedisCst.kitchenRefundAll(orderInfo.getId(), machine.getId())); + if (!isPrint) { + printConfig.getPrinter(machine.getBrand()).returnKitchenPrint(operator, orderInfo, detailList, machine); + redisService.set(RedisCst.kitchenRefundAll(orderInfo.getId(), machine.getId()), "", 180); + } }); } - /** - * 叫号打印 - * - * @param data 传递的数据 - */ - public void callHandler(String data) { - CallQueue queue = callQueueService.getById(data); - if (queue == null) { - throw new RuntimeException("叫号信息不存在: " + data); + protected List getCanPrintOrderDetails(PrintMachine machine, Long orderId, List tbOrderDetailList) { + Set canPrintProSet = new HashSet<>(); + boolean partPrint = false; + if ("1".equals(machine.getClassifyPrint())) { + partPrint = true; + List categoryIds = JSONObject.parseObject(StrUtil.emptyToDefault(machine.getCategoryIds(), "[]"), List.class); + if (CollUtil.isEmpty(categoryIds)) { + return Collections.emptyList(); + } + List productIds = tbOrderDetailList.stream().map(OrderDetail::getProductId).collect(Collectors.toList()); + canPrintProSet = productService.list(new QueryWrapper() + .in(Product::getCategoryId, categoryIds) + .in(Product::getId, productIds)) + .stream() + .map(Product::getId) + .collect(Collectors.toSet()); } - Long shopId = queue.getShopId(); - if (shopId == null) { - throw new RuntimeException("店铺不存在, id:" + shopId); - } - getPrintMachine(shopId, "cash", "", "queue").forEach(machine -> handleRequest(machine, null, queue, PrintTypeEnum.CALL)); - } - - /** - * 交班打印 - * - * @param data 传递的数据 - */ - public void handoverHandler(String data) { - HandoverRecordDTO record = handoverRecordService.getHandoverRecordById(Long.parseLong(data)); - if (record == null) { - throw new RuntimeException("交班票打印失败,交班记录不存在"); - } - Long shopId = record.getShopId(); - if (shopId == null) { - throw new RuntimeException("店铺不存在, id:" + shopId); - } - getPrintMachine(shopId, "cash", "", "handover").forEach(machine -> handleRequest(machine, null, record, PrintTypeEnum.HANDOVER)); - } - - private void handleRequest(PrintMachine machine, Integer placeNum, Object data, PrintTypeEnum printTypeEnum) { - if (canHandleRequest(machine.getContentType(), machine.getConnectionType())) { - log.info("打印机: {}, 传递信息: {}", machine.getName(), data); - print(machine, placeNum, data, printTypeEnum); - } else if (nextPrinter != null) { - log.info("当前打印机无法处理: {},将请求传递给下一个打印机:{}...", this.printerBrand, nextPrinter.printerBrand); - nextPrinter.handleRequest(machine, placeNum, data, printTypeEnum); - } else { - log.warn("未找到匹配打印机"); - } - } - - private void refundHandleRequest(PrintMachine machine, String printTitle, String operator, String refundAmount, String refundReason, String refundType, - OrderInfo orderInfo, List detailList) { - if (canHandleRequest(machine.getContentType(), machine.getConnectionType())) { - log.info("退款打印机: {}, 传递信息: {}", machine.getName(), orderInfo.getId()); - returnOrderPrint(printTitle, operator, refundAmount, refundReason, refundType, orderInfo, machine, detailList); - } else if (nextPrinter != null) { - log.info("当前打印机无法处理: {},将请求传递给下一个打印机:{}...", this.printerBrand, nextPrinter.printerBrand); - nextPrinter.refundHandleRequest(machine, printTitle, operator, refundAmount, refundReason, refundType, orderInfo, detailList); - } else { - log.warn("未找到匹配打印机"); - } - } - - boolean canHandleRequest(String currentBrand, String connectType) { - log.info("handle判断是否可处理: {}, 连接类型: {}, handler类型: {}", currentBrand, connectType, printerBrand); - if (StrUtil.isBlank(printerBrand)) { - throw new RuntimeException("打印机品牌未赋值"); - } - return printerBrand.equals(currentBrand) && "网络".equals(connectType); - } - - protected List getCanPrintOrderDetails(boolean partPrint, Long orderId, List tbOrderDetailList, List categoryIds) { - List productIds = tbOrderDetailList.stream().map(OrderDetail::getProductId).collect(Collectors.toList()); - - Map canPrintProMap = categoryIds.isEmpty() ? new HashMap<>() : - productService.list(new QueryWrapper().in(Product::getCategoryId, categoryIds).in(Product::getId, productIds)) - .stream().collect(Collectors.toMap(Product::getId, i -> true)); - ArrayList orderDetails = new ArrayList<>(); - tbOrderDetailList.forEach(item -> { - Object o = redisService.get(RedisCst.getPrintOrderDetailKey(orderId, item.getId())); - - if (item.getIsPrint() != null && item.getIsPrint() == 1 && (canPrintProMap.get(item.getProductId()) != null || !partPrint)) { - item.setReturnNum(item.getReturnNum() == null ? BigDecimal.ZERO : item.getReturnNum()); - PrintDetailInfo printDetailInfo = o != null ? JSONObject.parseObject((String) o, PrintDetailInfo.class) : null; - if (printDetailInfo != null) { - if (item.getNum().compareTo(BigDecimal.ZERO) != 0 && item.getNum().compareTo(printDetailInfo.getPrintNum()) <= 0) { - log.info("此菜品已打印, {} {} {}", item.getProductName(), item.getSkuName(), printDetailInfo); - } - - if (item.getReturnNum().compareTo(BigDecimal.ZERO) != 0 && item.getReturnNum().compareTo(printDetailInfo.getPrintReturnNum()) <= 0) { - log.info("此退菜菜品已打印, {} {} {}", item.getProductName(), item.getSkuName(), printDetailInfo); - } - item.setNum(item.getNum().subtract(printDetailInfo.getPrintNum())); - item.setReturnNum(item.getReturnNum().subtract(printDetailInfo.getPrintReturnNum())); - orderDetails.add(item); - } else { - orderDetails.add(item); - } - - + for (OrderDetail item : tbOrderDetailList) { + //-999 台位费 + if (item.getNum().compareTo(BigDecimal.ZERO) <= 0 || item.getProductId().equals(-999L)) { + continue; + } + Boolean isPrint = redisService.hasKey(RedisCst.kitchenNormal(orderId, machine.getId(), item.getId())); + if (isPrint) { + continue; + } + if (item.getIsPrint() != null && item.getIsPrint() == 1 && (!partPrint || canPrintProSet.contains(item.getProductId()))) { + orderDetails.add(item); } else { log.info("此菜品不在打印分类或属于免打, {} {} {}", item.getProductName(), item.getSkuName(), item.getId()); } - }); - + } return orderDetails; } - - protected void print(PrintMachine machine, Integer placeNum, Object data, PrintTypeEnum printTypeEnum) { - switch (printTypeEnum) { - case PrintTypeEnum.HANDOVER: - log.info("准备开始打印交班"); - if (data instanceof HandoverRecordDTO record) { - handoverPrint(machine, record); - } else { - throw new RuntimeException("传递数据类型有误"); - } - break; - case PrintTypeEnum.GUEST_ORDER: - log.info("准备开始打印客看订单"); - if (data instanceof OrderInfo orderInfo) { - orderInfo.setPlaceNum(placeNum); - List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()).eq(OrderDetail::getPlaceNum, placeNum)); - guestOrderPrint(orderInfo, machine, orderDetailList); - } else { - throw new RuntimeException("传递数据类型有误"); - } - break; - case PrintTypeEnum.ORDER: - log.info("准备开始打印订单"); - if (data instanceof OrderInfo orderInfo) { - redisService.set("order:print:" + orderInfo.getId(), "", 180); - List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId())); - orderPrint(machine, orderInfo, orderDetailList); - } else { - throw new RuntimeException("传递数据类型有误"); - } - break; - case PrintTypeEnum.PRE_ORDER: - log.info("准备开始打印预结算订单"); - if (data instanceof OrderInfo orderInfo) { - redisService.set("order:print:" + orderInfo.getId(), "", 180); - List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId())); - preOrderPrint(machine, orderInfo, orderDetailList); - } else { - throw new RuntimeException("传递数据类型有误"); - } - break; - case PrintTypeEnum.ONE: - log.info("准备开始打印菜品单"); - if (data instanceof OrderInfo orderInfo) { - redisService.set("order:print:" + orderInfo.getId(), "", 180); - List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId())); - onlyKitchen(machine, orderInfo, orderDetailList); - } else { - throw new RuntimeException("传递数据类型有误"); - } - break; - case PrintTypeEnum.CALL: - log.info("准备开始打印叫号单"); - if (data instanceof CallQueue queue) { - onlyCallNumPrint(machine, queue); - } else { - throw new RuntimeException("传递数据类型有误"); - } - break; - case PrintTypeEnum.ONE_AND_ORDER: - log.info("准备开始打印菜品以及结算单"); - if (data instanceof OrderInfo orderInfo) { - redisService.set("order:print:" + orderInfo.getId(), "", 180); - List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId())); - switch (machine.getPrintMethod()) { - case "all": - orderPrint(machine, orderInfo, orderDetailList); - onlyKitchen(machine, orderInfo, orderDetailList); - break; - case "one": - log.info("打印机仅打印one"); - onlyKitchen(machine, orderInfo, orderDetailList); - break; - case "normal": - log.info("打印机仅打印normal"); - orderPrint(machine, orderInfo, orderDetailList); - break; - default: - throw new RuntimeException("打印方法有误"); - } - } else { - throw new RuntimeException("传递数据类型有误"); - } - - } - - } - - /** - * 仅打印制作单「厨房」 - */ - private void onlyKitchen(PrintMachine machine, OrderInfo orderInfo, List tbOrderDetailList) { - // 判断订单是否是先付费或者已结算 - if (!"after-pay".equals(orderInfo.getPayMode()) && (OrderStatusEnums.UNPAID.getCode().equals(orderInfo.getStatus()) || OrderStatusEnums.CANCELLED.getCode().equals(orderInfo.getStatus()))) { - log.warn("此订单未支付, 订单信息: {}", orderInfo); - } - - List categoryIds = JSONObject.parseObject(StrUtil.emptyToDefault(machine.getCategoryIds(), "[]"), List.class); - if (StrUtil.isEmpty(machine.getClassifyPrint())) { - log.error("分类打印是空, classifyPrint: {}", machine.getClassifyPrint()); - return; - } - - // 已打印详情信息 - Map detailMap = tbOrderDetailList.stream().map(item -> BeanUtil.copyProperties(item, OrderDetail.class)).collect(Collectors.toMap(OrderDetail::getId, i -> i)); - tbOrderDetailList = getCanPrintOrderDetails("1".equals(machine.getClassifyPrint()), orderInfo.getId(), tbOrderDetailList, categoryIds); - tbOrderDetailList.parallelStream().filter(o -> ObjectUtil.defaultIfNull(o.getIsPrint(), 0) == 1).forEach(item -> { - if (item.getNum().compareTo(BigDecimal.ZERO) <= 0 && item.getReturnNum().compareTo(BigDecimal.ZERO) <= 0) { - return; - } - Integer isWaitCall = ObjectUtil.defaultIfNull(item.getIsWaitCall(), 0); - if (isWaitCall == 1) { - if (!item.getProductName().contains("【等叫】")) { - item.setProductName("【等叫】" + item.getProductName()); - } - } - Integer isTemporary = ObjectUtil.defaultIfNull(item.getIsTemporary(), 0); - if (isTemporary == 1) { - item.setProductId(0L); - item.setSkuId(0L); - if (!item.getProductName().contains("【临】")) { - item.setProductName("【临】" + item.getProductName()); - } - } - boolean isGift = item.getIsGift() != null && item.getIsGift() == 1; - if (isGift && !item.getProductName().contains("【赠】")) { - item.setProductName("【赠】" + item.getProductName()); - } - // 台位费不打印 - if (item.getProductId().equals(-999L)) { - log.info("台位费商品,不打印"); - return; - } - - if (item.getReturnNum().compareTo(BigDecimal.ZERO) > 0) { - returnDishesPrint("操作人名称", orderInfo, item, machine); - } - - if (item.getNum().compareTo(BigDecimal.ZERO) > 0) { - normalDishesPrint("操作人名称", orderInfo, item, machine); - } - - // 保存已打印信息 - OrderDetail orderDetail = detailMap.get(item.getId()); - redisService.set(RedisCst.getPrintOrderDetailKey(orderInfo.getId(), item.getId()), - JSONObject.toJSONString(new PrintDetailInfo().setPrint(item.getIsPrint() == 1).setDetailId(item.getId()) - .setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24); - - }); - - } - /** * 打印预结算单「前台」 */ @@ -617,7 +465,7 @@ public abstract class PrinterHandler { /** * 打印排队小票 */ - private void onlyCallNumPrint(PrintMachine machine, CallQueue queue) { + private void callNumPrintBefore(PrintMachine machine, CallQueue queue) { if (queue == null) { log.warn("叫号记录不存在"); return; @@ -648,26 +496,26 @@ public abstract class PrinterHandler { } - public PrintInfoDTO returnOrderPrint(String printTitle, String operator, String refundAmount, String refundReason, String refundType, - OrderInfo orderInfo, PrintMachine machine, List detailList) { + public OrderPrintDTO returnOrderPrint(String printTitle, String operator, String refundAmount, String refundReason, String refundType, + OrderInfo orderInfo, PrintMachine machine, List detailList) { ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId()); - PrintInfoDTO printInfoDTO = new PrintInfoDTO().setShopName(shopInfo.getShopName()).setPrintType("收银-堂食") + OrderPrintDTO orderPrintDTO = new OrderPrintDTO().setShopName(shopInfo.getShopName()).setPrintType("收银-堂食") .setOrderNo(orderInfo.getOrderNo()) .setTradeDate(DateUtil.format(orderInfo.getCreateTime(), "yyyy/MM/dd HH:mm:ss")) .setOperator(operator) .setReturn(true) .setPrintTitle(printTitle); - printInfoDTO.setSeatNum(orderInfo.getSeatNum() == null ? "" : orderInfo.getSeatNum().toString()); - printInfoDTO.setPickupNum(orderInfo.getTableName()); - printInfoDTO.setRefundAmount(refundAmount); - printInfoDTO.setRefundReason(refundReason); - printInfoDTO.setRefundType("cash".equals(refundType) ? "线下退款" : "原路退回"); - return printInfoDTO; + orderPrintDTO.setSeatNum(orderInfo.getSeatNum() == null ? "" : orderInfo.getSeatNum().toString()); + orderPrintDTO.setPickupNum(orderInfo.getTableName()); + orderPrintDTO.setRefundAmount(refundAmount); + orderPrintDTO.setRefundReason(refundReason); + orderPrintDTO.setRefundType("cash".equals(refundType) ? "线下退款" : "原路退回"); + return orderPrintDTO; } - public PrintInfoDTO guestOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = getPrintInfoDTO(orderInfo, "客看单"); + public OrderPrintDTO guestOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = getPrintInfoDTO(orderInfo, "客看单"); BigDecimal originalAmount = BigDecimal.ZERO; for (OrderDetail orderDetail : detailList) { @@ -692,24 +540,24 @@ public abstract class PrinterHandler { orderDetail.setProductName("【赠】%s".formatted(orderDetail.getProductName())); } } - log.info("客看单 第{}次下单--------------------------------------------", orderInfo.getPlaceNum()); +// log.info("客看单 第{}次下单--------------------------------------------", orderInfo.getPlaceNum()); if (orderInfo.getPlaceNum() != null && orderInfo.getPlaceNum() != 1) { orderInfo.setSeatAmount(BigDecimal.ZERO); - printInfoDTO.setSeatAmount(""); + orderPrintDTO.setSeatAmount(""); } - printInfoDTO.setOriginalAmount((originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee())) + orderPrintDTO.setOriginalAmount((originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee())) .setScale(2, RoundingMode.HALF_UP).toPlainString()); - printInfoDTO.setPayAmount((originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee()) + orderPrintDTO.setPayAmount((originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee()) .subtract(orderInfo.getDiscountAllAmount())).setScale(2, RoundingMode.HALF_UP).toPlainString()); if (orderInfo.getPackFee().compareTo(BigDecimal.ZERO) > 0) { - printInfoDTO.setPackFee(orderInfo.getPackFee().toPlainString()); + orderPrintDTO.setPackFee(orderInfo.getPackFee().toPlainString()); } - return printInfoDTO; + return orderPrintDTO; } - public PrintInfoDTO preOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = getPrintInfoDTO(orderInfo, "预结算单"); + public OrderPrintDTO preOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = getPrintInfoDTO(orderInfo, "预结算单"); BigDecimal originalAmount = BigDecimal.ZERO; for (OrderDetail orderDetail : detailList) { @@ -721,97 +569,48 @@ public abstract class PrinterHandler { originalAmount = originalAmount.add((orderDetail.getNum().subtract(orderDetail.getReturnNum()).subtract(orderDetail.getRefundNum())).multiply(orderDetail.getPrice())); } } - printInfoDTO.setOriginalAmount((originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee())) + orderPrintDTO.setOriginalAmount((originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee())) .setScale(2, RoundingMode.HALF_UP).toPlainString()); - printInfoDTO.setPayAmount(originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee()) + orderPrintDTO.setPayAmount(originalAmount.add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee()) .subtract(orderInfo.getDiscountAllAmount()).setScale(2, RoundingMode.HALF_UP).toPlainString()); if (orderInfo.getPackFee().compareTo(BigDecimal.ZERO) > 0) { - printInfoDTO.setPackFee(orderInfo.getPackFee().toPlainString()); + orderPrintDTO.setPackFee(orderInfo.getPackFee().toPlainString()); } - return printInfoDTO; + return orderPrintDTO; } - public PrintInfoDTO orderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = getPrintInfoDTO(orderInfo, "结算单"); + public OrderPrintDTO orderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = getPrintInfoDTO(orderInfo, "结算单"); BigDecimal originalAmount = orderInfo.getOriginAmount() == null ? BigDecimal.ZERO : orderInfo.getOriginAmount(); - printInfoDTO.setOriginalAmount(originalAmount.toPlainString()); - printInfoDTO.setPayAmount(originalAmount.subtract(orderInfo.getDiscountAllAmount()).setScale(2, RoundingMode.HALF_UP).toPlainString()); + orderPrintDTO.setOriginalAmount(originalAmount.toPlainString()); + orderPrintDTO.setPayAmount(originalAmount.subtract(orderInfo.getDiscountAllAmount()).setScale(2, RoundingMode.HALF_UP).toPlainString()); if (orderInfo.getPackFee().compareTo(BigDecimal.ZERO) > 0) { - printInfoDTO.setPackFee(orderInfo.getPackFee().toPlainString()); + orderPrintDTO.setPackFee(orderInfo.getPackFee().toPlainString()); } - return printInfoDTO; - } - - private PrintInfoDTO getPrintInfoDTO(OrderInfo orderInfo, String printTitle) { - ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId()); - long count = orderInfoService.count(new QueryWrapper().eq(OrderInfo::getTradeDay, orderInfo.getTradeDay()) - .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()) - .eq(OrderInfo::getShopId, orderInfo.getShopId()) - .le(OrderInfo::getCreateTime, orderInfo.getCreateTime())); - - PrintInfoDTO printInfoDTO = new PrintInfoDTO().setShopName(shopInfo.getShopName()) - .setPrintTitle(printTitle) - .setPickupNum(orderInfo.getTableName()) - .setOrderNo(orderInfo.getOrderNo()).setPayAmount(orderInfo.getPayAmount().toPlainString()).setReturn(false) - .setOutNumber(orderInfo.getTakeCode()).setCount(count).setRemark(orderInfo.getRemark()) - // 使用累计的总优惠金额,null 表示没有优惠 - .setDiscountAmount(orderInfo.getDiscountAllAmount() != null - ? orderInfo.getDiscountAllAmount().toPlainString() - : "0.00"); - - printInfoDTO.setSeatNum(orderInfo.getSeatNum() == null ? "" : orderInfo.getSeatNum().toString()); - if (orderInfo.getSeatNum() != null && orderInfo.getSeatAmount().compareTo(BigDecimal.ZERO) > 0) { - printInfoDTO.setSeatAmount(orderInfo.getSeatAmount().divide(BigDecimal.valueOf(orderInfo.getSeatNum()), 2, RoundingMode.DOWN).toPlainString()); - } - if (StrUtil.isNotBlank(orderInfo.getDineMode())) { - switch (orderInfo.getDineMode()) { - case "dine-in" -> printInfoDTO.setPrintType("收银-堂食"); - case "take-out" -> printInfoDTO.setPrintType("收银-外带"); - case "take-away" -> printInfoDTO.setPrintType("收银-外卖"); - } - if (!"dine-in".equals(orderInfo.getDineMode())) { - orderInfo.setSeatAmount(BigDecimal.ZERO); - printInfoDTO.setSeatAmount(""); - } - } - if (orderInfo.getStaffId() != null) { - ShopStaff detail = shopStaffService.getOne(new QueryWrapper().eq(ShopStaff::getId, orderInfo.getStaffId()).eq(ShopStaff::getShopId, orderInfo.getShopId())); - if (detail != null) { - printInfoDTO.setOperator(detail.getName()); - } else { - printInfoDTO.setOperator(""); - } - } else { - printInfoDTO.setOperator(""); - } - if ("结算单".equals(printTitle)) { - if (StrUtil.isNotBlank(orderInfo.getPayType())) { - switch (orderInfo.getPayType()) { - case "main_scan" -> printInfoDTO.setPayType("二维码收款"); - case "back_scan" -> printInfoDTO.setPayType("扫码收款"); - case "wechat_mini" -> printInfoDTO.setPayType("微信小程序"); - case "alipay_mini" -> printInfoDTO.setPayType("支付宝小程序"); - case "vip_pay" -> printInfoDTO.setPayType("余额支付"); - case "cash_pay" -> printInfoDTO.setPayType("现金支付"); - case "credit_pay" -> printInfoDTO.setPayType("挂账支付"); - case "free_pay" -> printInfoDTO.setPayType("霸王餐支付"); - } - } - printInfoDTO.setTradeDate(DateUtil.format(orderInfo.getPaidTime(), "yyyy/MM/dd HH:mm:ss")); - } - return printInfoDTO; + return orderPrintDTO; } /** - * 菜品打印 + * 后厨 总单打印 */ - protected abstract void normalDishesPrint(String operator, OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine); + public OrderPrintDTO allKitchenPrint(OrderInfo orderInfo, List orderDetails, PrintMachine machine) { + return getPrintInfoDTO(orderInfo, "后厨总单"); + } /** - * 菜品 退菜打印 + * 后厨 菜品打印 */ - protected abstract void returnDishesPrint(String operator, OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine); + protected abstract void onlyKitchenPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine); + + /** + * 后厨 退菜整单打印 + */ + public OrderPrintDTO returnKitchenPrint(String operator, OrderInfo orderInfo, List orderDetail, PrintMachine machine) { + OrderPrintDTO printInfo = getPrintInfoDTO(orderInfo, "后厨退菜单"); + printInfo.setOperator(operator); + return printInfo; + } /** * 叫号打印 @@ -819,9 +618,91 @@ public abstract class PrinterHandler { protected abstract void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote); + /** + * 出入库打印单 + */ + protected abstract void stockPrint(PrintMachine machine, StockPrintDTO record); + + /** + * 经营日报打印 + */ + protected abstract void dayReportPrint(PrintMachine machine, DayReportPrintDTO record); + + /** + * 商品报表打印 + */ + protected abstract void productReportPrint(PrintMachine machine, ProductReportPrintDTO record); + + /** + * 储值单打印 + */ + protected abstract void rechargePrint(PrintMachine machine, RechargePrintDTO record); + + /** + * 库存盘点打印 + */ + protected abstract void stockCheckPrint(PrintMachine machine, StockCheckPrintDTO record); + + /** * 交班打印 */ protected abstract void handoverPrint(PrintMachine machine, HandoverRecordDTO record); + + private OrderPrintDTO getPrintInfoDTO(OrderInfo orderInfo, String printTitle) { + ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId()); + OrderPrintDTO orderPrintDTO = new OrderPrintDTO().setShopName(shopInfo.getShopName()) + .setPrintTitle(printTitle) + .setPickupNum(orderInfo.getTableName()) + .setOrderNo(orderInfo.getOrderNo()).setPayAmount(orderInfo.getPayAmount().toPlainString()).setReturn(false) + .setOutNumber(orderInfo.getTakeCode()) + .setRemark(orderInfo.getRemark()) + // 使用累计的总优惠金额,null 表示没有优惠 + .setDiscountAmount(orderInfo.getDiscountAllAmount() != null + ? orderInfo.getDiscountAllAmount().toPlainString() + : "0.00"); + + orderPrintDTO.setSeatNum(orderInfo.getSeatNum() == null ? "" : orderInfo.getSeatNum().toString()); + if (orderInfo.getSeatNum() != null && orderInfo.getSeatAmount().compareTo(BigDecimal.ZERO) > 0) { + orderPrintDTO.setSeatAmount(orderInfo.getSeatAmount().divide(BigDecimal.valueOf(orderInfo.getSeatNum()), 2, RoundingMode.DOWN).toPlainString()); + } + if (StrUtil.isNotBlank(orderInfo.getDineMode())) { + switch (orderInfo.getDineMode()) { + case "dine-in" -> orderPrintDTO.setPrintType("收银-堂食"); + case "take-out" -> orderPrintDTO.setPrintType("收银-外带"); + case "take-away" -> orderPrintDTO.setPrintType("收银-外卖"); + } + if (!"dine-in".equals(orderInfo.getDineMode())) { + orderInfo.setSeatAmount(BigDecimal.ZERO); + orderPrintDTO.setSeatAmount(""); + } + } + if (orderInfo.getStaffId() != null) { + ShopStaff detail = shopStaffService.getOne(new QueryWrapper().eq(ShopStaff::getId, orderInfo.getStaffId()).eq(ShopStaff::getShopId, orderInfo.getShopId())); + if (detail != null) { + orderPrintDTO.setOperator(detail.getName()); + } else { + orderPrintDTO.setOperator(""); + } + } else { + orderPrintDTO.setOperator(""); + } + if ("结算单".equals(printTitle)) { + if (StrUtil.isNotBlank(orderInfo.getPayType())) { + switch (orderInfo.getPayType()) { + case "main_scan" -> orderPrintDTO.setPayType("二维码收款"); + case "back_scan" -> orderPrintDTO.setPayType("扫码收款"); + case "wechat_mini" -> orderPrintDTO.setPayType("微信小程序"); + case "alipay_mini" -> orderPrintDTO.setPayType("支付宝小程序"); + case "vip_pay" -> orderPrintDTO.setPayType("余额支付"); + case "cash_pay" -> orderPrintDTO.setPayType("现金支付"); + case "credit_pay" -> orderPrintDTO.setPayType("挂账支付"); + case "free_pay" -> orderPrintDTO.setPayType("霸王餐支付"); + } + } + orderPrintDTO.setTradeDate(DateUtil.format(orderInfo.getPaidTime(), "yyyy/MM/dd HH:mm:ss")); + } + return orderPrintDTO; + } } diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterImpl.java index b0195bd14..98c8124cb 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterImpl.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterImpl.java @@ -2,7 +2,6 @@ package com.czg.service.order.print; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -11,14 +10,14 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.czg.account.dto.HandoverRecordDTO; import com.czg.order.entity.OrderDetail; +import com.czg.print.*; import lombok.Data; import lombok.experimental.Accessors; -import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; /** @@ -109,61 +108,6 @@ public interface PrinterImpl { PrintSignLabel getSignLabelInfo(); - /** - * 获取对齐后的小票明细行数据 - * 例如:58mm 机器一行打印16个汉字/32个字母;80mm机器打印24个汉字/48个字母。 - * - * @param title 品名 - * @param price 单价 - * @param num 数量 - * @param total 小计 - * @param b1 品名占用字节数 - * @param b2 单价占用字节数 - * @param b3 数量占用字节数 - * @param b4 小计占用字节数 - * @return 格式化后的行数据(带
标签) - */ - default String getRow(String title, String price, String num, String total, - int b1, int b2, int b3, int b4) { - PrintSignLabel signLabelInfo = getSignLabelInfo(); - price = addSpace(price, b2); - num = addSpace(num, b3); - total = addSpace(total, b4); - String otherStr = "%s%s%s".formatted(price, num, total); - - int titleByteLen = StrUtil.bytes(title, CharsetUtil.CHARSET_GBK).length; - StringBuilder sb = new StringBuilder(); - - if (titleByteLen <= b1) { - // 品名可以在一行显示,直接补足空格 - title = titleAddSpace(title, b1); - sb.append(getFormatLabel(title + otherStr, signLabelInfo.s)); - } else { - // 品名超出一行,进行拆分 - List lines = isEn(title) - // 英文按 b1 个字符拆分 - ? getStrList(title, b1) - // 中文按 b1/2 个字符拆分 - : getStrList(title, b1 / 2); - - // 第一行拼接其它字段 - String firstLine = titleAddSpace(lines.getFirst(), b1); - sb.append(getFormatLabel(firstLine + otherStr, signLabelInfo.s)); - sb.append(signLabelInfo.br); - // 剩余的行单独换行输出 - for (int i = 1; i < lines.size(); i++) { - if (i + 1 != lines.size()) { - sb.append(getFormatLabel(titleAddSpace(lines.get(i), b1), signLabelInfo.s)); - sb.append(signLabelInfo.br); - } else { - sb.append(getFormatLabel(titleAddSpace(lines.get(i), b1), signLabelInfo.s)); - } - } - } - sb.append(signLabelInfo.br); - return sb.toString(); - } - default String getFormatLabel(String text, String[]... labels) { StringBuilder str = new StringBuilder(); for (String[] label : labels) { @@ -177,6 +121,9 @@ public interface PrinterImpl { return str.toString(); } + /** + * 构建交班 打印元数据 + */ default String buildHandoverData(HandoverRecordDTO handoverRecord) { PrintSignLabel signLabelInfo = getSignLabelInfo(); StringBuilder builder = new StringBuilder() @@ -207,7 +154,7 @@ public interface PrinterImpl { .append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br) .append(getFormatLabel(leftRightAlign("订单数量/订单总额", handoverRecord.getOrderCount() + "/" + handoverRecord.getOrderTurnover(), 32), signLabelInfo.s)).append(signLabelInfo.br) .append(getFormatLabel("----------- 销售数据 -----------", signLabelInfo.s)).append(signLabelInfo.br) - .append(getFormatLabel(formatItemLine("商品分类", "数量", "总计", 14, 8), signLabelInfo.s)) + .append(getFormatLabel(key3("商品分类", "数量", "总计", 14, 8), signLabelInfo.s)) .append(signLabelInfo.br); if (StrUtil.isNotBlank(handoverRecord.getCategoryData())) { @@ -216,7 +163,7 @@ public interface PrinterImpl { String categoryName = info.getString("categoryName"); Integer quantity = info.getInteger("quantity"); BigDecimal amount = info.getBigDecimal("amount"); - builder.append(getFormatLabel(formatItemLine(categoryName, quantity.toString(), amount.toPlainString(), 14, 8), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(key3(categoryName, quantity.toString(), amount.toPlainString(), 14, 8), signLabelInfo.s)).append(signLabelInfo.br); }); } builder.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br) @@ -229,23 +176,23 @@ public interface PrinterImpl { /** * 构建结算单 预结算单订单打印元数据 * - * @param printInfoDTO 打印信息 - * @param detailList 订单详情 + * @param orderPrintDTO 打印信息 + * @param detailList 订单详情 * @return 订单打印元数据 */ - default String buildOrderPrintData(PrinterHandler.PrintInfoDTO printInfoDTO, List detailList) { + default String buildOrderPrintData(OrderPrintDTO orderPrintDTO, List detailList) { PrintSignLabel signLabelInfo = getSignLabelInfo(); StringBuilder data = new StringBuilder(); - data.append(getFormatLabel(printInfoDTO.getShopName(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); - data.append(getFormatLabel(printInfoDTO.getPrintTitle(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); - data.append(getFormatLabel(printInfoDTO.getPickupNum(), signLabelInfo.f)).append(signLabelInfo.br); - data.append(getFormatLabel(getFormatLabel(leftRightAlign(printInfoDTO.getPrintType(), StrUtil.isNotBlank(printInfoDTO.getSeatNum()) ? printInfoDTO.getSeatNum() + "人" : "", 32)) + data.append(getFormatLabel(orderPrintDTO.getShopName(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + data.append(getFormatLabel(orderPrintDTO.getPrintTitle(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + data.append(getFormatLabel(orderPrintDTO.getPickupNum(), signLabelInfo.f)).append(signLabelInfo.br); + data.append(getFormatLabel(getFormatLabel(leftRightAlign(orderPrintDTO.getPrintType(), StrUtil.isNotBlank(orderPrintDTO.getSeatNum()) ? orderPrintDTO.getSeatNum() + "人" : "", 32)) , signLabelInfo.s)).append(signLabelInfo.br); - if (StrUtil.isNotBlank(printInfoDTO.getTradeDate())) { - data.append(getFormatLabel(StrUtil.format("结账时间:{}", printInfoDTO.getTradeDate()), signLabelInfo.s)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getTradeDate())) { + data.append(getFormatLabel(StrUtil.format("结账时间:{}", orderPrintDTO.getTradeDate()), signLabelInfo.s)).append(signLabelInfo.br); } data.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(formatItemLine("品名", "单价", "数量", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3("品名", "单价", "数量", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); for (OrderDetail detail : detailList) { BigDecimal subtract = detail.getNum().subtract(detail.getReturnNum()); @@ -254,7 +201,7 @@ public interface PrinterImpl { } String number = subtract.stripTrailingZeros().toPlainString(); String unitPrice = toPlainStr(detail.getUnitPrice().stripTrailingZeros().toPlainString()); - data.append(getFormatLabel(formatItemLine(detail.getProductName(), unitPrice, number, 18, 7), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3(detail.getProductName(), unitPrice, number, 18, 7), signLabelInfo.s)).append(signLabelInfo.br); if (StrUtil.isNotBlank(detail.getSkuName())) { data.append(getFormatLabel(StrUtil.format("规格:{}", detail.getSkuName()), signLabelInfo.s)) @@ -273,64 +220,63 @@ public interface PrinterImpl { jsonObject.getJSONArray("goods").forEach(item -> { String proName = ((JSONObject) item).getString("proName"); String qty = ((JSONObject) item).getString("number"); - data.append(getFormatLabel(formatItemLine(" - " + proName, "", qty, 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3(" - " + proName, "", qty, 18, 9), signLabelInfo.s)).append(signLabelInfo.br); }); } } - if (StrUtil.isNotBlank(printInfoDTO.getSeatAmount())) { - data.append(getFormatLabel(formatItemLine("餐位费", printInfoDTO.getSeatAmount(), printInfoDTO.getSeatNum(), 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getSeatAmount())) { + data.append(getFormatLabel(key3("餐位费", orderPrintDTO.getSeatAmount(), orderPrintDTO.getSeatNum(), 18, 9), signLabelInfo.s)).append(signLabelInfo.br); } - if (StrUtil.isNotBlank(printInfoDTO.getPackFee())) { - data.append(getFormatLabel(formatItemLine("打包费", toPlainStr(printInfoDTO.getPackFee()), "", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getPackFee())) { + data.append(getFormatLabel(key3("打包费", toPlainStr(orderPrintDTO.getPackFee()), "", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); } data.append(getFormatLabel("--------------------------------", signLabelInfo.s)) .append(signLabelInfo.br); - data.append(getFormatLabel(leftRightAlign("原价:", printInfoDTO.getOriginalAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); - if (ObjectUtil.isNotNull(printInfoDTO.getDiscountAmount())) { - data.append(getFormatLabel(leftRightAlign("优惠:", "-" + printInfoDTO.getDiscountAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(leftRightAlign("原价:", orderPrintDTO.getOriginalAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); + if (ObjectUtil.isNotNull(orderPrintDTO.getDiscountAmount())) { + data.append(getFormatLabel(leftRightAlign("优惠:", "-" + orderPrintDTO.getDiscountAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); } - if (StrUtil.isNotBlank(printInfoDTO.getRemark())) { - data.append(getFormatLabel(StrUtil.format("备注:{}", printInfoDTO.getRemark()), signLabelInfo.s)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getRemark())) { + data.append(getFormatLabel(StrUtil.format("备注:{}", orderPrintDTO.getRemark()), signLabelInfo.s)).append(signLabelInfo.br); } data.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(leftRightAlign("应付:", printInfoDTO.getPayAmount(), 16), signLabelInfo.f)).append(signLabelInfo.br); + data.append(getFormatLabel(leftRightAlign("应付:", orderPrintDTO.getPayAmount(), 16), signLabelInfo.f)).append(signLabelInfo.br); - if ("结算单".equals(printInfoDTO.getPrintTitle())) { + if ("结算单".equals(orderPrintDTO.getPrintTitle())) { data.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(leftRightAlign("已付:", printInfoDTO.getPayAmount(), 16), signLabelInfo.f)).append(signLabelInfo.br); - data.append(getFormatLabel(leftRightAlign("支付方式:", printInfoDTO.getPayType(), 32), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(leftRightAlign("已付:", orderPrintDTO.getPayAmount(), 16), signLabelInfo.f)).append(signLabelInfo.br); + data.append(getFormatLabel(leftRightAlign("支付方式:", orderPrintDTO.getPayType(), 32), signLabelInfo.s)).append(signLabelInfo.br); } data.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("操作员:{}", printInfoDTO.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("操作员:{}", orderPrintDTO.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); data.append(getFormatLabel(StrUtil.format("打印时间:{}", DateUtil.date().toString()), signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("订单号:{}", printInfoDTO.getOrderNo()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("订单号:{}", orderPrintDTO.getOrderNo()), signLabelInfo.s)).append(signLabelInfo.br); data.append(signLabelInfo.getOut(180)); data.append(signLabelInfo.cut); return data.toString(); } - /** * 构建客看单订单打印元数据 * - * @param printInfoDTO 打印信息 - * @param detailList 订单详情 + * @param orderPrintDTO 打印信息 + * @param detailList 订单详情 * @return 订单打印元数据 */ - default String buildGuestOrderPrintData(PrinterHandler.PrintInfoDTO printInfoDTO, List detailList) { + default String buildGuestOrderPrintData(OrderPrintDTO orderPrintDTO, List detailList) { PrintSignLabel signLabelInfo = getSignLabelInfo(); StringBuilder data = new StringBuilder(); - data.append(getFormatLabel(printInfoDTO.getShopName(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + data.append(getFormatLabel(orderPrintDTO.getShopName(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); data.append(getFormatLabel("客看单", signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); - if (StrUtil.isNotBlank(printInfoDTO.getPickupNum())) { - data.append(getFormatLabel(printInfoDTO.getPickupNum(), signLabelInfo.f)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getPickupNum())) { + data.append(getFormatLabel(orderPrintDTO.getPickupNum(), signLabelInfo.f)).append(signLabelInfo.br); } - data.append(getFormatLabel(getFormatLabel(leftRightAlign(printInfoDTO.getPrintType(), StrUtil.isNotBlank(printInfoDTO.getSeatNum()) ? printInfoDTO.getSeatNum() + "人" : "", 32)) + data.append(getFormatLabel(getFormatLabel(leftRightAlign(orderPrintDTO.getPrintType(), StrUtil.isNotBlank(orderPrintDTO.getSeatNum()) ? orderPrintDTO.getSeatNum() + "人" : "", 32)) , signLabelInfo.s)).append(signLabelInfo.br); data.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(formatItemLine("品名", "单价", "数量", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3("品名", "单价", "数量", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); for (OrderDetail detail : detailList) { BigDecimal subtract = detail.getNum().subtract(detail.getReturnNum()); @@ -339,7 +285,7 @@ public interface PrinterImpl { } String number = subtract.stripTrailingZeros().toPlainString(); String unitPrice = toPlainStr(detail.getUnitPrice().stripTrailingZeros().toPlainString()); - data.append(getFormatLabel(formatItemLine(detail.getProductName(), unitPrice, number, 18, 7), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3(detail.getProductName(), unitPrice, number, 18, 7), signLabelInfo.s)).append(signLabelInfo.br); if (StrUtil.isNotBlank(detail.getSkuName())) { data.append(getFormatLabel(StrUtil.format("规格:{}", detail.getSkuName()), signLabelInfo.s)) @@ -358,30 +304,30 @@ public interface PrinterImpl { jsonObject.getJSONArray("goods").forEach(item -> { String proName = ((JSONObject) item).getString("proName"); String qty = ((JSONObject) item).getString("number"); - data.append(getFormatLabel(formatItemLine(" - " + proName, "", qty, 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3(" - " + proName, "", qty, 18, 9), signLabelInfo.s)).append(signLabelInfo.br); }); } } - if (StrUtil.isNotBlank(printInfoDTO.getSeatAmount())) { - data.append(getFormatLabel(formatItemLine("餐位费", printInfoDTO.getSeatAmount(), printInfoDTO.getSeatNum(), 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getSeatAmount())) { + data.append(getFormatLabel(key3("餐位费", orderPrintDTO.getSeatAmount(), orderPrintDTO.getSeatNum(), 18, 9), signLabelInfo.s)).append(signLabelInfo.br); } - if (StrUtil.isNotBlank(printInfoDTO.getPackFee())) { - data.append(getFormatLabel(formatItemLine("打包费", toPlainStr(printInfoDTO.getPackFee()), "", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getPackFee())) { + data.append(getFormatLabel(key3("打包费", toPlainStr(orderPrintDTO.getPackFee()), "", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); } data.append(getFormatLabel("-------------------------------", signLabelInfo.s)) .append(signLabelInfo.br); - data.append(getFormatLabel(leftRightAlign("原价:", printInfoDTO.getOriginalAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); - if (ObjectUtil.isNotNull(printInfoDTO.getDiscountAmount())) { - data.append(getFormatLabel(leftRightAlign("优惠:", "-" + printInfoDTO.getDiscountAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(leftRightAlign("原价:", orderPrintDTO.getOriginalAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); + if (ObjectUtil.isNotNull(orderPrintDTO.getDiscountAmount())) { + data.append(getFormatLabel(leftRightAlign("优惠:", "-" + orderPrintDTO.getDiscountAmount(), 32), signLabelInfo.s)).append(signLabelInfo.br); } - if (StrUtil.isNotBlank(printInfoDTO.getRemark())) { - data.append(getFormatLabel(StrUtil.format("备注:{}", printInfoDTO.getRemark()), signLabelInfo.s)).append(signLabelInfo.br); + if (StrUtil.isNotBlank(orderPrintDTO.getRemark())) { + data.append(getFormatLabel(StrUtil.format("备注:{}", orderPrintDTO.getRemark()), signLabelInfo.s)).append(signLabelInfo.br); } data.append(getFormatLabel("--------------------------------", signLabelInfo.s)) .append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("操作员:{}", printInfoDTO.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("操作员:{}", orderPrintDTO.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); data.append(getFormatLabel(StrUtil.format("打印时间:{}", DateUtil.date().toString()), signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("订单号:{}", printInfoDTO.getOrderNo()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("订单号:{}", orderPrintDTO.getOrderNo()), signLabelInfo.s)).append(signLabelInfo.br); data.append(signLabelInfo.getOut(180)); data.append(signLabelInfo.cut); return data.toString(); @@ -390,29 +336,29 @@ public interface PrinterImpl { /** * 构建退款订单打印元数据 * - * @param printInfoDTO 打印信息 - * @param detailList 订单详情 + * @param orderPrintDTO 打印信息 + * @param detailList 订单详情 * @return 订单打印元数据 */ - default String buildRefundOrderPrintData(PrinterHandler.PrintInfoDTO printInfoDTO, List detailList) { + default String buildRefundOrderPrintData(OrderPrintDTO orderPrintDTO, List detailList) { PrintSignLabel signLabelInfo = getSignLabelInfo(); StringBuilder data = new StringBuilder(); - data.append(getFormatLabel(printInfoDTO.getShopName(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); - data.append(getFormatLabel(printInfoDTO.getPrintTitle(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); - data.append(getFormatLabel(printInfoDTO.getPickupNum(), signLabelInfo.f)).append(signLabelInfo.br); - data.append(getFormatLabel(getFormatLabel(leftRightAlign(printInfoDTO.getPrintType(), StrUtil.isNotBlank(printInfoDTO.getSeatNum()) ? printInfoDTO.getSeatNum() + "人" : "", 32)) + data.append(getFormatLabel(orderPrintDTO.getShopName(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + data.append(getFormatLabel(orderPrintDTO.getPrintTitle(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + data.append(getFormatLabel(orderPrintDTO.getPickupNum(), signLabelInfo.f)).append(signLabelInfo.br); + data.append(getFormatLabel(getFormatLabel(leftRightAlign(orderPrintDTO.getPrintType(), StrUtil.isNotBlank(orderPrintDTO.getSeatNum()) ? orderPrintDTO.getSeatNum() + "人" : "", 32)) , signLabelInfo.s)).append(signLabelInfo.br); data.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br); if (CollUtil.isNotEmpty(detailList)) { - data.append(getFormatLabel(formatItemLine("退款明细", "数量", "小计", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3("退款明细", "数量", "小计", 18, 9), signLabelInfo.s)).append(signLabelInfo.br); for (OrderDetail detail : detailList) { String number = detail.getNum().stripTrailingZeros().toPlainString(); String amount = ""; - if ("退款单".equals(printInfoDTO.getPrintTitle())) { + if ("退款单".equals(orderPrintDTO.getPrintTitle())) { amount = detail.getReturnAmount().stripTrailingZeros().toPlainString(); } - data.append(getFormatLabel(formatItemLine(detail.getProductName(), number, amount, 18, 7), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3(detail.getProductName(), number, amount, 18, 7), signLabelInfo.s)).append(signLabelInfo.br); if (StrUtil.isNotBlank(detail.getSkuName())) { data.append(getFormatLabel(StrUtil.format("规格:{}", detail.getSkuName()), signLabelInfo.s)) .append(signLabelInfo.br); @@ -430,91 +376,136 @@ public interface PrinterImpl { jsonObject.getJSONArray("goods").forEach(item -> { String proName = ((JSONObject) item).getString("proName"); String qty = ((JSONObject) item).getString("number"); - data.append(getFormatLabel(formatItemLine(" - " + proName, "", qty, 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(key3(" - " + proName, "", qty, 18, 9), signLabelInfo.s)).append(signLabelInfo.br); }); } } data.append(getFormatLabel("--------------------------------", signLabelInfo.s)) .append(signLabelInfo.br); } - if ("退款单".equals(printInfoDTO.getPrintTitle())) { - data.append(getFormatLabel(leftRightAlign("退款总计", printInfoDTO.getRefundAmount(), 16), signLabelInfo.f)).append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("退款方式: {}", printInfoDTO.getRefundType()), signLabelInfo.s)) + if ("退款单".equals(orderPrintDTO.getPrintTitle())) { + data.append(getFormatLabel(leftRightAlign("退款总计", orderPrintDTO.getRefundAmount(), 16), signLabelInfo.f)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("退款方式: {}", orderPrintDTO.getRefundType()), signLabelInfo.s)) .append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("退款原因: {}", printInfoDTO.getRefundReason()), signLabelInfo.s)) + data.append(getFormatLabel(StrUtil.format("退款原因: {}", orderPrintDTO.getRefundReason()), signLabelInfo.s)) .append(signLabelInfo.br); } else { - data.append(getFormatLabel(StrUtil.format("退菜原因: {}", printInfoDTO.getRefundReason()), signLabelInfo.s)) + data.append(getFormatLabel(StrUtil.format("退菜原因: {}", orderPrintDTO.getRefundReason()), signLabelInfo.s)) .append(signLabelInfo.br); } data.append(getFormatLabel("--------------------------------", signLabelInfo.s)) .append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("操作员:{}", printInfoDTO.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("操作员:{}", orderPrintDTO.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); data.append(getFormatLabel(StrUtil.format("打印时间:{}", DateUtil.date().toString()), signLabelInfo.s)).append(signLabelInfo.br); - data.append(getFormatLabel(StrUtil.format("订单号:{}", printInfoDTO.getOrderNo()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("订单号:{}", orderPrintDTO.getOrderNo()), signLabelInfo.s)).append(signLabelInfo.br); data.append(signLabelInfo.getOut(180)); data.append(signLabelInfo.cut); return data.toString(); } - /** - * 构建菜品单打印数据 + * 后厨-总单 + * 后厨-退菜单 * - * @param pickupNumber 取餐号 - * @param date 时间 - * @param productName 商品名 - * @param skuName 规格名称 - * @param number 数量 - * @param remark 备注 - * @param proGroupInfo 套餐信息 * @return 元数据 */ - default String buildDishPrintData(boolean isReturn, String pickupNumber, String date, String productName, String skuName, - BigDecimal number, String remark, String proGroupInfo, Long orderDetailId, boolean isUrgent) { + default String buildAllKitchenPrintData(OrderPrintDTO orderPrintDTO, List detailList) { + PrintSignLabel signLabelInfo = getSignLabelInfo(); + StringBuilder data = new StringBuilder(); + data.append(getFormatLabel(orderPrintDTO.getShopName(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + data.append(getFormatLabel(orderPrintDTO.getPrintTitle(), signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + data.append(getFormatLabel(orderPrintDTO.getPickupNum(), signLabelInfo.f)).append(signLabelInfo.br); + data.append(getFormatLabel(getFormatLabel(orderPrintDTO.getPrintType()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel("--------------------------------", signLabelInfo.s)).append(signLabelInfo.br); + if (CollUtil.isNotEmpty(detailList)) { + data.append(getFormatLabel(leftRightAlign("品名", "数量", 32), signLabelInfo.s)).append(signLabelInfo.br); + for (OrderDetail detail : detailList) { + BigDecimal num = detail.getNum().subtract(detail.getReturnNum()); + data.append(getFormatLabel(leftRightAlign(detail.getProductName(), num.stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + + if (StrUtil.isNotBlank(detail.getSkuName())) { + data.append(getFormatLabel(StrUtil.format("规格:{}", detail.getSkuName()), signLabelInfo.s)) + .append(signLabelInfo.br); + } + String proGroupInfo = detail.getProGroupInfo(); + if (StrUtil.isNotBlank(proGroupInfo) && JSONUtil.isTypeJSONArray(proGroupInfo)) { + JSONArray subItems = com.alibaba.fastjson2.JSONArray.parseArray(proGroupInfo); + for (Object subItem : subItems) { + JSONObject jsonObject = (JSONObject) subItem; + jsonObject.getJSONArray("goods").forEach(item -> { + String proName = ((JSONObject) item).getString("proName"); + String qty = ((JSONObject) item).getString("number"); + data.append(getFormatLabel(key3(" - " + proName, "", qty, 18, 9), signLabelInfo.s)).append(signLabelInfo.br); + }); + } + } + data.append(getFormatLabel(StrUtil.format(" 备注:{}", detail.getRemark()), signLabelInfo.s)).append(signLabelInfo.br); + } + data.append(getFormatLabel("--------------------------------", signLabelInfo.s)) + .append(signLabelInfo.br); + } + data.append(getFormatLabel(StrUtil.format("备注: {}", orderPrintDTO.getRemark()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel("--------------------------------", signLabelInfo.s)) + .append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("操作员:{}", orderPrintDTO.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("打印时间:{}", DateUtil.date().toString()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(getFormatLabel(StrUtil.format("订单号:{}", orderPrintDTO.getOrderNo()), signLabelInfo.s)).append(signLabelInfo.br); + data.append(signLabelInfo.getOut(180)); + data.append(signLabelInfo.cut); + return data.toString(); + } + + /** + * 后厨-单商品单 + * + * @param pickupNumber 取餐号 + * @return 元数据 + */ + default String buildOnlyKitchenPrintData(String pickupNumber, OrderDetail orderDetail) { PrintSignLabel signLabelInfo = getSignLabelInfo(); StringBuilder builder = new StringBuilder(); - if (isReturn) { - builder.append(getFormatLabel(StrUtil.format("{}【退】", pickupNumber), signLabelInfo.centerBold)) - .append(signLabelInfo.br) - .append(signLabelInfo.br); -// builder.append("").append(pickupNumber).append("【退】

"); - } else { - builder.append(getFormatLabel(pickupNumber, signLabelInfo.centerBold)) - .append(signLabelInfo.br) - .append(signLabelInfo.br); -// builder.append("").append(pickupNumber).append("

"); - } - builder.append(getFormatLabel(StrUtil.format("时间: {}", date), signLabelInfo.l, signLabelInfo.center)) - .append(signLabelInfo.br) + builder.append(getFormatLabel(pickupNumber, signLabelInfo.centerBold)) .append(signLabelInfo.br); -// builder.append("时间: ").append(date).append("


"); - if (productName.length() > 4) { - builder.append(getFormatLabel(StrUtil.format("{} x {}", productName, number.stripTrailingZeros().toPlainString()), signLabelInfo.l, signLabelInfo.f, signLabelInfo.center)) + builder.append(getFormatLabel(StrUtil.format("时间: {}", DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss")), signLabelInfo.f, signLabelInfo.center)) + .append(signLabelInfo.br); + Integer isWaitCall = ObjectUtil.defaultIfNull(orderDetail.getIsWaitCall(), 0); + if (isWaitCall == 1) { + if (!orderDetail.getProductName().contains("【等叫】")) { + orderDetail.setProductName("【等叫】" + orderDetail.getProductName()); + } + } + Integer isTemporary = ObjectUtil.defaultIfNull(orderDetail.getIsTemporary(), 0); + if (isTemporary == 1) { + orderDetail.setProductId(0L); + orderDetail.setSkuId(0L); + if (!orderDetail.getProductName().contains("【临】")) { + orderDetail.setProductName("【临】" + orderDetail.getProductName()); + } + } + boolean isGift = orderDetail.getIsGift() != null && orderDetail.getIsGift() == 1; + if (isGift && !orderDetail.getProductName().contains("【赠】")) { + orderDetail.setProductName("【赠】" + orderDetail.getProductName()); + } + if (orderDetail.getProductName().length() > 4) { + builder.append(getFormatLabel(StrUtil.format("{} x {}", orderDetail.getProductName(), orderDetail.getNum().stripTrailingZeros().toPlainString()), signLabelInfo.f, signLabelInfo.center)) .append(signLabelInfo.br); -// builder.append("").append(productName).append(" x ").append(number).append("
"); - if (StrUtil.isNotBlank(skuName)) { - builder.append(getFormatLabel("(" + skuName + ")", signLabelInfo.l, signLabelInfo.f, signLabelInfo.center)).append(signLabelInfo.br); -// builder.append("").append(skuName).append("
"); + if (StrUtil.isNotBlank(orderDetail.getSkuName())) { + builder.append(getFormatLabel("(" + orderDetail.getSkuName() + ")", signLabelInfo.f, signLabelInfo.center)).append(signLabelInfo.br); } } else { - builder.append(getFormatLabel(StrUtil.format("{} x {}", productName, number.stripTrailingZeros().toPlainString()), signLabelInfo.l, signLabelInfo.f, signLabelInfo.center)) + builder.append(getFormatLabel(StrUtil.format("{} x {}", orderDetail.getProductName(), orderDetail.getNum().stripTrailingZeros().toPlainString()), signLabelInfo.f, signLabelInfo.center)) .append(signLabelInfo.br); -// builder.append("").append(productName).append(" x ").append(number).append("
"); - if (StrUtil.isNotBlank(skuName)) { - builder.append(getFormatLabel("(" + skuName + ")", signLabelInfo.l, signLabelInfo.f, signLabelInfo.center)) + if (StrUtil.isNotBlank(orderDetail.getSkuName())) { + builder.append(getFormatLabel("(" + orderDetail.getSkuName() + ")", signLabelInfo.f, signLabelInfo.center)) .append(signLabelInfo.br); -// builder.append("").append(skuName).append("
"); } } - if (StrUtil.isNotBlank(remark)) { - builder.append(signLabelInfo.br); - builder.append(getFormatLabel(StrUtil.format("备注:{}", remark), signLabelInfo.s, signLabelInfo.l)) + if (StrUtil.isNotBlank(orderDetail.getRemark())) { + builder.append(getFormatLabel(StrUtil.format("备注:{}", orderDetail.getRemark()), signLabelInfo.f)) .append(signLabelInfo.br); -// builder.append("备注: ").append(note).append("
"); } - if (!StrUtil.isBlank(proGroupInfo) && JSONUtil.isTypeJSONArray(proGroupInfo)) { - JSONArray subItems = JSONArray.parseArray(proGroupInfo); + if (!StrUtil.isBlank(orderDetail.getProGroupInfo()) && JSONUtil.isTypeJSONArray(orderDetail.getProGroupInfo())) { + JSONArray subItems = JSONArray.parseArray(orderDetail.getProGroupInfo()); for (Object subItem : subItems) { JSONObject jsonObject = (JSONObject) subItem; jsonObject.getJSONArray("goods").forEach(item -> { @@ -523,24 +514,283 @@ public interface PrinterImpl { builder.append(StrUtil.format("({}) x {}", proName, qty)) .append(signLabelInfo.br); }); - -// builder.append("(").append(i + 1).append(")").append(proName).append(" x ").append(qty).append("
"); } } - if (isUrgent) { + if (orderDetail.isUrgent()) { builder.append(getFormatLabel("【加急】", signLabelInfo.center, signLabelInfo.bold)) .append(signLabelInfo.br); } -// builder.append(getFormatLabel("UP_ORDER_DETAIL:" + orderDetailId, signLabelInfo.center, signLabelInfo.qr)) -// .append(signLabelInfo.br); builder.append(signLabelInfo.br) .append(signLabelInfo.getOut(150)) .append(signLabelInfo.cut); -// builder.append(""); -// builder.append(""); return builder.toString(); } + /** + * 出入库打印单 + */ + default String buildStockData(StockPrintDTO record) { + PrintSignLabel signLabelInfo = getSignLabelInfo(); + StringBuilder builder = new StringBuilder(); + + // 标题:入库 + 店铺名称 + 入库单 + builder.append(getFormatLabel(record.getShopName(), signLabelInfo.center)).append(signLabelInfo.br); + builder.append(getFormatLabel("IN".equals(record.getType()) ? "入库单" : "出库单", signLabelInfo.s, signLabelInfo.center)).append(signLabelInfo.br); + + // 入库时间 + builder.append(getFormatLabel(StrUtil.format("IN".equals(record.getType()) ? "入库时间: {}" : "出库时间: {}", DateUtil.format(record.getInStockTime(), "yyyy/MM/dd HH:mm:ss")), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + builder.append(getFormatLabel(key4("耗材名称", "库存单位", "IN".equals(record.getType()) ? "入库数量" : "出库数量", "金额", + 14, 6, 6), signLabelInfo.s)).append(signLabelInfo.br); + + // 遍历耗材明细,逐行打印 + List items = record.getItems(); + if (CollUtil.isNotEmpty(items)) { + for (StockPrintDTO.InStockItem item : items) { + String stockNumber = item.getStockNumber().stripTrailingZeros().toPlainString(); + String amount = item.getAmount().stripTrailingZeros().toPlainString(); + // 左对齐排版,保证列对齐 + String itemLine = key4(item.getConsName(), item.getUnit(), stockNumber, amount, 14, 6, 6); + builder.append(getFormatLabel(itemLine, signLabelInfo.s)).append(signLabelInfo.br); + } + } + builder.append(signLabelInfo.br); + // 总计行 + String consCountStr = "耗材" + (record.getConsCount() == null ? "0" : record.getConsCount().toString()) + "种"; + String stockNumberCountStr = "数量" + record.getStockNumberCount(); + String amountCountStr = "金额" + record.getAmountCount(); + + String totalLine = key4("总计", consCountStr, stockNumberCountStr, amountCountStr, 8, 8, 8); + builder.append(getFormatLabel(totalLine, signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + + // 操作员、打印时间 + builder.append(getFormatLabel(StrUtil.format("操作员: {}", record.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("打印时间: {}", DateUtil.format(record.getPrintTime(), "yyyy/MM/dd HH:mm:ss")), signLabelInfo.s)).append(signLabelInfo.br); + + // 结尾空行 + 切纸(和充值单保持一致) + builder.append(signLabelInfo.getOut(150)).append(signLabelInfo.cut); + return builder.toString(); + } + + /** + * 日报表打印单 + */ + default String buildDayReportData(DayReportPrintDTO record) { + PrintSignLabel signLabelInfo = getSignLabelInfo(); + StringBuilder builder = new StringBuilder(); + + // 标题:店铺名称 + 经营日报(居中,和充值/入库单风格统一) + builder.append(getFormatLabel(record.getShopName(), signLabelInfo.center)).append(signLabelInfo.br); + builder.append(getFormatLabel("经营日报", signLabelInfo.centerBold)).append(signLabelInfo.br).append(signLabelInfo.br); + + // 基础信息:打印时间、操作人、统计时间 + builder.append(getFormatLabel(StrUtil.format("打印时间: {}", DateUtil.format(LocalDateTime.now(), "yyyy/MM/dd HH:mm:ss")), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("操作人: {}", record.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("统计时间: {}", record.getStatisticsTime()), signLabelInfo.s)).append(signLabelInfo.br).append(signLabelInfo.br); + + // 营业总额 + DayReportPrintDTO.TurnoverSts turnover = record.getTurnover(); + String turnoverStr = turnover.getTurnover().stripTrailingZeros().toPlainString(); + builder.append(getFormatLabel(leftRightAlign("营业总额:", turnoverStr, 32), signLabelInfo.s)).append(signLabelInfo.br).append(signLabelInfo.br); + + // 实际收款的支付方式 + builder.append(getFormatLabel("实际收款的支付方式", signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 现金", turnover.getCash().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 微信", turnover.getWechat().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 支付宝", turnover.getAlipay().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 二维码收款", turnover.getSelfScan().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 扫码收款", turnover.getBarScan().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 充值", turnover.getRecharge().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br).append(signLabelInfo.br); + + // 非实际收款的支付方式 + builder.append(getFormatLabel("非实际收款的支付方式", signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 挂账", turnover.getOwed().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 余额", turnover.getBalance().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + + // 退款/退菜 + String refundAmountStr = record.getRefundAmount().stripTrailingZeros().toPlainString(); + // 退菜数量:示例图为固定4,这里按业务逻辑预留,若DTO无该字段可按需求补充 + String returnDishCount = "4"; + builder.append(getFormatLabel("退款/退菜", signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 退款金额", refundAmountStr, 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 退菜数量", returnDishCount, 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + + // 订单(数量/订单总额) + DayReportPrintDTO.OrderSts order = record.getOrder(); + String orderInfo = order.getOrderCount() + "/" + order.getOrderAmount().stripTrailingZeros().toPlainString(); + builder.append(getFormatLabel(leftRightAlign("订单(数量/订单总额)", orderInfo, 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + + // 数据统计 + DayReportPrintDTO.Sts sts = record.getSts(); + builder.append(getFormatLabel("数据统计", signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign("就餐人数", sts.getCustomerCount().toString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign("客单价", sts.getAvgPayAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + // 翻台率、毛利率:保留%符号,按示例格式输出 + String turnoverRateStr = sts.getTurnoverRate().stripTrailingZeros().toPlainString() + "%"; + String profitRateStr = sts.getProfitRate().stripTrailingZeros().toPlainString() + "%"; + builder.append(getFormatLabel(leftRightAlign("翻台率", turnoverRateStr, 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign("毛利率", profitRateStr, 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign("商品成本", sts.getProductCostAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + + // 结尾空行 + 切纸(和充值/入库单完全一致) + builder.append(signLabelInfo.getOut(150)).append(signLabelInfo.cut); + return builder.toString(); + } + + /** + * 商品报表打印单 + */ + default String buildProductReportData(ProductReportPrintDTO record) { + PrintSignLabel signLabelInfo = getSignLabelInfo(); + StringBuilder builder = new StringBuilder(); + + // 标题:店铺名称 + 商品报表(居中,和之前的报表风格统一) + builder.append(getFormatLabel(record.getShopName(), signLabelInfo.center)).append(signLabelInfo.br); + builder.append(getFormatLabel("商品报表", signLabelInfo.centerBold)).append(signLabelInfo.br).append(signLabelInfo.br); + + // 基础信息:打印时间、操作人、统计时间 + builder.append(getFormatLabel(StrUtil.format("打印时间: {}", DateUtil.format(LocalDateTime.now(), "yyyy/MM/dd HH:mm:ss")), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("操作人: {}", record.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("统计时间: {}", record.getStatisticsTime()), signLabelInfo.s)).append(signLabelInfo.br).append(signLabelInfo.br); + + // 总计行:总计商品X件,实收金额X元 + String totalCountStr = record.getTotalProductCount().stripTrailingZeros().toPlainString(); + String totalActualStr = record.getTotalActualAmount().stripTrailingZeros().toPlainString(); + builder.append(getFormatLabel(StrUtil.format("总计商品{}件,实收金额{}元", totalCountStr, totalActualStr), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br).append(signLabelInfo.br); + + // 表头:商品、数量、实收、销售额(四列对齐,和示例图完全匹配) + String header = key4("商品", "数量", "实收", "销售额", 12, 8, 8); + builder.append(getFormatLabel(header, signLabelInfo.s)).append(signLabelInfo.br); + + // 遍历分类+商品明细 + Map> itemsMap = record.getItems(); + if (CollUtil.isNotEmpty(itemsMap)) { + for (Map.Entry> entry : itemsMap.entrySet()) { + String categoryName = entry.getKey(); + List productList = entry.getValue(); + + // 先打印分类名称行(分类名称+该分类汇总数量/实收/销售额,和示例图一致) + // 分类汇总:遍历该分类下所有商品,求和 + BigDecimal categoryTotalNum = BigDecimal.ZERO; + BigDecimal categoryTotalActual = BigDecimal.ZERO; + BigDecimal categoryTotalSales = BigDecimal.ZERO; + for (ProductReportPrintDTO.ProductItem item : productList) { + categoryTotalNum = categoryTotalNum.add(item.getNumber()); + categoryTotalActual = categoryTotalActual.add(item.getActualAmount()); + categoryTotalSales = categoryTotalSales.add(item.getSalesAmount()); + } + // 打印分类行(缩进0,和表头对齐) + String categoryLine = key4(categoryName, + categoryTotalNum.stripTrailingZeros().toPlainString(), + categoryTotalActual.stripTrailingZeros().toPlainString(), + categoryTotalSales.stripTrailingZeros().toPlainString(), + 12, 8, 8); + builder.append(getFormatLabel(categoryLine, signLabelInfo.s)).append(signLabelInfo.br); + + // 再打印该分类下的商品明细(缩进2个空格,和示例图一致) + for (ProductReportPrintDTO.ProductItem item : productList) { + String numStr = item.getNumber().stripTrailingZeros().toPlainString(); + String actualStr = item.getActualAmount().stripTrailingZeros().toPlainString(); + String salesStr = item.getSalesAmount().stripTrailingZeros().toPlainString(); + // 商品名称前加2个空格,实现缩进效果 + String productLine = key4(" " + item.getProductName(), numStr, actualStr, salesStr, 12, 8, 8); + builder.append(getFormatLabel(productLine, signLabelInfo.s)).append(signLabelInfo.br); + } + } + } + // 结尾空行 + 切纸(和之前所有打印单完全一致) + builder.append(signLabelInfo.getOut(150)).append(signLabelInfo.cut); + return builder.toString(); + } + + + /** + * 充值打印单 + */ + default String buildRechargeData(RechargePrintDTO record) { + PrintSignLabel signLabelInfo = getSignLabelInfo(); + StringBuilder builder = new StringBuilder(); + // 标题:店铺名称 + 充值凭证 + builder.append(getFormatLabel(record.getShopName(), signLabelInfo.centerBold)).append(signLabelInfo.br); + builder.append(getFormatLabel("充值凭证", signLabelInfo.centerBold)).append(signLabelInfo.br); + + // 用户信息 + builder.append(getFormatLabel(StrUtil.format("充值用户: {}(id{})", record.getUserName(), record.getUserId()), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("手机号: {}", record.getUserPhone()), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("支付时间: {}", DateUtil.format(record.getPayTime(), "yyyy/MM/dd HH:mm:ss")), signLabelInfo.s)).append(signLabelInfo.br); + // 充值明细 + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 充值金额:", record.getRechargeAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 赠送金额:", record.getGiftAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 赠送积分:", record.getGiftPoints().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 赠送优惠券:", record.getGiftCoupon() + "", 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign(" 充值后余额:", record.getBalance().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + // 支付信息 + builder.append(getFormatLabel(leftRightAlign("已付金额:", record.getPayAmount().stripTrailingZeros().toPlainString(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(leftRightAlign("支付方式:", record.getPayType(), 32), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("操作员: {}", record.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("充值编号: {}", record.getRechargeId()), signLabelInfo.s)).append(signLabelInfo.br); + + // 结尾空行 + 切纸 + builder.append(signLabelInfo.getOut(150)).append(signLabelInfo.cut); + return builder.toString(); + } + + /** + * 库存盘点打印单 + */ + default String buildStockCheckData(StockCheckPrintDTO record) { + PrintSignLabel signLabelInfo = getSignLabelInfo(); + StringBuilder builder = new StringBuilder(); + + // 标题:店铺名称 + 盘点单(居中,和之前所有打印单风格统一) + builder.append(getFormatLabel(record.getShopName(), signLabelInfo.center)).append(signLabelInfo.br); + builder.append(getFormatLabel("盘点单", signLabelInfo.centerBold)).append(signLabelInfo.br).append(signLabelInfo.br); + + // 表头:耗材名称、单价、实际数、盈亏数(四列对齐,复用key4工具方法) + String header = key4("耗材名称", "单价", "实际数", "盈亏数", 12, 10, 8); + builder.append(getFormatLabel(header, signLabelInfo.s)).append(signLabelInfo.br); + + // 遍历耗材明细,逐行打印 + List items = record.getItems(); + if (CollUtil.isNotEmpty(items)) { + for (StockCheckPrintDTO.StockCheckItem item : items) { + String priceStr = item.getPrice().stripTrailingZeros().toPlainString() + item.getUnit(); + String actualNumberStr = item.getActualNumber().toString(); + String winLossNumberStr = item.getWinLossNumber().toString(); + // 四列对齐打印 + String itemLine = key4(item.getConsName(), priceStr, actualNumberStr, winLossNumberStr, 12, 10, 8); + builder.append(getFormatLabel(itemLine, signLabelInfo.s)).append(signLabelInfo.br); + } + } + + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br).append(signLabelInfo.br); + + // 账存数量、盈亏金额、备注 + builder.append(getFormatLabel(StrUtil.format("账存数量: {}", record.getWinLossNumberCount()), signLabelInfo.s)).append(signLabelInfo.br); + String winLossAmountStr = record.getWinLossAmount().stripTrailingZeros().toPlainString(); + builder.append(getFormatLabel(StrUtil.format("盈亏金额: {}", winLossAmountStr), signLabelInfo.s)).append(signLabelInfo.br); + builder.append(getFormatLabel(StrUtil.format("备注: {}", StrUtil.isBlank(record.getRemark()) ? "" : record.getRemark()), signLabelInfo.s)).append(signLabelInfo.br); + + builder.append(getFormatLabel("----------------------------------------")).append(signLabelInfo.br).append(signLabelInfo.br); + // 操作员、打印时间 + builder.append(getFormatLabel(StrUtil.format("操作员: {}", record.getOperator()), signLabelInfo.s)).append(signLabelInfo.br); + // 打印时间:复用之前的DateUtil格式化,若DTO需补充printTime字段,可按需求添加 + builder.append(getFormatLabel(StrUtil.format("打印时间: {}", DateUtil.format(LocalDateTime.now(), "yyyy/MM/dd HH:mm:ss")), signLabelInfo.s)).append(signLabelInfo.br); + + // 结尾空行 + 切纸(和之前所有打印单完全一致) + builder.append(signLabelInfo.getOut(150)).append(signLabelInfo.cut); + return builder.toString(); + } + + /** * 构建叫号元数据 * @@ -555,17 +805,6 @@ public interface PrinterImpl { */ default String buildCallTicketData(String shopName, String tableName, String callNum, String preNum, String codeUrl, String shopNote, LocalDateTime takeTime) { PrintSignLabel signLabelInfo = getSignLabelInfo(); - // sb.append("").append(shopName).append("

") -// .append("------------------------
") -// .append(StrUtil.format(StrUtil.format("{} {}
", tableName, callNum))) -// .append(StrUtil.format("前面有{}桌
", preNum)) -// .append(StrUtil.format("{}
", codeUrl)) -// .append("怕过号扫一扫
") -// .append("------------------------
") -// .append(StrUtil.format("{}
", shopNote)) -// .append("------------------------
").append("取号时间:").append(DateUtil.format(takeTime, "yyyy-MM-dd HH:mm:ss")) -// .append("
").append("打印时间:").append(DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss")).append("
") -// .append("").append(""); return getFormatLabel(shopName, signLabelInfo.center, signLabelInfo.bold) + signLabelInfo.br + signLabelInfo.br + @@ -573,108 +812,17 @@ public interface PrinterImpl { signLabelInfo.br + getFormatLabel(StrUtil.format("前面有{}桌", preNum), signLabelInfo.center) + signLabelInfo.br + - getFormatLabel("怕过号扫一扫", signLabelInfo.center, signLabelInfo.bold) + + getFormatLabel("怕过号,扫一扫", signLabelInfo.center, signLabelInfo.bold) + signLabelInfo.br + getFormatLabel(codeUrl, signLabelInfo.center, signLabelInfo.qr) + signLabelInfo.br + "--------------------------------" + signLabelInfo.br + - getFormatLabel(shopNote, signLabelInfo.s) + - signLabelInfo.br + - "--------------------------------" + signLabelInfo.br + + getFormatLabel("听到叫号请到前台,过号可顺延1桌", signLabelInfo.s) + getFormatLabel(StrUtil.format("取号时间: {}", DateUtil.format(takeTime, "yyyy-MM-dd HH:mm:ss")), signLabelInfo.s) + signLabelInfo.br + - getFormatLabel(StrUtil.format("打印时间: {}", DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss")), signLabelInfo.s) + - signLabelInfo.br + signLabelInfo.cut; } - /** - * 按字符数补足空格(英文、数字时使用) - * - * @param str 对应字符串 - * @param size 总长度 - * @return 填充之后的字符串 - */ - default String addSpace(String str, int size) { - int len = str.length(); - if (len < size) { - str = str + " ".repeat(size - len); - } - return str; - } - - /** - * 按固定长度拆分字符串(按字符拆分) - * - * @param inputString 字符串 - * @param length 每个长度 - * @return 分割后的集合 - */ - default List getStrList(String inputString, int length) { - List list = new ArrayList<>(); - for (int i = 0; i < inputString.length(); i += length) { - list.add(StrUtil.sub(inputString, i, Math.min(i + length, inputString.length()))); - } - return list; - } - - - /** - * 判断字符串是否全为英文(GBK编码下,每个字符均为 1 字节) - * - * @param str 字符 - * @return 是否英文 - */ - default boolean isEn(String str) { - return StrUtil.bytes(str, CharsetUtil.CHARSET_GBK).length == str.length(); - } - - /** - * 根据 GBK 字节数补空格(用于中文排版) - * - * @param str 字符串 - * @param b1 总长度 - * @return 添加间距的字符串 - */ - default String titleAddSpace(String str, int b1) { - int k; - try { - k = str.getBytes("GBK").length; - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - str = str + " ".repeat(Math.max(0, b1 - k)); - return str; - } - - /** - * 获取填充字符串, 并且换行 - * - * @param length 长度 - * @param string 字符串 - * @return 填充字符串 - */ - default String getStringByEnter(String string, int length) { - PrintSignLabel signLabelInfo = getSignLabelInfo(); - StringBuilder result = new StringBuilder(); - while (!string.isEmpty()) { - int pos = 0, byteCount = 0; - for (int i = 0; i < string.length(); i++) { - int charByteLen = StrUtil.bytes(string.substring(i, i + 1), CharsetUtil.CHARSET_GBK).length; - if (byteCount + charByteLen > length) { - break; - } - byteCount += charByteLen; - pos = i + 1; - } - result.append(signLabelInfo.s[0]).append(string, 0, pos).append(signLabelInfo.s[1]); - string = string.substring(pos); - if (!string.isEmpty()) { - result.append("
"); - } - } - return result.toString(); - } /** * 获取规格化的字符串 @@ -689,7 +837,6 @@ public interface PrinterImpl { return NumberUtil.round(new BigDecimal(str), 2).toPlainString(); } - // 两个内容 左 右对齐 default String leftRightAlign(String leftText, String rightText, int totalWidth) { if (leftText == null) leftText = ""; @@ -709,30 +856,14 @@ public interface PrinterImpl { return leftText + spaces + rightText; } - /** - * 获取字符串实际打印宽度(汉字=2,字母/数字=1) - */ - static int getStringWidth(String str) { - if (str == null || str.isEmpty()) return 0; - int width = 0; - for (char c : str.toCharArray()) { - if (String.valueOf(c).getBytes().length > 1) { - width += 2; // 中文 - } else { - width += 1; // 英文/数字 - } - } - return width; - } - /** * 通用三列对齐方法(严格总长度) * 规则:key1=左对齐,key2=左对齐,key3=右对齐 * 整行总长度 = totalWidth,绝不超界 */ - default String formatItemLine(String key1, String key2, String key3, - int key1Width, - int key2Width) { + default String key3(String key1, String key2, String key3, + int key1Width, + int key2Width) { // 1. 空值安全处理 key1 = Objects.toString(key1, ""); key2 = Objects.toString(key2, ""); @@ -759,6 +890,54 @@ public interface PrinterImpl { + key3; } + default String key4(String key1, String key2, String key3, String key4, + int key1Width, int key2Width, int key3Width) { + // 1. 空值安全处理 + key1 = Objects.toString(key1, ""); + key2 = Objects.toString(key2, ""); + key3 = Objects.toString(key3, ""); + key4 = Objects.toString(key4, ""); + + // 👉 核心:key1 超长截取 + 加 ... + key1 = truncateWithEllipsis(key1, key1Width); + + int w1 = getStringWidth(key1); + int w2 = getStringWidth(key2); + int w3 = getStringWidth(key3); + int w4 = getStringWidth(key4); + + int space1 = Math.max(key1Width - w1, 0); + int space2 = Math.max(key2Width - w2, 0); + int space3 = Math.max(key3Width - w3, 0); + + // 6. 最终按总显示宽度截断(100%不超界) + int usedWidth = key1Width + key2Width + key3Width + w4; + int space4 = Math.max(32 - usedWidth, 0); + + // 5. 拼接:左1 + 空格 + 左2 + 空格 + (靠右空格) + 右3 + return key1 + " ".repeat(space1) + + key2 + " ".repeat(space2) + + key3 + " ".repeat(space3) + + " ".repeat(space4) + + key4; + } + + /** + * 获取字符串实际打印宽度(汉字=2,字母/数字=1) + */ + static int getStringWidth(String str) { + if (str == null || str.isEmpty()) return 0; + int width = 0; + for (char c : str.toCharArray()) { + if (String.valueOf(c).getBytes().length > 1) { + width += 2; // 中文 + } else { + width += 1; // 英文/数字 + } + } + return width; + } + private String truncateWithEllipsis(String text, int maxWidth) { if (maxWidth <= 0) return ""; if (getStringWidth(text) <= maxWidth) { diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java index 41b117bec..00a9d3caf 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java @@ -1,13 +1,12 @@ package com.czg.service.order.print; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.http.HttpUtil; import com.czg.account.dto.HandoverRecordDTO; import com.czg.account.entity.PrintMachine; import com.czg.order.entity.OrderDetail; import com.czg.order.entity.OrderInfo; +import com.czg.print.*; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -56,12 +55,157 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl { .setBr("
") .setBold(new String[]{"", ""}); + + @Override + protected void onlyKitchenPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) { + String buildDishPrintData = buildOnlyKitchenPrintData(getPickupNum(orderInfo), orderDetail); + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + if (1 == machine.getVolumeSwitch()) { + voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; + } + String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(orderInfo.getId(), machine, "后厨商品单", buildDishPrintData, resp); + } + + @Override + public OrderPrintDTO allKitchenPrint(OrderInfo orderInfo, List orderDetails, PrintMachine machine) { + OrderPrintDTO orderPrintDTO = super.allKitchenPrint(orderInfo, orderDetails, machine); + String buildDishPrintData = buildAllKitchenPrintData(orderPrintDTO, orderDetails); + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + if (1 == machine.getVolumeSwitch()) { + voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; + } + String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(orderInfo.getId(), machine, "后厨总单", buildDishPrintData, resp); + return null; + } + + @Override + public OrderPrintDTO returnKitchenPrint(String operator, OrderInfo orderInfo, List orderDetail, PrintMachine machine) { + OrderPrintDTO orderPrintDTO = super.returnKitchenPrint(operator, orderInfo, orderDetail, machine); + String buildDishPrintData = buildAllKitchenPrintData(orderPrintDTO, orderDetail); + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + if (1 == machine.getVolumeSwitch()) { + voiceJson = "{\"bizType\":\"2\",\"content\":\"退菜消息,请及时处理\"}"; + } + String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(orderInfo.getId(), machine, "后厨退菜", buildDishPrintData, resp); + return null; + } + + @Override + public OrderPrintDTO returnOrderPrint(String printTitle, String operator, String refundAmount, String refundReason, String refundType, + OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.returnOrderPrint(printTitle, operator, refundAmount, refundReason, refundType, orderInfo, machine, detailList); + String data = buildRefundOrderPrintData(orderPrintDTO, detailList); + sendOrderPrint(data, orderInfo.getId(), machine, "退款单"); + return null; + } + + @Override + public OrderPrintDTO guestOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.guestOrderPrint(orderInfo, machine, detailList); + String data = buildGuestOrderPrintData(orderPrintDTO, detailList); + sendOrderPrint(data, orderInfo.getId(), machine, "客看单"); + return null; + } + + @Override + public OrderPrintDTO preOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.preOrderPrint(orderInfo, machine, detailList); + String data = buildOrderPrintData(orderPrintDTO, detailList); + sendOrderPrint(data, orderInfo.getId(), machine, "预结算单"); + return null; + } + + @Override + public OrderPrintDTO orderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { + OrderPrintDTO orderPrintDTO = super.orderPrint(orderInfo, machine, detailList); + String data = buildOrderPrintData(orderPrintDTO, detailList); + sendOrderPrint(data, orderInfo.getId(), machine, "结算单"); + return null; + } + + /** + * 叫号单打印 + */ + @Override + protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) { + String resp = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime); + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + if (1 == machine.getVolumeSwitch()) { + voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一条新的排号记录\"}"; + } + sendPrintRequest(machine.getAddress(), resp, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + } + + + @Override + protected void stockPrint(PrintMachine machine, StockPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildStockData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "入库单", data, resp); + } + + @Override + protected void dayReportPrint(PrintMachine machine, DayReportPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildDayReportData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "经营日报单", data, resp); + } + + @Override + protected void productReportPrint(PrintMachine machine, ProductReportPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildProductReportData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "商品报表单", data, resp); + } + + @Override + protected void rechargePrint(PrintMachine machine, RechargePrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildRechargeData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "储值单", data, resp); + } + + @Override + protected void stockCheckPrint(PrintMachine machine, StockCheckPrintDTO record) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + String data = buildStockCheckData(record); + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(machine, "盘点单", data, resp); + } + + + /** + * 交班单打印 + */ + @Override + protected void handoverPrint(PrintMachine machine, HandoverRecordDTO record) { + String string = buildHandoverData(record); + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + sendPrintRequest(machine.getAddress(), string, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + } + + + private void sendOrderPrint(String data, Long orderId, PrintMachine machine, String bizType) { + String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; + if (1 == machine.getVolumeSwitch()) { + voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; + } + String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, machine.getPrintNum() == null ? "1" : machine.getPrintNum().toString()); + printMachineLogService.save(orderId, machine, bizType, data, resp); + } + @Override public PrintSignLabel getSignLabelInfo() { return printSignLabel; } - @Override public String sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum) { log.info("开始请求云享印,请求数据:{}, {}", voiceData, metaPrintData); @@ -98,85 +242,6 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl { return httpResponse; } - @Override - protected void normalDishesPrint(String operator, OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) { - String buildDishPrintData = buildDishPrintData(false, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(), - orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent()); - String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; - if (1 == machine.getVolumeSwitch()) { - voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; - } - String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1"); - printMachineLogService.save(orderInfo.getId(), machine, "新订单", buildDishPrintData, resp); - - } - - @Override - protected void returnDishesPrint(String operator, OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) { - String buildDishPrintData = buildDishPrintData(true, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(), - orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent()); - String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; - String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1"); - printMachineLogService.save(orderInfo.getId(), machine, "退款单", buildDishPrintData, resp); - - } - - @Override - public PrintInfoDTO returnOrderPrint(String printTitle, String operator, String refundAmount, String refundReason, String refundType, - OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.returnOrderPrint(printTitle, operator, refundAmount, refundReason, refundType, orderInfo, machine, detailList); - String data = buildRefundOrderPrintData(printInfoDTO, detailList); - sendOrderPrint(data, orderInfo.getId(), machine, "退款单"); - return null; - } - - @Override - public PrintInfoDTO guestOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.guestOrderPrint(orderInfo, machine, detailList); - String data = buildGuestOrderPrintData(printInfoDTO, detailList); - sendOrderPrint(data, orderInfo.getId(), machine, "客看单"); - return null; - } - - @Override - public PrintInfoDTO preOrderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.preOrderPrint(orderInfo, machine, detailList); - String data = buildOrderPrintData(printInfoDTO, detailList); - sendOrderPrint(data, orderInfo.getId(), machine, "预结算单"); - return null; - } - - @Override - public PrintInfoDTO orderPrint(OrderInfo orderInfo, PrintMachine machine, List detailList) { - PrintInfoDTO printInfoDTO = super.orderPrint(orderInfo, machine, detailList); - String data = buildOrderPrintData(printInfoDTO, detailList); - sendOrderPrint(data, orderInfo.getId(), machine, "结算单"); - return null; - } - - /** - * 叫号单打印 - */ - @Override - protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) { - String resp = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime); - String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; - if (1 == machine.getVolumeSwitch()) { - voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一条新的排号记录\"}"; - } - sendPrintRequest(machine.getAddress(), resp, voiceJson, "1"); - } - - - /** - * 交班单打印 - */ - @Override - protected void handoverPrint(PrintMachine machine, HandoverRecordDTO record) { - String string = buildHandoverData(record); - String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; - sendPrintRequest(machine.getAddress(), string, voiceJson, "1"); - } /** * 获取TOKEN值 @@ -200,20 +265,6 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl { return SecureUtil.md5(token + APP_SECRET).toUpperCase(); } - private void sendOrderPrint(String data, Long orderId, PrintMachine machine, String bizType) { - String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}"; - if (1 == machine.getVolumeSwitch()) { - voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; - } - String printerNum = "1"; - if (StrUtil.isNotBlank(machine.getPrintQty())) { - printerNum = machine.getPrintQty().split("\\^")[1]; - } - String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum); - printMachineLogService.save(orderId, machine, bizType, data, resp); - } - - /** * 检查打印状态 * diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java index 062ec684f..a888f5a6f 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java @@ -332,11 +332,13 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService { if ("after-pay".equals(orderInfo.getPayMode())) { // log.info("后付费生成订单{},第{}", orderInfo.getId(), orderInfo.getPlaceNum()); + //客看单 printerHandler.orderHandler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.GUEST_ORDER, orderInfo.getPlaceNum()); - //发送打票信息 后付费推送多次 需要处理 //orderId_0_0 订单ID_先付后付(1先付0后付)_订单状态 0未完成 1完成_第几次下单 //orderInfo.getId() + "_" + (!"after-pay".equals(orderInfo.getPayMode()) ? 1 : 0) + "_0" + //后付费 菜品单 rabbitPublisher.sendKitchenOrderPrintMsg(orderInfo.getId() + "_0_0", false, "后付费打印"); + // 消息通知 本地打印机执行 rabbitPublisher.sendOrderPrintMsg(orderInfo.getId() + "_0_0_" + orderInfo.getPlaceNum(), true, "后付费打印"); } else { redisService.set(RedisCst.classKeyExpired.EXPIRED_ORDER + orderInfo.getId(), "", 60 * 15); @@ -1616,9 +1618,6 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService { } switch (orderInfoPrintDTO.getType()) { - case 0://菜品和结算单同时打印 - printerHandler.orderHandler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.ONE_AND_ORDER, null); - break; case 1://预结算单 printerHandler.orderHandler(orderInfo.getId().toString(), PrinterHandler.PrintTypeEnum.PRE_ORDER, null); break; diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoRpcServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoRpcServiceImpl.java index a69581f31..38d1375ec 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoRpcServiceImpl.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoRpcServiceImpl.java @@ -1,7 +1,6 @@ package com.czg.service.order.service.impl; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.convert.Convert; import cn.hutool.core.util.NumberUtil; import com.alibaba.fastjson2.JSONObject; import com.czg.account.entity.HandoverRecord; @@ -25,7 +24,8 @@ import org.apache.dubbo.config.annotation.DubboService; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; -import java.util.*; +import java.util.ArrayList; +import java.util.List; /** * 订单Rpc ServiceImpl @@ -169,7 +169,8 @@ public class OrderInfoRpcServiceImpl implements OrderInfoRpcService { } @Override - public void sendHandoverReceiptPrintMsgToMq(Long handoverRecordId) { - rabbitPublisher.sendHandoverPrintMsg(Convert.toStr(handoverRecordId)); + public void sendHandoverReceiptPrintMsgToMq(Long shopId, HandoverRecord record) { + rabbitPublisher.sendOtherPrintMsg(shopId, record, "HANDOVER"); + } } diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderPayServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderPayServiceImpl.java index 9d85fa5f3..fb2b0ae57 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderPayServiceImpl.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderPayServiceImpl.java @@ -381,7 +381,7 @@ public class OrderPayServiceImpl implements OrderPayService { } boolean isFirstRefund = orderInfo.getRefundAmount().compareTo(BigDecimal.ZERO) == 0; ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId()); - Map productStockMap = new HashMap<>(); + Map productStockMap = new HashMap<>(); boolean isPay = true; String refPayOrderNo = "REFO" + IdUtil.getSnowflakeNextId(); if (orderInfo.getStatus().equals(OrderStatusEnums.UNPAID.getCode())) { @@ -524,13 +524,20 @@ public class OrderPayServiceImpl implements OrderPayService { orderInfoService.updateById(orderInfo); //退款后续 退款单/退菜单 if (param.isPrint()) { - printerHandler.refundOrderHandler(printTitle, StrUtil.isNotBlank(param.getOperator()) ? param.getOperator() : "" - , isPay ? param.getRefundAmount().toPlainString() : "0" - , param.getRefundReason(), orderInfo.getRefundType(), orderInfo, param.getRefundDetails()); + String finalPrintTitle = printTitle; + boolean finalIsPay = isPay; + FunUtils.safeRunVoid(() -> printerHandler.refundOrderHandler(finalPrintTitle, StrUtil.isNotBlank(param.getOperator()) ? param.getOperator() : "" + , finalIsPay ? param.getRefundAmount().toPlainString() : "0" + , param.getRefundReason(), orderInfo.getRefundType(), orderInfo, param.getRefundDetails()), + "订单id:{} 退款,前台打印消息失败", orderInfo.getId()); } + //后厨退菜单 + FunUtils.safeRunVoid(() -> printerHandler.kitchenRefundAllHandler(StrUtil.isNotBlank(param.getOperator()) ? param.getOperator() : "", orderInfo, param.getRefundDetails()), + "订单id:{} 退款,后厨退菜单打印消息失败", orderInfo.getId()); //退款返还库存 if (!productStockMap.isEmpty()) { - orderInfoCustomService.refundStock(shopInfo, orderInfo.getId(), productStockMap, param.isRefundStock()); + FunUtils.safeRunVoid(() -> orderInfoCustomService.refundStock(shopInfo, orderInfo.getId(), productStockMap, param.isRefundStock()), + "订单id:{} 退款,库存处理失败", orderInfo.getId()); } refundOrderAfter(orderInfo.getId(), orderInfo.getShopId(), orderInfo.getUserId(), orderInfo.getOrderNo(), orderInfo.getPointsNum(), isFirstRefund, orderInfo.getStatus().equals(OrderStatusEnums.REFUND.getCode())); diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java index c13a5395c..bf61615f2 100644 --- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java +++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java @@ -93,7 +93,7 @@ public class PrintMachineLogServiceImpl extends ServiceImpl sendInOutPrintMsg("IN", shopId, param)); return param; } @@ -145,6 +149,33 @@ public class ConsStockFlowServiceImpl extends ServiceImpl sendInOutPrintMsg("OUT", shopId, param)); + } + + private void sendInOutPrintMsg(String type, Long shopId, ConsInOutStockHeadParam param) { + StockPrintDTO stockPrint = new StockPrintDTO(); + stockPrint.setType(type); + stockPrint.setPrintTime(LocalDateTime.now()); + stockPrint.setOperator(param.getOperator()); + stockPrint.setConsCount(param.getBodyList().size()); + List items = new ArrayList<>(); + BigDecimal totalInOutNumber = BigDecimal.ZERO; + BigDecimal totalAmount = BigDecimal.ZERO; + for (ConsInOutStockBodyParam cons : param.getBodyList()) { + StockPrintDTO.InStockItem item = new StockPrintDTO.InStockItem(); + item.setConsName(cons.getConName()); + item.setUnit(cons.getUnitName()); + item.setStockNumber(cons.getInOutNumber()); + item.setAmount(cons.getSubTotal()); + items.add(item); + totalInOutNumber = NumberUtil.add(totalInOutNumber, cons.getInOutNumber()); + totalAmount = NumberUtil.add(totalAmount, cons.getSubTotal()); + } + stockPrint.setStockNumberCount(totalInOutNumber); + stockPrint.setAmountCount(totalAmount); + stockPrint.setItems(items); + //库存盘点 + rabbitPublisher.sendOtherPrintMsg(shopId, stockPrint, "STOCK"); } @Override @@ -183,6 +214,19 @@ public class ConsStockFlowServiceImpl extends ServiceImpl { + StockCheckPrintDTO stockCheckPrintDTO = new StockCheckPrintDTO(); + stockCheckPrintDTO.setWinLossNumberCount(winLossNumber.intValue()); + stockCheckPrintDTO.setWinLossAmount(entity.getSubTotal()); + stockCheckPrintDTO.setRemark(entity.getRemark()); + stockCheckPrintDTO.setOperator(param.getOperator()); + List items = new ArrayList<>(); + items.add(new StockCheckPrintDTO.StockCheckItem(consInfo.getConName(), param.getPrice(), consInfo.getConUnit(), param.getActualNumber(), param.getWinLossNumber())); + stockCheckPrintDTO.setItems(items); + //库存盘点 + rabbitPublisher.sendOtherPrintMsg(shopId, stockCheckPrintDTO, "STOCK_CHECK"); + }); } @Override