feat: add delivery assignment and rider APIs
This commit is contained in:
@@ -0,0 +1,92 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.api.ApiResponse;
|
||||||
|
import com.linhelp.common.enums.DeliveryTaskStatus;
|
||||||
|
import com.linhelp.common.security.AuthService;
|
||||||
|
import com.linhelp.common.security.CurrentUser;
|
||||||
|
import com.linhelp.common.security.RequireRole;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequireRole({"PLATFORM_ADMIN", "COMMUNITY_ADMIN"})
|
||||||
|
public class DeliveryAdminController {
|
||||||
|
private final DeliveryUserService deliveryUserService;
|
||||||
|
private final DeliveryAssignmentService assignmentService;
|
||||||
|
private final AuthService authService;
|
||||||
|
|
||||||
|
public DeliveryAdminController(DeliveryUserService deliveryUserService,
|
||||||
|
DeliveryAssignmentService assignmentService,
|
||||||
|
AuthService authService) {
|
||||||
|
this.deliveryUserService = deliveryUserService;
|
||||||
|
this.assignmentService = assignmentService;
|
||||||
|
this.authService = authService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/admin/delivery-users")
|
||||||
|
public ApiResponse<List<DeliveryUserResponse>> listUsers() {
|
||||||
|
CurrentUser user = authService.currentUser();
|
||||||
|
return ApiResponse.ok(deliveryUserService.list(user.getCommunityId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/api/admin/delivery-users")
|
||||||
|
public ApiResponse<DeliveryUserResponse> createUser(@Valid @RequestBody DeliveryUserRequest request) {
|
||||||
|
CurrentUser user = authService.currentUser();
|
||||||
|
request.setTenantId(user.getTenantId());
|
||||||
|
request.setCommunityId(user.getCommunityId());
|
||||||
|
return ApiResponse.ok(deliveryUserService.create(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/api/admin/delivery-users/{id}")
|
||||||
|
public ApiResponse<DeliveryUserResponse> updateUser(@PathVariable Long id, @Valid @RequestBody DeliveryUserRequest request) {
|
||||||
|
CurrentUser user = authService.currentUser();
|
||||||
|
request.setTenantId(user.getTenantId());
|
||||||
|
request.setCommunityId(user.getCommunityId());
|
||||||
|
return ApiResponse.ok(deliveryUserService.update(id, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/api/admin/delivery-users/{id}/enable")
|
||||||
|
public ApiResponse<DeliveryUserResponse> enableUser(@PathVariable Long id) {
|
||||||
|
return ApiResponse.ok(deliveryUserService.enable(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/api/admin/delivery-users/{id}/disable")
|
||||||
|
public ApiResponse<DeliveryUserResponse> disableUser(@PathVariable Long id) {
|
||||||
|
return ApiResponse.ok(deliveryUserService.disable(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/api/admin/delivery-orders/assign-goods-order")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> assignGoodsOrder(@Valid @RequestBody DeliveryAssignRequest request) {
|
||||||
|
return ApiResponse.ok(assignmentService.assignGoodsOrder(request.getOrderId(), request.getRiderId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/api/admin/delivery-orders/assign-express-order")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> assignExpressOrder(@Valid @RequestBody DeliveryAssignRequest request) {
|
||||||
|
return ApiResponse.ok(assignmentService.assignExpressOrder(request.getOrderId(), request.getRiderId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/api/admin/delivery-orders/assign-group-buy-order")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> assignGroupBuyOrder(@Valid @RequestBody DeliveryAssignRequest request) {
|
||||||
|
CurrentUser user = authService.currentUser();
|
||||||
|
return ApiResponse.ok(assignmentService.assignGroupBuyOrder(user.getCommunityId(), request.getOrderId(), request.getRiderId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/admin/delivery-orders")
|
||||||
|
public ApiResponse<List<DeliveryOrderResponse>> listTasks(@RequestParam(required = false) DeliveryTaskStatus status) {
|
||||||
|
CurrentUser user = authService.currentUser();
|
||||||
|
return ApiResponse.ok(assignmentService.listAdmin(user.getCommunityId(), status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/admin/delivery-orders/{id}")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> taskDetail(@PathVariable Long id) {
|
||||||
|
return ApiResponse.ok(assignmentService.detail(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class DeliveryAssignRequest {
|
||||||
|
@NotNull
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Long riderId;
|
||||||
|
|
||||||
|
public Long getOrderId() {
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderId(Long orderId) {
|
||||||
|
this.orderId = orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getRiderId() {
|
||||||
|
return riderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRiderId(Long riderId) {
|
||||||
|
this.riderId = riderId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.enums.DeliveryMethod;
|
||||||
|
import com.linhelp.common.enums.DeliveryTaskStatus;
|
||||||
|
import com.linhelp.common.enums.ExpressOrderStatus;
|
||||||
|
import com.linhelp.common.enums.GoodsOrderStatus;
|
||||||
|
import com.linhelp.common.exception.BizException;
|
||||||
|
import com.linhelp.express.ExpressOrderResponse;
|
||||||
|
import com.linhelp.express.ExpressOrderService;
|
||||||
|
import com.linhelp.order.GoodsOrderResponse;
|
||||||
|
import com.linhelp.order.GoodsOrderService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DeliveryAssignmentService {
|
||||||
|
public static final String BIZ_TYPE_GOODS_ORDER = "GOODS_ORDER";
|
||||||
|
public static final String BIZ_TYPE_EXPRESS_ORDER = "EXPRESS_ORDER";
|
||||||
|
public static final String BIZ_TYPE_GROUP_BUY_ORDER = "GROUP_BUY_ORDER";
|
||||||
|
|
||||||
|
private final DeliveryUserService deliveryUserService;
|
||||||
|
private final GoodsOrderService goodsOrderService;
|
||||||
|
private final ExpressOrderService expressOrderService;
|
||||||
|
private final AtomicLong ids = new AtomicLong(1L);
|
||||||
|
private final Map<Long, DeliveryOrderResponse> tasks = new LinkedHashMap<Long, DeliveryOrderResponse>();
|
||||||
|
|
||||||
|
public DeliveryAssignmentService(DeliveryUserService deliveryUserService,
|
||||||
|
GoodsOrderService goodsOrderService,
|
||||||
|
ExpressOrderService expressOrderService) {
|
||||||
|
this.deliveryUserService = deliveryUserService;
|
||||||
|
this.goodsOrderService = goodsOrderService;
|
||||||
|
this.expressOrderService = expressOrderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryOrderResponse assignGoodsOrder(Long goodsOrderId, Long riderId) {
|
||||||
|
DeliveryUserResponse rider = deliveryUserService.requireEnabled(riderId);
|
||||||
|
GoodsOrderResponse order = goodsOrderService.detail(goodsOrderId);
|
||||||
|
if (DeliveryMethod.SELF_PICKUP.equals(order.getDeliveryMethod())) {
|
||||||
|
throw new BizException("自提订单无需派单");
|
||||||
|
}
|
||||||
|
if (GoodsOrderStatus.PENDING_DELIVERY != order.getStatus()) {
|
||||||
|
throw new BizException("订单未待配送");
|
||||||
|
}
|
||||||
|
DeliveryOrderResponse task = createBaseTask(order.getTenantId(), order.getCommunityId(), rider);
|
||||||
|
task.setBizType(BIZ_TYPE_GOODS_ORDER);
|
||||||
|
task.setBizOrderId(order.getId());
|
||||||
|
task.setBizOrderNo(order.getOrderNo());
|
||||||
|
task.setAddress(order.getAddressId() == null ? null : "地址ID " + order.getAddressId());
|
||||||
|
task.setAmountCent(order.getPayableAmountCent());
|
||||||
|
task.setRemark(order.getRemark());
|
||||||
|
tasks.put(task.getId(), task);
|
||||||
|
return copy(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryOrderResponse assignExpressOrder(Long expressOrderId, Long riderId) {
|
||||||
|
if (expressOrderService == null) {
|
||||||
|
throw new BizException("快递代取服务未启用");
|
||||||
|
}
|
||||||
|
DeliveryUserResponse rider = deliveryUserService.requireEnabled(riderId);
|
||||||
|
ExpressOrderResponse order = expressOrderService.detail(expressOrderId);
|
||||||
|
if (ExpressOrderStatus.PENDING_PICKUP != order.getStatus()) {
|
||||||
|
throw new BizException("快递订单未待取件");
|
||||||
|
}
|
||||||
|
DeliveryOrderResponse task = createBaseTask(order.getTenantId(), order.getCommunityId(), rider);
|
||||||
|
task.setBizType(BIZ_TYPE_EXPRESS_ORDER);
|
||||||
|
task.setBizOrderId(order.getId());
|
||||||
|
task.setBizOrderNo(order.getOrderNo());
|
||||||
|
task.setContactName(order.getContactName());
|
||||||
|
task.setContactPhone(order.getContactPhone());
|
||||||
|
task.setAddress(order.getDeliveryAddress());
|
||||||
|
task.setAmountCent(order.getFeeCent());
|
||||||
|
task.setRemark(order.getRemark());
|
||||||
|
tasks.put(task.getId(), task);
|
||||||
|
return copy(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryOrderResponse assignGroupBuyOrder(Long communityId, Long groupBuyOrderId, Long riderId) {
|
||||||
|
DeliveryUserResponse rider = deliveryUserService.requireEnabled(riderId);
|
||||||
|
DeliveryOrderResponse task = createBaseTask(rider.getTenantId(), communityId, rider);
|
||||||
|
task.setBizType(BIZ_TYPE_GROUP_BUY_ORDER);
|
||||||
|
task.setBizOrderId(groupBuyOrderId);
|
||||||
|
task.setBizOrderNo("GB" + String.format("%08d", groupBuyOrderId));
|
||||||
|
tasks.put(task.getId(), task);
|
||||||
|
return copy(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized List<DeliveryOrderResponse> listAdmin(Long communityId, DeliveryTaskStatus status) {
|
||||||
|
List<DeliveryOrderResponse> result = new ArrayList<DeliveryOrderResponse>();
|
||||||
|
for (DeliveryOrderResponse task : tasks.values()) {
|
||||||
|
if (!communityId.equals(task.getCommunityId())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (status != null && status != task.getStatus()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.add(copy(task));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryOrderResponse detail(Long id) {
|
||||||
|
return copy(require(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized List<DeliveryOrderResponse> listRiderTasks(Long riderId) {
|
||||||
|
List<DeliveryOrderResponse> result = new ArrayList<DeliveryOrderResponse>();
|
||||||
|
for (DeliveryOrderResponse task : tasks.values()) {
|
||||||
|
if (riderId.equals(task.getRiderId())) {
|
||||||
|
result.add(copy(task));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryOrderResponse detailForRider(Long riderId, Long taskId) {
|
||||||
|
return copy(requireForRider(riderId, taskId));
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized DeliveryOrderResponse requireForRider(Long riderId, Long taskId) {
|
||||||
|
DeliveryOrderResponse task = require(taskId);
|
||||||
|
if (!riderId.equals(task.getRiderId())) {
|
||||||
|
throw new BizException(404, "配送任务不存在");
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized DeliveryOrderResponse copyTask(DeliveryOrderResponse task) {
|
||||||
|
return copy(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryOrderResponse createBaseTask(Long tenantId, Long communityId, DeliveryUserResponse rider) {
|
||||||
|
DeliveryOrderResponse task = new DeliveryOrderResponse();
|
||||||
|
task.setId(ids.getAndIncrement());
|
||||||
|
task.setTenantId(tenantId);
|
||||||
|
task.setCommunityId(communityId);
|
||||||
|
task.setRiderId(rider.getId());
|
||||||
|
task.setRiderName(rider.getName());
|
||||||
|
task.setStatus(DeliveryTaskStatus.ASSIGNED);
|
||||||
|
task.setCreatedAt(LocalDateTime.now());
|
||||||
|
task.setUpdatedAt(task.getCreatedAt());
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryOrderResponse require(Long id) {
|
||||||
|
DeliveryOrderResponse task = tasks.get(id);
|
||||||
|
if (task == null) {
|
||||||
|
throw new BizException(404, "配送任务不存在");
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryOrderResponse copy(DeliveryOrderResponse source) {
|
||||||
|
DeliveryOrderResponse target = new DeliveryOrderResponse();
|
||||||
|
target.setId(source.getId());
|
||||||
|
target.setTenantId(source.getTenantId());
|
||||||
|
target.setCommunityId(source.getCommunityId());
|
||||||
|
target.setBizType(source.getBizType());
|
||||||
|
target.setBizOrderId(source.getBizOrderId());
|
||||||
|
target.setBizOrderNo(source.getBizOrderNo());
|
||||||
|
target.setRiderId(source.getRiderId());
|
||||||
|
target.setRiderName(source.getRiderName());
|
||||||
|
target.setContactName(source.getContactName());
|
||||||
|
target.setContactPhone(source.getContactPhone());
|
||||||
|
target.setAddress(source.getAddress());
|
||||||
|
target.setAmountCent(source.getAmountCent());
|
||||||
|
target.setRemark(source.getRemark());
|
||||||
|
target.setStatus(source.getStatus());
|
||||||
|
target.setDeliveredPhotoUrl(source.getDeliveredPhotoUrl());
|
||||||
|
target.setExceptionType(source.getExceptionType());
|
||||||
|
target.setExceptionNote(source.getExceptionNote());
|
||||||
|
target.setCreatedAt(source.getCreatedAt());
|
||||||
|
target.setUpdatedAt(source.getUpdatedAt());
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.enums.DeliveryTaskStatus;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class DeliveryOrderResponse {
|
||||||
|
private Long id;
|
||||||
|
private Long tenantId;
|
||||||
|
private Long communityId;
|
||||||
|
private String bizType;
|
||||||
|
private Long bizOrderId;
|
||||||
|
private String bizOrderNo;
|
||||||
|
private Long riderId;
|
||||||
|
private String riderName;
|
||||||
|
private String contactName;
|
||||||
|
private String contactPhone;
|
||||||
|
private String address;
|
||||||
|
private int amountCent;
|
||||||
|
private String remark;
|
||||||
|
private DeliveryTaskStatus status;
|
||||||
|
private String deliveredPhotoUrl;
|
||||||
|
private String exceptionType;
|
||||||
|
private String exceptionNote;
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getTenantId() {
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(Long tenantId) {
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCommunityId() {
|
||||||
|
return communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommunityId(Long communityId) {
|
||||||
|
this.communityId = communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBizType() {
|
||||||
|
return bizType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBizType(String bizType) {
|
||||||
|
this.bizType = bizType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getBizOrderId() {
|
||||||
|
return bizOrderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBizOrderId(Long bizOrderId) {
|
||||||
|
this.bizOrderId = bizOrderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBizOrderNo() {
|
||||||
|
return bizOrderNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBizOrderNo(String bizOrderNo) {
|
||||||
|
this.bizOrderNo = bizOrderNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getRiderId() {
|
||||||
|
return riderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRiderId(Long riderId) {
|
||||||
|
this.riderId = riderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRiderName() {
|
||||||
|
return riderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRiderName(String riderName) {
|
||||||
|
this.riderName = riderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContactName() {
|
||||||
|
return contactName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactName(String contactName) {
|
||||||
|
this.contactName = contactName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContactPhone() {
|
||||||
|
return contactPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContactPhone(String contactPhone) {
|
||||||
|
this.contactPhone = contactPhone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmountCent() {
|
||||||
|
return amountCent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmountCent(int amountCent) {
|
||||||
|
this.amountCent = amountCent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemark() {
|
||||||
|
return remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemark(String remark) {
|
||||||
|
this.remark = remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryTaskStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(DeliveryTaskStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeliveredPhotoUrl() {
|
||||||
|
return deliveredPhotoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeliveredPhotoUrl(String deliveredPhotoUrl) {
|
||||||
|
this.deliveredPhotoUrl = deliveredPhotoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExceptionType() {
|
||||||
|
return exceptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExceptionType(String exceptionType) {
|
||||||
|
this.exceptionType = exceptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExceptionNote() {
|
||||||
|
return exceptionNote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExceptionNote(String exceptionNote) {
|
||||||
|
this.exceptionNote = exceptionNote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(LocalDateTime createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
public class DeliveryUserRequest {
|
||||||
|
private Long tenantId;
|
||||||
|
private Long communityId;
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
public Long getTenantId() {
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(Long tenantId) {
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCommunityId() {
|
||||||
|
return communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommunityId(Long communityId) {
|
||||||
|
this.communityId = communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhone() {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhone(String phone) {
|
||||||
|
this.phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
public class DeliveryUserResponse {
|
||||||
|
private Long id;
|
||||||
|
private Long tenantId;
|
||||||
|
private Long communityId;
|
||||||
|
private Long userId;
|
||||||
|
private String name;
|
||||||
|
private String phone;
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getTenantId() {
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(Long tenantId) {
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCommunityId() {
|
||||||
|
return communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommunityId(Long communityId) {
|
||||||
|
this.communityId = communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhone() {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhone(String phone) {
|
||||||
|
this.phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.exception.BizException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DeliveryUserService {
|
||||||
|
private final AtomicLong ids = new AtomicLong(1L);
|
||||||
|
private final Map<Long, DeliveryUserResponse> users = new LinkedHashMap<Long, DeliveryUserResponse>();
|
||||||
|
|
||||||
|
public synchronized DeliveryUserResponse create(DeliveryUserRequest request) {
|
||||||
|
DeliveryUserResponse user = new DeliveryUserResponse();
|
||||||
|
user.setId(ids.getAndIncrement());
|
||||||
|
user.setTenantId(request.getTenantId());
|
||||||
|
user.setCommunityId(request.getCommunityId());
|
||||||
|
copyFields(request, user);
|
||||||
|
users.put(user.getId(), user);
|
||||||
|
return copy(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryUserResponse update(Long id, DeliveryUserRequest request) {
|
||||||
|
DeliveryUserResponse user = require(id);
|
||||||
|
if (request.getTenantId() != null) {
|
||||||
|
user.setTenantId(request.getTenantId());
|
||||||
|
}
|
||||||
|
if (request.getCommunityId() != null) {
|
||||||
|
user.setCommunityId(request.getCommunityId());
|
||||||
|
}
|
||||||
|
copyFields(request, user);
|
||||||
|
return copy(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized List<DeliveryUserResponse> list(Long communityId) {
|
||||||
|
List<DeliveryUserResponse> result = new ArrayList<DeliveryUserResponse>();
|
||||||
|
for (DeliveryUserResponse user : users.values()) {
|
||||||
|
if (communityId.equals(user.getCommunityId())) {
|
||||||
|
result.add(copy(user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryUserResponse enable(Long id) {
|
||||||
|
DeliveryUserResponse user = require(id);
|
||||||
|
user.setEnabled(true);
|
||||||
|
return copy(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryUserResponse disable(Long id) {
|
||||||
|
DeliveryUserResponse user = require(id);
|
||||||
|
user.setEnabled(false);
|
||||||
|
return copy(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryUserResponse requireEnabled(Long id) {
|
||||||
|
DeliveryUserResponse user = require(id);
|
||||||
|
if (!user.isEnabled()) {
|
||||||
|
throw new BizException("配送员已停用");
|
||||||
|
}
|
||||||
|
return copy(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DeliveryUserResponse requireByUserId(Long userId) {
|
||||||
|
for (DeliveryUserResponse user : users.values()) {
|
||||||
|
if (userId.equals(user.getUserId())) {
|
||||||
|
return copy(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new BizException(404, "配送员不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryUserResponse require(Long id) {
|
||||||
|
DeliveryUserResponse user = users.get(id);
|
||||||
|
if (user == null) {
|
||||||
|
throw new BizException(404, "配送员不存在");
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyFields(DeliveryUserRequest request, DeliveryUserResponse user) {
|
||||||
|
user.setUserId(request.getUserId());
|
||||||
|
user.setName(request.getName());
|
||||||
|
user.setPhone(request.getPhone());
|
||||||
|
user.setEnabled(request.isEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryUserResponse copy(DeliveryUserResponse source) {
|
||||||
|
DeliveryUserResponse target = new DeliveryUserResponse();
|
||||||
|
target.setId(source.getId());
|
||||||
|
target.setTenantId(source.getTenantId());
|
||||||
|
target.setCommunityId(source.getCommunityId());
|
||||||
|
target.setUserId(source.getUserId());
|
||||||
|
target.setName(source.getName());
|
||||||
|
target.setPhone(source.getPhone());
|
||||||
|
target.setEnabled(source.isEnabled());
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
public class RiderDeliveredRequest {
|
||||||
|
private String photoUrl;
|
||||||
|
|
||||||
|
public String getPhotoUrl() {
|
||||||
|
return photoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhotoUrl(String photoUrl) {
|
||||||
|
this.photoUrl = photoUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
public class RiderExceptionRequest {
|
||||||
|
@NotBlank
|
||||||
|
private String exceptionType;
|
||||||
|
|
||||||
|
private String exceptionNote;
|
||||||
|
|
||||||
|
public String getExceptionType() {
|
||||||
|
return exceptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExceptionType(String exceptionType) {
|
||||||
|
this.exceptionType = exceptionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExceptionNote() {
|
||||||
|
return exceptionNote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExceptionNote(String exceptionNote) {
|
||||||
|
this.exceptionNote = exceptionNote;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
public class RiderIncomeSummaryResponse {
|
||||||
|
private int assignedCount;
|
||||||
|
private int deliveringCount;
|
||||||
|
private int deliveredCount;
|
||||||
|
private int estimatedIncomeCent;
|
||||||
|
|
||||||
|
public int getAssignedCount() {
|
||||||
|
return assignedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignedCount(int assignedCount) {
|
||||||
|
this.assignedCount = assignedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDeliveringCount() {
|
||||||
|
return deliveringCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeliveringCount(int deliveringCount) {
|
||||||
|
this.deliveringCount = deliveringCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDeliveredCount() {
|
||||||
|
return deliveredCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeliveredCount(int deliveredCount) {
|
||||||
|
this.deliveredCount = deliveredCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getEstimatedIncomeCent() {
|
||||||
|
return estimatedIncomeCent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEstimatedIncomeCent(int estimatedIncomeCent) {
|
||||||
|
this.estimatedIncomeCent = estimatedIncomeCent;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.api.ApiResponse;
|
||||||
|
import com.linhelp.common.security.AuthService;
|
||||||
|
import com.linhelp.common.security.CurrentUser;
|
||||||
|
import com.linhelp.common.security.RequireRole;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequireRole("RIDER")
|
||||||
|
public class RiderTaskController {
|
||||||
|
private final RiderTaskService riderTaskService;
|
||||||
|
private final DeliveryUserService deliveryUserService;
|
||||||
|
private final AuthService authService;
|
||||||
|
|
||||||
|
public RiderTaskController(RiderTaskService riderTaskService,
|
||||||
|
DeliveryUserService deliveryUserService,
|
||||||
|
AuthService authService) {
|
||||||
|
this.riderTaskService = riderTaskService;
|
||||||
|
this.deliveryUserService = deliveryUserService;
|
||||||
|
this.authService = authService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/rider/tasks")
|
||||||
|
public ApiResponse<List<DeliveryOrderResponse>> listTasks() {
|
||||||
|
return ApiResponse.ok(riderTaskService.listTasks(currentDeliveryUserId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/rider/tasks/{id}")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> detail(@PathVariable Long id) {
|
||||||
|
return ApiResponse.ok(riderTaskService.detail(currentDeliveryUserId(), id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/api/rider/tasks/{id}/start")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> start(@PathVariable Long id) {
|
||||||
|
return ApiResponse.ok(riderTaskService.start(currentDeliveryUserId(), id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/api/rider/tasks/{id}/delivered")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> delivered(@PathVariable Long id, @RequestBody(required = false) RiderDeliveredRequest request) {
|
||||||
|
return ApiResponse.ok(riderTaskService.delivered(currentDeliveryUserId(), id, request == null ? null : request.getPhotoUrl()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/api/rider/tasks/{id}/exception")
|
||||||
|
public ApiResponse<DeliveryOrderResponse> exception(@PathVariable Long id, @Valid @RequestBody RiderExceptionRequest request) {
|
||||||
|
return ApiResponse.ok(riderTaskService.exception(currentDeliveryUserId(), id, request.getExceptionType(), request.getExceptionNote()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/api/rider/income-summary")
|
||||||
|
public ApiResponse<RiderIncomeSummaryResponse> incomeSummary() {
|
||||||
|
return ApiResponse.ok(riderTaskService.incomeSummary(currentDeliveryUserId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long currentDeliveryUserId() {
|
||||||
|
CurrentUser user = authService.currentUser();
|
||||||
|
return deliveryUserService.requireByUserId(user.getUserId()).getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
120
backend/src/main/java/com/linhelp/delivery/RiderTaskService.java
Normal file
120
backend/src/main/java/com/linhelp/delivery/RiderTaskService.java
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.enums.DeliveryTaskStatus;
|
||||||
|
import com.linhelp.common.enums.ExpressOrderStatus;
|
||||||
|
import com.linhelp.common.exception.BizException;
|
||||||
|
import com.linhelp.express.ExpressOrderResponse;
|
||||||
|
import com.linhelp.express.ExpressOrderService;
|
||||||
|
import com.linhelp.order.GoodsOrderService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class RiderTaskService {
|
||||||
|
private static final int INCOME_PER_DELIVERED_TASK_CENT = 300;
|
||||||
|
|
||||||
|
private final DeliveryAssignmentService assignmentService;
|
||||||
|
private final GoodsOrderService goodsOrderService;
|
||||||
|
private final ExpressOrderService expressOrderService;
|
||||||
|
|
||||||
|
public RiderTaskService(DeliveryAssignmentService assignmentService,
|
||||||
|
GoodsOrderService goodsOrderService,
|
||||||
|
ExpressOrderService expressOrderService) {
|
||||||
|
this.assignmentService = assignmentService;
|
||||||
|
this.goodsOrderService = goodsOrderService;
|
||||||
|
this.expressOrderService = expressOrderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeliveryOrderResponse> listTasks(Long riderId) {
|
||||||
|
return assignmentService.listRiderTasks(riderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryOrderResponse detail(Long riderId, Long taskId) {
|
||||||
|
return assignmentService.detailForRider(riderId, taskId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryOrderResponse start(Long riderId, Long taskId) {
|
||||||
|
DeliveryOrderResponse task = assignmentService.requireForRider(riderId, taskId);
|
||||||
|
if (task.getStatus() != DeliveryTaskStatus.ASSIGNED && task.getStatus() != DeliveryTaskStatus.ACCEPTED) {
|
||||||
|
throw new BizException("任务状态不允许操作");
|
||||||
|
}
|
||||||
|
if (DeliveryAssignmentService.BIZ_TYPE_GOODS_ORDER.equals(task.getBizType())) {
|
||||||
|
goodsOrderService.markDelivering(task.getBizOrderId());
|
||||||
|
} else if (DeliveryAssignmentService.BIZ_TYPE_EXPRESS_ORDER.equals(task.getBizType())) {
|
||||||
|
startExpressOrder(task.getBizOrderId());
|
||||||
|
}
|
||||||
|
task.setStatus(DeliveryTaskStatus.DELIVERING);
|
||||||
|
task.setUpdatedAt(LocalDateTime.now());
|
||||||
|
return assignmentService.copyTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryOrderResponse delivered(Long riderId, Long taskId, String photoUrl) {
|
||||||
|
DeliveryOrderResponse task = assignmentService.requireForRider(riderId, taskId);
|
||||||
|
if (task.getStatus() != DeliveryTaskStatus.DELIVERING) {
|
||||||
|
throw new BizException("任务状态不允许操作");
|
||||||
|
}
|
||||||
|
if (DeliveryAssignmentService.BIZ_TYPE_GOODS_ORDER.equals(task.getBizType())) {
|
||||||
|
goodsOrderService.complete(task.getBizOrderId());
|
||||||
|
} else if (DeliveryAssignmentService.BIZ_TYPE_EXPRESS_ORDER.equals(task.getBizType())) {
|
||||||
|
deliverExpressOrder(task.getBizOrderId(), photoUrl);
|
||||||
|
}
|
||||||
|
task.setDeliveredPhotoUrl(photoUrl);
|
||||||
|
task.setStatus(DeliveryTaskStatus.DELIVERED);
|
||||||
|
task.setUpdatedAt(LocalDateTime.now());
|
||||||
|
return assignmentService.copyTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryOrderResponse exception(Long riderId, Long taskId, String exceptionType, String exceptionNote) {
|
||||||
|
DeliveryOrderResponse task = assignmentService.requireForRider(riderId, taskId);
|
||||||
|
task.setExceptionType(exceptionType);
|
||||||
|
task.setExceptionNote(exceptionNote);
|
||||||
|
task.setStatus(DeliveryTaskStatus.EXCEPTION);
|
||||||
|
task.setUpdatedAt(LocalDateTime.now());
|
||||||
|
return assignmentService.copyTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RiderIncomeSummaryResponse incomeSummary(Long riderId) {
|
||||||
|
RiderIncomeSummaryResponse response = new RiderIncomeSummaryResponse();
|
||||||
|
for (DeliveryOrderResponse task : listTasks(riderId)) {
|
||||||
|
if (task.getStatus() == DeliveryTaskStatus.ASSIGNED || task.getStatus() == DeliveryTaskStatus.ACCEPTED) {
|
||||||
|
response.setAssignedCount(response.getAssignedCount() + 1);
|
||||||
|
} else if (task.getStatus() == DeliveryTaskStatus.DELIVERING) {
|
||||||
|
response.setDeliveringCount(response.getDeliveringCount() + 1);
|
||||||
|
} else if (task.getStatus() == DeliveryTaskStatus.DELIVERED || task.getStatus() == DeliveryTaskStatus.COMPLETED) {
|
||||||
|
response.setDeliveredCount(response.getDeliveredCount() + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.setEstimatedIncomeCent(response.getDeliveredCount() * INCOME_PER_DELIVERED_TASK_CENT);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startExpressOrder(Long orderId) {
|
||||||
|
if (expressOrderService == null) {
|
||||||
|
throw new BizException("快递代取服务未启用");
|
||||||
|
}
|
||||||
|
ExpressOrderResponse order = expressOrderService.detail(orderId);
|
||||||
|
if (order.getStatus() == ExpressOrderStatus.PENDING_PICKUP) {
|
||||||
|
expressOrderService.markPickingUp(orderId);
|
||||||
|
} else if (order.getStatus() == ExpressOrderStatus.PICKING_UP) {
|
||||||
|
expressOrderService.markDelivering(orderId);
|
||||||
|
} else {
|
||||||
|
throw new BizException("快递订单状态不允许操作");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deliverExpressOrder(Long orderId, String photoUrl) {
|
||||||
|
if (expressOrderService == null) {
|
||||||
|
throw new BizException("快递代取服务未启用");
|
||||||
|
}
|
||||||
|
ExpressOrderResponse order = expressOrderService.detail(orderId);
|
||||||
|
if (order.getStatus() == ExpressOrderStatus.PENDING_PICKUP) {
|
||||||
|
expressOrderService.markPickingUp(orderId);
|
||||||
|
expressOrderService.markDelivering(orderId);
|
||||||
|
} else if (order.getStatus() == ExpressOrderStatus.PICKING_UP) {
|
||||||
|
expressOrderService.markDelivering(orderId);
|
||||||
|
}
|
||||||
|
expressOrderService.markDelivered(orderId, photoUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.enums.DeliveryMethod;
|
||||||
|
import com.linhelp.common.enums.DeliveryTaskStatus;
|
||||||
|
import com.linhelp.order.CreateGoodsOrderItemRequest;
|
||||||
|
import com.linhelp.order.CreateGoodsOrderRequest;
|
||||||
|
import com.linhelp.order.GoodsOrderResponse;
|
||||||
|
import com.linhelp.order.GoodsOrderService;
|
||||||
|
import com.linhelp.product.ProductService;
|
||||||
|
import com.linhelp.product.ProductSkuResponse;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
class DeliveryAssignmentServiceTests {
|
||||||
|
@Test
|
||||||
|
void adminCanAssignPendingDeliveryGoodsOrderToRider() {
|
||||||
|
TestFixture fixture = new TestFixture();
|
||||||
|
GoodsOrderResponse order = fixture.preparedDeliveryOrder();
|
||||||
|
DeliveryUserResponse rider = fixture.rider();
|
||||||
|
|
||||||
|
DeliveryOrderResponse task = fixture.assignmentService.assignGoodsOrder(order.getId(), rider.getId());
|
||||||
|
|
||||||
|
assertThat(task.getBizType()).isEqualTo(DeliveryAssignmentService.BIZ_TYPE_GOODS_ORDER);
|
||||||
|
assertThat(task.getStatus()).isEqualTo(DeliveryTaskStatus.ASSIGNED);
|
||||||
|
assertThat(task.getRiderId()).isEqualTo(rider.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void cannotAssignSelfPickupGoodsOrder() {
|
||||||
|
TestFixture fixture = new TestFixture();
|
||||||
|
GoodsOrderResponse order = fixture.preparedSelfPickupOrder();
|
||||||
|
DeliveryUserResponse rider = fixture.rider();
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> fixture.assignmentService.assignGoodsOrder(order.getId(), rider.getId()))
|
||||||
|
.hasMessageContaining("自提订单无需派单");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestFixture {
|
||||||
|
private final ProductService productService = new ProductService();
|
||||||
|
private final GoodsOrderService goodsOrderService = new GoodsOrderService(productService);
|
||||||
|
private final DeliveryUserService deliveryUserService = new DeliveryUserService();
|
||||||
|
private final DeliveryAssignmentService assignmentService =
|
||||||
|
new DeliveryAssignmentService(deliveryUserService, goodsOrderService, null);
|
||||||
|
|
||||||
|
private GoodsOrderResponse preparedDeliveryOrder() {
|
||||||
|
return preparedOrder(DeliveryMethod.IMMEDIATE, 1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GoodsOrderResponse preparedSelfPickupOrder() {
|
||||||
|
return preparedOrder(DeliveryMethod.SELF_PICKUP, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GoodsOrderResponse preparedOrder(DeliveryMethod deliveryMethod, Long addressId) {
|
||||||
|
ProductSkuResponse sku = productService.createDemoSku(1L, 1L, 1L, "500g", 990, 5);
|
||||||
|
CreateGoodsOrderRequest request = new CreateGoodsOrderRequest();
|
||||||
|
request.setTenantId(1L);
|
||||||
|
request.setCommunityId(1L);
|
||||||
|
request.setMerchantId(1L);
|
||||||
|
request.setAddressId(addressId);
|
||||||
|
request.setDeliveryMethod(deliveryMethod);
|
||||||
|
request.setItems(Collections.singletonList(new CreateGoodsOrderItemRequest(1L, sku.getId(), 1)));
|
||||||
|
GoodsOrderResponse order = goodsOrderService.create(1L, request);
|
||||||
|
goodsOrderService.confirm(order.getId());
|
||||||
|
return goodsOrderService.markPrepared(order.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryUserResponse rider() {
|
||||||
|
DeliveryUserRequest request = new DeliveryUserRequest();
|
||||||
|
request.setTenantId(1L);
|
||||||
|
request.setCommunityId(1L);
|
||||||
|
request.setUserId(3L);
|
||||||
|
request.setName("骑手一号");
|
||||||
|
request.setPhone("13900000000");
|
||||||
|
return deliveryUserService.create(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package com.linhelp.delivery;
|
||||||
|
|
||||||
|
import com.linhelp.common.enums.DeliveryMethod;
|
||||||
|
import com.linhelp.common.enums.DeliveryTaskStatus;
|
||||||
|
import com.linhelp.common.enums.GoodsOrderStatus;
|
||||||
|
import com.linhelp.order.CreateGoodsOrderItemRequest;
|
||||||
|
import com.linhelp.order.CreateGoodsOrderRequest;
|
||||||
|
import com.linhelp.order.GoodsOrderResponse;
|
||||||
|
import com.linhelp.order.GoodsOrderService;
|
||||||
|
import com.linhelp.product.ProductService;
|
||||||
|
import com.linhelp.product.ProductSkuResponse;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class RiderTaskServiceTests {
|
||||||
|
@Test
|
||||||
|
void riderOnlySeesOwnTasks() {
|
||||||
|
TestFixture fixture = new TestFixture();
|
||||||
|
GoodsOrderResponse order = fixture.preparedDeliveryOrder();
|
||||||
|
DeliveryUserResponse firstRider = fixture.rider(3L, "骑手一号");
|
||||||
|
DeliveryUserResponse secondRider = fixture.rider(4L, "骑手二号");
|
||||||
|
|
||||||
|
fixture.assignmentService.assignGoodsOrder(order.getId(), firstRider.getId());
|
||||||
|
|
||||||
|
assertThat(fixture.riderTaskService.listTasks(firstRider.getId())).hasSize(1);
|
||||||
|
assertThat(fixture.riderTaskService.listTasks(secondRider.getId())).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void startingGoodsOrderTaskMovesGoodsOrderToDelivering() {
|
||||||
|
TestFixture fixture = new TestFixture();
|
||||||
|
GoodsOrderResponse order = fixture.preparedDeliveryOrder();
|
||||||
|
DeliveryUserResponse rider = fixture.rider(3L, "骑手一号");
|
||||||
|
DeliveryOrderResponse task = fixture.assignmentService.assignGoodsOrder(order.getId(), rider.getId());
|
||||||
|
|
||||||
|
DeliveryOrderResponse started = fixture.riderTaskService.start(rider.getId(), task.getId());
|
||||||
|
|
||||||
|
assertThat(started.getStatus()).isEqualTo(DeliveryTaskStatus.DELIVERING);
|
||||||
|
assertThat(fixture.goodsOrderService.detail(order.getId()).getStatus()).isEqualTo(GoodsOrderStatus.DELIVERING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void deliveredTaskStoresPhotoUrl() {
|
||||||
|
TestFixture fixture = new TestFixture();
|
||||||
|
GoodsOrderResponse order = fixture.preparedDeliveryOrder();
|
||||||
|
DeliveryUserResponse rider = fixture.rider(3L, "骑手一号");
|
||||||
|
DeliveryOrderResponse task = fixture.assignmentService.assignGoodsOrder(order.getId(), rider.getId());
|
||||||
|
fixture.riderTaskService.start(rider.getId(), task.getId());
|
||||||
|
|
||||||
|
DeliveryOrderResponse delivered = fixture.riderTaskService.delivered(rider.getId(), task.getId(), "https://img.test/done.jpg");
|
||||||
|
|
||||||
|
assertThat(delivered.getStatus()).isEqualTo(DeliveryTaskStatus.DELIVERED);
|
||||||
|
assertThat(delivered.getDeliveredPhotoUrl()).isEqualTo("https://img.test/done.jpg");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestFixture {
|
||||||
|
private final ProductService productService = new ProductService();
|
||||||
|
private final GoodsOrderService goodsOrderService = new GoodsOrderService(productService);
|
||||||
|
private final DeliveryUserService deliveryUserService = new DeliveryUserService();
|
||||||
|
private final DeliveryAssignmentService assignmentService =
|
||||||
|
new DeliveryAssignmentService(deliveryUserService, goodsOrderService, null);
|
||||||
|
private final RiderTaskService riderTaskService =
|
||||||
|
new RiderTaskService(assignmentService, goodsOrderService, null);
|
||||||
|
|
||||||
|
private GoodsOrderResponse preparedDeliveryOrder() {
|
||||||
|
ProductSkuResponse sku = productService.createDemoSku(1L, 1L, 1L, "500g", 990, 5);
|
||||||
|
CreateGoodsOrderRequest request = new CreateGoodsOrderRequest();
|
||||||
|
request.setTenantId(1L);
|
||||||
|
request.setCommunityId(1L);
|
||||||
|
request.setMerchantId(1L);
|
||||||
|
request.setAddressId(1L);
|
||||||
|
request.setDeliveryMethod(DeliveryMethod.IMMEDIATE);
|
||||||
|
request.setItems(Collections.singletonList(new CreateGoodsOrderItemRequest(1L, sku.getId(), 1)));
|
||||||
|
GoodsOrderResponse order = goodsOrderService.create(1L, request);
|
||||||
|
goodsOrderService.confirm(order.getId());
|
||||||
|
return goodsOrderService.markPrepared(order.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeliveryUserResponse rider(Long userId, String name) {
|
||||||
|
DeliveryUserRequest request = new DeliveryUserRequest();
|
||||||
|
request.setTenantId(1L);
|
||||||
|
request.setCommunityId(1L);
|
||||||
|
request.setUserId(userId);
|
||||||
|
request.setName(name);
|
||||||
|
request.setPhone("13900000000");
|
||||||
|
return deliveryUserService.create(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user