feat: gate overseas receiving and harden phase4 workflows
This commit is contained in:
+5
-1
@@ -36,7 +36,11 @@ public final class OverseasProcurementRequests {
|
||||
String productName, String status, String purchaseWarehouseId,
|
||||
LocalDateTime createdFrom, LocalDateTime createdTo) {}
|
||||
|
||||
public record Review(@NotBlank String decision, @Size(max = 1000) String remark) {}
|
||||
public record Review(
|
||||
@NotNull @Min(0) Long version,
|
||||
@NotBlank String decision,
|
||||
@NotBlank @Size(max = 255) String idempotencyKey,
|
||||
@Size(max = 1000) String remark) {}
|
||||
|
||||
public record Update(
|
||||
@NotNull @Min(0) Long version,
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ public final class OverseasProcurementResponses {
|
||||
|
||||
public record History(
|
||||
String operationType, String fromStatus, String toStatus, String operatorId,
|
||||
String changeDetail, String remark,
|
||||
String idempotencyKey, String changeDetail, String remark,
|
||||
LocalDateTime createdAt) {}
|
||||
|
||||
public record Detail(
|
||||
|
||||
+2
@@ -42,6 +42,8 @@ public class OverseasProcurementOrder {
|
||||
private String createdBy;
|
||||
private String reviewedBy;
|
||||
private String reviewRemark;
|
||||
private String reviewIdempotencyKey;
|
||||
private String reviewRequestHash;
|
||||
private LocalDateTime reviewedAt;
|
||||
private Long version;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
+1
@@ -17,6 +17,7 @@ public class OverseasProcurementStatusHistory {
|
||||
private String fromStatus;
|
||||
private String toStatus;
|
||||
private String operatorId;
|
||||
private String idempotencyKey;
|
||||
private String changeDetail;
|
||||
private String remark;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
+21
-6
@@ -89,7 +89,8 @@ public class OverseasProcurementService {
|
||||
if (concurrent != null) return replay(customerId, concurrent, requestHash);
|
||||
throw exception;
|
||||
}
|
||||
history(order, "CREATE", null, PENDING_REVIEW, operatorId, null, request.remark(), now);
|
||||
history(order, "CREATE", null, PENDING_REVIEW, operatorId,
|
||||
key, null, request.remark(), now);
|
||||
return detail(customerId, order.getOrderNo());
|
||||
}
|
||||
|
||||
@@ -144,7 +145,8 @@ public class OverseasProcurementService {
|
||||
order.getCreatedBy(), order.getReviewedBy(), order.getReviewRemark(), order.getReviewedAt(),
|
||||
histories.listOrder(customerId, order.getId()).stream().map(value ->
|
||||
new OverseasProcurementResponses.History(value.getOperationType(), value.getFromStatus(),
|
||||
value.getToStatus(), value.getOperatorId(), value.getChangeDetail(), value.getRemark(),
|
||||
value.getToStatus(), value.getOperatorId(), value.getIdempotencyKey(),
|
||||
value.getChangeDetail(), value.getRemark(),
|
||||
value.getCreatedAt())).toList());
|
||||
}
|
||||
|
||||
@@ -157,16 +159,27 @@ public class OverseasProcurementService {
|
||||
default -> throw badRequest("Review decision must be APPROVE or REJECT");
|
||||
};
|
||||
OverseasProcurementOrder order = lock(customerId, orderNo);
|
||||
if (next.equals(order.getStatus())) return detail(customerId, orderNo);
|
||||
String key = request.idempotencyKey().trim();
|
||||
String requestHash = hash(request);
|
||||
if (key.equals(order.getReviewIdempotencyKey())) {
|
||||
if (!requestHash.equals(order.getReviewRequestHash())) {
|
||||
throw conflict("Review idempotency key was reused with a different payload");
|
||||
}
|
||||
return detail(customerId, orderNo);
|
||||
}
|
||||
if (!request.version().equals(order.getVersion())) throw conflict("Order was changed; refresh and retry");
|
||||
if (!PENDING_REVIEW.equals(order.getStatus())) throw conflict("Overseas procurement order was already reviewed");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
order.setStatus(next);
|
||||
order.setReviewedBy(operatorId);
|
||||
order.setReviewRemark(trim(request.remark()));
|
||||
order.setReviewIdempotencyKey(key);
|
||||
order.setReviewRequestHash(requestHash);
|
||||
order.setReviewedAt(now);
|
||||
touch(order, now);
|
||||
orders.updateById(order);
|
||||
history(order, "REVIEW", PENDING_REVIEW, next, operatorId, null, request.remark(), now);
|
||||
history(order, "REVIEW", PENDING_REVIEW, next, operatorId,
|
||||
key, null, request.remark(), now);
|
||||
return detail(customerId, orderNo);
|
||||
}
|
||||
|
||||
@@ -197,7 +210,7 @@ public class OverseasProcurementService {
|
||||
touch(order, now);
|
||||
orders.updateById(order);
|
||||
history(order, "UPDATE", order.getStatus(), order.getStatus(), operatorId,
|
||||
changeDetail(before, after), null, now);
|
||||
null, changeDetail(before, after), null, now);
|
||||
return detail(customerId, orderNo);
|
||||
}
|
||||
|
||||
@@ -224,7 +237,8 @@ public class OverseasProcurementService {
|
||||
}
|
||||
|
||||
private void history(OverseasProcurementOrder order, String operationType, String from, String to,
|
||||
String operator, String changeDetail, String remark, LocalDateTime now) {
|
||||
String operator, String idempotencyKey, String changeDetail,
|
||||
String remark, LocalDateTime now) {
|
||||
OverseasProcurementStatusHistory history = new OverseasProcurementStatusHistory();
|
||||
history.setId(IdWorker.getId());
|
||||
history.setOrderId(order.getId());
|
||||
@@ -233,6 +247,7 @@ public class OverseasProcurementService {
|
||||
history.setFromStatus(from);
|
||||
history.setToStatus(to);
|
||||
history.setOperatorId(operator);
|
||||
history.setIdempotencyKey(trim(idempotencyKey));
|
||||
history.setChangeDetail(changeDetail);
|
||||
history.setRemark(trim(remark));
|
||||
history.setCreatedAt(now);
|
||||
|
||||
Reference in New Issue
Block a user