feat: add self-operated analytics and enforce Lastleg module boundaries
This commit is contained in:
+31
@@ -0,0 +1,31 @@
|
||||
package com.baiyue.integration.dto.lingxing;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/** Control identities are supplied by the collector and revalidated by its durable authority. */
|
||||
public final class LingxingEgressDtos {
|
||||
private LingxingEgressDtos() { }
|
||||
public enum CollectionMode { OFF, VALIDATION, BUSINESS }
|
||||
public enum Operation { WAREHOUSES, OUTBOUND_QUERY, OUTBOUND_LOCATE, OUTBOUND_DETAIL, PRODUCT_INVENTORY }
|
||||
public record EgressContext(String sourceAccount, CollectionMode executionPurpose, String rootTaskId,
|
||||
String sessionId, String attemptId, String exclusiveGrantId) {
|
||||
public boolean wellFormed() {
|
||||
return (executionPurpose == CollectionMode.VALIDATION || executionPurpose == CollectionMode.BUSINESS)
|
||||
&& identifier(sourceAccount, 64) && identifier(rootTaskId, 128) && identifier(sessionId, 128)
|
||||
&& identifier(attemptId, 128) && identifier(exclusiveGrantId, 128);
|
||||
}
|
||||
private static boolean identifier(String value, int maximum) {
|
||||
return value != null && value.length() <= maximum && value.matches("[A-Za-z0-9][A-Za-z0-9._:-]*");
|
||||
}
|
||||
}
|
||||
public record AuthorizationRequest(EgressContext context, Operation operation, String requestHash) { }
|
||||
public record AttemptPermit(EgressContext context, Operation operation, String requestHash,
|
||||
int allowedAttempts, Instant expiresAt, boolean exclusiveConfirmed,
|
||||
boolean budgetConsumed) { }
|
||||
public record CompletionRequest(EgressContext context, Operation operation, String requestHash,
|
||||
int actualHttpAttempts, String errorCode, Integer upstreamStatus,
|
||||
Integer sourceCode, boolean accountPaused, Instant cooldownUntil) { }
|
||||
public record AttemptMetadata(String attemptId, int actualHttpAttempts, boolean accountPaused,
|
||||
Instant cooldownUntil) { }
|
||||
public record AuthorizationDenial(String errorCode, boolean sampleDone, Instant waitUntil) { }
|
||||
}
|
||||
+32
-2
@@ -3,10 +3,14 @@ package com.baiyue.integration.dto.lingxing;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import com.baiyue.integration.dto.lingxing.LingxingEgressDtos.AttemptMetadata;
|
||||
|
||||
public final class LingxingWmsDtos {
|
||||
private LingxingWmsDtos() { }
|
||||
@@ -14,12 +18,38 @@ public final class LingxingWmsDtos {
|
||||
public record QueryRequest(@NotNull LocalDateTime startTime, @NotNull LocalDateTime endTime,
|
||||
@Min(1) int current, @Min(1) @Max(100) int size) { }
|
||||
|
||||
// Preserve source time strings until the account's source timezone has been verified.
|
||||
public record WarehouseQueryRequest(@Min(1) int current, @Min(1) @Max(1000) int size) { }
|
||||
public record LocateRequest(@NotBlank @Size(max=128) String deliveryNo,
|
||||
@Min(1) int current, @Min(1) @Max(1000) int size) { }
|
||||
public record DetailRequest(@NotBlank @Size(max=64) String warehouseCode,
|
||||
@NotBlank @Size(max=64) String customerCode,
|
||||
@NotBlank @Size(max=128) String deliveryNo) { }
|
||||
public record InventoryQueryRequest(@NotBlank @Size(max=64) String warehouseCode,
|
||||
@Min(1) int current, @Min(1) @Max(1000) int size) { }
|
||||
public record Warehouse(String whCode, String whNameCn, Integer warehouseType,
|
||||
Integer status, String timeZone) { }
|
||||
public record SkuLine(String productSku, String productName, BigDecimal actualDeliveryQty,
|
||||
BigDecimal deliveryQty) { }
|
||||
public record OrderDetail(String deliveryNo, String sourceNo, String customerCode, String whCode,
|
||||
Integer status, String orderCreateTime, String outboundTime,
|
||||
List<SkuLine> skuVOList, int sourceCode, Instant observedAt, AttemptMetadata egress) {
|
||||
public OrderDetail { skuVOList = List.copyOf(skuVOList); }
|
||||
}
|
||||
public record ProductStock(String customerCode, String whCode, String productSku, String productName,
|
||||
Integer productQuality, BigDecimal stkQty, BigDecimal freezeQty,
|
||||
BigDecimal useStkQty, BigDecimal transitQty, String innerBatchNo,
|
||||
String outBatchNo, String uniqueKey4tenant) { }
|
||||
public record QueryPage<T>(List<T> records, Long total, int current, int size, int pages,
|
||||
int sourceCurrent, int sourceSize, int sourceCode, Instant observedAt, AttemptMetadata egress) {
|
||||
public QueryPage { records = List.copyOf(records); }
|
||||
}
|
||||
|
||||
// Preserve source strings; the collector interprets confirmed Asia/Shanghai source time.
|
||||
public record OrderSummary(String deliveryNo, String sourceNo, String customerCode, String whCode,
|
||||
Integer status, String createTime, String outboundTime) { }
|
||||
|
||||
public record PageResult(List<OrderSummary> records, Long total, int current, int size,
|
||||
int sourceCode, Instant observedAt) {
|
||||
int pages, int sourceCurrent, int sourceSize, int sourceCode, Instant observedAt, AttemptMetadata egress) {
|
||||
public PageResult { records = List.copyOf(records); }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user