第三期装柜验收优化修改

This commit is contained in:
2026-08-12 13:34:26 +08:00
parent d2704f68a6
commit c2b1ab92ff
27 changed files with 258 additions and 71 deletions
@@ -37,7 +37,7 @@ public class OrderFulfillmentSplitService {
String hash = hash(req);
List<OrderFulfillmentSplitEntity> replay = splits.findByIdempotency(req.tenantId(), req.parentOrderId(), req.idempotencyKey());
if (!replay.isEmpty()) {
requireMatchingReplay(replay, hash);
requireMatchingReplay(replay, req);
return response(req, splits.lockOrder(req.tenantId(), req.parentOrderId()), replay);
}
@@ -45,7 +45,7 @@ public class OrderFulfillmentSplitService {
if (root == null) throw new BizException(ResultCode.NOT_FOUND, "根订单不存在或不属于该客户");
replay = splits.findByIdempotency(req.tenantId(), req.parentOrderId(), req.idempotencyKey());
if (!replay.isEmpty()) {
requireMatchingReplay(replay, hash);
requireMatchingReplay(replay, req);
return response(req, root, replay);
}
if (!"MASTER".equals(root.getOrderRole())) throw new BizException(ResultCode.CONFLICT, "根订单层级非法");
@@ -174,14 +174,33 @@ public class OrderFulfillmentSplitService {
|| r.lines().stream().mapToInt(OrderSplitDtos.QuantityLine::packageCount).sum() != r.sourcePackageCount())
throw new BizException(ResultCode.VALIDATION_FAILED, "来源明细箱数必须唯一且合计等于来源箱数");
}
private void requireMatchingReplay(List<OrderFulfillmentSplitEntity> rows, String hash) {
if (rows.stream().anyMatch(row -> !Objects.equals(hash, row.getRequestHash())))
private void requireMatchingReplay(List<OrderFulfillmentSplitEntity> rows, OrderSplitDtos.CreateRequest request) {
String details = sourceDetails(request);
boolean mismatch = rows.stream().anyMatch(row ->
!Objects.equals(row.getParentOrderId(), request.parentOrderId())
|| !Objects.equals(row.getSourceOrderId(), request.sourceOrderId())
|| !Objects.equals(row.getLoadingPlanId(), request.loadingPlanId())
|| !Objects.equals(row.getContainerBookingId(), request.containerBookingId())
|| !Objects.equals(row.getSourcePackageCount(), request.sourcePackageCount())
|| !Objects.equals(row.getLoadedPackageCount(), request.loadedPackageCount())
|| !Objects.equals(row.getRemainingPackageCount(), request.remainingPackageCount())
|| !Objects.equals(row.getOperationId(), request.operationId())
|| !sameJson(row.getSourceDetailJson(), details));
if (mismatch)
throw new BizException(ResultCode.CONFLICT, "幂等键对应的请求内容不一致");
}
private String sourceDetails(OrderSplitDtos.CreateRequest request) {
try { return json.writeValueAsString(request.lines()); }
catch (Exception exception) { throw new BizException(ResultCode.INTERNAL_ERROR, "无法保存来源明细快照"); }
}
private boolean sameJson(String left, String right) {
try {
return json.readTree(left).equals(json.readTree(right));
} catch (Exception exception) {
return Objects.equals(left, right);
}
}
private String hash(Object value) {
try { byte[] digest = MessageDigest.getInstance("SHA-256").digest(json.writeValueAsString(value).getBytes(StandardCharsets.UTF_8));
StringBuilder result = new StringBuilder(); for (byte b : digest) result.append(String.format("%02x", b)); return result.toString();