From d778036daf23067940caa9d17ce8fa6137ae5dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Mon, 9 Feb 2026 20:39:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(ticket):=20=E5=AE=9E=E7=8E=B0=E8=B5=B7?= =?UTF-8?q?=E5=A7=8B=E9=80=81=E6=B0=B4=E8=87=AA=E5=8A=A8=E6=A0=B8=E9=94=80?= =?UTF-8?q?=E5=B9=B6=E7=94=9F=E6=88=90=E9=80=81=E6=B0=B4=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在自动核销成功后创建送水订单用于配送端跟踪 - 添加对用户水票更新失败的异常处理机制 - 添加对送水订单创建失败的异常处理机制 - 更新水票日志关联到送水订单并保留来源商城订单号 - 实现地址快照功能,优先使用地址表数据并兼容旧数据格式 - 添加安全字符串处理方法防止空指针异常 - 集成 ShopUserAddressService 和 GltTicketOrderService 服务 --- .../glt/service/GltTicketIssueService.java | 99 ++++++++++++++++++- 1 file changed, 94 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/gxwebsoft/glt/service/GltTicketIssueService.java b/src/main/java/com/gxwebsoft/glt/service/GltTicketIssueService.java index 542b7cc..004abf2 100644 --- a/src/main/java/com/gxwebsoft/glt/service/GltTicketIssueService.java +++ b/src/main/java/com/gxwebsoft/glt/service/GltTicketIssueService.java @@ -2,22 +2,27 @@ package com.gxwebsoft.glt.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.gxwebsoft.glt.entity.GltTicketOrder; import com.gxwebsoft.glt.entity.GltTicketTemplate; import com.gxwebsoft.glt.entity.GltUserTicket; import com.gxwebsoft.glt.entity.GltUserTicketLog; import com.gxwebsoft.glt.entity.GltUserTicketRelease; import com.gxwebsoft.shop.entity.ShopOrder; import com.gxwebsoft.shop.entity.ShopOrderGoods; +import com.gxwebsoft.shop.entity.ShopUserAddress; import com.gxwebsoft.shop.service.ShopOrderGoodsService; import com.gxwebsoft.shop.service.ShopOrderService; +import com.gxwebsoft.shop.service.ShopUserAddressService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.support.TransactionTemplate; +import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -55,6 +60,8 @@ public class GltTicketIssueService { private final GltUserTicketService gltUserTicketService; private final GltUserTicketReleaseService gltUserTicketReleaseService; private final GltUserTicketLogService gltUserTicketLogService; + private final GltTicketOrderService gltTicketOrderService; + private final ShopUserAddressService shopUserAddressService; private final TransactionTemplate transactionTemplate; /** @@ -312,7 +319,15 @@ public class GltTicketIssueService { userTicket.setAvailableQty(availableBefore - toUse); userTicket.setUsedQty(usedBefore + toUse); userTicket.setUpdateTime(now); - gltUserTicketService.updateById(userTicket); + if (!gltUserTicketService.updateById(userTicket)) { + throw new IllegalStateException("起始送水自动核销:更新用户水票失败 userTicketId=" + userTicket.getId()); + } + + // 起始送水:自动核销成功后,生成一条送水订单(用于配送端/后台跟踪) + GltTicketOrder ticketOrder = buildStartSendTicketOrder(tenantId, order, userTicket, toUse, now); + if (!gltTicketOrderService.save(ticketOrder)) { + throw new IllegalStateException("起始送水自动核销:创建送水订单失败 userTicketId=" + userTicket.getId()); + } GltUserTicketLog writeOffLog = new GltUserTicketLog(); writeOffLog.setUserTicketId(userTicket.getId()); @@ -323,12 +338,12 @@ public class GltTicketIssueService { writeOffLog.setAvailableAfter(userTicket.getAvailableQty()); writeOffLog.setFrozenAfter(userTicket.getFrozenQty() != null ? userTicket.getFrozenQty() : 0); writeOffLog.setUsedAfter(userTicket.getUsedQty()); - // 关联原始商城订单,便于追溯该次自动核销来源 - writeOffLog.setOrderId(order.getOrderId()); - writeOffLog.setOrderNo(order.getOrderNo()); + // 关联送水订单(保持与“用户下单核销”的日志一致),并在备注里保留来源商城订单号便于追溯 + writeOffLog.setOrderId(ticketOrder.getId()); + writeOffLog.setOrderNo(ticketOrder.getId() == null ? null : String.valueOf(ticketOrder.getId())); writeOffLog.setUserId(order.getUserId()); writeOffLog.setSortNumber(0); - writeOffLog.setComments("起始送水自动核销"); + writeOffLog.setComments("起始送水自动核销(来源商城订单:" + safe(order.getOrderNo()) + ")"); writeOffLog.setStatus(0); writeOffLog.setDeleted(0); writeOffLog.setTenantId(tenantId); @@ -423,4 +438,78 @@ public class GltTicketIssueService { LocalDate adjusted = nextMonth.withDayOfMonth(day); return LocalDateTime.of(adjusted, time); } + + private static final DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + private GltTicketOrder buildStartSendTicketOrder(Integer tenantId, + ShopOrder shopOrder, + GltUserTicket userTicket, + int totalNum, + LocalDateTime now) { + GltTicketOrder o = new GltTicketOrder(); + o.setUserTicketId(userTicket.getId()); + o.setUserId(shopOrder.getUserId()); + o.setStoreId(shopOrder.getStoreId()); + o.setWarehouseId(shopOrder.getWarehouseId()); + o.setRiderId(shopOrder.getRiderId()); + o.setTotalNum(totalNum); + o.setPrice(BigDecimal.ZERO); + o.setBuyerRemarks(shopOrder.getBuyerRemarks()); + + // 地址快照:优先使用地址表快照;兜底使用商城订单上的 address 字段 + Integer addressId = shopOrder.getAddressId(); + o.setAddressId(addressId); + String addressSnapshot = null; + if (addressId != null) { + ShopUserAddress addr = shopUserAddressService.getOne(new LambdaQueryWrapper() + .eq(ShopUserAddress::getId, addressId) + .eq(ShopUserAddress::getUserId, shopOrder.getUserId()) + .eq(ShopUserAddress::getTenantId, tenantId) + .last("limit 1")); + addressSnapshot = buildAddressSnapshot(addr); + } + if (addressSnapshot == null || addressSnapshot.isBlank()) { + addressSnapshot = shopOrder.getAddress(); + } + o.setAddress(addressSnapshot); + + String preferredSendTime = shopOrder.getSendStartTime(); + if (preferredSendTime == null || preferredSendTime.isBlank()) { + preferredSendTime = now.format(DATETIME_FMT); + } + o.setSendTime(preferredSendTime); + o.setDeliveryStatus(GltTicketOrderService.DELIVERY_STATUS_WAITING); + o.setSortNumber(0); + o.setComments("起始送水自动下单(来源商城订单:" + safe(shopOrder.getOrderNo()) + ")"); + o.setStatus(0); + o.setDeleted(0); + o.setTenantId(tenantId); + o.setCreateTime(now); + o.setUpdateTime(now); + return o; + } + + private static String buildAddressSnapshot(ShopUserAddress addr) { + if (addr == null) { + return null; + } + if (addr.getFullAddress() != null && !addr.getFullAddress().isBlank()) { + return addr.getFullAddress(); + } + // 兼容旧数据:fullAddress 为空时,拼接省市区 + 详细地址 + StringBuilder sb = new StringBuilder(); + if (addr.getProvince() != null) sb.append(addr.getProvince()); + if (addr.getCity() != null) sb.append(addr.getCity()); + if (addr.getRegion() != null) sb.append(addr.getRegion()); + if (addr.getAddress() != null) sb.append(addr.getAddress()); + String s = sb.toString(); + if (!s.isBlank()) { + return s; + } + return addr.getAddress(); + } + + private static String safe(String s) { + return s == null ? "" : s; + } }