diff --git a/src/main/java/com/budwk/app/sys/controller/v4/SysV4MsgController.java b/src/main/java/com/budwk/app/sys/controller/v4/SysV4MsgController.java index 8340f0a3..829997e6 100644 --- a/src/main/java/com/budwk/app/sys/controller/v4/SysV4MsgController.java +++ b/src/main/java/com/budwk/app/sys/controller/v4/SysV4MsgController.java @@ -50,8 +50,10 @@ public class SysV4MsgController { m.title, m.content, m.type, + m.sendTime, r.isRead, - r.readTime + r.readTime, + r.createdAt FROM global_message m INNER JOIN global_message_receiver r ON m.id = r.messageId @@ -69,7 +71,7 @@ public class SysV4MsgController { cnd.andEX("m.type", "=", type); - cnd.desc("m.sendTime"); + cnd.desc("m.sendTime").desc("r.createdAt"); sql.setCondition(cnd); String title = "审批待办"; diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/mode/GlobalMessageSendRequest.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/mode/GlobalMessageSendRequest.java index 328d03f6..a45c22f1 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/message/mode/GlobalMessageSendRequest.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/mode/GlobalMessageSendRequest.java @@ -45,4 +45,24 @@ public class GlobalMessageSendRequest { */ private List receiverIds; + /** + * 是否系统发送 + */ + private Boolean systemSend; + + /** + * 发送人ID + */ + private String senderId; + + /** + * 发送人名称 + */ + private String senderName; + + /** + * 发送人工号 + */ + private String senderLoginName; + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/GlobalMessageSendService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/GlobalMessageSendService.java index eb846e79..6441cafd 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/GlobalMessageSendService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/GlobalMessageSendService.java @@ -97,6 +97,66 @@ public class GlobalMessageSendService { sendMessage(request); } + /** + * 发送系统消息(不依赖当前登录token) + */ + public void sendSystemMessage(String title, String content, Integer type, List receiverIds, JSONObject config) { + GlobalMessageSendRequest request = new GlobalMessageSendRequest(); + request.setTitle(title); + request.setContent(content); + request.setType(type); + request.setReceiverIds(receiverIds); + request.setConfig(config); + request.setSystemSend(true); + request.setSenderId("system"); + request.setSenderName("系统"); + request.setSenderLoginName("system"); + + sendMessage(request); + } + + /** + * 发送本地系统消息(不依赖当前登录token) + */ + public void sendLocalSystemMessage(String title, String content, Integer type, List receiverIds, JSONObject config) { + GlobalMessageSendRequest request = new GlobalMessageSendRequest(); + request.setTitle(title); + request.setContent(content); + request.setType(type); + request.setReceiverIds(receiverIds); + request.setConfig(config); + request.setSystemSend(true); + request.setSenderId("system"); + request.setSenderName("系统"); + request.setSenderLoginName("system"); + + sendLocalMessage(request); + } + + /** + * 发送本地消息(使用请求对象) + */ + public void sendLocalMessage(GlobalMessageSendRequest request) { + try { + log.info("开始发送本地全局消息,标题:{},接收人数量:{}", request.getTitle(), + request.getReceiverIds() != null ? request.getReceiverIds().size() : 0); + + validateRequest(request); + applySystemSenderConfig(request); + + if (localStrategy == null) { + throw new RuntimeException("本地消息发送策略未找到,系统无法正常工作"); + } + + localStrategy.send(request.getTitle(), request.getContent(), request.getType(), + request.getReceiverIds(), request.getConfig()); + log.info("本地全局消息发送完成,标题:{}", request.getTitle()); + } catch (Exception e) { + log.error("本地全局消息发送失败,标题:{},错误:{}", request.getTitle(), e.getMessage(), e); + throw new RuntimeException("本地消息发送失败:" + e.getMessage(), e); + } + } + /** * 发送消息(使用请求对象) */ @@ -107,6 +167,7 @@ public class GlobalMessageSendService { // 参数校验 validateRequest(request); + applySystemSenderConfig(request); // 获取启用的策略 List enabledStrategies = getEnabledStrategies(); @@ -161,6 +222,21 @@ public class GlobalMessageSendService { } } + private void applySystemSenderConfig(GlobalMessageSendRequest request) { + if (!Boolean.TRUE.equals(request.getSystemSend())) { + return; + } + JSONObject config = request.getConfig(); + if (config == null) { + config = new JSONObject(); + request.setConfig(config); + } + config.set("systemSend", true); + config.set("senderId", request.getSenderId()); + config.set("senderName", request.getSenderName()); + config.set("senderLoginName", request.getSenderLoginName()); + } + /** * 参数校验 */ diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/LocalMessageSendStrategy.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/LocalMessageSendStrategy.java index 895bc2b6..922c22a6 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/LocalMessageSendStrategy.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/LocalMessageSendStrategy.java @@ -13,6 +13,7 @@ import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import java.util.Date; import java.util.List; /** @@ -56,9 +57,15 @@ public class LocalMessageSendStrategy implements GlobalMessageSendStrategy { globalMessage.setTitle(title); globalMessage.setContent(content); globalMessage.setType(type); - globalMessage.setSenderId(SecurityUtil.getUserId()); - globalMessage.setSenderName(SecurityUtil.getUserUsername()); - globalMessage.setSenderLoginName(SecurityUtil.getUserLoginname()); + if (config != null && Boolean.TRUE.equals(config.getBool("systemSend"))) { + globalMessage.setSenderId(config.getStr("senderId")); + globalMessage.setSenderName(config.getStr("senderName")); + globalMessage.setSenderLoginName(config.getStr("senderLoginName")); + } else { + globalMessage.setSenderId(SecurityUtil.getUserId()); + globalMessage.setSenderName(SecurityUtil.getUserUsername()); + globalMessage.setSenderLoginName(SecurityUtil.getUserLoginname()); + } globalMessage.setStatus(1); // 草稿状态 globalMessage.setSendSuccess(false); dao.insert(globalMessage); @@ -77,6 +84,7 @@ public class LocalMessageSendStrategy implements GlobalMessageSendStrategy { // 更新消息状态为已发送 globalMessage.setStatus(2); + globalMessage.setSendTime(new Date()); globalMessage.setSendSuccess(true); globalMessage.setSendResult("本地消息发送成功"); dao.update(globalMessage); diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallOrderEventDTO.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallOrderEventDTO.java index 35a0ecf8..941548c1 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallOrderEventDTO.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/dto/MallOrderEventDTO.java @@ -10,5 +10,9 @@ public class MallOrderEventDTO { private String orderId; private String mainOrderId; private String userId; + private Integer deliveryStatus; + private String deliveryTime; + private String logisticsOrderId; + private String crrgBsnNm; private Long time; } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallShipOrderEventHandler.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallShipOrderEventHandler.java new file mode 100644 index 00000000..f89becef --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallShipOrderEventHandler.java @@ -0,0 +1,29 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers; + +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderEventDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.event.MallOrderEventHandler; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; +import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallInboundEventService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * MallShipOrderEventHandler + * orderType=99: 供应商已发货 / 更新发货状态。 + */ +@IocBean +public class MallShipOrderEventHandler implements MallOrderEventHandler { + + @Inject + private MallInboundEventService inboundEventService; + + @Override + public int getType() { + return 99; + } + + @Override + public MallInboundResult handle(MallOrderEventDTO dto) { + return inboundEventService.updateDeliveryStatus(dto); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/exception/MallBridgeError.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/exception/MallBridgeError.java new file mode 100644 index 00000000..6cd0864a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/exception/MallBridgeError.java @@ -0,0 +1,32 @@ +package com.budwk.app.zhgh.pointsmall.mallbridge.exception; + +/** + * MallBridgeError + * 说明: 商城桥接的统一错误码枚举, 包含HTTP风格的resultCode与默认提示文案。 + * 用于抛出MallBridgeException时传递标准化的错误信息。 + */ +public enum MallBridgeError { + ERROR(-1, "校验失败"), + AUTH_FAIL(401, "鉴权失败"), + PARAM_ERROR(400, "参数错误"), + ORDER_EXISTS(409, "订单已存在"), + ORDER_NOT_EXISTS(410, "订单不存在"), + NOT_FOUND(404, "资源不存在"), + SERVER_ERROR(500, "服务器内部错误"); + + private final int code; + private final String message; + + MallBridgeError(int code, String message) { + this.code = code; + this.message = message; + } + + public int code() { + return code; + } + + public String message() { + return message; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundEventService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundEventService.java index 5844f3df..ca04e64c 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundEventService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundEventService.java @@ -14,6 +14,7 @@ import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallCancelSubOrde import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallConfirmReceiptEventHandler; import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallExchangeSubEventHandler; import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallInvoiceInfoEventHandler; +import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallShipOrderEventHandler; import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallSplitSubOrderEventHandler; import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallSubOrderReturnEventHandler; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; @@ -69,6 +70,8 @@ public class MallInboundEventService extends AbstractMallBridgeSupport { private MallAbolishSubOrderEventHandler mallAbolishSubOrderEventHandler; @Inject private MallInvoiceInfoEventHandler mallInvoiceInfoEventHandler; + @Inject + private MallShipOrderEventHandler mallShipOrderEventHandler; public MallInboundEventService(Dao dao) { super(dao); @@ -105,6 +108,7 @@ public class MallInboundEventService extends AbstractMallBridgeSupport { register(handlerRegistry, mallCancelPayedMainOrderEventHandler); register(handlerRegistry, mallAbolishSubOrderEventHandler); register(handlerRegistry, mallInvoiceInfoEventHandler); + register(handlerRegistry, mallShipOrderEventHandler); return handlerRegistry; } @@ -346,6 +350,66 @@ public class MallInboundEventService extends AbstractMallBridgeSupport { } } + public MallInboundResult updateDeliveryStatus(MallOrderEventDTO dto) { + if (StrUtil.isBlank(dto.getSupplierId()) || StrUtil.isBlank(dto.getOrderId())) { + return MallInboundResult.fail(400, "供应商或订单不能为空"); + } + + List orderIds = splitIds(dto.getOrderId()); + if (orderIds.isEmpty()) { + return MallInboundResult.fail(400, "订单信息不能为空"); + } + + Date deliveryTime = parseDate(dto.getDeliveryTime()); + if (deliveryTime == null) { + deliveryTime = new Date(); + } + + Cnd subCnd = Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "in", orderIds) + .and("delFlag", "=", false); + if (StrUtil.isNotBlank(dto.getUserId())) { + subCnd.and("userId", "=", dto.getUserId()); + } + + List subs = dao.query(PointsMallOrderSub.class, subCnd); + if (subs.isEmpty()) { + return MallInboundResult.fail(404, "订单不存在"); + } + + Date finalDeliveryTime = deliveryTime; + Integer deliveredStatus = 1; + Trans.exec((Atom) () -> { + Chain subChain = Chain.make("deliveryStatus", deliveredStatus) + .add("deliveryTime", finalDeliveryTime); + if (StrUtil.isNotBlank(dto.getLogisticsOrderId())) { + subChain.add("logisticsOrderId", dto.getLogisticsOrderId()); + } + if (StrUtil.isNotBlank(dto.getCrrgBsnNm())) { + subChain.add("crrgBsnNm", dto.getCrrgBsnNm()); + } + dao.update(PointsMallOrderSub.class, subChain, subCnd); + + String mainOrderId = StrUtil.blankToDefault(dto.getMainOrderId(), subs.get(0).getMainOrderId()); + if (StrUtil.isNotBlank(mainOrderId)) { + Chain mainChain = Chain.make("deliveryStatus", String.valueOf(deliveredStatus)) + .add("deliveryTime", finalDeliveryTime); + if (StrUtil.isNotBlank(dto.getLogisticsOrderId())) { + mainChain.add("logisticsOrderId", dto.getLogisticsOrderId()); + } + if (StrUtil.isNotBlank(dto.getCrrgBsnNm())) { + mainChain.add("crrgBsnNm", dto.getCrrgBsnNm()); + } + dao.update(PointsMallOrderMain.class, mainChain, Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "=", mainOrderId).and("delFlag", "=", false)); + } + }); + + log.info("供应商已发货事件处理完成,supplierId={},mainOrderId={},orderIds={},deliveryStatus={}", + dto.getSupplierId(), dto.getMainOrderId(), orderIds, deliveredStatus); + return MallInboundResult.success(); + } + public MallInboundResult invoiceInfo(MallOrderEventDTO dto) { String mainOrderId = StrUtil.blankToDefault(dto.getMainOrderId(), dto.getOrderId()); if (StrUtil.isBlank(mainOrderId)) { diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundPurchaseResultService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundPurchaseResultService.java index 5d1ac433..ed7b8e3e 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundPurchaseResultService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallInboundPurchaseResultService.java @@ -1,10 +1,20 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.service; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallPurchaseResultDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderProInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.exception.MallBridgeError; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; +import com.budwk.app.zhgh.pointsmall.order.enums.MallOrderStatusEnum; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; -import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMainHistory; import com.budwk.app.zhgh.pointsmall.points.service.PointsMallPointsLockService; +import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; @@ -14,10 +24,14 @@ import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.trans.Atom; import org.nutz.trans.Trans; -import java.util.Date; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Collections; +import java.util.List; +import java.util.Objects; /** - * 商城桥接购买结果通知服务。 + * 9.2.14 支付结果通知接口 */ @Slf4j @IocBean(args = {"refer:dao"}) @@ -25,45 +39,105 @@ public class MallInboundPurchaseResultService { private final Dao dao; - @Inject - private MallInboundConfirmPurchaseService mallInboundConfirmPurchaseService; @Inject private PointsMallPointsLockService pointsMallPointsLockService; + @Inject + private GlobalMessageSendService globalMessageSendService; public MallInboundPurchaseResultService(Dao dao) { this.dao = dao; } - /** - * 接收购买结果。支付成功只同步现金支付状态;支付失败取消主单并释放锁定积分。 - */ public MallInboundResult purchaseResult(MallPurchaseResultDTO dto) { - log.info("积分商城购买结果通知,supplierId={},orderId={},purchaseResult={}", dto.getSupplierId(), dto.getOrderId(), dto.getPurchaseResult()); - PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) + log.info("9.2.14 支付结果通知接口 调用开始:{}", dto); + // 查询订单是否存在 + PointsMallOrderMain orderMain = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) .and("orderId", "=", dto.getOrderId()).and("delFlag", "=", false)); - if (main == null) { - return MallInboundResult.fail(404, "订单不存在"); + if (null == orderMain) { + return MallInboundResult.fail(MallBridgeError.ORDER_NOT_EXISTS.code(), "订单不存在"); } - if (Boolean.TRUE.equals(dto.getPurchaseResult())) { - Integer cashPaid = main.getWPayOrAPay() != null && main.getWPayOrAPay().signum() > 0 ? 2 : 0; - return mallInboundConfirmPurchaseService.updateMainOrderPay(dto.getSupplierId(), dto.getOrderId(), cashPaid, - dto.getTotalPrice(), dto.getWPayOrAPay(), dto.getPointsPrice()); + // 支付结果 + if (dto.getPurchaseResult()) { + log.info("9.2.14 支付结果通知接口,支付成功"); + if (BigDecimal.ZERO.compareTo(orderMain.getWPayOrAPay()) != 0) { + dao.update(PointsMallOrderMain.class, Chain.make("cashPaid", 2), Cnd.where("id", "=", orderMain.getId())); + } + try { + // callP消息推送 + pushMessageToCallP(orderMain); + } catch (Exception e) { + log.error("9.2.14 支付结果通知接口,callP消息推送:{},{}", dto, e.getMessage()); + } + return MallInboundResult.success(); } + if (Objects.equals(orderMain.getOrderState(), MallOrderStatusEnum.CANCELLED.getCode())) { + return MallInboundResult.fail(MallBridgeError.PARAM_ERROR.code(), "订单已取消,请不要重复推送"); + } + log.info("9.2.14 支付结果通知接口,支付失败,1.修改主订单支付状态为已取消 2.释放积分"); + // 支付失败,修改主订单支付状态为已取消 Trans.exec((Atom) () -> { - dao.update(PointsMallOrderMain.class, - Chain.make("orderState", 3) - .add("cashPaid", main.getWPayOrAPay() != null && main.getWPayOrAPay().signum() > 0 ? 3 : main.getCashPaid()) - .add("totalPrice", dto.getTotalPrice()) - .add("pointsPrice", dto.getPointsPrice()) - .add("wPayOrAPay", dto.getWPayOrAPay()) - .add("orderUpdateTime", new Date()), - Cnd.where("id", "=", main.getId())); - dao.update(PointsMallOrderSub.class, - Chain.make("orderState", 3).add("orderUpdateTime", new Date()), - Cnd.where("supplierId", "=", dto.getSupplierId()).and("mainOrderId", "=", dto.getOrderId()).and("delFlag", "=", false)); - pointsMallPointsLockService.releaseMain(main.getUserId(), main.getSupplierId(), main.getOrderId()); + Chain mainOrderUpdate = Chain.make("totalPrice", dto.getTotalPrice()) + .add("pointsPrice", dto.getPointsPrice()) + .add("wPayOrAPay", dto.getWPayOrAPay()) + .add("orderState", MallOrderStatusEnum.CANCELLED.getCode()); + if (BigDecimal.ZERO.compareTo(orderMain.getWPayOrAPay()) != 0) { + // 取消现金支付 + mainOrderUpdate.add("cashPaid", 3); + } + dao.update(PointsMallOrderMain.class, mainOrderUpdate, Cnd.where("id", "=", orderMain.getId())); + // 支付失败,释放积分 + pointsMallPointsLockService.releaseMain(orderMain.getUserId(), orderMain.getSupplierId(), orderMain.getOrderId()); + + // 添加历史记录 + PointsMallOrderMainHistory orderMainHistory = BeanUtil.copyProperties(orderMain, PointsMallOrderMainHistory.class); + // id 主键 + orderMainHistory.setId(null); + log.info("9.2.14 支付结果通知接口,保存订单主表流水记录"); + dao.insert(orderMainHistory); }); - log.info("积分商城购买失败处理完成,supplierId={},orderId={}", dto.getSupplierId(), dto.getOrderId()); + log.info("9.2.14 支付结果通知接口 调用结束"); return MallInboundResult.success(); } + + /** + * callP消息推送 + * + * @param mainOrder 订单信息 + */ + public void pushMessageToCallP(PointsMallOrderMain mainOrder) { + Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", mainOrder.getUserId()).or("loginname", "=", mainOrder.getUserId())); + PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class, Cnd.where("supplierId", "=", mainOrder.getSupplierId()).and("delFlag", "=", false)); + String supplierName = supplier == null || StrUtil.isBlank(supplier.getSupplierName()) ? mainOrder.getSupplierId() : supplier.getSupplierName(); + + StringBuilder sb = new StringBuilder(); + sb.append("商品列表:
    "); + List productList = StrUtil.isBlank(mainOrder.getExtJson()) + ? Collections.emptyList() + : JSONUtil.toList(mainOrder.getExtJson(), OrderProInfoDTO.class); + productList.forEach(product -> + sb.append("
  1. 商品名称:").append(product.getName()).append(",商品价格:").append(formatMoney(product.getPrice())).append("元
  2. ") + ); + sb.append("
"); + + String userName = user == null || StrUtil.isBlank(user.getUsername()) ? mainOrder.getUserId() : user.getUsername(); + String content = "尊敬的" + userName + ",您的积分商城订单已支付成功。" + + "
" + + "订单时间:" + DateUtil.formatDateTime(mainOrder.getOrderCreateTime()) + + "
" + + "消费积分:" + mainOrder.getPointsPrice() + + "
" + + "供应商:" + supplierName + + "
" + + "订单总金额:" + mainOrder.getTotalPrice() + + "
" + + "现金金额:" + mainOrder.getWPayOrAPay() + + "
" + + sb; + + globalMessageSendService.sendLocalSystemMessage("积分商城支付成功", content, 1, Collections.singletonList(mainOrder.getUserId()), null); + } + + private String formatMoney(BigDecimal value) { + return (value == null ? BigDecimal.ZERO : value).setScale(2, RoundingMode.HALF_UP).toPlainString(); + } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/order/models/PointsMallOrderMainHistory.java b/src/main/java/com/budwk/app/zhgh/pointsmall/order/models/PointsMallOrderMainHistory.java new file mode 100644 index 00000000..07f2461c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/order/models/PointsMallOrderMainHistory.java @@ -0,0 +1,136 @@ +package com.budwk.app.zhgh.pointsmall.order.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.ColDefine; +import org.nutz.dao.entity.annotation.ColType; +import org.nutz.dao.entity.annotation.Column; +import org.nutz.dao.entity.annotation.Comment; +import org.nutz.dao.entity.annotation.Name; +import org.nutz.dao.entity.annotation.Table; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 商城主订单历史记录 当主单数据变化时 落库到历史表 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("points_mall_order_main_history") +@Comment("积分商城主订单历史记录") +public class PointsMallOrderMainHistory extends BaseModel implements Serializable { + + @Name + @Column + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("主订单ID") + @ColDefine(type = ColType.VARCHAR, width = 64) + private String orderId; + + @Column + @Comment("供应商编码") + @ColDefine(type = ColType.VARCHAR, width = 64) + private String supplierId; + + @Column + @Comment("订单编号") + @ColDefine(type = ColType.VARCHAR, width = 64) + private String orderNumberId; + + @Column + @Comment("用户ID") + @ColDefine(type = ColType.VARCHAR, width = 64) + private String userId; + + @Column + @Comment("应用名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String aplName; + + @Column + @Comment("订单创建时间") + private Date orderCreateTime; + + @Column + @Comment("订单更新时间") + private Date orderUpdateTime; + + @Column + @Comment("发货时间") + private Date deliveryTime; + + @Column + @Comment("确认收货时间") + private Date orderFinishTime; + + @Column + @Comment("完成时间") + private Date orderCompleteTime; + + @Column + @Comment("发货状态") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String deliveryStatus; + + @Column + @Comment("运费积分") + @ColDefine(type = ColType.FLOAT, width = 18, precision = 2) + private BigDecimal freightCost; + + @Column + @Comment("退款积分") + @ColDefine(type = ColType.FLOAT, width = 18, precision = 2) + private BigDecimal refund; + + @Column + @Comment("物流单号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String logisticsOrderId; + + @Column + @Comment("物流承运商") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String crrgBsnNm; + + @Column + @Comment("订单状态") + private Integer orderState; + + @Column + @Comment("订单总金额") + @ColDefine(type = ColType.FLOAT, width = 18, precision = 2) + private BigDecimal totalPrice; + + @Column + @Comment("现金金额") + @ColDefine(type = ColType.FLOAT, width = 18, precision = 2) + private BigDecimal wPayOrAPay; + + @Column + @Comment("消费积分") + @ColDefine(type = ColType.FLOAT, width = 18, precision = 2) + private BigDecimal pointsPrice; + + @Column + @Comment("发票代码") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String invoiceCode; + + @Column + @Comment("商品扩展信息JSON") + @ColDefine(type = ColType.TEXT) + private String extJson; + + @Column + @Comment("现金支付状态") + private Integer cashPaid; +} diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java index 0784e429..df1c4b70 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/PointsMallOrderService.java @@ -11,6 +11,7 @@ import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; import com.budwk.app.zhgh.pointsmall.order.param.PointsMallOrderPageParam; import com.budwk.app.zhgh.pointsmall.order.vo.PointsMallMobileOrderVO; import org.nutz.dao.entity.Record; +import org.nutz.lang.util.NutMap; import java.util.List; @@ -28,9 +29,9 @@ public interface PointsMallOrderService extends BaseService List listExchange(String mainOrderId); - List listSubProducts(String orderId); + List listSubProducts(String orderId); - List listExchangeProducts(String orderId); + List listExchangeProducts(String orderId); boolean updateSub(PointsMallOrderSub orderSub); diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java index e335a1c0..bec33659 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/order/service/impl/PointsMallOrderServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderProInfoDTO; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderExchange; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; @@ -28,6 +29,7 @@ import org.nutz.dao.sql.Sql; import org.nutz.dao.util.Daos; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; import org.nutz.trans.Atom; import org.nutz.trans.Trans; @@ -198,7 +200,26 @@ public class PointsMallOrderServiceImpl extends BaseServiceImpl listSubProducts(String orderId) { + public List listSubProducts(String orderId) { + PointsMallOrderSub orderSub = dao().fetch(PointsMallOrderSub.class, Cnd.where("orderId", "=", orderId).and("delFlag", "=", false)); + List extProducts = parseProductExtJson(orderId, orderSub == null ? null : orderSub.getExtJson()); + if (!extProducts.isEmpty()) { + return extProducts; + } + return listProductTable(orderId); + } + + @Override + public List listExchangeProducts(String orderId) { + PointsMallOrderExchange orderExchange = dao().fetch(PointsMallOrderExchange.class, Cnd.where("orderId", "=", orderId).and("delFlag", "=", false)); + List extProducts = parseProductExtJson(orderId, orderExchange == null ? null : orderExchange.getExtJson()); + if (!extProducts.isEmpty()) { + return extProducts; + } + return listProductTable(orderId); + } + + private List listProductTable(String orderId) { Cnd cnd = Cnd.where("delFlag", "=", false); if (StrUtil.isNotBlank(orderId)) { cnd.and("orderSubId", "=", orderId); @@ -206,12 +227,43 @@ public class PointsMallOrderServiceImpl extends BaseServiceImpl listExchangeProducts(String orderId) { - return listSubProducts(orderId); + private List parseProductExtJson(String orderId, String extJson) { + if (StrUtil.isBlank(extJson) || "null".equalsIgnoreCase(extJson)) { + return Collections.emptyList(); + } + try { + return JSONUtil.toList(extJson, OrderProInfoDTO.class).stream().map(product -> { + return NutMap.NEW() + .addv("orderId", orderId) + .addv("sku", product.getSku()) + .addv("number", product.getNumber()) + .addv("price", product.getPrice()) + .addv("name", product.getName()) + .addv("taxRate", product.getTaxRate()) + .addv("picInfo", product.getPicInfo()) + .addv("fileId", product.getFileId()) + .addv("filePath", product.getFilePath()); + }).collect(Collectors.toList()); + } catch (Exception e) { + log.warn("解析订单商品扩展信息失败,orderId={},extJson={}", orderId, extJson, e); + return Collections.emptyList(); + } + } + + private NutMap toProductRecord(Record item) { + return NutMap.NEW() + .addv("orderId", item.getString("orderSubId")) + .addv("sku", item.getString("sku")) + .addv("number", item.get("number")) + .addv("price", item.get("price")) + .addv("name", item.getString("name")) + .addv("taxRate", item.get("taxRate")) + .addv("picInfo", item.getString("picInfo")) + .addv("fileId", item.getString("fileId")) + .addv("filePath", item.getString("filePath")); } @Override diff --git a/src/main/resources/views/layouts/v4/msg.html b/src/main/resources/views/layouts/v4/msg.html index da3ad46e..6c141dad 100644 --- a/src/main/resources/views/layouts/v4/msg.html +++ b/src/main/resources/views/layouts/v4/msg.html @@ -130,6 +130,20 @@ layout("/layouts/v4/baseLayout.html"){ color: #303133; } + .detail-content { + white-space: pre-line; + } + + .detail-content ol { + list-style-type: decimal; + padding-left: 22px; + margin: 6px 0; + } + + .detail-content li { + display: list-item; + } + .pagination-container { margin-top: 20px; display: flex; @@ -297,7 +311,7 @@ layout("/layouts/v4/baseLayout.html"){ {{formatTime(currentMessage.createdAt)}} -
+
关闭 diff --git a/src/main/resources/views/platform/zhgh/points-mall/order/index.html b/src/main/resources/views/platform/zhgh/points-mall/order/index.html index 456246ba..ed339486 100644 --- a/src/main/resources/views/platform/zhgh/points-mall/order/index.html +++ b/src/main/resources/views/platform/zhgh/points-mall/order/index.html @@ -68,81 +68,222 @@ layout("/layouts/platform.html"){ > - - - - - - - - - - - - - - - - - - - - 关闭 - - - - - - - - - - - - - - 关闭 - - - - - - - - - - - - - - - - - - - - 关闭 - - +