feat(ticket): 添加水票订单配送流程功能
- 在GltTicketOrder实体类中新增配送相关的字段,包括配送状态、配送时间、收货人信息等 - 实现配送员端订单查询接口,支持按配送状态筛选和权限隔离 - 添加配送流程核心接口:接单、开始配送、确认送达、用户确认收货等功能 - 实现配送状态流转的状态机校验和并发安全的原子更新操作 - 优化数据库查询SQL,增加配送状态和租户ID的索引提升查询性能 - 添加配送员身份验证和权限检查机制,确保操作安全性
This commit is contained in:
@@ -14,6 +14,7 @@ import com.gxwebsoft.glt.param.GltTicketOrderParam;
|
||||
import com.gxwebsoft.glt.service.GltTicketOrderService;
|
||||
import com.gxwebsoft.glt.service.GltUserTicketLogService;
|
||||
import com.gxwebsoft.glt.service.GltUserTicketService;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -114,6 +115,9 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
|
||||
gltTicketOrder.setStatus(0);
|
||||
gltTicketOrder.setDeleted(0);
|
||||
gltTicketOrder.setTenantId(tenantId);
|
||||
if (gltTicketOrder.getDeliveryStatus() == null) {
|
||||
gltTicketOrder.setDeliveryStatus(DELIVERY_STATUS_WAITING);
|
||||
}
|
||||
if (gltTicketOrder.getSortNumber() == null) {
|
||||
gltTicketOrder.setSortNumber(0);
|
||||
}
|
||||
@@ -159,4 +163,189 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
|
||||
return gltTicketOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Integer id, Integer riderId, Integer tenantId) {
|
||||
if (id == null) {
|
||||
throw new BusinessException("订单id不能为空");
|
||||
}
|
||||
if (riderId == null) {
|
||||
throw new BusinessException("配送员信息缺失");
|
||||
}
|
||||
if (tenantId == null) {
|
||||
throw new BusinessException("租户信息缺失");
|
||||
}
|
||||
|
||||
// 原子接单:避免并发抢单
|
||||
boolean ok = this.lambdaUpdate()
|
||||
.set(GltTicketOrder::getRiderId, riderId)
|
||||
.set(GltTicketOrder::getUpdateTime, LocalDateTime.now())
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.and(w -> w.eq(GltTicketOrder::getDeliveryStatus, DELIVERY_STATUS_WAITING)
|
||||
.or().isNull(GltTicketOrder::getDeliveryStatus))
|
||||
.and(w -> w.isNull(GltTicketOrder::getRiderId).or().eq(GltTicketOrder::getRiderId, 0))
|
||||
.update();
|
||||
if (ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 回查给出更明确的错误
|
||||
GltTicketOrder order = this.lambdaQuery()
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.one();
|
||||
if (order == null) {
|
||||
throw new BusinessException("订单不存在");
|
||||
}
|
||||
if (order.getRiderId() != null && order.getRiderId() > 0) {
|
||||
throw new BusinessException("订单已被其他配送员接单");
|
||||
}
|
||||
throw new BusinessException("订单状态不允许接单");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Integer id, Integer riderId, Integer tenantId) {
|
||||
if (id == null) {
|
||||
throw new BusinessException("订单id不能为空");
|
||||
}
|
||||
if (riderId == null) {
|
||||
throw new BusinessException("配送员信息缺失");
|
||||
}
|
||||
if (tenantId == null) {
|
||||
throw new BusinessException("租户信息缺失");
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
boolean ok = this.lambdaUpdate()
|
||||
.set(GltTicketOrder::getDeliveryStatus, DELIVERY_STATUS_DELIVERING)
|
||||
.set(GltTicketOrder::getSendStartTime, now)
|
||||
.set(GltTicketOrder::getUpdateTime, now)
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.eq(GltTicketOrder::getRiderId, riderId)
|
||||
.and(w -> w.eq(GltTicketOrder::getDeliveryStatus, DELIVERY_STATUS_WAITING)
|
||||
.or().isNull(GltTicketOrder::getDeliveryStatus))
|
||||
.update();
|
||||
if (ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
GltTicketOrder order = this.lambdaQuery()
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.one();
|
||||
if (order == null) {
|
||||
throw new BusinessException("订单不存在");
|
||||
}
|
||||
if (!riderId.equals(order.getRiderId())) {
|
||||
throw new BusinessException("无权限操作该订单");
|
||||
}
|
||||
if (order.getDeliveryStatus() != null && order.getDeliveryStatus() == DELIVERY_STATUS_DELIVERING) {
|
||||
// 幂等:重复开始配送视为成功
|
||||
return;
|
||||
}
|
||||
throw new BusinessException("订单状态不允许开始配送");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delivered(Integer id, Integer riderId, Integer tenantId, String sendEndImg) {
|
||||
if (id == null) {
|
||||
throw new BusinessException("订单id不能为空");
|
||||
}
|
||||
if (riderId == null) {
|
||||
throw new BusinessException("配送员信息缺失");
|
||||
}
|
||||
if (tenantId == null) {
|
||||
throw new BusinessException("租户信息缺失");
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
var update = this.lambdaUpdate()
|
||||
.set(GltTicketOrder::getDeliveryStatus, DELIVERY_STATUS_WAIT_CONFIRM)
|
||||
.set(GltTicketOrder::getSendEndTime, now)
|
||||
.set(GltTicketOrder::getUpdateTime, now);
|
||||
if (StringUtils.hasText(sendEndImg)) {
|
||||
update.set(GltTicketOrder::getSendEndImg, sendEndImg);
|
||||
}
|
||||
boolean ok = update
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.eq(GltTicketOrder::getRiderId, riderId)
|
||||
.eq(GltTicketOrder::getDeliveryStatus, DELIVERY_STATUS_DELIVERING)
|
||||
.update();
|
||||
if (ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
GltTicketOrder order = this.lambdaQuery()
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.one();
|
||||
if (order == null) {
|
||||
throw new BusinessException("订单不存在");
|
||||
}
|
||||
if (!riderId.equals(order.getRiderId())) {
|
||||
throw new BusinessException("无权限操作该订单");
|
||||
}
|
||||
if (order.getDeliveryStatus() != null
|
||||
&& (order.getDeliveryStatus() == DELIVERY_STATUS_WAIT_CONFIRM
|
||||
|| order.getDeliveryStatus() == DELIVERY_STATUS_FINISHED)) {
|
||||
// 幂等:重复送达视为成功
|
||||
return;
|
||||
}
|
||||
throw new BusinessException("订单状态不允许确认送达");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirmReceive(Integer id, Integer userId, Integer tenantId) {
|
||||
if (id == null) {
|
||||
throw new BusinessException("订单id不能为空");
|
||||
}
|
||||
if (userId == null) {
|
||||
throw new BusinessException("请先登录");
|
||||
}
|
||||
if (tenantId == null) {
|
||||
throw new BusinessException("租户信息缺失");
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
boolean ok = this.lambdaUpdate()
|
||||
.set(GltTicketOrder::getDeliveryStatus, DELIVERY_STATUS_FINISHED)
|
||||
.set(GltTicketOrder::getReceiveConfirmTime, now)
|
||||
.set(GltTicketOrder::getReceiveConfirmType, RECEIVE_CONFIRM_TYPE_MANUAL)
|
||||
.set(GltTicketOrder::getUpdateTime, now)
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.eq(GltTicketOrder::getUserId, userId)
|
||||
.eq(GltTicketOrder::getDeliveryStatus, DELIVERY_STATUS_WAIT_CONFIRM)
|
||||
.update();
|
||||
if (ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
GltTicketOrder order = this.lambdaQuery()
|
||||
.eq(GltTicketOrder::getId, id)
|
||||
.eq(GltTicketOrder::getTenantId, tenantId)
|
||||
.eq(GltTicketOrder::getDeleted, 0)
|
||||
.one();
|
||||
if (order == null) {
|
||||
throw new BusinessException("订单不存在");
|
||||
}
|
||||
if (!userId.equals(order.getUserId())) {
|
||||
throw new BusinessException("无权限操作该订单");
|
||||
}
|
||||
if (order.getDeliveryStatus() != null && order.getDeliveryStatus() == DELIVERY_STATUS_FINISHED) {
|
||||
// 幂等:重复确认收货视为成功
|
||||
return;
|
||||
}
|
||||
throw new BusinessException("订单状态不允许确认收货");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user