feat(firstleg): expose customs receipt history

This commit is contained in:
2026-09-28 09:49:53 +08:00
parent cf76f7d6d3
commit f6e70ea5d0
5 changed files with 23 additions and 3 deletions
@@ -17,10 +17,14 @@ public final class ContainerCustomsDtos {
public record FileView(long fileId, String fileName, String fileHash, String contentType,
long sizeBytes, int version, LocalDateTime uploadedAt) {}
public record ReceiptVersionView(long version, FileView file, String operatorName,
LocalDateTime createdAt) {}
public record DocumentView(long documentId, long tenantId, FileView source,
List<Long> inboundIds, List<String> inboundCodes,
boolean frozen, FileView receipt, String receiptStatus,
String receiptRejectReason, FileView finalDocument) {}
String receiptRejectReason, FileView finalDocument,
List<ReceiptVersionView> receiptHistory) {}
public record ContainerView(long aggregateId, long loadingPlanId, long containerBookingId,
String planNo, String cabinetNo, String containerNo, String status, boolean hasActualCargo,
@@ -340,6 +340,12 @@ public interface ContainerCustomsMapper {
"WHERE r.source_document_id=#{documentId} FOR UPDATE")
CompletionRow lockCompletion(@Param("documentId") long documentId);
@Select("SELECT v.document_version documentVersion,v.file_id fileId,v.file_name fileName,v.file_hash fileHash,"
+ "v.content_type contentType,v.size_bytes sizeBytes,v.operator_id operatorId,v.operator_name operatorName,v.created_at createdAt "
+ "FROM fl_customs_completion_document_version v WHERE v.completion_document_id=#{completionId} "
+ "ORDER BY v.document_version")
List<CompletionVersionRow> completionVersions(@Param("completionId") long completionId);
@Insert("""
INSERT INTO fl_customs_completion_document
(id,source_document_id,file_id,file_name,file_hash,content_type,size_bytes,uploaded_by,uploaded_by_name,
@@ -553,6 +559,8 @@ public interface ContainerCustomsMapper {
record CompletionRow(Long id,Long sourceDocumentId,Long fileId,String fileName,String fileHash,String contentType,
Long sizeBytes,Long uploadedBy,String uploadedByName,LocalDateTime uploadedAt,Integer version,
String customerConfirmStatus,String customerRejectReason) {}
record CompletionVersionRow(Integer documentVersion,Long fileId,String fileName,String fileHash,String contentType,
Long sizeBytes,Long operatorId,String operatorName,LocalDateTime createdAt) {}
record FinalRow(Long id,Long sourceDocumentId,Long fileId,String fileName,String fileHash,String contentType,
Long sizeBytes,Long uploadedBy,String uploadedByName,LocalDateTime uploadedAt,Integer version) {}
record CommandRow(Long id,Long actorId,String action,String idempotencyKey,String requestHash,String status,
@@ -581,11 +581,13 @@ public class ContainerCustomsService {
FinalRow finalDocument = mapper.finalDocument(source.id());
ContainerRow container = mapper.containerById(source.customsContainerId());
FileView result = completion == null ? null : file(completion);
List<ReceiptVersionView> receiptHistory = completion == null ? List.of() : Optional.ofNullable(mapper.completionVersions(completion.id())).orElseGet(List::of).stream()
.map(version -> new ReceiptVersionView(version.documentVersion(), file(version), version.operatorName(), version.createdAt())).toList();
return new DocumentView(source.id(), source.tenantId(), file(source), scopes.stream().map(ScopeRow::inboundId).toList(),
scopes.stream().map(ScopeRow::inboundCode).toList(), source.frozenAt() != null, result,
completion == null ? null : completion.customerConfirmStatus(),
completion == null ? null : completion.customerRejectReason(),
finalDocument == null ? null : file(finalDocument));
finalDocument == null ? null : file(finalDocument), receiptHistory);
}
private void completeContainer(ContainerRow container, long operatorId, String operatorName, String remark) {
@@ -657,6 +659,10 @@ public class ContainerCustomsService {
private static FileView file(DocumentRow row) { return new FileView(row.fileId(),row.fileName(),row.fileHash(),row.contentType(),row.sizeBytes(),row.version(),row.uploadedAt()); }
private static FileView file(CompletionRow row) { return new FileView(row.fileId(),row.fileName(),row.fileHash(),row.contentType(),row.sizeBytes(),row.version(),row.uploadedAt()); }
private static FileView file(ContainerCustomsMapper.CompletionVersionRow row) {
return new FileView(row.fileId(), row.fileName(), row.fileHash(), row.contentType(), row.sizeBytes(),
row.documentVersion(), row.createdAt());
}
private static FileView file(FinalRow row) { return new FileView(row.fileId(),row.fileName(),row.fileHash(),row.contentType(),row.sizeBytes(),row.version(),row.uploadedAt()); }
private static long size(CustomsFileClient.Metadata value) { return value.sizeBytes() == null ? 0 : value.sizeBytes(); }
private static void validateFile(MultipartFile file) { if (file == null || file.isEmpty()) throw bad("请选择文件"); if (file.getSize() > MAX_FILE_BYTES) throw bad("单文件不能超过50MB"); }