feat(order): 完善送水订单与商城订单同步功能

- 在订单更新时增加租户ID获取逻辑并传递给相关服务方法
- 新增后台直接修改订单为已完成状态时同步商城订单的功能
- 优化数据库查询,使用COALESCE函数处理订单号显示逻辑
- 新增通过订单商品ID反向查找商城订单的兼容性处理
- 增加历史数据兜底机制,自动回填缺失的订单关联信息
- 添加详细的日志记录用于调试和监控订单同步状态
This commit is contained in:
2026-02-10 17:27:45 +08:00
parent e1ef21f140
commit 4fbd55cd41
4 changed files with 126 additions and 2 deletions

View File

@@ -242,6 +242,7 @@ public class GltTicketOrderController extends BaseController {
@PutMapping() @PutMapping()
public ApiResult<?> update(@RequestBody GltTicketOrder gltTicketOrder) { public ApiResult<?> update(@RequestBody GltTicketOrder gltTicketOrder) {
if (gltTicketOrderService.updateById(gltTicketOrder)) { if (gltTicketOrderService.updateById(gltTicketOrder)) {
Integer tenantId = getTenantId();
// 后台指派配送员(直接改 riderId同步商城订单为“已发货”(deliveryStatus=20) // 后台指派配送员(直接改 riderId同步商城订单为“已发货”(deliveryStatus=20)
if (gltTicketOrder != null if (gltTicketOrder != null
&& gltTicketOrder.getId() != null && gltTicketOrder.getId() != null
@@ -249,10 +250,17 @@ public class GltTicketOrderController extends BaseController {
&& gltTicketOrder.getRiderId() > 0) { && gltTicketOrder.getRiderId() > 0) {
gltTicketOrderService.markShopOrderShippedAfterRiderAssigned( gltTicketOrderService.markShopOrderShippedAfterRiderAssigned(
gltTicketOrder.getId(), gltTicketOrder.getId(),
getTenantId(), tenantId,
gltTicketOrder.getRiderId() gltTicketOrder.getRiderId()
); );
} }
// 后台直接改“已完成”(deliveryStatus=40)时,同步商城订单为“已完成”(orderStatus=1)
if (gltTicketOrder != null
&& gltTicketOrder.getId() != null
&& gltTicketOrder.getDeliveryStatus() != null
&& gltTicketOrder.getDeliveryStatus() == GltTicketOrderService.DELIVERY_STATUS_FINISHED) {
gltTicketOrderService.markShopOrderCompletedAfterTicketFinished(gltTicketOrder.getId(), tenantId);
}
return success("修改成功"); return success("修改成功");
} }
return fail("修改失败"); return fail("修改失败");

View File

@@ -11,7 +11,7 @@
d.name as receiverName, d.phone as receiverPhone, d.name as receiverName, d.phone as receiverPhone,
d.province as receiverProvince, d.city as receiverCity, d.region as receiverRegion, d.province as receiverProvince, d.city as receiverCity, d.region as receiverRegion,
d.address as receiverAddress, d.full_address as receiverFullAddress, d.lat as receiverLat, d.lng as receiverLng, d.address as receiverAddress, d.full_address as receiverFullAddress, d.lat as receiverLat, d.lng as receiverLng,
f.order_no as orderNo COALESCE(o.order_no, f.order_no) as orderNo
FROM glt_ticket_order a FROM glt_ticket_order a
LEFT JOIN shop_store b ON a.store_id = b.id LEFT JOIN shop_store b ON a.store_id = b.id
LEFT JOIN shop_store_warehouse w ON a.warehouse_id = w.id LEFT JOIN shop_store_warehouse w ON a.warehouse_id = w.id
@@ -19,6 +19,7 @@
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
LEFT JOIN shop_user_address d ON a.address_id = d.id LEFT JOIN shop_user_address d ON a.address_id = d.id
LEFT JOIN glt_user_ticket f ON a.user_ticket_id = f.id LEFT JOIN glt_user_ticket f ON a.user_ticket_id = f.id
LEFT JOIN shop_order o ON f.order_id = o.order_id AND f.tenant_id = o.tenant_id AND o.deleted = 0
<where> <where>
<if test="param.id != null"> <if test="param.id != null">

View File

@@ -71,6 +71,13 @@ public interface GltTicketOrderService extends IService<GltTicketOrder> {
*/ */
void markShopOrderShippedAfterRiderAssigned(Integer ticketOrderId, Integer tenantId, Integer riderId); void markShopOrderShippedAfterRiderAssigned(Integer ticketOrderId, Integer tenantId, Integer riderId);
/**
* 送水订单完成后,同步关联商城订单为“已完成”(orderStatus=1)。
*
* <p>用于后台直接改 deliveryStatus=40 等不经过 confirmReceive/autoConfirmTimeout 的兜底同步。</p>
*/
void markShopOrderCompletedAfterTicketFinished(Integer ticketOrderId, Integer tenantId);
/** /**
* 配送员开始配送10 -> 20并写 sendStartTime。 * 配送员开始配送10 -> 20并写 sendStartTime。
*/ */

View File

@@ -21,8 +21,10 @@ import com.gxwebsoft.glt.service.GltUserTicketService;
import com.gxwebsoft.shop.entity.ShopDealerCapital; import com.gxwebsoft.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.entity.ShopDealerUser; import com.gxwebsoft.shop.entity.ShopDealerUser;
import com.gxwebsoft.shop.entity.ShopOrder; import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
import com.gxwebsoft.shop.service.ShopDealerCapitalService; import com.gxwebsoft.shop.service.ShopDealerCapitalService;
import com.gxwebsoft.shop.service.ShopDealerUserService; import com.gxwebsoft.shop.service.ShopDealerUserService;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService; import com.gxwebsoft.shop.service.ShopOrderService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@@ -77,6 +79,9 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
@Resource @Resource
private ShopOrderService shopOrderService; private ShopOrderService shopOrderService;
@Resource
private ShopOrderGoodsService shopOrderGoodsService;
@Override @Override
public PageResult<GltTicketOrder> pageRel(GltTicketOrderParam param) { public PageResult<GltTicketOrder> pageRel(GltTicketOrderParam param) {
PageParam<GltTicketOrder, GltTicketOrderParam> page = new PageParam<>(param); PageParam<GltTicketOrder, GltTicketOrderParam> page = new PageParam<>(param);
@@ -249,6 +254,11 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
updateShopOrderDeliveryStatusAfterAccept(ticketOrderId, tenantId, riderId, LocalDateTime.now()); updateShopOrderDeliveryStatusAfterAccept(ticketOrderId, tenantId, riderId, LocalDateTime.now());
} }
@Override
public void markShopOrderCompletedAfterTicketFinished(Integer ticketOrderId, Integer tenantId) {
updateShopOrderOrderStatusAfterTicketFinished(ticketOrderId, tenantId, LocalDateTime.now());
}
private void updateShopOrderDeliveryStatusAfterAccept(Integer ticketOrderId, Integer tenantId, Integer riderId, LocalDateTime now) { private void updateShopOrderDeliveryStatusAfterAccept(Integer ticketOrderId, Integer tenantId, Integer riderId, LocalDateTime now) {
if (ticketOrderId == null || tenantId == null) { if (ticketOrderId == null || tenantId == null) {
return; return;
@@ -281,9 +291,58 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
Integer shopOrderId = userTicket.getOrderId(); Integer shopOrderId = userTicket.getOrderId();
String shopOrderNo = userTicket.getOrderNo(); String shopOrderNo = userTicket.getOrderNo();
boolean resolvedByOrderGoodsId = false;
// 兼容历史数据:部分水票可能只写了 orderGoodsId未写 orderId/orderNo此处兜底通过 orderGoodsId 反查 ShopOrder.orderId。
if (shopOrderId == null && !StringUtils.hasText(shopOrderNo) && userTicket.getOrderGoodsId() != null) {
ShopOrderGoods og = shopOrderGoodsService.getOne(
new LambdaQueryWrapper<ShopOrderGoods>()
.select(ShopOrderGoods::getOrderId)
.eq(ShopOrderGoods::getTenantId, tenantId)
.eq(ShopOrderGoods::getId, userTicket.getOrderGoodsId())
.last("limit 1")
);
if (og != null) {
shopOrderId = og.getOrderId();
resolvedByOrderGoodsId = shopOrderId != null;
}
}
if (shopOrderId == null && !StringUtils.hasText(shopOrderNo)) { if (shopOrderId == null && !StringUtils.hasText(shopOrderNo)) {
log.warn("同步商城订单发货状态失败:未找到关联商城订单 - tenantId={}, ticketOrderId={}, userTicketId={}, userTicket.orderId={}, userTicket.orderNo={}, userTicket.orderGoodsId={}",
tenantId, ticketOrderId, userTicket.getId(), userTicket.getOrderId(), userTicket.getOrderNo(), userTicket.getOrderGoodsId());
return; return;
} }
// 若是通过 orderGoodsId 兜底反查到 orderId则顺便回填 glt_user_ticket.order_id/order_no减少后续同步/查询依赖兜底分支。
if (resolvedByOrderGoodsId && userTicket.getOrderId() == null && shopOrderId != null) {
if (!StringUtils.hasText(shopOrderNo)) {
ShopOrder order = shopOrderService.getOne(
new LambdaQueryWrapper<ShopOrder>()
.select(ShopOrder::getOrderNo)
.eq(ShopOrder::getTenantId, tenantId)
.eq(ShopOrder::getDeleted, 0)
.eq(ShopOrder::getOrderId, shopOrderId)
.last("limit 1")
);
if (order != null) {
shopOrderNo = order.getOrderNo();
}
}
LambdaUpdateWrapper<GltUserTicket> backfill = new LambdaUpdateWrapper<GltUserTicket>()
.eq(GltUserTicket::getTenantId, tenantId)
.eq(GltUserTicket::getDeleted, 0)
.eq(GltUserTicket::getId, userTicket.getId());
backfill.set(GltUserTicket::getOrderId, shopOrderId);
if (!StringUtils.hasText(userTicket.getOrderNo()) && StringUtils.hasText(shopOrderNo)) {
backfill.set(GltUserTicket::getOrderNo, shopOrderNo);
}
backfill.set(GltUserTicket::getUpdateTime, now);
try {
gltUserTicketService.update(backfill);
} catch (Exception e) {
log.debug("回填水票关联商城订单信息失败(不影响主流程) - tenantId={}, userTicketId={}, orderId={}, orderNo={}",
tenantId, userTicket.getId(), shopOrderId, shopOrderNo, e);
}
}
LambdaUpdateWrapper<ShopOrder> uw = new LambdaUpdateWrapper<ShopOrder>() LambdaUpdateWrapper<ShopOrder> uw = new LambdaUpdateWrapper<ShopOrder>()
.eq(ShopOrder::getTenantId, tenantId) .eq(ShopOrder::getTenantId, tenantId)
@@ -586,9 +645,58 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
Integer shopOrderId = userTicket.getOrderId(); Integer shopOrderId = userTicket.getOrderId();
String shopOrderNo = userTicket.getOrderNo(); String shopOrderNo = userTicket.getOrderNo();
boolean resolvedByOrderGoodsId = false;
// 兼容历史数据:部分水票可能只写了 orderGoodsId未写 orderId/orderNo此处兜底通过 orderGoodsId 反查 ShopOrder.orderId。
if (shopOrderId == null && !StringUtils.hasText(shopOrderNo) && userTicket.getOrderGoodsId() != null) {
ShopOrderGoods og = shopOrderGoodsService.getOne(
new LambdaQueryWrapper<ShopOrderGoods>()
.select(ShopOrderGoods::getOrderId)
.eq(ShopOrderGoods::getTenantId, tenantId)
.eq(ShopOrderGoods::getId, userTicket.getOrderGoodsId())
.last("limit 1")
);
if (og != null) {
shopOrderId = og.getOrderId();
resolvedByOrderGoodsId = shopOrderId != null;
}
}
if (shopOrderId == null && !StringUtils.hasText(shopOrderNo)) { if (shopOrderId == null && !StringUtils.hasText(shopOrderNo)) {
log.warn("送水订单完成但未找到关联商城订单,无法同步完成状态 - tenantId={}, ticketOrderId={}, userTicketId={}, userTicket.orderId={}, userTicket.orderNo={}, userTicket.orderGoodsId={}",
tenantId, ticketOrderId, userTicket.getId(), userTicket.getOrderId(), userTicket.getOrderNo(), userTicket.getOrderGoodsId());
return; return;
} }
// 若是通过 orderGoodsId 兜底反查到 orderId则顺便回填 glt_user_ticket.order_id/order_no减少后续同步/查询依赖兜底分支。
if (resolvedByOrderGoodsId && userTicket.getOrderId() == null && shopOrderId != null) {
if (!StringUtils.hasText(shopOrderNo)) {
ShopOrder order = shopOrderService.getOne(
new LambdaQueryWrapper<ShopOrder>()
.select(ShopOrder::getOrderNo)
.eq(ShopOrder::getTenantId, tenantId)
.eq(ShopOrder::getDeleted, 0)
.eq(ShopOrder::getOrderId, shopOrderId)
.last("limit 1")
);
if (order != null) {
shopOrderNo = order.getOrderNo();
}
}
LambdaUpdateWrapper<GltUserTicket> backfill = new LambdaUpdateWrapper<GltUserTicket>()
.eq(GltUserTicket::getTenantId, tenantId)
.eq(GltUserTicket::getDeleted, 0)
.eq(GltUserTicket::getId, userTicket.getId());
backfill.set(GltUserTicket::getOrderId, shopOrderId);
if (!StringUtils.hasText(userTicket.getOrderNo()) && StringUtils.hasText(shopOrderNo)) {
backfill.set(GltUserTicket::getOrderNo, shopOrderNo);
}
backfill.set(GltUserTicket::getUpdateTime, now);
try {
gltUserTicketService.update(backfill);
} catch (Exception e) {
log.debug("回填水票关联商城订单信息失败(不影响主流程) - tenantId={}, userTicketId={}, orderId={}, orderNo={}",
tenantId, userTicket.getId(), shopOrderId, shopOrderNo, e);
}
}
LambdaUpdateWrapper<ShopOrder> uw = new LambdaUpdateWrapper<ShopOrder>() LambdaUpdateWrapper<ShopOrder> uw = new LambdaUpdateWrapper<ShopOrder>()
.eq(ShopOrder::getTenantId, tenantId) .eq(ShopOrder::getTenantId, tenantId)