feat(ticket): 添加水票订单配送流程功能
- 在GltTicketOrder实体类中新增配送相关的字段,包括配送状态、配送时间、收货人信息等 - 实现配送员端订单查询接口,支持按配送状态筛选和权限隔离 - 添加配送流程核心接口:接单、开始配送、确认送达、用户确认收货等功能 - 实现配送状态流转的状态机校验和并发安全的原子更新操作 - 优化数据库查询SQL,增加配送状态和租户ID的索引提升查询性能 - 添加配送员身份验证和权限检查机制,确保操作安全性
This commit is contained in:
@@ -5,15 +5,20 @@ import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.core.exception.BusinessException;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.glt.entity.GltTicketOrder;
|
||||
import com.gxwebsoft.glt.param.GltTicketOrderDeliveredParam;
|
||||
import com.gxwebsoft.glt.param.GltTicketOrderParam;
|
||||
import com.gxwebsoft.glt.service.GltTicketOrderService;
|
||||
import com.gxwebsoft.shop.entity.ShopStoreRider;
|
||||
import com.gxwebsoft.shop.entity.ShopUserAddress;
|
||||
import com.gxwebsoft.shop.service.ShopStoreRiderService;
|
||||
import com.gxwebsoft.shop.service.ShopUserAddressService;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -34,6 +39,8 @@ public class GltTicketOrderController extends BaseController {
|
||||
private GltTicketOrderService gltTicketOrderService;
|
||||
@Resource
|
||||
private ShopUserAddressService shopUserAddressService;
|
||||
@Resource
|
||||
private ShopStoreRiderService shopStoreRiderService;
|
||||
|
||||
@Operation(summary = "分页查询送水订单")
|
||||
@GetMapping("/page")
|
||||
@@ -42,6 +49,30 @@ public class GltTicketOrderController extends BaseController {
|
||||
return success(gltTicketOrderService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@Operation(summary = "配送员端:分页查询我的送水订单")
|
||||
@GetMapping("/rider/page")
|
||||
public ApiResult<PageResult<GltTicketOrder>> riderPage(GltTicketOrderParam param) {
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser == null) {
|
||||
return fail("请先登录");
|
||||
}
|
||||
Integer tenantId = getTenantId();
|
||||
param.setTenantId(tenantId);
|
||||
// 仅允许配送员访问
|
||||
requireActiveRider(loginUser.getUserId(), tenantId);
|
||||
|
||||
param.setRiderId(loginUser.getUserId());
|
||||
if (param.getDeliveryStatus() == null) {
|
||||
param.setDeliveryStatus(GltTicketOrderService.DELIVERY_STATUS_WAITING);
|
||||
}
|
||||
// 配送员端默认按期望配送时间优先
|
||||
if (StrUtil.isBlank(param.getSort())) {
|
||||
param.setSort("sendTime asc, createTime desc");
|
||||
}
|
||||
return success(gltTicketOrderService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部送水订单")
|
||||
@GetMapping()
|
||||
public ApiResult<List<GltTicketOrder>> list(GltTicketOrderParam param) {
|
||||
@@ -92,6 +123,83 @@ public class GltTicketOrderController extends BaseController {
|
||||
return success("下单成功");
|
||||
}
|
||||
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@Operation(summary = "配送员接单")
|
||||
@PostMapping("/{id}/accept")
|
||||
public ApiResult<?> accept(@PathVariable("id") Integer id) {
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser == null) {
|
||||
return fail("请先登录");
|
||||
}
|
||||
Integer tenantId = getTenantId();
|
||||
requireActiveRider(loginUser.getUserId(), tenantId);
|
||||
gltTicketOrderService.accept(id, loginUser.getUserId(), tenantId);
|
||||
return success("接单成功");
|
||||
}
|
||||
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@Operation(summary = "配送员开始配送")
|
||||
@PostMapping("/{id}/start")
|
||||
public ApiResult<?> start(@PathVariable("id") Integer id) {
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser == null) {
|
||||
return fail("请先登录");
|
||||
}
|
||||
Integer tenantId = getTenantId();
|
||||
requireActiveRider(loginUser.getUserId(), tenantId);
|
||||
gltTicketOrderService.start(id, loginUser.getUserId(), tenantId);
|
||||
return success("开始配送");
|
||||
}
|
||||
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@Operation(summary = "配送员确认送达")
|
||||
@PostMapping("/{id}/delivered")
|
||||
public ApiResult<?> delivered(@PathVariable("id") Integer id,
|
||||
@RequestBody(required = false) GltTicketOrderDeliveredParam body) {
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser == null) {
|
||||
return fail("请先登录");
|
||||
}
|
||||
Integer tenantId = getTenantId();
|
||||
requireActiveRider(loginUser.getUserId(), tenantId);
|
||||
String sendEndImg = body == null ? null : body.getSendEndImg();
|
||||
gltTicketOrderService.delivered(id, loginUser.getUserId(), tenantId, sendEndImg);
|
||||
return success("确认送达");
|
||||
}
|
||||
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@Operation(summary = "用户确认收货")
|
||||
@PostMapping("/{id}/confirm-receive")
|
||||
public ApiResult<?> confirmReceive(@PathVariable("id") Integer id) {
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser == null) {
|
||||
return fail("请先登录");
|
||||
}
|
||||
gltTicketOrderService.confirmReceive(id, loginUser.getUserId(), getTenantId());
|
||||
return success("确认收货成功");
|
||||
}
|
||||
|
||||
private ShopStoreRider requireActiveRider(Integer userId, Integer tenantId) {
|
||||
if (userId == null) {
|
||||
throw new BusinessException("请先登录");
|
||||
}
|
||||
if (tenantId == null) {
|
||||
throw new BusinessException("租户信息缺失");
|
||||
}
|
||||
ShopStoreRider rider = shopStoreRiderService.getOne(new LambdaQueryWrapper<ShopStoreRider>()
|
||||
.eq(ShopStoreRider::getUserId, userId)
|
||||
.eq(ShopStoreRider::getTenantId, tenantId)
|
||||
.eq(ShopStoreRider::getIsDelete, 0)
|
||||
.last("limit 1"));
|
||||
if (rider == null) {
|
||||
throw new BusinessException("非配送员,无权限操作");
|
||||
}
|
||||
if (rider.getStatus() == null || rider.getStatus() != 1) {
|
||||
throw new BusinessException("配送员已禁用");
|
||||
}
|
||||
return rider;
|
||||
}
|
||||
|
||||
private String buildAddressSnapshot(ShopUserAddress addr) {
|
||||
if (addr == null) {
|
||||
return null;
|
||||
|
||||
@@ -68,6 +68,10 @@ public class GltTicketOrder implements Serializable {
|
||||
@TableField(exist = false)
|
||||
private String warehouseAddress;
|
||||
|
||||
@Schema(description = "仓库手机号")
|
||||
@TableField(exist = false)
|
||||
private String warehousePhone;
|
||||
|
||||
@Schema(description = "关联收货地址")
|
||||
private Integer addressId;
|
||||
|
||||
@@ -99,6 +103,27 @@ public class GltTicketOrder implements Serializable {
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private String sendTime;
|
||||
|
||||
@Schema(description = "配送状态:10待配送、20配送中、30待客户确认、40已完成")
|
||||
private Integer deliveryStatus;
|
||||
|
||||
@Schema(description = "开始配送时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime sendStartTime;
|
||||
|
||||
@Schema(description = "确认送达时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime sendEndTime;
|
||||
|
||||
@Schema(description = "送达拍照留档图片URL")
|
||||
private String sendEndImg;
|
||||
|
||||
@Schema(description = "客户确认收货时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime receiveConfirmTime;
|
||||
|
||||
@Schema(description = "确认方式:10客户手动确认、20配送照片自动确认、30超时自动确认")
|
||||
private Integer receiveConfirmType;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@@ -114,6 +139,50 @@ public class GltTicketOrder implements Serializable {
|
||||
@TableField(exist = false)
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "收货人姓名")
|
||||
@TableField(exist = false)
|
||||
private String receiverName;
|
||||
|
||||
@Schema(description = "收货人手机号")
|
||||
@TableField(exist = false)
|
||||
private String receiverPhone;
|
||||
|
||||
@Schema(description = "收货省")
|
||||
@TableField(exist = false)
|
||||
private String receiverProvince;
|
||||
|
||||
@Schema(description = "收货市")
|
||||
@TableField(exist = false)
|
||||
private String receiverCity;
|
||||
|
||||
@Schema(description = "收货区")
|
||||
@TableField(exist = false)
|
||||
private String receiverRegion;
|
||||
|
||||
@Schema(description = "收货详细地址")
|
||||
@TableField(exist = false)
|
||||
private String receiverAddress;
|
||||
|
||||
@Schema(description = "收货完整地址")
|
||||
@TableField(exist = false)
|
||||
private String receiverFullAddress;
|
||||
|
||||
@Schema(description = "收货纬度")
|
||||
@TableField(exist = false)
|
||||
private String receiverLat;
|
||||
|
||||
@Schema(description = "收货经度")
|
||||
@TableField(exist = false)
|
||||
private String receiverLng;
|
||||
|
||||
@Schema(description = "门店经纬度(lng,lat)")
|
||||
@TableField(exist = false)
|
||||
private String storeLngAndLat;
|
||||
|
||||
@Schema(description = "仓库经纬度(lng,lat)")
|
||||
@TableField(exist = false)
|
||||
private String warehouseLngAndLat;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
|
||||
@@ -4,13 +4,19 @@
|
||||
|
||||
<!-- 关联查询sql -->
|
||||
<sql id="selectSql">
|
||||
SELECT a.*, b.name as storeName, b.address as storeAddress, b.phone as storePhone,
|
||||
SELECT a.*, b.name as storeName, b.address as storeAddress, b.phone as storePhone, b.lng_and_lat as storeLngAndLat,
|
||||
w.name as warehouseName, w.address as warehouseAddress, w.phone as warehousePhone, w.lng_and_lat as warehouseLngAndLat,
|
||||
c.real_name as riderName, c.mobile as riderPhone,
|
||||
u.nickname, u.phone, u.avatar
|
||||
u.nickname, u.phone, u.avatar,
|
||||
d.name as receiverName, d.phone as receiverPhone,
|
||||
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
|
||||
FROM glt_ticket_order a
|
||||
LEFT JOIN shop_store b ON a.store_id = b.id
|
||||
LEFT JOIN shop_warehouse w ON a.warehouse_id = w.id
|
||||
LEFT JOIN shop_store_rider c ON a.rider_id = c.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
|
||||
|
||||
<where>
|
||||
<if test="param.id != null">
|
||||
@@ -25,6 +31,9 @@
|
||||
<if test="param.riderId != null">
|
||||
AND a.rider_id = #{param.riderId}
|
||||
</if>
|
||||
<if test="param.deliveryStatus != null">
|
||||
AND a.delivery_status = #{param.deliveryStatus}
|
||||
</if>
|
||||
<if test="param.warehouseId != null">
|
||||
AND a.warehouse_id = #{param.warehouseId}
|
||||
</if>
|
||||
@@ -55,6 +64,9 @@
|
||||
<if test="param.status != null">
|
||||
AND a.status = #{param.status}
|
||||
</if>
|
||||
<if test="param.tenantId != null">
|
||||
AND a.tenant_id = #{param.tenantId}
|
||||
</if>
|
||||
<if test="param.deleted != null">
|
||||
AND a.deleted = #{param.deleted}
|
||||
</if>
|
||||
@@ -68,9 +80,15 @@
|
||||
AND a.create_time <= #{param.createTimeEnd}
|
||||
</if>
|
||||
<if test="param.keywords != null">
|
||||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
AND (
|
||||
a.address LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
OR a.buyer_remarks LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
OR a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
OR u.nickname LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
OR u.phone LIKE CONCAT('%', #{param.keywords}, '%')
|
||||
)
|
||||
</if>
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.gxwebsoft.glt.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 配送员确认送达参数
|
||||
*/
|
||||
@Data
|
||||
public class GltTicketOrderDeliveredParam implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "送达拍照留档图片URL")
|
||||
private String sendEndImg;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ public class GltTicketOrderParam extends BaseParam {
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer riderId;
|
||||
|
||||
@Schema(description = "配送状态:10待配送、20配送中、30待客户确认、40已完成")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer deliveryStatus;
|
||||
|
||||
@Schema(description = "仓库ID")
|
||||
@QueryField(type = QueryType.EQ)
|
||||
private Integer warehouseId;
|
||||
|
||||
@@ -15,6 +15,15 @@ import java.util.List;
|
||||
*/
|
||||
public interface GltTicketOrderService extends IService<GltTicketOrder> {
|
||||
|
||||
int DELIVERY_STATUS_WAITING = 10;
|
||||
int DELIVERY_STATUS_DELIVERING = 20;
|
||||
int DELIVERY_STATUS_WAIT_CONFIRM = 30;
|
||||
int DELIVERY_STATUS_FINISHED = 40;
|
||||
|
||||
int RECEIVE_CONFIRM_TYPE_MANUAL = 10;
|
||||
int RECEIVE_CONFIRM_TYPE_PHOTO = 20;
|
||||
int RECEIVE_CONFIRM_TYPE_TIMEOUT = 30;
|
||||
|
||||
/**
|
||||
* 分页关联查询
|
||||
*
|
||||
@@ -49,4 +58,24 @@ public interface GltTicketOrderService extends IService<GltTicketOrder> {
|
||||
*/
|
||||
GltTicketOrder createWithWriteOff(GltTicketOrder gltTicketOrder, Integer userId, Integer tenantId);
|
||||
|
||||
/**
|
||||
* 配送员接单(原子):仅当 riderId 为空(或0)且 deliveryStatus=10 时写入 riderId。
|
||||
*/
|
||||
void accept(Integer id, Integer riderId, Integer tenantId);
|
||||
|
||||
/**
|
||||
* 配送员开始配送:10 -> 20,并写 sendStartTime。
|
||||
*/
|
||||
void start(Integer id, Integer riderId, Integer tenantId);
|
||||
|
||||
/**
|
||||
* 配送员确认送达:20 -> 30,并写 sendEndTime / sendEndImg。
|
||||
*/
|
||||
void delivered(Integer id, Integer riderId, Integer tenantId, String sendEndImg);
|
||||
|
||||
/**
|
||||
* 用户确认收货:30 -> 40,并写 receiveConfirmTime / receiveConfirmType=10。
|
||||
*/
|
||||
void confirmReceive(Integer id, Integer userId, Integer tenantId);
|
||||
|
||||
}
|
||||
|
||||
@@ -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