diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/PointsMallInvoiceService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/PointsMallInvoiceService.java index 6a293735..cd09dda3 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/PointsMallInvoiceService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/PointsMallInvoiceService.java @@ -3,6 +3,8 @@ package com.budwk.app.zhgh.pointsmall.invoice.service; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.pointsmall.invoice.models.PointsMallInvoiceMain; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderEventDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; import com.budwk.app.zhgh.pointsmall.invoice.models.PointsMallInvoiceInfo; import com.budwk.app.zhgh.pointsmall.invoice.param.PointsMallInvoiceApplyParam; import com.budwk.app.zhgh.pointsmall.invoice.param.PointsMallInvoiceInfoPageParam; @@ -16,6 +18,12 @@ import java.util.List; public interface PointsMallInvoiceService extends BaseService { + /** 同步供应商发票信息及本地文件。 */ + MallInboundResult invoiceInfo(MallOrderEventDTO dto); + + /** 同步发票,可指定是否重新生成失败发票。 */ + MallInboundResult invoiceInfo(MallOrderEventDTO dto, boolean retry); + Pagination mainPage(PointsMallInvoiceMainPageParam param); Pagination infoPage(PointsMallInvoiceInfoPageParam param); diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java index 588ecc59..e9402885 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/invoice/service/impl/PointsMallInvoiceServiceImpl.java @@ -36,17 +36,24 @@ import java.math.BigDecimal; import com.budwk.app.zhgh.pointsmall.invoice.models.PointsMallInvoiceInfo; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderEventDTO; import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallInboundResult; -import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallInboundEventService; +import com.budwk.app.sys.enums.SysFileEngineTypeEnum; +import com.budwk.app.sys.services.SysFileService; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallPictureOutboundResult; +import lombok.extern.slf4j.Slf4j; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +@Slf4j @IocBean(args = {"refer:dao"}) public class PointsMallInvoiceServiceImpl extends BaseServiceImpl implements PointsMallInvoiceService { @Inject private MallInvoiceApplyOutboundService mallInvoiceApplyOutboundService; @Inject - private MallInboundEventService mallInboundEventService; + private SysFileService sysFileService; @Inject private MallInvoiceInfoQueryService mallInvoiceInfoQueryService; @@ -54,6 +61,147 @@ public class PointsMallInvoiceServiceImpl extends BaseServiceImpl fileIds = result.getInvoiceInfos().stream().map(InvoiceInfoDTO::getInvoiceId).collect(Collectors.toList()); + if (fileIds.stream().anyMatch(StrUtil::isBlank)) { + throw new IllegalArgumentException("供应商发票文件标识为空"); + } + MallPictureOutboundResult files = mallInvoiceInfoQueryService.queryInvoiceFiles(dto.getSupplierId(), settlementId, fileIds); + for (InvoiceInfoDTO item : result.getInvoiceInfos()) { + if (item.getStatus() != null && item.getStatus() != 1) { + throw new IllegalArgumentException("供应商发票尚未生成成功"); + } + String base64 = files.getImageEncodeMap() == null ? null : files.getImageEncodeMap().get(item.getInvoiceId()); + if (StrUtil.isBlank(base64)) { + throw new IllegalArgumentException("未获取到发票文件Base64:" + item.getInvoiceId()); + } + if (base64.startsWith("data:")) { + base64 = base64.substring(base64.indexOf(',') + 1); + } + byte[] bytes = Base64.getDecoder().decode(base64.replaceAll("\\s", "")); + if (bytes.length == 0) { + throw new IllegalArgumentException("发票文件内容为空"); + } + String fileType = StrUtil.blankToDefault(files.getFileType(), StrUtil.blankToDefault(item.getFileType(), "PDF")); + if (!fileType.matches("(?i)pdf|jpg|jpeg|png")) { + throw new IllegalArgumentException("不支持的发票文件类型:" + fileType); + } + String localUrl = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), + "invoice-" + java.util.UUID.randomUUID() + "." + fileType.toLowerCase(java.util.Locale.ROOT), bytes); + item.setUrl(localUrl); + item.setImageEncode(localUrl); + item.setFileType(fileType); + } + } catch (Exception e) { + log.error("发票文件同步失败,settlementId={}", settlementId, e); + return MallInboundResult.fail(502, "发票文件同步失败:" + e.getMessage()); + } + } + Trans.exec((Atom) () -> { + main.setBSuccess(success); + main.setSucOrderIds(result.getSucOrderIds()); + main.setFailOrderIds(result.getFailOrderIds()); + main.setFailMsg(result.getFailMsg()); + if (result.getInvoiceInfos() != null) { + for (InvoiceInfoDTO item : result.getInvoiceInfos()) { + PointsMallInvoiceInfo info = dao().fetch(PointsMallInvoiceInfo.class, + Cnd.where("mainId", "=", main.getId()).and("invoiceId", "=", item.getInvoiceId()).and("delFlag", "=", false)); + if (info == null) { + info = new PointsMallInvoiceInfo(); + info.setMainId(main.getId()); + info.setInvoiceId(item.getInvoiceId()); + } + info.setInvoiceCode(item.getInvoiceCode()); + info.setInvoiceDate(item.getInvoiceDate() == null ? null : DateUtil.parse(item.getInvoiceDate().toString())); + info.setInvoiceNakeAmount(item.getInvoiceNakeAmount()); + info.setInvoiceTaxRate(item.getInvoiceTaxRate()); + info.setInvoiceTaxAmount(item.getInvoiceTaxAmount()); + info.setInvoiceAmount(item.getInvoiceAmount()); + info.setInvoiceType(item.getInvoiceType()); + info.setUrl(item.getUrl()); + info.setImageEncode(item.getImageEncode()); + info.setFileType(item.getFileType()); + info.setCheckCode(item.getCheckCode()); + info.setInvoiceAddress(item.getInvoiceAddress()); + info.setRemark(item.getRemark()); + if (success != 0) { + info.setUrl(""); + info.setImageEncode(""); + } + if (StrUtil.isBlank(info.getId())) { + dao().insert(info); + } else { + dao().updateIgnoreNull(info); + } + } + } + + List successOrderIds = splitInvoiceOrderIds(result.getSucOrderIds()); + List failOrderIds = splitInvoiceOrderIds(result.getFailOrderIds()); + if (!successOrderIds.isEmpty()) { + dao().update(PointsMallOrderSub.class, Chain.make("invoiceStatus", 1), Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "in", successOrderIds).and("delFlag", "=", false)); + } + if (!failOrderIds.isEmpty()) { + dao().update(PointsMallOrderSub.class, Chain.make("invoiceStatus", 0), Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "in", failOrderIds).and("delFlag", "=", false)); + } + dao().updateIgnoreNull(main); + }); + log.info("供应商发票信息更新完成,supplierId={},settlementId={}", dto.getSupplierId(), settlementId); + return MallInboundResult.success(); + } + + /** 拆分开票结果中的订单号,去除空项和重复项,保留原有顺序。 */ + private List splitInvoiceOrderIds(String value) { + if (StrUtil.isBlank(value)) { + return Collections.emptyList(); + } + return Arrays.stream(value.split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .distinct() + .collect(Collectors.toList()); + } + @Override public Pagination mainPage(PointsMallInvoiceMainPageParam param) { Cnd cnd = Cnd.where("delFlag", "=", false); @@ -87,7 +235,7 @@ public class PointsMallInvoiceServiceImpl extends BaseServiceImpl { + sub.setOrderState(state); + sub.setOrderUpdateTime(new Date()); + dao.updateIgnoreNull(sub); + }); + log.info("积分商城子单状态更新完成,supplierId={},orderId={},state={}", dto.getSupplierId(), dto.getOrderId(), state); + return MallInboundResult.success(); } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPayedMainOrderEventHandler.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPayedMainOrderEventHandler.java index 3bd3653a..ec76d571 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPayedMainOrderEventHandler.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPayedMainOrderEventHandler.java @@ -3,7 +3,18 @@ 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 cn.hutool.core.util.StrUtil; +import com.budwk.app.zhgh.pointsmall.mallbridge.service.support.AbstractMallBridgeSupport; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; +import com.budwk.app.zhgh.pointsmall.points.service.PointsMallPointsLockService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.trans.Atom; +import org.nutz.trans.Trans; +import java.util.Date; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -11,19 +22,50 @@ import org.nutz.ioc.loader.annotation.IocBean; * MallCancelPayedMainOrderEventHandler * orderType=7: 已支付未拆单的整个父单取消。 */ -@IocBean -public class MallCancelPayedMainOrderEventHandler implements MallOrderEventHandler { +@Slf4j +@IocBean(args = {"refer:dao"}) +public class MallCancelPayedMainOrderEventHandler extends AbstractMallBridgeSupport implements MallOrderEventHandler { @Inject - private MallInboundEventService inboundEventService; + private PointsMallPointsLockService pointsMallPointsLockService; + + public MallCancelPayedMainOrderEventHandler(Dao dao) { + super(dao); + } @Override public int getType() { return 7; } + /** + * 处理已支付未拆单主单取消通知,沿用原 paidNotSplit=true 分支的校验与积分处理。 + */ @Override public MallInboundResult handle(MallOrderEventDTO dto) { - return inboundEventService.cancelMainOrder(dto, true); + // 优先使用 mainOrderId,未提供时使用事件中的 orderId 查询主订单。 + String mainOrderId = StrUtil.blankToDefault(dto.getMainOrderId(), dto.getOrderId()); + if (StrUtil.isBlank(mainOrderId)) { + return MallInboundResult.fail(400, "主订单信息不能为空"); + } + PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "=", mainOrderId).and("delFlag", "=", false)); + if (main == null) { + return MallInboundResult.fail(404, "主订单不存在"); + } + Date now = new Date(); + // 主子订单状态更新与主单积分锁释放在同一事务内完成。 + Trans.exec((Atom) () -> { + main.setOrderState(ORDER_CANCELLED); + main.setOrderUpdateTime(now); + dao.updateIgnoreNull(main); + // 同步取消该供应商、该主订单下尚未删除的子订单,保持原处理范围。 + dao.update(PointsMallOrderSub.class, Chain.make("orderState", ORDER_CANCELLED).add("orderUpdateTime", now), + Cnd.where("supplierId", "=", dto.getSupplierId()).and("mainOrderId", "=", mainOrderId).and("delFlag", "=", false)); + // 使用主订单归属信息释放主单积分锁。 + pointsMallPointsLockService.releaseMain(main.getUserId(), main.getSupplierId(), main.getOrderId()); + }); + log.info("积分商城主单取消完成,supplierId={},mainOrderId={},paidNotSplit={}", dto.getSupplierId(), mainOrderId, true); + return MallInboundResult.success(); } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPendingOrderEventHandler.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPendingOrderEventHandler.java index 8d38ae87..68f72dfb 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPendingOrderEventHandler.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelPendingOrderEventHandler.java @@ -3,7 +3,18 @@ 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 cn.hutool.core.util.StrUtil; +import com.budwk.app.zhgh.pointsmall.mallbridge.service.support.AbstractMallBridgeSupport; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; +import com.budwk.app.zhgh.pointsmall.points.service.PointsMallPointsLockService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.trans.Atom; +import org.nutz.trans.Trans; +import java.util.Date; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -11,19 +22,54 @@ import org.nutz.ioc.loader.annotation.IocBean; * MallCancelPendingOrderEventHandler * orderType=1: 取消待支付主单事件处理器。 */ -@IocBean -public class MallCancelPendingOrderEventHandler implements MallOrderEventHandler { +@Slf4j +@IocBean(args = {"refer:dao"}) +public class MallCancelPendingOrderEventHandler extends AbstractMallBridgeSupport implements MallOrderEventHandler { @Inject - private MallInboundEventService inboundEventService; + private PointsMallPointsLockService pointsMallPointsLockService; + + public MallCancelPendingOrderEventHandler(Dao dao) { + super(dao); + } @Override public int getType() { return 1; } + /** + * 处理待支付主单取消通知,校验待支付状态后取消订单并释放主单积分锁。 + */ @Override public MallInboundResult handle(MallOrderEventDTO dto) { - return inboundEventService.cancelMainOrder(dto, false); + // 优先使用 mainOrderId,未提供时使用事件中的 orderId 查询主订单。 + String mainOrderId = StrUtil.blankToDefault(dto.getMainOrderId(), dto.getOrderId()); + if (StrUtil.isBlank(mainOrderId)) { + return MallInboundResult.fail(400, "主订单信息不能为空"); + } + PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "=", mainOrderId).and("delFlag", "=", false)); + if (main == null) { + return MallInboundResult.fail(404, "主订单不存在"); + } + // 待支付取消事件仅允许取消尚未支付的主订单。 + if (!Integer.valueOf(ORDER_PENDING_PAY).equals(main.getOrderState())) { + return MallInboundResult.fail(400, "只能取消未支付主单"); + } + Date now = new Date(); + // 主子订单状态更新与主单积分锁释放在同一事务内完成。 + Trans.exec((Atom) () -> { + main.setOrderState(ORDER_CANCELLED); + main.setOrderUpdateTime(now); + dao.updateIgnoreNull(main); + // 同步取消该供应商、该主订单下尚未删除的子订单,保持原处理范围。 + dao.update(PointsMallOrderSub.class, Chain.make("orderState", ORDER_CANCELLED).add("orderUpdateTime", now), + Cnd.where("supplierId", "=", dto.getSupplierId()).and("mainOrderId", "=", mainOrderId).and("delFlag", "=", false)); + // 使用主订单归属信息释放主单积分锁。 + pointsMallPointsLockService.releaseMain(main.getUserId(), main.getSupplierId(), main.getOrderId()); + }); + log.info("积分商城主单取消完成,supplierId={},mainOrderId={},paidNotSplit={}", dto.getSupplierId(), mainOrderId, false); + return MallInboundResult.success(); } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelSubOrderEventHandler.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelSubOrderEventHandler.java index 5e52549d..784207d4 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelSubOrderEventHandler.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallCancelSubOrderEventHandler.java @@ -1,6 +1,8 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderMessageDTO; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.budwk.app.sys.models.Sys_user; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderEventDTO; @@ -102,7 +104,10 @@ public class MallCancelSubOrderEventHandler implements MallOrderEventHandler { pointsMallOrderService.updateMainOrderStatus(sub.getMainOrderId(), sub.getSupplierId()); }); try { - mallCallPMessagePushService.pushMessageToGlobal(StrUtil.blankToDefault(user.getUsername(), user.getLoginname()), sub); + MallOrderMessageDTO message = BeanUtil.copyProperties(sub, MallOrderMessageDTO.class); + message.setOperationTime(StrUtil.isBlank(dto.getOperationTime()) ? null : DateUtil.parse(dto.getOperationTime().replace("T", " "))); + message.setUserName(StrUtil.blankToDefault(user.getUsername(), user.getLoginname())); + mallCallPMessagePushService.pushMessageToGlobal("66666666", message); } catch (Exception e) { log.error("9.2.1 子单取消,callP消息推送:{},{}", dto, e.getMessage()); } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallConfirmReceiptEventHandler.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallConfirmReceiptEventHandler.java index 246f65fd..42fbfeba 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallConfirmReceiptEventHandler.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallConfirmReceiptEventHandler.java @@ -1,9 +1,26 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderMessageDTO; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.sys.models.Sys_user; 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 com.budwk.app.zhgh.pointsmall.mallbridge.service.support.AbstractMallBridgeSupport; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.trans.Atom; +import org.nutz.trans.Trans; +import java.util.Date; +import cn.hutool.json.JSONUtil; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderQueryDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderInfoDTO; +import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallOutboundResult; +import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallOrderQueryOutboundService; +import com.budwk.app.zhgh.pointsmall.mallbridge.service.MallCallPMessagePushService; import com.budwk.app.zhgh.pointsmall.order.enums.MallOrderStatusEnum; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -16,19 +33,103 @@ import org.nutz.ioc.loader.annotation.IocBean; *

注意:供应商侧“确认收货”对应 zhgh/callP 侧“已妥投(4)”, * 不等同于 zhgh/callP 用户确认收货后的“已完成(5)”。

*/ -@IocBean -public class MallConfirmReceiptEventHandler implements MallOrderEventHandler { +@Slf4j +@IocBean(args = {"refer:dao"}) +public class MallConfirmReceiptEventHandler extends AbstractMallBridgeSupport implements MallOrderEventHandler { @Inject - private MallInboundEventService inboundEventService; + private MallOrderQueryOutboundService mallOrderQueryOutboundService; + @Inject + private MallCallPMessagePushService mallCallPMessagePushService; + + public MallConfirmReceiptEventHandler(Dao dao) { + super(dao); + } @Override public int getType() { return 6; } + /** + * 处理供应商确认收货通知,仅更新为已妥投,不执行用户确认完成后的积分扣减。 + */ @Override public MallInboundResult handle(MallOrderEventDTO dto) { - return inboundEventService.updateSubOrderStatus(dto, MallOrderStatusEnum.RECEIVED); + Integer state = MallOrderStatusEnum.RECEIVED.getCode(); + PointsMallOrderSub sub = dao.fetch(PointsMallOrderSub.class, Cnd.where("supplierId", "=", dto.getSupplierId()) + .and("orderId", "=", dto.getOrderId()).and("delFlag", "=", false)); + if (sub == null) { + return MallInboundResult.fail(404, "订单不存在"); + } + // 已妥投的重复通知直接返回,保留原处理的幂等行为。 + if (state.equals(sub.getOrderState())) { + log.info("积分商城子单状态已是目标状态,跳过重复处理,supplierId={},orderId={},state={}", dto.getSupplierId(), dto.getOrderId(), state); + return MallInboundResult.success(); + } + Trans.exec((Atom) () -> { + // 补查供应商订单详情;查询失败时沿用原逻辑,仍更新本地妥投状态。 + fillReceivedSubOrder(dto, sub); + sub.setOrderState(state); + // 优先保留订单详情中的时间,缺失时使用当前时间。 + if (sub.getOrderUpdateTime() == null) { + sub.setOrderUpdateTime(new Date()); + } + if (sub.getOrderFinishTime() == null) { + sub.setOrderFinishTime(new Date()); + } + dao.updateIgnoreNull(sub); + }); + // 妥投状态保存成功后发送提醒,消息异常不回滚订单处理。 + try { + // 按子订单所属用户读取姓名,显式传入妥投提醒的 userName 模板变量。 + Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", sub.getUserId()).or("loginname", "=", sub.getUserId())); + if (user == null) { + throw new IllegalArgumentException("订单所属用户不存在,无法生成妥投提醒"); + } + MallOrderMessageDTO message = BeanUtil.copyProperties(sub, MallOrderMessageDTO.class); + message.setOperationTime(parseDate(dto.getOperationTime())); + message.setUserName(StrUtil.blankToDefault(user.getUsername(), user.getLoginname())); + mallCallPMessagePushService.pushMessageToGlobal("22222222", message); + } catch (Exception e) { + log.error("订单类型为:6(确认收货)时,全局消息推送失败:{}", dto, e); + } + log.info("积分商城子单状态更新完成,supplierId={},orderId={},state={}", dto.getSupplierId(), dto.getOrderId(), state); + return MallInboundResult.success(); + } + + /** + * 订单类型为:6(确认收货)时,调用 9.2.2 获取订单详情接口,补充子单妥投相关信息。 + * + *

供应商侧确认收货只代表电商处已收货,对 zhgh/callP 侧应更新为已妥投(4), + * 等待 callP 用户侧确认收货后才进入已完成(5)。

+ */ + private void fillReceivedSubOrder(MallOrderEventDTO dto, PointsMallOrderSub sub) { + if (mallOrderQueryOutboundService == null) { + return; + } + MallOrderQueryDTO queryDTO = new MallOrderQueryDTO(); + queryDTO.setSupplierId(dto.getSupplierId()); + queryDTO.setOrderId(dto.getOrderId()); + queryDTO.setOrderType(2); + log.info("订单类型为:6(确认收货)时,调用9.2.2获取订单详情接口:{}", queryDTO); + try { + MallOutboundResult result = mallOrderQueryOutboundService.queryOrderInfo(queryDTO); + if (result == null || result.getResultCode() != 0 || result.getOrderInfo() == null || result.getOrderInfo().isEmpty()) { + log.error("订单类型为:6(确认收货)时,调用9.2.2 获取订单详情失败:{},{}", queryDTO, result == null ? null : result.getMessage()); + return; + } + OrderInfoDTO orderInfo = result.getOrderInfo().get(0); + sub.setOrderCreateTime(parseDate(orderInfo.getCreateTime())); + sub.setOrderUpdateTime(parseDate(orderInfo.getUpdateTime())); + sub.setOrderFinishTime(parseDate(orderInfo.getOrderFinishTime())); + sub.setDeliveryTime(parseDate(orderInfo.getDeliveryTime())); + sub.setDeliveryStatus(parseInteger(orderInfo.getDeliveryStatus())); + if (orderInfo.getOrderProInfos() != null) { + sub.setExtJson(JSONUtil.toJsonStr(orderInfo.getOrderProInfos())); + } + } catch (Exception e) { + log.error("订单类型为:6(确认收货)时,调用9.2.2 获取订单详情异常:{},{}", queryDTO, e.getMessage()); + } } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallInvoiceInfoEventHandler.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallInvoiceInfoEventHandler.java index 4a51cf59..2012194a 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallInvoiceInfoEventHandler.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallInvoiceInfoEventHandler.java @@ -3,7 +3,7 @@ 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 com.budwk.app.zhgh.pointsmall.invoice.service.PointsMallInvoiceService; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -15,7 +15,7 @@ import org.nutz.ioc.loader.annotation.IocBean; public class MallInvoiceInfoEventHandler implements MallOrderEventHandler { @Inject - private MallInboundEventService inboundEventService; + private PointsMallInvoiceService pointsMallInvoiceService; @Override public int getType() { @@ -24,6 +24,6 @@ public class MallInvoiceInfoEventHandler implements MallOrderEventHandler { @Override public MallInboundResult handle(MallOrderEventDTO dto) { - return inboundEventService.invoiceInfo(dto); + return pointsMallInvoiceService.invoiceInfo(dto); } } 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 index f89becef..fd5f40c8 100644 --- 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 @@ -3,27 +3,116 @@ 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 cn.hutool.core.util.StrUtil; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.zhgh.pointsmall.mallbridge.service.support.AbstractMallBridgeSupport; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; +import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.trans.Atom; +import org.nutz.trans.Trans; +import java.util.Date; +import java.util.List; import org.nutz.ioc.loader.annotation.IocBean; /** * MallShipOrderEventHandler * orderType=99: 供应商已发货 / 更新发货状态。 + * 在处理器内完成订单校验及主子订单物流信息更新,不再回调事件分发服务。 + * 本事件仅更新发货状态和物流信息,不修改订单业务状态 orderState。 */ -@IocBean -public class MallShipOrderEventHandler implements MallOrderEventHandler { +@Slf4j +@IocBean(args = {"refer:dao"}) +public class MallShipOrderEventHandler extends AbstractMallBridgeSupport implements MallOrderEventHandler { - @Inject - private MallInboundEventService inboundEventService; + public MallShipOrderEventHandler(Dao dao) { + super(dao); + } @Override public int getType() { return 99; } + /** + * 处理供应商发货通知,在同一事务中更新匹配的子订单及一个主订单。 + * + * @param dto 发货事件,orderId 为英文逗号分隔的子订单号,userId 为可选的用户虚拟 ID + * @return 参数或用户映射无效时返回 400,无匹配子订单时返回 404,更新完成返回成功 + */ @Override public MallInboundResult handle(MallOrderEventDTO dto) { - return inboundEventService.updateDeliveryStatus(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())) { + // 供应商传入虚拟 ID,转换为本地用户 ID 后参与订单归属查询。 + Sys_user user = fetchUser(dto.getUserId()); + if (user == null) { + return MallInboundResult.fail(400, "用户ID未配置或不存在"); + } + subCnd.and("userId", "=", user.getId()); + } + + List subs = dao.query(PointsMallOrderSub.class, subCnd); + if (subs.isEmpty()) { + return MallInboundResult.fail(404, "订单不存在"); + } + + Date finalDeliveryTime = deliveryTime; + // 已发货事件固定写入 deliveryStatus=1,不使用通知中的状态值覆盖该语义。 + 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(); } } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallSubOrderReturnEventHandler.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallSubOrderReturnEventHandler.java index 2410de4d..27c1dec3 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallSubOrderReturnEventHandler.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/event/handlers/MallSubOrderReturnEventHandler.java @@ -1,4 +1,5 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderMessageDTO; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; @@ -148,13 +149,15 @@ public class MallSubOrderReturnEventHandler extends AbstractMallBridgeSupport im }); try { // callP消息推送 - PointsMallOrderSub notifySub = BeanUtil.copyProperties(sub, PointsMallOrderSub.class); + MallOrderMessageDTO notifySub = BeanUtil.copyProperties(sub, MallOrderMessageDTO.class); + notifySub.setOperationTime(parseDate(dto.getOperationTime())); notifySub.setOrderId(dto.getOrderId()); notifySub.setPointsPrice(refund); notifySub.setTotalPrice(orderInfo.getTotalPrice()); notifySub.setWPayOrAPay(orderInfo.getWPayOrAPay()); notifySub.setExtJson(orderExchange.getExtJson()); - mallCallPMessagePushService.pushMessageToGlobal(StrUtil.blankToDefault(user.getUsername(), user.getLoginname()), notifySub); + notifySub.setUserName(StrUtil.blankToDefault(user.getUsername(), user.getLoginname())); + mallCallPMessagePushService.pushMessageToGlobal("66666666", notifySub); } catch (Exception e) { log.error("9.2.1 子单取消 或 退货,callP消息推送: {}, {}", dto, e.getMessage()); } diff --git a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallCallPMessagePushService.java b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallCallPMessagePushService.java index 41716465..a214c4aa 100644 --- a/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallCallPMessagePushService.java +++ b/src/main/java/com/budwk/app/zhgh/pointsmall/mallbridge/service/MallCallPMessagePushService.java @@ -8,8 +8,7 @@ import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderProInfoDTO; import com.budwk.app.zhgh.pointsmall.message.models.PointsMallMessage; import com.budwk.app.zhgh.pointsmall.message.models.PointsMallMessageTemplate; -import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderMain; -import com.budwk.app.zhgh.pointsmall.order.models.PointsMallOrderSub; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderMessageDTO; import com.budwk.app.zhgh.pointsmall.supplier.models.PointsMallSupplier; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; @@ -39,123 +38,102 @@ public class MallCallPMessagePushService { } /** - * 支付成功callP消息推送。 - * - * @param mainOrder 订单信息 + * 统一订单消息入口:11111111 支付成功,22222222 妥投提醒,66666666 积分退回。 + * 主单、子单均转换为 MallOrderMessageDTO,退货传入退货单号及本次退款积分。 + * 已成功消息不重复发送;失败记录可在再次调用时重用。 + * synchronized 防止当前服务实例内的并发通知重复创建消息。 */ - public void pushMessageToGlobal(PointsMallOrderMain mainOrder) { - PointsMallMessageTemplate template = dao.fetch(PointsMallMessageTemplate.class, Cnd.where("id", "=", "11111111").and("delFlag", "=", false)); - if (template == null) { - log.info("支付成功推送消息失败,未配置消息模板"); + public synchronized void pushMessageToGlobal(String templateId, MallOrderMessageDTO order) { + if (order == null || StrUtil.hasBlank(templateId, order.getSupplierId(), order.getUserId(), order.getOrderId())) { + throw new IllegalArgumentException("消息模板、供应商、用户和订单不能为空"); + } + if ("66666666".equals(templateId) && nvl(order.getPointsPrice()).signum() <= 0) { return; } - 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(); - // 消息唯一标识 模板id+供应商+订单号 - String uniqueNo = template.getId().concat("-").concat(mainOrder.getSupplierId()).concat("-").concat(mainOrder.getOrderId()); - int count = dao.count(PointsMallMessage.class, Cnd.where("uniqueNo", "=", uniqueNo).and("delFlag", "=", false)); - if (count > 0) { - log.info("9.2.14支付结果通知接口-支付成功2,消息重复推送:{}", uniqueNo); - return; - } - - StringBuilder sb = new StringBuilder(); - sb.append(" 商品列表:").append(System.lineSeparator()); - List productList = StrUtil.isBlank(mainOrder.getExtJson()) - ? Collections.emptyList() - : JSONUtil.toList(mainOrder.getExtJson(), OrderProInfoDTO.class); - productList.forEach(product -> - sb.append(" 商品名称:").append(product.getName()).append(",商品价格:").append(formatMoney(product.getPrice())).append("元").append(System.lineSeparator()) - ); - // 模板变量替换数据 - Map paramMap = new HashMap<>(); - paramMap.put("#{userName}", user == null || StrUtil.isBlank(user.getUsername()) ? mainOrder.getUserId() : user.getUsername()); - paramMap.put("#{orderFinishTime}", DateUtil.formatDateTime(mainOrder.getOrderCreateTime())); - paramMap.put("#{pointPrice}", nvl(mainOrder.getPointsPrice()).toPlainString()); - paramMap.put("#{supplierName}", supplierName); - paramMap.put("#{totalPrice}", nvl(mainOrder.getTotalPrice()).toPlainString()); - paramMap.put("#{payPrice}", nvl(mainOrder.getWPayOrAPay()).toPlainString()); - paramMap.put("#{productList}", sb.toString()); - - // 模板转换成具体的消息 - String content = template.getContent(); - for (Map.Entry entry : paramMap.entrySet()) { - content = content.replace(entry.getKey(), entry.getValue()); - } - // 生成记录 - PointsMallMessage message = new PointsMallMessage(); - message.setUniqueNo(uniqueNo); - message.setPushType("CALLP"); - message.setTemplateId(template.getId()); - message.setTouser(mainOrder.getUserId()); - message.setContent(content); - message.setContentLink(template.getContentLink()); - message.setPlanPushTime(new Date()); - // 状态设置为已推送 - message.setStatus(1); - dao.insert(message); - - globalMessageSendService.sendLocalSystemMessage(template.getName(), content, 1, Collections.singletonList(mainOrder.getUserId()), null); - } - - /** - * callP消息推送。 - * - * @param userName 用户姓名 - * @param subOrder 订单信息 - */ - public void pushMessageToGlobal(String userName, PointsMallOrderSub subOrder) { - PointsMallMessageTemplate template = dao.fetch(PointsMallMessageTemplate.class, Cnd.where("id", "=", "22222222").and("delFlag", "=", false)); - if (template == null) { - log.info("子单取消后推送消息失败,未配置消息模板"); - return; - } - PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class, Cnd.where("supplierId", "=", subOrder.getSupplierId()).and("delFlag", "=", false)); - String supplierName = supplier == null || StrUtil.isBlank(supplier.getSupplierName()) ? subOrder.getSupplierId() : supplier.getSupplierName(); - + String userId = order.getUserId(); Date now = new Date(); - Date finishTime = subOrder.getOrderFinishTime() == null ? now : subOrder.getOrderFinishTime(); - long day = DateUtil.betweenDay(DateUtil.beginOfDay(finishTime), DateUtil.beginOfDay(now), false); - String uniqueNo = template.getId().concat("-").concat(subOrder.getSupplierId()).concat("-") - .concat(subOrder.getOrderId()).concat("-").concat(String.valueOf(day)); - - StringBuilder sb = new StringBuilder(); - sb.append("商品列表: ").append(System.lineSeparator()); - List productList = StrUtil.isBlank(subOrder.getExtJson()) - ? Collections.emptyList() - : JSONUtil.toList(subOrder.getExtJson(), OrderProInfoDTO.class); - productList.forEach(product -> - sb.append(" 商品名称: ").append(product.getName()).append(",商品价格:").append(formatMoney(product.getPrice())).append("元").append(System.lineSeparator()) - ); - - Map paramMap = new HashMap<>(); - paramMap.put("#{userName}", userName); - paramMap.put("#{orderFinishTime}", DateUtil.formatDateTime(finishTime)); - paramMap.put("#{pointPrice}", nvl(subOrder.getPointsPrice()).toPlainString()); - paramMap.put("#{supplierName}", supplierName); - paramMap.put("#{totalPrice}", nvl(subOrder.getTotalPrice()).toPlainString()); - paramMap.put("#{payPrice}", nvl(subOrder.getWPayOrAPay()).toPlainString()); - paramMap.put("#{productList}", sb.toString()); - + Date finishTime = "11111111".equals(templateId) ? order.getOrderCreateTime() + : order.getOrderFinishTime() == null ? now : order.getOrderFinishTime(); + Date planPushTime = now; + String uniqueNo = templateId + "-" + order.getSupplierId() + "-" + order.getOrderId(); + if ("22222222".equals(templateId)) { + // 妥投提醒按自然日去重;取消、退货按业务订单号去重。 + if (DateUtil.beginOfDay(finishTime).after(DateUtil.beginOfDay(now))) { + return; + } + long day = DateUtil.betweenDay(DateUtil.beginOfDay(finishTime), DateUtil.beginOfDay(now), false); + uniqueNo += "-" + day; + planPushTime = DateUtil.offsetDay(finishTime, (int) day); + } + PointsMallMessageTemplate template = dao.fetch(PointsMallMessageTemplate.class, + Cnd.where("id", "=", templateId).and("delFlag", "=", false)); + if (template == null || StrUtil.isBlank(template.getContent())) { + log.info("订单消息推送失败,未配置消息模板或模板内容为空,templateId={}", templateId); + return; + } + PointsMallMessage message = dao.fetch(PointsMallMessage.class, + Cnd.where("uniqueNo", "=", uniqueNo).and("delFlag", "=", false)); + if (message != null && Integer.valueOf(1).equals(message.getStatus())) { + log.info("订单消息已推送,跳过重复通知:{}", uniqueNo); + return; + } + Map params = orderParams(order.getSupplierId(), userId, order.getExtJson()); + if (StrUtil.isNotBlank(order.getUserName())) { + params.put("#{userName}", order.getUserName()); + } + params.put("#{orderId}", order.getOrderId()); + params.put("#{orderFinishTime}", finishTime == null ? "" : DateUtil.formatDateTime(finishTime)); + params.put("#{operationTime}", order.getOperationTime() == null ? "" : DateUtil.formatDateTime(order.getOperationTime())); + params.put("#{pointPrice}", nvl(order.getPointsPrice()).toPlainString()); + params.put("#{totalPrice}", nvl(order.getTotalPrice()).toPlainString()); + params.put("#{payPrice}", nvl(order.getWPayOrAPay()).toPlainString()); String content = template.getContent(); - for (Map.Entry entry : paramMap.entrySet()) { - content = content.replace(entry.getKey(), entry.getValue()); + for (Map.Entry entry : params.entrySet()) { + content = content.replace(entry.getKey(), StrUtil.blankToDefault(entry.getValue(), "")); + } + boolean create = message == null; + if (create) { + message = new PointsMallMessage(); + message.setUniqueNo(uniqueNo); } - - Date planPushTime = DateUtil.offsetDay(finishTime, (int) day); - PointsMallMessage message = new PointsMallMessage(); - message.setUniqueNo(uniqueNo); message.setPushType("CALLP"); - message.setTemplateId(template.getId()); - message.setTouser(subOrder.getUserId()); + message.setTemplateId(templateId); + message.setTouser(userId); message.setContent(content); message.setContentLink(template.getContentLink()); message.setPlanPushTime(planPushTime); message.setStatus(0); - dao.insert(message); + if (create) { + dao.insert(message); + } else { + dao.updateIgnoreNull(message); + } + try { + globalMessageSendService.sendLocalSystemMessage(template.getName(), content, 1, Collections.singletonList(userId), null); + message.setStatus(1); + dao.updateIgnoreNull(message); + } catch (Exception e) { + message.setStatus(2); + dao.updateIgnoreNull(message); + throw new IllegalStateException("订单消息推送失败:" + uniqueNo, e); + } + } - globalMessageSendService.sendLocalSystemMessage(template.getName(), content, 1, Collections.singletonList(subOrder.getUserId()), null); + /** 公共模板变量:用户姓名、供应商名称和订单商品列表。 */ + private Map orderParams(String supplierId, String userId, String extJson) { + Sys_user user = dao.fetch(Sys_user.class, Cnd.where("id", "=", userId).or("loginname", "=", userId)); + PointsMallSupplier supplier = dao.fetch(PointsMallSupplier.class, Cnd.where("supplierId", "=", supplierId).and("delFlag", "=", false)); + Map params = new HashMap<>(); + params.put("#{userName}", user == null ? userId : StrUtil.blankToDefault(user.getUsername(), userId)); + params.put("#{supplierName}", supplier == null ? supplierId : StrUtil.blankToDefault(supplier.getSupplierName(), supplierId)); + StringBuilder sb = new StringBuilder(); + sb.append("商品列表: ").append(System.lineSeparator()); + List products = StrUtil.isBlank(extJson) || "null".equalsIgnoreCase(extJson.trim()) + ? Collections.emptyList() : JSONUtil.toList(extJson, OrderProInfoDTO.class); + products.forEach(product -> sb.append(" 商品名称: ").append(product.getName()) + .append(",商品价格:").append(formatMoney(product.getPrice())).append("元").append(System.lineSeparator())); + params.put("#{productList}", sb.toString()); + return params; } private String formatMoney(BigDecimal value) { 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 84e4d5af..7be394ac 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 @@ -1,18 +1,6 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.service; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.json.JSONUtil; -import com.budwk.app.sys.models.Sys_user; -import com.budwk.app.zhgh.pointsmall.invoice.models.PointsMallInvoiceInfo; -import com.budwk.app.zhgh.pointsmall.invoice.models.PointsMallInvoiceMain; -import com.budwk.app.zhgh.pointsmall.mallbridge.dto.GetInvoiceInfoDTO; -import com.budwk.app.zhgh.pointsmall.mallbridge.dto.InvoiceInfoDTO; -import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderQueryDTO; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderEventDTO; -import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderInfoDTO; -import com.budwk.app.zhgh.pointsmall.mallbridge.dto.OrderProInfoDTO; -import com.budwk.app.zhgh.pointsmall.mallbridge.dto.QueryInvoiceInfoDTO; import com.budwk.app.zhgh.pointsmall.mallbridge.event.MallOrderEventHandler; import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallAbolishSubOrderEventHandler; import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallCancelPayedMainOrderEventHandler; @@ -25,33 +13,15 @@ import com.budwk.app.zhgh.pointsmall.mallbridge.event.handlers.MallShipOrderEven 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; -import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallOutboundResult; import com.budwk.app.zhgh.pointsmall.mallbridge.service.support.AbstractMallBridgeSupport; -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.points.service.PointsMallPointsLockService; import lombok.extern.slf4j.Slf4j; -import org.nutz.dao.Chain; -import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.trans.Atom; -import org.nutz.trans.Trans; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Base64; -import java.util.stream.Collectors; import com.budwk.app.sys.services.SysFileService; -import com.budwk.app.sys.enums.SysFileEngineTypeEnum; -import com.budwk.app.zhgh.pointsmall.mallbridge.model.MallPictureOutboundResult; /** * 商城桥接订单事件入站服务。 @@ -133,425 +103,4 @@ public class MallInboundEventService extends AbstractMallBridgeSupport { handlerRegistry.put(handler.getType(), handler); } } - - public MallInboundResult cancelMainOrder(MallOrderEventDTO dto, boolean paidNotSplit) { - String mainOrderId = StrUtil.blankToDefault(dto.getMainOrderId(), dto.getOrderId()); - if (StrUtil.isBlank(mainOrderId)) { - return MallInboundResult.fail(400, "主订单信息不能为空"); - } - PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) - .and("orderId", "=", mainOrderId).and("delFlag", "=", false)); - if (main == null) { - return MallInboundResult.fail(404, "主订单不存在"); - } - if (!paidNotSplit && !Integer.valueOf(ORDER_PENDING_PAY).equals(main.getOrderState())) { - return MallInboundResult.fail(400, "只能取消未支付主单"); - } - Date now = new Date(); - Trans.exec((Atom) () -> { - main.setOrderState(ORDER_CANCELLED); - main.setOrderUpdateTime(now); - dao.updateIgnoreNull(main); - dao.update(PointsMallOrderSub.class, Chain.make("orderState", ORDER_CANCELLED).add("orderUpdateTime", now), - Cnd.where("supplierId", "=", dto.getSupplierId()).and("mainOrderId", "=", mainOrderId).and("delFlag", "=", false)); - pointsMallPointsLockService.releaseMain(main.getUserId(), main.getSupplierId(), main.getOrderId()); - }); - log.info("积分商城主单取消完成,supplierId={},mainOrderId={},paidNotSplit={}", dto.getSupplierId(), mainOrderId, paidNotSplit); - return MallInboundResult.success(); - } - - public MallInboundResult saveOrderSub(MallOrderEventDTO dto) { - PointsMallOrderMain main = dao.fetch(PointsMallOrderMain.class, Cnd.where("supplierId", "=", dto.getSupplierId()) - .and("orderId", "=", dto.getMainOrderId()).and("delFlag", "=", false)); - if (main == null) { - return MallInboundResult.fail(404, "主订单不存在"); - } - List subOrderIds = splitIds(dto.getOrderId()); - if (mallOrderQueryOutboundService != null) { - try { - return splitSubOrderByQuery(dto, main, subOrderIds); - } catch (Exception e) { - log.error("split sub order by query failed, fallback to local split logic, supplierId={}, mainOrderId={}, orderId={}", - dto.getSupplierId(), dto.getMainOrderId(), dto.getOrderId(), e); - } - } - if (subOrderIds.isEmpty()) { - return MallInboundResult.fail(400, "子订单信息不能为空"); - } - List products = StrUtil.isBlank(main.getExtJson()) || "null".equalsIgnoreCase(main.getExtJson()) - ? Collections.emptyList() - : JSONUtil.toList(main.getExtJson(), OrderProInfoDTO.class); - List subLocks = new ArrayList<>(); - Trans.exec((Atom) () -> { - for (String subOrderId : subOrderIds) { - PointsMallOrderSub sub = dao.fetch(PointsMallOrderSub.class, Cnd.where("orderId", "=", subOrderId) - .and("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false)); - if (sub == null) { - sub = toSub(main, subOrderId); - sub.setOrderState(ORDER_IN_PROGRESS); - dao.insert(sub); - insertProducts(subOrderId, products); - } else { - sub.setOrderState(ORDER_IN_PROGRESS); - sub.setOrderUpdateTime(new Date()); - dao.updateIgnoreNull(sub); - } - subLocks.add(sub); - } - pointsMallPointsLockService.createSubLocks(main, subLocks); - }); - log.info("积分商城拆单完成,supplierId={},mainOrderId={},subOrderCount={}", dto.getSupplierId(), dto.getMainOrderId(), subOrderIds.size()); - return MallInboundResult.success(); - } - - private MallInboundResult splitSubOrderByQuery(MallOrderEventDTO dto, PointsMallOrderMain main, List subOrderIds) { - log.info("9.2.1 生成订单信息推送-订单状态为:2(拆单子单)开始执行:{}", dto); - if (subOrderIds.isEmpty()) { - return MallInboundResult.fail(400, "缺少拆单信息"); - } - log.info("9.2.1 生成订单信息推送-订单状态为:2(拆单子单)调用外部服务获取子单信息:{}", dto); - List orderInfoList; - try { - orderInfoList = getOrderInfoList(dto); - } catch (Exception e) { - log.error("9.2.1 生成订单信息推送-订单状态为:2(拆单子单),调用9.2.2获取订单详情接口异常:{}", e.getMessage(), e); - return MallInboundResult.fail(-1, "调用9.2.2获取订单详情接口异常,异常订单:" + subOrderIds); - } - if (orderInfoList == null || orderInfoList.isEmpty()) { - return MallInboundResult.fail(404, "子单不存在"); - } - - List subLocks = new ArrayList<>(); - Trans.exec((Atom) () -> { - for (OrderInfoDTO info : orderInfoList) { - PointsMallOrderSub sub = dao.fetch(PointsMallOrderSub.class, Cnd.where("orderId", "=", info.getOrderId()) - .and("supplierId", "=", dto.getSupplierId()).and("delFlag", "=", false)); - if (sub == null) { - sub = toSub(main, info); - sub.setOrderState(ORDER_IN_PROGRESS); - dao.insert(sub); - insertProducts(info.getOrderId(), info.getOrderProInfos() == null ? Collections.emptyList() : info.getOrderProInfos()); - } else { - log.info("9.2.1 生成订单信息推送-订单状态为:2(拆单子单)子单已存在:{}", info); - sub.setOrderState(ORDER_IN_PROGRESS); - sub.setOrderUpdateTime(new Date()); - dao.updateIgnoreNull(sub); - } - subLocks.add(sub); - } - pointsMallPointsLockService.createSubLocks(main, subLocks); - }); - log.info("9.2.1 生成订单信息推送-订单状态为:2(拆单子单)结束,supplierId={},mainOrderId={},subOrderCount={}", - dto.getSupplierId(), dto.getMainOrderId(), orderInfoList.size()); - return MallInboundResult.success(); - } - - private List getOrderInfoList(MallOrderEventDTO dto) { - MallOrderQueryDTO queryDTO = new MallOrderQueryDTO(); - queryDTO.setSupplierId(dto.getSupplierId()); - queryDTO.setOrderId(dto.getOrderId()); - queryDTO.setOrderType(dto.getOrderType()); - MallOutboundResult result = mallOrderQueryOutboundService.orderQuery(queryDTO); - if (result == null || result.getResultCode() != 0) { - throw new RuntimeException(result == null ? "获取订单详情返回为空" : result.getMessage()); - } - return result.getOrderInfo(); - } - - private PointsMallOrderSub toSub(PointsMallOrderMain main, OrderInfoDTO info) { - PointsMallOrderSub sub = toSub(main, info.getOrderId()); - sub.setOrderNumberId(info.getOrderNumberId()); - sub.setAplName(StrUtil.blankToDefault(info.getAplName(), main.getAplName())); - sub.setOrderCreateTime(parseDate(info.getCreateTime())); - sub.setOrderUpdateTime(parseDate(info.getUpdateTime())); - sub.setDeliveryTime(parseDate(info.getDeliveryTime())); - sub.setOrderFinishTime(parseDate(info.getOrderFinishTime())); - sub.setOrderCompleteTime(parseDate(info.getCompleteTime())); - sub.setDeliveryStatus(parseInteger(info.getDeliveryStatus())); - sub.setFreightCost(nvl(info.getFreightCost())); - sub.setWPayOrAPayFreightCost(nvl(info.getWPayOrAPayFreightCost())); - sub.setRefund(nvl(info.getRefund())); - sub.setWPayOrAPayRefund(nvl(info.getWPayOrAPayRefund())); - sub.setLogisticsOrderId(info.getLogisticsOrderId()); - sub.setCrrgBsnNm(info.getCrrgBsnNm()); - sub.setTotalPrice(nvl(info.getTotalPrice())); - sub.setWPayOrAPay(nvl(info.getWPayOrAPay())); - sub.setPointsPrice(nvl(info.getPointsPrice())); - sub.setInvoiceCode(info.getInvoiceCode()); - sub.setExtJson(JSONUtil.toJsonStr(info.getOrderProInfos() == null ? Collections.emptyList() : info.getOrderProInfos())); - sub.setReconciliationStatus(0); - sub.setInvoiceStatus(0); - return sub; - } - - /** - * 更新子单状态。 - * - *

订单类型为:6(确认收货)时,供应商侧“确认收货”对应 zhgh/callP 侧“已妥投(4)”, - * 需重新调用 9.2.2 获取订单详情接口,补充确认收货时间、发货时间、商品信息等字段。

- * - * @param dto 请求参数 - * @param statusEnum zhgh/callP 侧订单状态枚举 - * @return 操作结果 - */ - public MallInboundResult updateSubOrderStatus(MallOrderEventDTO dto, MallOrderStatusEnum statusEnum) { - Integer state = statusEnum.getCode(); - PointsMallOrderSub sub = dao.fetch(PointsMallOrderSub.class, Cnd.where("supplierId", "=", dto.getSupplierId()) - .and("orderId", "=", dto.getOrderId()).and("delFlag", "=", false)); - if (sub == null) { - return MallInboundResult.fail(404, "订单不存在"); - } - if (Integer.valueOf(state).equals(sub.getOrderState())) { - log.info("积分商城子单状态已是目标状态,跳过重复处理,supplierId={},orderId={},state={}", dto.getSupplierId(), dto.getOrderId(), state); - return MallInboundResult.success(); - } - Trans.exec((Atom) () -> { - if (statusEnum == MallOrderStatusEnum.RECEIVED) { - fillReceivedSubOrder(dto, sub); - } - sub.setOrderState(state); - if (statusEnum != MallOrderStatusEnum.RECEIVED || sub.getOrderUpdateTime() == null) { - sub.setOrderUpdateTime(new Date()); - } - if (statusEnum == MallOrderStatusEnum.RECEIVED && sub.getOrderFinishTime() == null) { - sub.setOrderFinishTime(new Date()); - } - if (statusEnum == MallOrderStatusEnum.COMPLETED) { - sub.setOrderCompleteTime(new Date()); - } - dao.updateIgnoreNull(sub); - if (statusEnum == MallOrderStatusEnum.CANCELLED || statusEnum == MallOrderStatusEnum.REFUNDED || statusEnum == MallOrderStatusEnum.ABOLISH) { - pointsMallPointsLockService.releaseOrReturnPoints(sub, state, nvl(sub.getRefund(), BigDecimal.ZERO)); - } - if (statusEnum == MallOrderStatusEnum.COMPLETED) { - pointsMallPointsLockService.deductCompletedSub(sub); - } - }); - log.info("积分商城子单状态更新完成,supplierId={},orderId={},state={}", dto.getSupplierId(), dto.getOrderId(), state); - return MallInboundResult.success(); - } - - /** - * 订单类型为:6(确认收货)时,调用 9.2.2 获取订单详情接口,补充子单妥投相关信息。 - * - *

供应商侧确认收货只代表电商处已收货,对 zhgh/callP 侧应更新为已妥投(4), - * 等待 callP 用户侧确认收货后才进入已完成(5)。

- */ - private void fillReceivedSubOrder(MallOrderEventDTO dto, PointsMallOrderSub sub) { - if (mallOrderQueryOutboundService == null) { - return; - } - MallOrderQueryDTO queryDTO = new MallOrderQueryDTO(); - queryDTO.setSupplierId(dto.getSupplierId()); - queryDTO.setOrderId(dto.getOrderId()); - queryDTO.setOrderType(2); - log.info("订单类型为:6(确认收货)时,调用9.2.2获取订单详情接口:{}", queryDTO); - try { - MallOutboundResult result = mallOrderQueryOutboundService.queryOrderInfo(queryDTO); - if (result == null || result.getResultCode() != 0 || result.getOrderInfo() == null || result.getOrderInfo().isEmpty()) { - log.error("订单类型为:6(确认收货)时,调用9.2.2 获取订单详情失败:{},{}", queryDTO, result == null ? null : result.getMessage()); - return; - } - OrderInfoDTO orderInfo = result.getOrderInfo().get(0); - sub.setOrderCreateTime(parseDate(orderInfo.getCreateTime())); - sub.setOrderUpdateTime(parseDate(orderInfo.getUpdateTime())); - sub.setOrderFinishTime(parseDate(orderInfo.getOrderFinishTime())); - sub.setDeliveryTime(parseDate(orderInfo.getDeliveryTime())); - sub.setDeliveryStatus(parseInteger(orderInfo.getDeliveryStatus())); - if (orderInfo.getOrderProInfos() != null) { - sub.setExtJson(JSONUtil.toJsonStr(orderInfo.getOrderProInfos())); - } - } catch (Exception e) { - log.error("订单类型为:6(确认收货)时,调用9.2.2 获取订单详情异常:{},{}", queryDTO, e.getMessage()); - } - } - - 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())) { - Sys_user user = fetchUser(dto.getUserId()); - if (user == null) { - return MallInboundResult.fail(400, "用户ID未配置或不存在"); - } - subCnd.and("userId", "=", user.getId()); - } - - 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) { - return invoiceInfo(dto, false); - } - - public MallInboundResult invoiceInfo(MallOrderEventDTO dto, boolean retry) { - String settlementId = dto.getOrderId(); - if (StrUtil.hasBlank(dto.getSupplierId(), settlementId)) { - return MallInboundResult.fail(400, "供应商和结算单号不能为空"); - } - QueryInvoiceInfoDTO query = new QueryInvoiceInfoDTO(); - query.setSupplierId(dto.getSupplierId()); - query.setSettlementId(settlementId); - query.setRetry(retry); - GetInvoiceInfoDTO result; - try { - result = mallInvoiceInfoQueryService.queryInvoicesInfo(query); - } catch (Exception e) { - log.error("调用供应商获取发票信息失败,supplierId={},settlementId={}", dto.getSupplierId(), settlementId, e); - return MallInboundResult.fail(-1, "获取供应商发票信息失败"); - } - - PointsMallInvoiceMain main = dao.fetch(PointsMallInvoiceMain.class, - Cnd.where("settlementId", "=", settlementId).and("delFlag", "=", false)); - if (main == null) { - return MallInboundResult.fail(404, "开票申请记录不存在"); - } - if (result == null || !settlementId.equals(result.getSettlementId())) { - return MallInboundResult.fail(502, "供应商返回的发票结算单不匹配"); - } - Integer success = result.getBSuccess() == null ? 0 : result.getBSuccess(); - if (success == 0) { - if (result.getInvoiceInfos() == null || result.getInvoiceInfos().isEmpty() || StrUtil.isBlank(result.getSucOrderIds())) { - return MallInboundResult.fail(502, "供应商开票结果缺少发票明细或成功订单"); - } - try { - List fileIds = result.getInvoiceInfos().stream().map(InvoiceInfoDTO::getInvoiceId).collect(Collectors.toList()); - if (fileIds.stream().anyMatch(StrUtil::isBlank)) { - throw new IllegalArgumentException("供应商发票文件标识为空"); - } - MallPictureOutboundResult files = mallInvoiceInfoQueryService.queryInvoiceFiles(dto.getSupplierId(), settlementId, fileIds); - for (InvoiceInfoDTO item : result.getInvoiceInfos()) { - if (item.getStatus() != null && item.getStatus() != 1) { - throw new IllegalArgumentException("供应商发票尚未生成成功"); - } - String base64 = files.getImageEncodeMap() == null ? null : files.getImageEncodeMap().get(item.getInvoiceId()); - if (StrUtil.isBlank(base64)) { - throw new IllegalArgumentException("未获取到发票文件Base64:" + item.getInvoiceId()); - } - if (base64.startsWith("data:")) { - base64 = base64.substring(base64.indexOf(',') + 1); - } - byte[] bytes = Base64.getDecoder().decode(base64.replaceAll("\\s", "")); - if (bytes.length == 0) { - throw new IllegalArgumentException("发票文件内容为空"); - } - String fileType = StrUtil.blankToDefault(files.getFileType(), StrUtil.blankToDefault(item.getFileType(), "PDF")); - if (!fileType.matches("(?i)pdf|jpg|jpeg|png")) { - throw new IllegalArgumentException("不支持的发票文件类型:" + fileType); - } - String localUrl = sysFileService.uploadReturnUrl(SysFileEngineTypeEnum.MINIO.getValue(), - "invoice-" + java.util.UUID.randomUUID() + "." + fileType.toLowerCase(java.util.Locale.ROOT), bytes); - item.setUrl(localUrl); - item.setImageEncode(localUrl); - item.setFileType(fileType); - } - } catch (Exception e) { - log.error("发票文件同步失败,settlementId={}", settlementId, e); - return MallInboundResult.fail(502, "发票文件同步失败:" + e.getMessage()); - } - } - Trans.exec((Atom) () -> { - main.setBSuccess(success); - main.setSucOrderIds(result.getSucOrderIds()); - main.setFailOrderIds(result.getFailOrderIds()); - main.setFailMsg(result.getFailMsg()); - if (result.getInvoiceInfos() != null) { - for (InvoiceInfoDTO item : result.getInvoiceInfos()) { - PointsMallInvoiceInfo info = dao.fetch(PointsMallInvoiceInfo.class, - Cnd.where("mainId", "=", main.getId()).and("invoiceId", "=", item.getInvoiceId()).and("delFlag", "=", false)); - if (info == null) { - info = new PointsMallInvoiceInfo(); - info.setMainId(main.getId()); - info.setInvoiceId(item.getInvoiceId()); - } - info.setInvoiceCode(item.getInvoiceCode()); - info.setInvoiceDate(item.getInvoiceDate() == null ? null : DateUtil.parse(item.getInvoiceDate().toString())); - info.setInvoiceNakeAmount(item.getInvoiceNakeAmount()); - info.setInvoiceTaxRate(item.getInvoiceTaxRate()); - info.setInvoiceTaxAmount(item.getInvoiceTaxAmount()); - info.setInvoiceAmount(item.getInvoiceAmount()); - info.setInvoiceType(item.getInvoiceType()); - info.setUrl(item.getUrl()); - info.setImageEncode(item.getImageEncode()); - info.setFileType(item.getFileType()); - info.setCheckCode(item.getCheckCode()); - info.setInvoiceAddress(item.getInvoiceAddress()); - info.setRemark(item.getRemark()); - if (success != 0) { - info.setUrl(""); - info.setImageEncode(""); - } - if (StrUtil.isBlank(info.getId())) { - dao.insert(info); - } else { - dao.updateIgnoreNull(info); - } - } - } - - List successOrderIds = splitIds(result.getSucOrderIds()); - List failOrderIds = splitIds(result.getFailOrderIds()); - if (!successOrderIds.isEmpty()) { - dao.update(PointsMallOrderSub.class, Chain.make("invoiceStatus", 1), Cnd.where("supplierId", "=", dto.getSupplierId()) - .and("orderId", "in", successOrderIds).and("delFlag", "=", false)); - } - if (!failOrderIds.isEmpty()) { - dao.update(PointsMallOrderSub.class, Chain.make("invoiceStatus", 0), Cnd.where("supplierId", "=", dto.getSupplierId()) - .and("orderId", "in", failOrderIds).and("delFlag", "=", false)); - } - dao.updateIgnoreNull(main); - }); - log.info("供应商发票信息更新完成,supplierId={},settlementId={}", dto.getSupplierId(), settlementId); - return MallInboundResult.success(); - } } 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 e0121300..c5e0364c 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,4 +1,5 @@ package com.budwk.app.zhgh.pointsmall.mallbridge.service; +import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallOrderMessageDTO; import cn.hutool.core.bean.BeanUtil; import com.budwk.app.zhgh.pointsmall.mallbridge.dto.MallPurchaseResultDTO; @@ -58,7 +59,7 @@ public class MallInboundPurchaseResultService { } try { // callP消息推送 - mallCallPMessagePushService.pushMessageToGlobal(orderMain); + mallCallPMessagePushService.pushMessageToGlobal("11111111", BeanUtil.copyProperties(orderMain, MallOrderMessageDTO.class)); } catch (Exception e) { log.error("9.2.14 支付结果通知接口,callP消息推送:{},{}", dto, e.getMessage()); }