diff --git a/mall-common/src/main/java/com/suisung/mall/common/pojo/vo/OrderPrintVO.java b/mall-common/src/main/java/com/suisung/mall/common/pojo/vo/OrderPrintVO.java index 9c7db24a..d1f166ab 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/pojo/vo/OrderPrintVO.java +++ b/mall-common/src/main/java/com/suisung/mall/common/pojo/vo/OrderPrintVO.java @@ -29,6 +29,9 @@ public class OrderPrintVO implements Serializable { @ApiModelProperty(value = "退单编号") private String return_id; + @ApiModelProperty(value = "店铺Id") + private Integer store_id; + @ApiModelProperty(value = "店铺名称") private String store_name; @@ -132,7 +135,7 @@ public class OrderPrintVO implements Serializable { private String cashier = "收银员"; @ApiModelProperty(value = "订单商品详情打印对象列表") - private List orderItemPrintVOList; + private List order_items; } diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/FreeMakerUtils.java b/mall-common/src/main/java/com/suisung/mall/common/utils/FreeMakerUtils.java index 90877d3c..955df822 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/FreeMakerUtils.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/FreeMakerUtils.java @@ -39,7 +39,7 @@ public class FreeMakerUtils { * @throws IOException * @throws TemplateException */ - public static String processTemplate(Configuration configuration, String templateName, String templateValue, Map binding) { + public static String processTemplate(Configuration configuration, String templateName, String templateValue, Object binding) { StringWriter stringWriter = new StringWriter(); try { Template template = new Template(templateName, templateValue, configuration); @@ -63,4 +63,8 @@ public class FreeMakerUtils { public static String processTemplate(String templateName, String templateValue, Map binding) { return processTemplate(stringTempConfiguration(), templateName, templateValue, binding); } + + public static String processTemplate(String templateName, String templateValue, Object binding) { + return processTemplate(stringTempConfiguration(), templateName, templateValue, binding); + } } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java index 7d5f3e00..43ee78a6 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java @@ -20,6 +20,7 @@ import com.suisung.mall.shop.message.service.PushMessageService; import com.suisung.mall.shop.order.service.ShopOrderBaseService; import com.suisung.mall.shop.order.service.ShopOrderReturnService; import com.suisung.mall.shop.sfexpress.service.SFExpressApiService; +import com.suisung.mall.shop.store.service.ShopStorePrinterService; import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -77,7 +78,7 @@ public class LakalaController extends BaseControllerImpl { @Lazy @Resource - private LakalaApiService lakalaApiService; + private ShopStorePrinterService shopStorePrinterService; @Resource private LklLedgerEcService lklLedgerEcService; @@ -93,7 +94,7 @@ public class LakalaController extends BaseControllerImpl { // return lakalaApiService.tradeQuery(paramsJSON.getInt("storeId"), paramsJSON.getStr("orderId")); - return JSONUtil.parseObj(shopOrderReturnService.fetchReturnOrderPrintInfo("", "FX_20251127_9")); + return shopStorePrinterService.printShopStoreReturnOrder(paramsJSON.getStr("orderId"), paramsJSON.getStr("returnId")); } @ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例") diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStorePrinterService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStorePrinterService.java index 833c0e35..7aa53d9f 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStorePrinterService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStorePrinterService.java @@ -80,6 +80,15 @@ public interface ShopStorePrinterService extends IBaseService */ Boolean printShopStoreOrder(Integer storeId, String orderId); + /** + * 退货成功后,立即打印门店的退货信息 + * + * @param orderId + * @param returnId + * @return + */ + Boolean printShopStoreReturnOrder(String orderId, String returnId); + /** * 获取店铺所有有效打印机 * diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterLogServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterLogServiceImpl.java index 413bd440..8257424e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterLogServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterLogServiceImpl.java @@ -5,11 +5,9 @@ import cn.hutool.core.util.StrUtil; import com.suisung.mall.common.modules.store.ShopStorePrinterLog; import com.suisung.mall.core.web.service.impl.BaseServiceImpl; import com.suisung.mall.shop.store.mapper.ShopStorePrinterLogMapper; -import com.suisung.mall.shop.store.mapper.ShopStorePrinterMapper; import com.suisung.mall.shop.store.service.ShopStorePrinterLogService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @@ -19,41 +17,70 @@ import java.util.List; public class ShopStorePrinterLogServiceImpl extends BaseServiceImpl implements ShopStorePrinterLogService { private static final Logger logger = LoggerFactory.getLogger(ShopStorePrinterLogServiceImpl.class); - @Autowired - private ShopStorePrinterMapper shopStorePrinterMapper; @Override public Boolean insertShopStorePrinterLog(ShopStorePrinterLog record) { + // 参数校验 if (record == null) { + logger.warn("插入打印日志失败:记录为空"); return false; } + // 必要字段校验 if (record.getStore_id() == null || StrUtil.isBlank(record.getOrder_id()) || StrUtil.isBlank(record.getTemplate_value()) || StrUtil.isBlank(record.getPrint_content())) { + logger.warn("插入打印日志失败:必要字段缺失,storeId={}, orderId={}", + record.getStore_id(), record.getOrder_id()); return false; } - return add(record); + try { + // 执行插入操作 + return add(record); + } catch (Exception e) { + logger.error("插入打印日志时发生异常,storeId={}, orderId={}", + record.getStore_id(), record.getOrder_id(), e); + return false; + } } + @Override public void insertShopStorePrinterLogBatch(List records) { + // 参数校验 if (CollUtil.isEmpty(records)) { + logger.debug("批量插入打印日志失败:记录列表为空"); return; } - for (ShopStorePrinterLog record : records) { - if (record.getStore_id() == null || - StrUtil.isBlank(record.getOrder_id()) || - StrUtil.isBlank(record.getTemplate_value()) || - StrUtil.isBlank(record.getPrint_content())) { - continue; + try { + for (ShopStorePrinterLog record : records) { + // 单条记录校验 + if (record == null) { + logger.warn("批量插入打印日志跳过:记录为空"); + continue; + } + + if (record.getStore_id() == null || + StrUtil.isBlank(record.getOrder_id()) || + StrUtil.isBlank(record.getTemplate_value()) || + StrUtil.isBlank(record.getPrint_content())) { + logger.warn("批量插入打印日志跳过:必要字段缺失,storeId={}, orderId={}", + record.getStore_id(), record.getOrder_id()); + continue; + } + + // 执行插入操作 + add(record); } - add(record); + logger.debug("批量插入打印日志完成,共处理 {} 条记录", records.size()); + } catch (Exception e) { + logger.error("批量插入打印日志时发生异常,记录数: {}", records.size(), e); } } + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterServiceImpl.java index 1efc3c6a..a1debf34 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStorePrinterServiceImpl.java @@ -14,13 +14,15 @@ import com.suisung.mall.common.domain.UserDto; import com.suisung.mall.common.modules.store.ShopStorePrinter; import com.suisung.mall.common.modules.store.ShopStorePrinterLog; import com.suisung.mall.common.modules.store.ShopStorePrinterTemplate; +import com.suisung.mall.common.pojo.vo.OrderItemPrintVO; +import com.suisung.mall.common.pojo.vo.OrderPrintVO; import com.suisung.mall.common.pojo.vo.ShopStorePrinterVO; import com.suisung.mall.common.utils.CheckUtil; import com.suisung.mall.common.utils.FreeMakerUtils; import com.suisung.mall.common.utils.JsonUtil; import com.suisung.mall.core.web.service.impl.BaseServiceImpl; import com.suisung.mall.shop.order.service.ShopOrderBaseService; -import com.suisung.mall.shop.order.service.impl.ShopOrderInfoServiceImpl; +import com.suisung.mall.shop.order.service.ShopOrderReturnService; import com.suisung.mall.shop.store.mapper.ShopStorePrinterMapper; import com.suisung.mall.shop.store.service.ShopStorePrinterLogService; import com.suisung.mall.shop.store.service.ShopStorePrinterService; @@ -49,15 +51,13 @@ public class ShopStorePrinterServiceImpl extends BaseServiceImpl + * 该方法通过调用飞鹅打票机接口,完成指定订单的退货小票打印功能。主要流程包括: + * 1. 校验订单号是否合法; + * 2. 获取订单及店铺相关信息; + * 3. 查询对应店铺绑定的打印机列表与打印模板; + * 4. 渲染打印内容并发送至所有绑定的打印机; + * 5. 记录打印日志。 + *

+ * + * @param orderId 订单编号,不能为空 + * @param returnId 退货单编号,用于标识具体的退货记录 + * @return 打印操作是否成功,成功返回 true,否则返回 false + */ + @Override + public Boolean printShopStoreReturnOrder(String orderId, String returnId) { + logger.debug("#### 调用飞鹅打票机的打印退款订单操作开始 ####"); + + // 参数校验 + if (StrUtil.isBlank(returnId)) { + logger.error("退款订单为空,无法打印小票。"); + return false; + } + + try { + // 获取打印的订单信息,并检查订单是否存在且已支付 + OrderPrintVO binding = shopOrderReturnService.fetchReturnOrderPrintInfo(orderId, returnId); + if (binding == null) { + logger.error("退款订单Id{}信息无法获取,无法打印小票。", returnId); + return false; + } + + logger.debug("退款订单信息:{}", binding); + + orderId = binding.getOrder_id(); + Integer storeId = binding.getStore_id(); + if (CheckUtil.isEmpty(storeId) || CheckUtil.isEmpty(orderId)) { + logger.warn("订单Id:{},店铺ID:{}为空,无法打印小票。", orderId, storeId); + return false; + } + + // 查询店铺配置的打印机列表 + List printerList = selectPrinterList(storeId); + if (CollUtil.isEmpty(printerList)) { + // 店铺没有打印机,不再继续执行打印逻辑 + logger.error("店铺{}未添加打票机,无法打印小票。", storeId); + return false; + } + + // 获取适用于退货场景的打印模板 + ShopStorePrinterTemplate template = shopStorePrinterTemplateService.getShopStorePrinterTemplateInner(storeId, StateCode.PRINTER_TEMP_CATE_REFUND); + if (template == null || StrUtil.isBlank(template.getTemplate_name()) || StrUtil.isBlank(template.getTemplate_value())) { + // 模板缺失或无效,终止打印流程 + logger.error("店铺{}未添加打票机打印模版,无法打印小票。", storeId); + return false; + } + + // 重要:重构实体类,处理标题,数量,价格适应长度 + List orderItems = binding.getOrder_items(); + if (CollUtil.isEmpty(orderItems)) { + logger.error("订单{}商品信息为空,无法打印小票。", orderId); + return false; + } + + List rebuiltItems = new ArrayList<>(orderItems.size()); + for (OrderItemPrintVO item : orderItems) { + if (item != null) { + rebuiltItems.add(item.rebuild()); + } + } + binding.setOrder_items(rebuiltItems); + + // 使用 FreeMarker 模板引擎渲染实际要打印的内容 + String printContent = FreeMakerUtils.processTemplate(template.getTemplate_name(), template.getTemplate_value(), binding); + if (StrUtil.isBlank(printContent)) { + logger.error("订单{}信息模版渲染异常,无法打印小票。", orderId); + return false; + } + logger.debug("打印内容长度:{}", printContent.length()); + + // 提取所有打印机设备序列号,准备批量打印 + List printerSnList = new ArrayList<>(printerList.size()); + for (ShopStorePrinter printer : printerList) { + if (printer != null && StrUtil.isNotBlank(printer.getPrinter_sn())) { + printerSnList.add(printer.getPrinter_sn()); + } + } + + if (CollUtil.isEmpty(printerSnList)) { + logger.error("订单{}没有有效的打印机设备,无法打印小票。", orderId); + return false; + } + + // 向飞鹅打票机发送打印任务 + List> respList = feieUtil.printContentByList(printerSnList, printContent); + if (CollUtil.isEmpty(respList)) { + // 所有打印机均未能响应,视为失败 + logger.error("订单{}信息打印,调用飞鹅打印机打印失败。", orderId); + return false; + } + + // 遍历每台打印机的响应结果,记录打印日志 + for (Pair respSn : respList) { + if (respSn != null) { + // 构造并保存本次打印的日志记录 + ShopStorePrinterLog shopStorePrinterLog = new ShopStorePrinterLog( + template.getCategory(), + storeId, + orderId, + template.getTemplate_id(), + template.getTemplate_value(), + JsonUtil.object2json(binding), + printContent, + respSn.getSecond(), + respSn.getFirst() + ); + shopStorePrinterLogService.insertShopStorePrinterLog(shopStorePrinterLog); + } + } + + logger.debug("#### 调用飞鹅打票机的打印操作结束 ####"); + return true; + + } catch (Exception e) { + logger.error("打印退货订单小票时发生异常,订单ID: {}, 退货单ID: {}", orderId, returnId, e); + return false; + } + } + + @Override public List selectPrinterList(Integer storeId) { if (storeId == null) { diff --git a/mall-shop/src/main/resources/mapper/order/ShopOrderReturnMapper.xml b/mall-shop/src/main/resources/mapper/order/ShopOrderReturnMapper.xml index 3cfd21a3..8ae0e6c9 100644 --- a/mall-shop/src/main/resources/mapper/order/ShopOrderReturnMapper.xml +++ b/mall-shop/src/main/resources/mapper/order/ShopOrderReturnMapper.xml @@ -92,6 +92,7 @@ + @@ -123,7 +124,7 @@ - + diff --git a/mall-shop/src/main/resources/templates/refund_order_printer.txt b/mall-shop/src/main/resources/templates/refund_order_printer.txt index 43bcf846..f4aa09e7 100644 --- a/mall-shop/src/main/resources/templates/refund_order_printer.txt +++ b/mall-shop/src/main/resources/templates/refund_order_printer.txt @@ -47,16 +47,16 @@ --------------------------------
#${order_pickup_num_str}
退款原因:${return_buyer_message!'-'}
-配送时间:${payment_time}(之后20-30分钟)
+配送时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}(之后20-30分钟)
--------------------------------
订单编号:${order_id}
退单编号:${return_id}
订单来源:${order_channel_name!'微信小程序'}
支付方式:${payment_type_name!'微信支付'}
配送来源:${deliver_type_name!'顺丰同城'}
-付款时间:${payment_time}
-申请退款:${return_add_time}
-确认退款:${return_finish_time}
+付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}
+申请退款:${return_add_time?string('yyyy-MM-dd HH:mm:ss')}
+确认退款:${return_finish_time?string('yyyy-MM-dd HH:mm:ss')}
--------------------------------
******* 退款商品 ******
--------------------------------
@@ -78,4 +78,4 @@ ${store_name}
--------------------------------
#${order_pickup_num_str}
买家备注:${order_message!'-'}
配送时间:${delivery_time}
--------------------------------
订单编号:${order_id}
订单来源:微信小程序
支付方式:微信支付
配送来源:顺丰同城
付款时间:${payment_time}
--------------------------------
商品名称 数量 金额
--------------------------------
<#list order_items as item>${item.s_name}${item.s_quantity}${item.s_amount}
<#if item.s_name_segs??><#list item.s_name_segs as seg>${seg}
<#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}
--------------------------------
商品总件数:${order_items_count!0}
商品总额:¥${order_product_amount?string('0.00')}
押金:¥${(yajin!0)?string('0.00')}
运费:¥${order_shipping_fee?string('0.00')}
会员权益:-¥${(quanyi!0)?string('0.00')}
秒杀:-¥${(miaosha!0)?string('0.00')}
实付金额:¥${order_payment_amount?string('0.00')}
<#if seller_message?default("")?trim?length gt 1>--------------------------------
商家备注:${seller_message!'---'}
--------------------------------
收货人:${buyer_user_name!''}
收货人手机:${store_tel!''}
收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}
--------------------------------
门店:${store_name}
门店电话:${store_tel!'-'}
收银员:${cashier!'-'}
带参模版: -用户退款订单
${store_name}
--------------------------------
#${order_pickup_num_str}
退款原因:${return_buyer_message!'-'}
配送时间:${payment_time}(之后20-30分钟)
--------------------------------
订单编号:${order_id}
退单编号:${return_id}
订单来源:${order_channel_name!'微信小程序'}
支付方式:${payment_type_name!'微信支付'}
配送来源:${deliver_type_name!'顺丰同城'}
付款时间:${payment_time}
申请退款:${return_add_time}
确认退款:${return_finish_time}
--------------------------------
******* 退款商品 ******
--------------------------------
<#list order_items as item>${item.s_name}${item.s_quantity}${item.s_amount}
<#if item.s_name_segs??><#list item.s_name_segs as seg>${seg}
<#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}
--------------------------------
实付金额:¥${order_payment_amount?string('0.00')}元
配送费:¥${order_shipping_fee?string('0.00')}元
申请退款:¥${return_refund_amount?string('0.00')}
退款方式:${return_flag_str}
商家审批备注:${return_store_message!'-'}
--------------------------------
会员名称:${buyer_user_name}
会员手机:${return_tel}
--------------------------------
操作员:${cashier!'-'}
+用户退款订单
${store_name}
--------------------------------
#${order_pickup_num_str}
退款原因:${return_buyer_message!'-'}
配送时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}(20-30分钟)
--------------------------------
订单编号:${order_id}
退单编号:${return_id}
订单来源:${order_channel_name!'微信小程序'}
支付方式:${payment_type_name!'微信支付'}
配送来源:${deliver_type_name!'顺丰同城'}
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}
申请退款:${return_add_time?string('yyyy-MM-dd HH:mm:ss')}
确认退款:${return_finish_time?string('yyyy-MM-dd HH:mm:ss')}
--------------------------------
******* 退款商品 ******
--------------------------------
<#list order_items as item>${item.s_name}${item.s_quantity}${item.s_amount}
<#if item.s_name_segs??><#list item.s_name_segs as seg>${seg}
<#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}
--------------------------------
实付金额:¥${order_payment_amount?string('0.00')}元
配送费:¥${order_shipping_fee?string('0.00')}元
申请退款:¥${return_refund_amount?string('0.00')}
退款方式:${return_flag_str}
商家审批备注:${return_store_message!'-'}
--------------------------------
会员名称:${buyer_user_name}
会员手机:${return_tel}
--------------------------------
操作员:${cashier!'-'}