feat: add express pickup orders
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
public class ExpressCancelRequest {
|
||||
private String reason;
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
public class ExpressFeeAdjustRequest {
|
||||
@Min(0)
|
||||
private int feeCent;
|
||||
|
||||
@NotBlank
|
||||
private String reason;
|
||||
|
||||
public int getFeeCent() {
|
||||
return feeCent;
|
||||
}
|
||||
|
||||
public void setFeeCent(int feeCent) {
|
||||
this.feeCent = feeCent;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
public final class ExpressFeeCalculator {
|
||||
private ExpressFeeCalculator() {
|
||||
}
|
||||
|
||||
public static int calculateCent(int packageCount) {
|
||||
if (packageCount <= 0) {
|
||||
throw new IllegalArgumentException("件数必须大于0");
|
||||
}
|
||||
return 300 + Math.max(0, packageCount - 1) * 100;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import com.linhelp.common.enums.OfflinePayStatus;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class ExpressOfflinePayRequest {
|
||||
@NotNull
|
||||
private OfflinePayStatus status;
|
||||
|
||||
public OfflinePayStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(OfflinePayStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import com.linhelp.common.api.ApiResponse;
|
||||
import com.linhelp.common.enums.ExpressOrderStatus;
|
||||
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
|
||||
public class ExpressOrderController {
|
||||
private final ExpressOrderService expressOrderService;
|
||||
private final AuthService authService;
|
||||
|
||||
public ExpressOrderController(ExpressOrderService expressOrderService, AuthService authService) {
|
||||
this.expressOrderService = expressOrderService;
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
@PostMapping("/api/mini/express-orders")
|
||||
public ApiResponse<ExpressOrderResponse> create(@Valid @RequestBody ExpressOrderRequest request) {
|
||||
CurrentUser user = authService.currentUser();
|
||||
request.setTenantId(user.getTenantId());
|
||||
request.setCommunityId(user.getCommunityId());
|
||||
return ApiResponse.ok(expressOrderService.create(user.getUserId(), request));
|
||||
}
|
||||
|
||||
@GetMapping("/api/mini/express-orders")
|
||||
public ApiResponse<List<ExpressOrderResponse>> listMine() {
|
||||
CurrentUser user = authService.currentUser();
|
||||
return ApiResponse.ok(expressOrderService.listMine(user.getUserId()));
|
||||
}
|
||||
|
||||
@GetMapping("/api/mini/express-orders/{id}")
|
||||
public ApiResponse<ExpressOrderResponse> miniDetail(@PathVariable Long id) {
|
||||
return ApiResponse.ok(expressOrderService.detail(id));
|
||||
}
|
||||
|
||||
@PutMapping("/api/mini/express-orders/{id}/cancel")
|
||||
public ApiResponse<ExpressOrderResponse> miniCancel(@PathVariable Long id, @RequestBody(required = false) ExpressCancelRequest request) {
|
||||
return ApiResponse.ok(expressOrderService.cancel(id, request == null ? null : request.getReason()));
|
||||
}
|
||||
|
||||
@PutMapping("/api/mini/express-orders/{id}/complete")
|
||||
public ApiResponse<ExpressOrderResponse> miniComplete(@PathVariable Long id) {
|
||||
return ApiResponse.ok(expressOrderService.complete(id));
|
||||
}
|
||||
|
||||
@GetMapping("/api/admin/express-orders")
|
||||
@RequireRole({"PLATFORM_ADMIN", "COMMUNITY_ADMIN", "MERCHANT"})
|
||||
public ApiResponse<List<ExpressOrderResponse>> listAdmin(@RequestParam(required = false) ExpressOrderStatus status) {
|
||||
CurrentUser user = authService.currentUser();
|
||||
return ApiResponse.ok(expressOrderService.listAdmin(user.getCommunityId(), status));
|
||||
}
|
||||
|
||||
@GetMapping("/api/admin/express-orders/{id}")
|
||||
@RequireRole({"PLATFORM_ADMIN", "COMMUNITY_ADMIN", "MERCHANT"})
|
||||
public ApiResponse<ExpressOrderResponse> adminDetail(@PathVariable Long id) {
|
||||
return ApiResponse.ok(expressOrderService.detail(id));
|
||||
}
|
||||
|
||||
@PutMapping("/api/admin/express-orders/{id}/confirm")
|
||||
@RequireRole({"PLATFORM_ADMIN", "COMMUNITY_ADMIN", "MERCHANT"})
|
||||
public ApiResponse<ExpressOrderResponse> confirm(@PathVariable Long id) {
|
||||
return ApiResponse.ok(expressOrderService.confirm(id));
|
||||
}
|
||||
|
||||
@PutMapping("/api/admin/express-orders/{id}/adjust-fee")
|
||||
@RequireRole({"PLATFORM_ADMIN", "COMMUNITY_ADMIN", "MERCHANT"})
|
||||
public ApiResponse<ExpressOrderResponse> adjustFee(@PathVariable Long id,
|
||||
@Valid @RequestBody ExpressFeeAdjustRequest request) {
|
||||
return ApiResponse.ok(expressOrderService.adjustFee(id, request.getFeeCent(), request.getReason()));
|
||||
}
|
||||
|
||||
@PutMapping("/api/admin/express-orders/{id}/cancel")
|
||||
@RequireRole({"PLATFORM_ADMIN", "COMMUNITY_ADMIN", "MERCHANT"})
|
||||
public ApiResponse<ExpressOrderResponse> adminCancel(@PathVariable Long id, @RequestBody(required = false) ExpressCancelRequest request) {
|
||||
return ApiResponse.ok(expressOrderService.cancel(id, request == null ? null : request.getReason()));
|
||||
}
|
||||
|
||||
@PutMapping("/api/admin/express-orders/{id}/offline-pay-status")
|
||||
@RequireRole({"PLATFORM_ADMIN", "COMMUNITY_ADMIN", "MERCHANT"})
|
||||
public ApiResponse<ExpressOrderResponse> updateOfflinePayStatus(@PathVariable Long id,
|
||||
@Valid @RequestBody ExpressOfflinePayRequest request) {
|
||||
return ApiResponse.ok(expressOrderService.updateOfflinePayStatus(id, request.getStatus()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class ExpressOrderLogResponse {
|
||||
private Long id;
|
||||
private Long orderId;
|
||||
private String action;
|
||||
private String content;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(Long orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class ExpressOrderRequest {
|
||||
private Long tenantId;
|
||||
private Long communityId;
|
||||
|
||||
@NotNull
|
||||
private Long addressId;
|
||||
|
||||
@NotBlank
|
||||
private String expressCompany;
|
||||
|
||||
@NotBlank
|
||||
private String pickupCode;
|
||||
|
||||
@NotBlank
|
||||
private String pickupAddress;
|
||||
|
||||
private String receiverPhone;
|
||||
|
||||
@Min(1)
|
||||
private int packageCount = 1;
|
||||
|
||||
private String remark;
|
||||
|
||||
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 getAddressId() {
|
||||
return addressId;
|
||||
}
|
||||
|
||||
public void setAddressId(Long addressId) {
|
||||
this.addressId = addressId;
|
||||
}
|
||||
|
||||
public String getExpressCompany() {
|
||||
return expressCompany;
|
||||
}
|
||||
|
||||
public void setExpressCompany(String expressCompany) {
|
||||
this.expressCompany = expressCompany;
|
||||
}
|
||||
|
||||
public String getPickupCode() {
|
||||
return pickupCode;
|
||||
}
|
||||
|
||||
public void setPickupCode(String pickupCode) {
|
||||
this.pickupCode = pickupCode;
|
||||
}
|
||||
|
||||
public String getPickupAddress() {
|
||||
return pickupAddress;
|
||||
}
|
||||
|
||||
public void setPickupAddress(String pickupAddress) {
|
||||
this.pickupAddress = pickupAddress;
|
||||
}
|
||||
|
||||
public String getReceiverPhone() {
|
||||
return receiverPhone;
|
||||
}
|
||||
|
||||
public void setReceiverPhone(String receiverPhone) {
|
||||
this.receiverPhone = receiverPhone;
|
||||
}
|
||||
|
||||
public int getPackageCount() {
|
||||
return packageCount;
|
||||
}
|
||||
|
||||
public void setPackageCount(int packageCount) {
|
||||
this.packageCount = packageCount;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import com.linhelp.common.enums.ExpressOrderStatus;
|
||||
import com.linhelp.common.enums.OfflinePayStatus;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ExpressOrderResponse {
|
||||
private Long id;
|
||||
private String orderNo;
|
||||
private Long tenantId;
|
||||
private Long communityId;
|
||||
private Long userId;
|
||||
private Long addressId;
|
||||
private String contactName;
|
||||
private String contactPhone;
|
||||
private String deliveryAddress;
|
||||
private String expressCompany;
|
||||
private String pickupCode;
|
||||
private String pickupAddress;
|
||||
private String receiverPhone;
|
||||
private int packageCount;
|
||||
private int feeCent;
|
||||
private OfflinePayStatus offlinePayStatus;
|
||||
private ExpressOrderStatus status;
|
||||
private String remark;
|
||||
private String cancelReason;
|
||||
private String deliveredPhotoUrl;
|
||||
private List<ExpressOrderLogResponse> logs = new ArrayList<ExpressOrderLogResponse>();
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getOrderNo() {
|
||||
return orderNo;
|
||||
}
|
||||
|
||||
public void setOrderNo(String orderNo) {
|
||||
this.orderNo = orderNo;
|
||||
}
|
||||
|
||||
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 Long getAddressId() {
|
||||
return addressId;
|
||||
}
|
||||
|
||||
public void setAddressId(Long addressId) {
|
||||
this.addressId = addressId;
|
||||
}
|
||||
|
||||
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 getDeliveryAddress() {
|
||||
return deliveryAddress;
|
||||
}
|
||||
|
||||
public void setDeliveryAddress(String deliveryAddress) {
|
||||
this.deliveryAddress = deliveryAddress;
|
||||
}
|
||||
|
||||
public String getExpressCompany() {
|
||||
return expressCompany;
|
||||
}
|
||||
|
||||
public void setExpressCompany(String expressCompany) {
|
||||
this.expressCompany = expressCompany;
|
||||
}
|
||||
|
||||
public String getPickupCode() {
|
||||
return pickupCode;
|
||||
}
|
||||
|
||||
public void setPickupCode(String pickupCode) {
|
||||
this.pickupCode = pickupCode;
|
||||
}
|
||||
|
||||
public String getPickupAddress() {
|
||||
return pickupAddress;
|
||||
}
|
||||
|
||||
public void setPickupAddress(String pickupAddress) {
|
||||
this.pickupAddress = pickupAddress;
|
||||
}
|
||||
|
||||
public String getReceiverPhone() {
|
||||
return receiverPhone;
|
||||
}
|
||||
|
||||
public void setReceiverPhone(String receiverPhone) {
|
||||
this.receiverPhone = receiverPhone;
|
||||
}
|
||||
|
||||
public int getPackageCount() {
|
||||
return packageCount;
|
||||
}
|
||||
|
||||
public void setPackageCount(int packageCount) {
|
||||
this.packageCount = packageCount;
|
||||
}
|
||||
|
||||
public int getFeeCent() {
|
||||
return feeCent;
|
||||
}
|
||||
|
||||
public void setFeeCent(int feeCent) {
|
||||
this.feeCent = feeCent;
|
||||
}
|
||||
|
||||
public OfflinePayStatus getOfflinePayStatus() {
|
||||
return offlinePayStatus;
|
||||
}
|
||||
|
||||
public void setOfflinePayStatus(OfflinePayStatus offlinePayStatus) {
|
||||
this.offlinePayStatus = offlinePayStatus;
|
||||
}
|
||||
|
||||
public ExpressOrderStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(ExpressOrderStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getCancelReason() {
|
||||
return cancelReason;
|
||||
}
|
||||
|
||||
public void setCancelReason(String cancelReason) {
|
||||
this.cancelReason = cancelReason;
|
||||
}
|
||||
|
||||
public String getDeliveredPhotoUrl() {
|
||||
return deliveredPhotoUrl;
|
||||
}
|
||||
|
||||
public void setDeliveredPhotoUrl(String deliveredPhotoUrl) {
|
||||
this.deliveredPhotoUrl = deliveredPhotoUrl;
|
||||
}
|
||||
|
||||
public List<ExpressOrderLogResponse> getLogs() {
|
||||
return logs;
|
||||
}
|
||||
|
||||
public void setLogs(List<ExpressOrderLogResponse> logs) {
|
||||
this.logs = logs;
|
||||
}
|
||||
|
||||
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,229 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import com.linhelp.common.enums.ExpressOrderStatus;
|
||||
import com.linhelp.common.enums.OfflinePayStatus;
|
||||
import com.linhelp.common.exception.BizException;
|
||||
import com.linhelp.user.AddressResponse;
|
||||
import com.linhelp.user.UserAddressService;
|
||||
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 ExpressOrderService {
|
||||
private final UserAddressService addressService;
|
||||
private final AtomicLong orderIds = new AtomicLong(1L);
|
||||
private final AtomicLong logIds = new AtomicLong(1L);
|
||||
private final Map<Long, ExpressOrderResponse> orders = new LinkedHashMap<Long, ExpressOrderResponse>();
|
||||
|
||||
public ExpressOrderService(UserAddressService addressService) {
|
||||
this.addressService = addressService;
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse create(Long userId, ExpressOrderRequest request) {
|
||||
AddressResponse address = addressService.detailMine(userId, request.getAddressId());
|
||||
Long orderId = orderIds.getAndIncrement();
|
||||
ExpressOrderResponse order = new ExpressOrderResponse();
|
||||
order.setId(orderId);
|
||||
order.setOrderNo("EO" + String.format("%08d", orderId));
|
||||
order.setTenantId(request.getTenantId());
|
||||
order.setCommunityId(request.getCommunityId());
|
||||
order.setUserId(userId);
|
||||
order.setAddressId(request.getAddressId());
|
||||
order.setContactName(address.getContactName());
|
||||
order.setContactPhone(address.getPhone());
|
||||
order.setDeliveryAddress(buildDeliveryAddress(address));
|
||||
order.setExpressCompany(request.getExpressCompany());
|
||||
order.setPickupCode(request.getPickupCode());
|
||||
order.setPickupAddress(request.getPickupAddress());
|
||||
order.setReceiverPhone(request.getReceiverPhone());
|
||||
order.setPackageCount(request.getPackageCount());
|
||||
order.setFeeCent(ExpressFeeCalculator.calculateCent(request.getPackageCount()));
|
||||
order.setOfflinePayStatus(OfflinePayStatus.UNPAID);
|
||||
order.setStatus(ExpressOrderStatus.PENDING_CONFIRM);
|
||||
order.setRemark(request.getRemark());
|
||||
order.setCreatedAt(LocalDateTime.now());
|
||||
order.setUpdatedAt(order.getCreatedAt());
|
||||
addLog(order, "CREATE", "用户提交快递代取");
|
||||
orders.put(order.getId(), order);
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse detail(Long id) {
|
||||
return copyOrder(requireOrder(id));
|
||||
}
|
||||
|
||||
public synchronized List<ExpressOrderResponse> listMine(Long userId) {
|
||||
List<ExpressOrderResponse> result = new ArrayList<ExpressOrderResponse>();
|
||||
for (ExpressOrderResponse order : orders.values()) {
|
||||
if (userId.equals(order.getUserId())) {
|
||||
result.add(copyOrder(order));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized List<ExpressOrderResponse> listAdmin(Long communityId, ExpressOrderStatus status) {
|
||||
List<ExpressOrderResponse> result = new ArrayList<ExpressOrderResponse>();
|
||||
for (ExpressOrderResponse order : orders.values()) {
|
||||
if (!communityId.equals(order.getCommunityId())) {
|
||||
continue;
|
||||
}
|
||||
if (status != null && status != order.getStatus()) {
|
||||
continue;
|
||||
}
|
||||
result.add(copyOrder(order));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse confirm(Long id) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
move(order, ExpressOrderStatus.PENDING_PICKUP, "CONFIRM", "后台确认快递代取");
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse adjustFee(Long id, int feeCent, String reason) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
order.setFeeCent(feeCent);
|
||||
order.setUpdatedAt(LocalDateTime.now());
|
||||
addLog(order, "ADJUST_FEE", "调整服务费为" + feeCent + "分:" + reason);
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse cancel(Long id, String reason) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
order.setCancelReason(reason);
|
||||
move(order, ExpressOrderStatus.CANCELED, "CANCEL", "取消订单:" + nullToEmpty(reason));
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse complete(Long id) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
move(order, ExpressOrderStatus.COMPLETED, "COMPLETE", "订单完成");
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse markPickingUp(Long id) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
move(order, ExpressOrderStatus.PICKING_UP, "PICKING_UP", "配送员开始取件");
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse markDelivering(Long id) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
move(order, ExpressOrderStatus.DELIVERING, "DELIVERING", "配送员开始配送");
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse markDelivered(Long id, String photoUrl) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
order.setDeliveredPhotoUrl(photoUrl);
|
||||
move(order, ExpressOrderStatus.DELIVERED, "DELIVERED", "配送员送达");
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
public synchronized ExpressOrderResponse updateOfflinePayStatus(Long id, OfflinePayStatus status) {
|
||||
ExpressOrderResponse order = requireOrder(id);
|
||||
order.setOfflinePayStatus(status);
|
||||
order.setUpdatedAt(LocalDateTime.now());
|
||||
addLog(order, "OFFLINE_PAY", "线下收款状态:" + status.name());
|
||||
return copyOrder(order);
|
||||
}
|
||||
|
||||
private void move(ExpressOrderResponse order, ExpressOrderStatus target, String action, String content) {
|
||||
if (!order.getStatus().canMoveTo(target)) {
|
||||
throw new BizException("订单状态不允许操作");
|
||||
}
|
||||
order.setStatus(target);
|
||||
order.setUpdatedAt(LocalDateTime.now());
|
||||
addLog(order, action, content);
|
||||
}
|
||||
|
||||
private ExpressOrderResponse requireOrder(Long id) {
|
||||
ExpressOrderResponse order = orders.get(id);
|
||||
if (order == null) {
|
||||
throw new BizException(404, "快递代取订单不存在");
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
private void addLog(ExpressOrderResponse order, String action, String content) {
|
||||
ExpressOrderLogResponse log = new ExpressOrderLogResponse();
|
||||
log.setId(logIds.getAndIncrement());
|
||||
log.setOrderId(order.getId());
|
||||
log.setAction(action);
|
||||
log.setContent(content);
|
||||
log.setCreatedAt(LocalDateTime.now());
|
||||
order.getLogs().add(log);
|
||||
}
|
||||
|
||||
private String buildDeliveryAddress(AddressResponse address) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
append(builder, address.getBuilding());
|
||||
append(builder, address.getRoom());
|
||||
append(builder, address.getDetail());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void append(StringBuilder builder, String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (builder.length() > 0) {
|
||||
builder.append(' ');
|
||||
}
|
||||
builder.append(value);
|
||||
}
|
||||
|
||||
private String nullToEmpty(String value) {
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
|
||||
private ExpressOrderResponse copyOrder(ExpressOrderResponse source) {
|
||||
ExpressOrderResponse target = new ExpressOrderResponse();
|
||||
target.setId(source.getId());
|
||||
target.setOrderNo(source.getOrderNo());
|
||||
target.setTenantId(source.getTenantId());
|
||||
target.setCommunityId(source.getCommunityId());
|
||||
target.setUserId(source.getUserId());
|
||||
target.setAddressId(source.getAddressId());
|
||||
target.setContactName(source.getContactName());
|
||||
target.setContactPhone(source.getContactPhone());
|
||||
target.setDeliveryAddress(source.getDeliveryAddress());
|
||||
target.setExpressCompany(source.getExpressCompany());
|
||||
target.setPickupCode(source.getPickupCode());
|
||||
target.setPickupAddress(source.getPickupAddress());
|
||||
target.setReceiverPhone(source.getReceiverPhone());
|
||||
target.setPackageCount(source.getPackageCount());
|
||||
target.setFeeCent(source.getFeeCent());
|
||||
target.setOfflinePayStatus(source.getOfflinePayStatus());
|
||||
target.setStatus(source.getStatus());
|
||||
target.setRemark(source.getRemark());
|
||||
target.setCancelReason(source.getCancelReason());
|
||||
target.setDeliveredPhotoUrl(source.getDeliveredPhotoUrl());
|
||||
target.setCreatedAt(source.getCreatedAt());
|
||||
target.setUpdatedAt(source.getUpdatedAt());
|
||||
target.setLogs(copyLogs(source.getLogs()));
|
||||
return target;
|
||||
}
|
||||
|
||||
private List<ExpressOrderLogResponse> copyLogs(List<ExpressOrderLogResponse> sourceLogs) {
|
||||
List<ExpressOrderLogResponse> logs = new ArrayList<ExpressOrderLogResponse>();
|
||||
for (ExpressOrderLogResponse source : sourceLogs) {
|
||||
ExpressOrderLogResponse target = new ExpressOrderLogResponse();
|
||||
target.setId(source.getId());
|
||||
target.setOrderId(source.getOrderId());
|
||||
target.setAction(source.getAction());
|
||||
target.setContent(source.getContent());
|
||||
target.setCreatedAt(source.getCreatedAt());
|
||||
logs.add(target);
|
||||
}
|
||||
return logs;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,10 @@ public class UserAddressService {
|
||||
return result;
|
||||
}
|
||||
|
||||
public synchronized AddressResponse detailMine(Long userId, Long id) {
|
||||
return requireMine(userId, id);
|
||||
}
|
||||
|
||||
public synchronized AddressResponse update(Long userId, Long id, AddressRequest request) {
|
||||
AddressResponse address = requireMine(userId, id);
|
||||
copy(request, address);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class ExpressFeeCalculatorTests {
|
||||
@Test
|
||||
void firstPackageCostsThreeYuan() {
|
||||
assertThat(ExpressFeeCalculator.calculateCent(1)).isEqualTo(300);
|
||||
}
|
||||
|
||||
@Test
|
||||
void extraPackagesCostOneYuanEach() {
|
||||
assertThat(ExpressFeeCalculator.calculateCent(3)).isEqualTo(500);
|
||||
}
|
||||
|
||||
@Test
|
||||
void packageCountMustBePositive() {
|
||||
assertThatThrownBy(() -> ExpressFeeCalculator.calculateCent(0))
|
||||
.hasMessageContaining("件数必须大于0");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.linhelp.express;
|
||||
|
||||
import com.linhelp.common.enums.ExpressOrderStatus;
|
||||
import com.linhelp.user.AddressRequest;
|
||||
import com.linhelp.user.AddressResponse;
|
||||
import com.linhelp.user.UserAddressService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class ExpressOrderServiceTests {
|
||||
@Test
|
||||
void confirmedExpressOrderMovesToPendingPickup() {
|
||||
UserAddressService addressService = new UserAddressService();
|
||||
AddressResponse address = addressService.create(1L, addressRequest());
|
||||
ExpressOrderService expressOrderService = new ExpressOrderService(addressService);
|
||||
|
||||
ExpressOrderRequest request = expressRequest(address.getId());
|
||||
request.setPackageCount(3);
|
||||
ExpressOrderResponse order = expressOrderService.create(1L, request);
|
||||
|
||||
assertThat(order.getFeeCent()).isEqualTo(500);
|
||||
|
||||
expressOrderService.confirm(order.getId());
|
||||
|
||||
assertThat(expressOrderService.detail(order.getId()).getStatus()).isEqualTo(ExpressOrderStatus.PENDING_PICKUP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addressMustBelongToCurrentUser() {
|
||||
UserAddressService addressService = new UserAddressService();
|
||||
AddressResponse otherUserAddress = addressService.create(2L, addressRequest());
|
||||
ExpressOrderService expressOrderService = new ExpressOrderService(addressService);
|
||||
|
||||
assertThatThrownBy(() -> expressOrderService.create(1L, expressRequest(otherUserAddress.getId())))
|
||||
.hasMessageContaining("地址不存在");
|
||||
}
|
||||
|
||||
@Test
|
||||
void feeAdjustmentWritesLog() {
|
||||
UserAddressService addressService = new UserAddressService();
|
||||
AddressResponse address = addressService.create(1L, addressRequest());
|
||||
ExpressOrderService expressOrderService = new ExpressOrderService(addressService);
|
||||
ExpressOrderResponse order = expressOrderService.create(1L, expressRequest(address.getId()));
|
||||
|
||||
expressOrderService.adjustFee(order.getId(), 800, "大件加价");
|
||||
|
||||
ExpressOrderResponse detail = expressOrderService.detail(order.getId());
|
||||
assertThat(detail.getFeeCent()).isEqualTo(800);
|
||||
assertThat(detail.getLogs()).extracting(ExpressOrderLogResponse::getContent)
|
||||
.anyMatch(content -> content.contains("大件加价"));
|
||||
}
|
||||
|
||||
private ExpressOrderRequest expressRequest(Long addressId) {
|
||||
ExpressOrderRequest request = new ExpressOrderRequest();
|
||||
request.setTenantId(1L);
|
||||
request.setCommunityId(1L);
|
||||
request.setExpressCompany("顺丰");
|
||||
request.setPickupCode("A-1234");
|
||||
request.setPickupAddress("北门快递站");
|
||||
request.setReceiverPhone("13800000000");
|
||||
request.setAddressId(addressId);
|
||||
request.setPackageCount(1);
|
||||
return request;
|
||||
}
|
||||
|
||||
private AddressRequest addressRequest() {
|
||||
AddressRequest request = new AddressRequest();
|
||||
request.setTenantId(1L);
|
||||
request.setCommunityId(1L);
|
||||
request.setContactName("张三");
|
||||
request.setPhone("13800000000");
|
||||
request.setBuilding("1栋");
|
||||
request.setRoom("101");
|
||||
request.setDetail("门口");
|
||||
return request;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user