fix(lastleg): enforce delivery and return workflows
This commit is contained in:
+10
@@ -10,10 +10,12 @@ import com.baiyue.lastleg.security.OverseasPermissions;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -53,6 +55,14 @@ public class ExceptionOrderController {
|
||||
return ApiResponse.success(service.detail(requiredScope(user, customerId), exceptionNo));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/exception-orders/{exceptionNo}/evidence", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.EXCEPTION_ORDER_PROCESS + "')")
|
||||
public ApiResponse<ExceptionOrderResponses.UploadedEvidence> uploadEvidence(
|
||||
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId,
|
||||
@PathVariable String exceptionNo, @RequestPart("file") MultipartFile file) {
|
||||
return ApiResponse.success(service.uploadEvidence(requiredScope(user, customerId), operatorId(user), exceptionNo, file));
|
||||
}
|
||||
|
||||
@PostMapping("/exception-orders/{exceptionNo}/start-processing")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.EXCEPTION_ORDER_PROCESS + "')")
|
||||
public ApiResponse<ExceptionOrderResponses.CommandResult> startProcessing(
|
||||
|
||||
+10
-10
@@ -26,15 +26,15 @@ public final class ExceptionOrderRequests {
|
||||
@Min(1) Integer packageCount,
|
||||
@Size(max = 128) String skuCode) {}
|
||||
|
||||
public record MarkReturn(@NotNull Long inboundOrderId,
|
||||
public record MarkReturn(@NotNull @Min(1) Long inboundOrderId,
|
||||
@NotBlank @Size(max = 1000) String reason,
|
||||
@NotBlank @Size(max = 32) String returnDirection,
|
||||
@Size(max = 128) String returnLogisticsNo,
|
||||
@NotNull @Size(min = 1, max = 200) List<ReturnItem> items,
|
||||
@NotNull @Size(min = 1, max = 200) List<@NotNull ReturnItem> items,
|
||||
@NotBlank @Size(max = 255) String idempotencyKey) {}
|
||||
|
||||
public record ReturnItem(@NotNull Long outboundPalletItemId,
|
||||
@NotNull Long inventoryPositionId,
|
||||
public record ReturnItem(@NotNull @Min(1) Long outboundPalletItemId,
|
||||
@NotNull @Min(1) Long inventoryPositionId,
|
||||
@Min(1) long packageCount) {}
|
||||
|
||||
public record StartProcessing(@Min(0) long expectedVersion,
|
||||
@@ -44,15 +44,15 @@ public final class ExceptionOrderRequests {
|
||||
public record Complete(@Min(0) long expectedVersion,
|
||||
@NotBlank @Size(max = 255) String idempotencyKey,
|
||||
@NotBlank @Size(max = 2000) String handlingResult,
|
||||
@NotNull @Size(min = 1, max = 20) List<String> evidenceFileIds,
|
||||
@Size(max = 200) List<ReturnReceipt> receipts) {}
|
||||
@NotNull @Size(min = 1, max = 20) List<@NotNull @Min(1) Long> evidenceFileIds,
|
||||
@Size(max = 200) List<@NotNull ReturnReceipt> receipts) {}
|
||||
|
||||
public record ReturnReceipt(@NotNull Long outboundPalletItemId,
|
||||
@NotNull Long inventoryPositionId,
|
||||
public record ReturnReceipt(@NotNull @Min(1) Long outboundPalletItemId,
|
||||
@NotNull @Min(1) Long inventoryPositionId,
|
||||
@Min(1) long receivedPackages,
|
||||
@NotNull Long targetPalletId,
|
||||
@NotNull @Min(1) Long targetPalletId,
|
||||
@NotBlank @Size(max = 128) String targetPalletNo,
|
||||
@NotNull Long targetLocationId,
|
||||
@NotNull @Min(1) Long targetLocationId,
|
||||
@NotBlank @Size(max = 128) String targetLocationCode) {}
|
||||
|
||||
public record Cancel(@Min(0) long expectedVersion,
|
||||
|
||||
+3
-2
@@ -16,7 +16,7 @@ public final class ExceptionOrderResponses {
|
||||
String returnLogisticsNo, String handlingAction,
|
||||
String handlingResult, String handlerName, LocalDateTime exceptionAt,
|
||||
LocalDateTime completedAt, LocalDateTime updatedAt, long version,
|
||||
List<String> evidenceFileIds, List<String> allowedActions) {}
|
||||
List<Long> evidenceFileIds, List<String> allowedActions) {}
|
||||
|
||||
public record Relation(Long lastMileOrderId, String lastMileOrderNo,
|
||||
Long inboundOrderId, String inboundCode,
|
||||
@@ -31,5 +31,6 @@ public final class ExceptionOrderResponses {
|
||||
public record CommandResult(Long id, String exceptionNo, String status, long version,
|
||||
Long inventoryAdjustmentId, long restoredPackages,
|
||||
LocalDateTime completedAt, boolean replayed) {}
|
||||
public record Created(Long id, String exceptionNo, String status, long version) {}
|
||||
public record UploadedEvidence(Long fileId, String fileName, String contentType, long sizeBytes) {}
|
||||
public record Created(Long id, String exceptionNo, String status, long version, boolean replayed) {}
|
||||
}
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.baiyue.lastleg.exceptionorder.gateway;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
public interface ExceptionEvidenceFileGateway {
|
||||
Uploaded upload(String customerId, long exceptionOrderId, String operatorId, MultipartFile file);
|
||||
void validate(String customerId, long exceptionOrderId, long fileId);
|
||||
|
||||
record Uploaded(long fileId, String fileName, String contentType, long sizeBytes) { }
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
package com.baiyue.lastleg.exceptionorder.gateway;
|
||||
|
||||
import com.baiyue.lastleg.config.LastlegRestClientFactory;
|
||||
import com.baiyue.lastleg.config.LastlegRestClientProperties;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.MultipartBodyBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestClient;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class HttpExceptionEvidenceFileGateway implements ExceptionEvidenceFileGateway {
|
||||
private static final String BUSINESS_TYPE = "OVERSEAS_EXCEPTION_EVIDENCE";
|
||||
@Resource private RestClient.Builder restClientBuilder;
|
||||
@Resource private LastlegRestClientFactory restClientFactory;
|
||||
@Resource private LastlegRestClientProperties restClientProperties;
|
||||
@Value("${baiyue.clients.file.url:http://127.0.0.1:9205}") private String baseUrl;
|
||||
@Value("${baiyue.security.internal-service-token:}") private String internalToken;
|
||||
private RestClient client;
|
||||
|
||||
@PostConstruct
|
||||
void initializeClient() {
|
||||
client = restClientFactory.build(restClientBuilder, baseUrl, restClientProperties.getCustomerVisitFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uploaded upload(String customerId, long exceptionOrderId, String operatorId, MultipartFile file) {
|
||||
MultipartBodyBuilder body = new MultipartBodyBuilder();
|
||||
try {
|
||||
body.part("file", new ByteArrayResource(file.getBytes()) {
|
||||
@Override public String getFilename() { return file.getOriginalFilename(); }
|
||||
}).contentType(file.getContentType() == null ? MediaType.APPLICATION_OCTET_STREAM
|
||||
: MediaType.parseMediaType(file.getContentType()));
|
||||
} catch (IOException exception) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "无法读取异常处理证据", exception); }
|
||||
MetadataEnvelope response = client.post()
|
||||
.uri("/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}",
|
||||
tenantId(customerId), BUSINESS_TYPE, exceptionOrderId)
|
||||
.header("X-Internal-Service-Token", internalToken).header("X-Operator-Id", operatorId)
|
||||
.contentType(MediaType.MULTIPART_FORM_DATA).body(body.build()).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, (request, result) -> { throw new ResponseStatusException(
|
||||
result.getStatusCode().is4xxClientError() ? HttpStatus.BAD_REQUEST : HttpStatus.SERVICE_UNAVAILABLE,
|
||||
"异常处理证据上传失败"); }).body(MetadataEnvelope.class);
|
||||
Metadata data = require(response);
|
||||
return new Uploaded(data.fileId(), data.fileName(), data.contentType(), data.sizeBytes() == null ? 0 : data.sizeBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(String customerId, long exceptionOrderId, long fileId) {
|
||||
long tenantId = tenantId(customerId);
|
||||
MetadataEnvelope response = client.get()
|
||||
.uri("/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}/{fileId}",
|
||||
tenantId, BUSINESS_TYPE, exceptionOrderId, fileId)
|
||||
.header("X-Internal-Service-Token", internalToken).retrieve()
|
||||
.onStatus(HttpStatusCode::isError, (request, result) -> { throw new ResponseStatusException(
|
||||
result.getStatusCode().is4xxClientError() ? HttpStatus.BAD_REQUEST : HttpStatus.SERVICE_UNAVAILABLE,
|
||||
"异常处理证据不存在或归属不正确"); }).body(MetadataEnvelope.class);
|
||||
Metadata data = require(response);
|
||||
if (data.fileId() != fileId || data.tenantId() == null || data.tenantId() != tenantId
|
||||
|| !BUSINESS_TYPE.equals(data.businessType()) || !String.valueOf(exceptionOrderId).equals(data.businessId())) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "异常处理证据与当前异常单不匹配");
|
||||
}
|
||||
}
|
||||
|
||||
private static Metadata require(MetadataEnvelope response) {
|
||||
if (response == null || !"200".equals(response.code()) || response.data() == null || response.data().fileId() == null) {
|
||||
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "文件服务未返回异常处理证据元数据");
|
||||
}
|
||||
return response.data();
|
||||
}
|
||||
private static long tenantId(String value) {
|
||||
try { return Long.parseLong(value); }
|
||||
catch (NumberFormatException exception) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "客户ID格式无效", exception); }
|
||||
}
|
||||
private record MetadataEnvelope(String code, String message, Metadata data) { }
|
||||
private record Metadata(Long fileId, Long tenantId, String businessType, String businessId,
|
||||
String fileName, String contentType, Long sizeBytes) { }
|
||||
}
|
||||
-1
@@ -5,7 +5,6 @@ import com.baiyue.lastleg.exceptionorder.entity.ExceptionOrder;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
@Mapper
|
||||
public interface ExceptionOrderMapper extends BaseMapper<ExceptionOrder> {
|
||||
|
||||
+48
-12
@@ -14,6 +14,7 @@ import com.baiyue.lastleg.delivery.entity.OutboundPdaPick;
|
||||
import com.baiyue.lastleg.delivery.mapper.OutboundOrderMapper;
|
||||
import com.baiyue.lastleg.delivery.mapper.OutboundPalletItemMapper;
|
||||
import com.baiyue.lastleg.delivery.mapper.OutboundPdaPickMapper;
|
||||
import com.baiyue.lastleg.delivery.model.DeliveryStatusPolicy;
|
||||
import com.baiyue.lastleg.entity.LastlegInboundOrder;
|
||||
import com.baiyue.lastleg.entity.LastlegOrder;
|
||||
import com.baiyue.lastleg.exceptionorder.dto.ExceptionOrderRequests;
|
||||
@@ -21,6 +22,7 @@ import com.baiyue.lastleg.exceptionorder.dto.ExceptionOrderResponses;
|
||||
import com.baiyue.lastleg.exceptionorder.entity.ExceptionOrder;
|
||||
import com.baiyue.lastleg.exceptionorder.entity.ExceptionOrderCommand;
|
||||
import com.baiyue.lastleg.exceptionorder.entity.ExceptionReturnItem;
|
||||
import com.baiyue.lastleg.exceptionorder.gateway.ExceptionEvidenceFileGateway;
|
||||
import com.baiyue.lastleg.exceptionorder.mapper.ExceptionOrderCommandMapper;
|
||||
import com.baiyue.lastleg.exceptionorder.mapper.ExceptionOrderMapper;
|
||||
import com.baiyue.lastleg.exceptionorder.mapper.ExceptionReturnItemMapper;
|
||||
@@ -39,9 +41,9 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -67,6 +69,7 @@ public class ExceptionOrderService {
|
||||
@Resource private ExceptionReturnItemMapper returnItems;
|
||||
@Resource private ExceptionOrderCommandMapper commands;
|
||||
@Resource private InventoryCommandService inventoryCommands;
|
||||
@Resource private ExceptionEvidenceFileGateway evidenceFiles;
|
||||
@Resource private ObjectMapper objectMapper;
|
||||
|
||||
public PageResult<ExceptionOrderResponses.Row> page(String scopedCustomerId, ExceptionOrderRequests.Query query) {
|
||||
@@ -102,9 +105,28 @@ public class ExceptionOrderService {
|
||||
return new ExceptionOrderResponses.Detail(row(order), storedReturnSources(order));
|
||||
}
|
||||
|
||||
public ExceptionOrderResponses.UploadedEvidence uploadEvidence(String customerId, String operatorId,
|
||||
String exceptionNo, MultipartFile file) {
|
||||
ExceptionOrder order = exceptionOrders.findByNo(customerId, exceptionNo);
|
||||
if (order == null) throw notFound("异常订单不存在");
|
||||
if (file == null || file.isEmpty()) throw badRequest("请选择异常处理证据文件");
|
||||
ExceptionEvidenceFileGateway.Uploaded uploaded = evidenceFiles.upload(customerId, order.getId(), operatorId, file);
|
||||
return new ExceptionOrderResponses.UploadedEvidence(uploaded.fileId(), uploaded.fileName(),
|
||||
uploaded.contentType(), uploaded.sizeBytes());
|
||||
}
|
||||
|
||||
public List<ExceptionOrderResponses.Relation> returnCandidates(String customerId, String deliveryNo) {
|
||||
DeliveryOrder delivery = deliveryOrders.findByNo(customerId, deliveryNo);
|
||||
if (delivery == null) throw notFound("派送单不存在");
|
||||
if (!DeliveryStatusPolicy.allowedActions(delivery.getStatus()).contains("MARK_RETURN")) {
|
||||
throw conflict("当前派送状态不允许标记退回");
|
||||
}
|
||||
return returnCandidates(delivery);
|
||||
}
|
||||
|
||||
private List<ExceptionOrderResponses.Relation> returnCandidates(DeliveryOrder delivery) {
|
||||
String customerId = delivery.getCustomerId();
|
||||
String deliveryNo = delivery.getDeliveryNo();
|
||||
return lastMileOrders.selectList(new LambdaQueryWrapper<LastlegOrder>()
|
||||
.eq(LastlegOrder::getCustomerId, customerId)
|
||||
.eq(LastlegOrder::getDeliveryOrderNo, deliveryNo)
|
||||
@@ -129,12 +151,15 @@ public class ExceptionOrderService {
|
||||
String requestHash = hash(request);
|
||||
ExceptionOrderCommand replay = commands.findByKey(customerId, "MARK_RETURN", request.idempotencyKey().trim());
|
||||
if (replay != null) return replayCreated(replay, requestHash);
|
||||
DeliveryOrder delivery = deliveryOrders.findByNo(customerId, deliveryNo);
|
||||
DeliveryOrder delivery = deliveryOrders.lockByNo(customerId, deliveryNo);
|
||||
if (delivery == null) throw notFound("派送单不存在");
|
||||
if (!DeliveryStatusPolicy.allowedActions(delivery.getStatus()).contains("MARK_RETURN")) {
|
||||
throw conflict("当前派送状态不允许标记退回");
|
||||
}
|
||||
ExceptionOrder existing = exceptionOrders.findDeliveryReturn(customerId, delivery.getId());
|
||||
if (existing != null) throw conflict("该派送单已存在退回异常单");
|
||||
|
||||
List<ExceptionOrderResponses.Relation> candidates = returnCandidates(customerId, deliveryNo);
|
||||
List<ExceptionOrderResponses.Relation> candidates = returnCandidates(delivery);
|
||||
ExceptionOrderResponses.Relation selected = candidates.stream()
|
||||
.filter(candidate -> Objects.equals(candidate.inboundOrderId(), request.inboundOrderId()))
|
||||
.findFirst().orElseThrow(() -> conflict("所选入仓单不属于该派送单"));
|
||||
@@ -145,8 +170,12 @@ public class ExceptionOrderService {
|
||||
Set<String> skus = available.stream().filter(source -> requested.stream().anyMatch(item -> sameSource(source, item)))
|
||||
.map(ExceptionOrderResponses.ReturnSource::skuCode).filter(StringUtils::hasText).collect(java.util.stream.Collectors.toSet());
|
||||
String sku = skus.size() == 1 ? skus.iterator().next() : "MIXED";
|
||||
String returnDirection = trim(request.returnDirection()).toUpperCase(java.util.Locale.ROOT);
|
||||
if (!Set.of("OVERSEAS_WAREHOUSE", "CUSTOMER", "OTHER").contains(returnDirection)) {
|
||||
throw badRequest("不支持的退回方向");
|
||||
}
|
||||
ExceptionOrderResponses.Created created = insert(selected, delivery, "RETURN", request.reason(),
|
||||
packages, sku, request.returnDirection(), request.returnLogisticsNo(),
|
||||
packages, sku, returnDirection, request.returnLogisticsNo(),
|
||||
"DELIVERY_RETURN", operatorId, operatorName);
|
||||
|
||||
for (ExceptionOrderRequests.ReturnItem requestedItem : requested) {
|
||||
@@ -163,11 +192,12 @@ public class ExceptionOrderService {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
delivery.setStatus("RETURN_PENDING");
|
||||
delivery.setUpdatedAt(now);
|
||||
delivery.setVersion(Objects.requireNonNullElse(delivery.getVersion(), 0L) + 1);
|
||||
deliveryOrders.updateById(delivery);
|
||||
LastlegOrder tail = lastMileOrders.selectById(selected.lastMileOrderId());
|
||||
if (tail != null) {
|
||||
tail.setAbnormal(true);
|
||||
tail.setSubOrderStatus("RETURN_PENDING");
|
||||
tail.setSubOrderStatus("DELIVERY:RETURN_PENDING");
|
||||
tail.setUpdatedAt(now);
|
||||
lastMileOrders.updateById(tail);
|
||||
}
|
||||
@@ -222,6 +252,7 @@ public class ExceptionOrderService {
|
||||
ExceptionOrderCommand replay = commands.findByKey(customerId, "COMPLETE", request.idempotencyKey().trim());
|
||||
if (replay != null) return replayResult(replay, requestHash);
|
||||
ExceptionOrder order = lock(customerId, exceptionNo, request.expectedVersion(), "PROCESSING");
|
||||
request.evidenceFileIds().stream().distinct().forEach(fileId -> evidenceFiles.validate(customerId, order.getId(), fileId));
|
||||
ReturnedInventoryRestoreResponse restored = null;
|
||||
if ("RETURN".equals(order.getExceptionType()) && "OVERSEAS_WAREHOUSE".equals(order.getReturnDirection())) {
|
||||
List<ExceptionReturnItem> stored = returnItems.findByException(customerId, order.getId());
|
||||
@@ -237,7 +268,7 @@ public class ExceptionOrderService {
|
||||
receipt.outboundPalletItemId(), receipt.inventoryPositionId(), receipt.receivedPackages(),
|
||||
receipt.targetPalletId(), receipt.targetPalletNo(), receipt.targetLocationId(),
|
||||
receipt.targetLocationCode())).toList(), request.idempotencyKey().trim(),
|
||||
request.evidenceFileIds()));
|
||||
request.evidenceFileIds().stream().map(String::valueOf).toList()));
|
||||
} else if (request.receipts() != null && !request.receipts().isEmpty()) {
|
||||
throw badRequest("非退回海外仓异常不能提交库存实收明细");
|
||||
}
|
||||
@@ -318,7 +349,7 @@ public class ExceptionOrderService {
|
||||
value.setExceptionAt(now); value.setCreatedAt(now); value.setUpdatedAt(now);
|
||||
try { exceptionOrders.insert(value); }
|
||||
catch (DuplicateKeyException exception) { throw conflict("该关联单据已存在异常退货单"); }
|
||||
return new ExceptionOrderResponses.Created(value.getId(), value.getExceptionNo(), value.getStatus(), version(value));
|
||||
return new ExceptionOrderResponses.Created(value.getId(), value.getExceptionNo(), value.getStatus(), version(value), false);
|
||||
}
|
||||
|
||||
private LastlegOrder uniqueTail(String customerId, String orderNo, String inboundCode) {
|
||||
@@ -364,7 +395,7 @@ public class ExceptionOrderService {
|
||||
value.getOutboundNo(), value.getSkuCode(), value.getPackageCount(), value.getReturnDirection(),
|
||||
value.getReturnLogisticsNo(), value.getHandlingAction(), value.getHandlingResult(), value.getHandlerName(),
|
||||
value.getExceptionAt(), value.getCompletedAt(), value.getUpdatedAt(), version(value),
|
||||
readStringList(value.getEvidenceFileIdsJson()), allowedActions(value));
|
||||
readEvidenceFileIds(value.getEvidenceFileIdsJson()), allowedActions(value));
|
||||
}
|
||||
|
||||
private ExceptionOrderResponses.Relation withReturnSources(ExceptionOrderResponses.Relation relation,
|
||||
@@ -430,11 +461,13 @@ public class ExceptionOrderService {
|
||||
|
||||
private void closeReturnedDelivery(ExceptionOrder order, String operatorId, LocalDateTime now) {
|
||||
if (!"RETURN".equals(order.getExceptionType()) || !StringUtils.hasText(order.getDeliveryNo())) return;
|
||||
DeliveryOrder delivery = deliveryOrders.findByNo(order.getCustomerId(), order.getDeliveryNo());
|
||||
DeliveryOrder delivery = deliveryOrders.lockByNo(order.getCustomerId(), order.getDeliveryNo());
|
||||
if (delivery == null || !"RETURN_PENDING".equals(delivery.getStatus())) {
|
||||
throw conflict("关联派送单不是退货处理中状态");
|
||||
}
|
||||
delivery.setStatus("RETURNED"); delivery.setUpdatedAt(now); deliveryOrders.updateById(delivery);
|
||||
delivery.setStatus("RETURNED"); delivery.setUpdatedAt(now);
|
||||
delivery.setVersion(Objects.requireNonNullElse(delivery.getVersion(), 0L) + 1);
|
||||
deliveryOrders.updateById(delivery);
|
||||
for (LastlegOrder tail : lastMileOrders.selectList(new LambdaQueryWrapper<LastlegOrder>()
|
||||
.eq(LastlegOrder::getCustomerId, order.getCustomerId())
|
||||
.eq(LastlegOrder::getDeliveryOrderNo, order.getDeliveryNo()))) {
|
||||
@@ -482,7 +515,10 @@ public class ExceptionOrderService {
|
||||
|
||||
private ExceptionOrderResponses.Created replayCreated(ExceptionOrderCommand command, String requestHash) {
|
||||
requireReplayHash(command, requestHash);
|
||||
try { return objectMapper.readValue(command.getResultJson(), ExceptionOrderResponses.Created.class); }
|
||||
try {
|
||||
ExceptionOrderResponses.Created result = objectMapper.readValue(command.getResultJson(), ExceptionOrderResponses.Created.class);
|
||||
return new ExceptionOrderResponses.Created(result.id(), result.exceptionNo(), result.status(), result.version(), true);
|
||||
}
|
||||
catch (JsonProcessingException exception) { throw new IllegalStateException("异常命令结果损坏", exception); }
|
||||
}
|
||||
|
||||
@@ -500,7 +536,7 @@ public class ExceptionOrderService {
|
||||
catch (JsonProcessingException exception) { throw new IllegalStateException("无法保存异常处理结果", exception); }
|
||||
}
|
||||
|
||||
private List<String> readStringList(String value) {
|
||||
private List<Long> readEvidenceFileIds(String value) {
|
||||
if (!StringUtils.hasText(value)) return List.of();
|
||||
try { return objectMapper.readValue(value, new TypeReference<>() { }); }
|
||||
catch (JsonProcessingException exception) { throw new IllegalStateException("异常处理证据数据损坏", exception); }
|
||||
|
||||
Reference in New Issue
Block a user