优化
This commit is contained in:
@@ -3,6 +3,7 @@ package com.baiyue.firstleg.client;
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
@@ -29,6 +30,12 @@ public interface LoadingDocumentFileClient {
|
||||
ResponseEntity<byte[]> download(@RequestHeader("X-Internal-Service-Token") String token,
|
||||
@PathVariable long tenantId,@PathVariable String businessType,@PathVariable String businessId,@PathVariable long fileId);
|
||||
|
||||
@DeleteMapping("/{tenantId}/{businessType}/{businessId}/{fileId}")
|
||||
ApiResponse<Void> delete(@RequestHeader("X-Internal-Service-Token") String token,
|
||||
@RequestHeader("X-Operator-Id") long operatorId,
|
||||
@PathVariable long tenantId, @PathVariable String businessType,
|
||||
@PathVariable String businessId, @PathVariable long fileId);
|
||||
|
||||
record Metadata(Long fileId, Long tenantId, String businessType, String businessId,
|
||||
String fileName, String sha256, String contentType, Long sizeBytes) {}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,10 @@ package com.baiyue.firstleg.customs.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baiyue.firstleg.customs.entity.CustomsCaseEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface CustomsCaseMapper extends BaseMapper<CustomsCaseEntity> {}
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
@Mapper public interface CustomsCaseMapper extends BaseMapper<CustomsCaseEntity> {
|
||||
@Select("SELECT COUNT(*) FROM fl_container_document WHERE container_booking_id=#{containerBookingId} "
|
||||
+ "AND document_type='CUSTOMS_DECLARATION' AND completed_at IS NOT NULL")
|
||||
int completedLoadingDeclaration(@Param("containerBookingId") long containerBookingId);
|
||||
}
|
||||
|
||||
+2
-5
@@ -81,11 +81,8 @@ public class CustomsRepository {
|
||||
.eq(CustomsCaseEntity::getContainerBookingId, containerBookingId)
|
||||
.orderByDesc(CustomsCaseEntity::getUpdatedAt).last("LIMIT 1"));
|
||||
}
|
||||
public CustomsCaseEntity clearedContainerCase(long containerBookingId) {
|
||||
return cases.selectOne(new LambdaQueryWrapper<CustomsCaseEntity>()
|
||||
.eq(CustomsCaseEntity::getContainerBookingId, containerBookingId)
|
||||
.eq(CustomsCaseEntity::getStatus, "CLEARANCE_COMPLETED")
|
||||
.orderByDesc(CustomsCaseEntity::getUpdatedAt).last("LIMIT 1"));
|
||||
public boolean loadingDeclarationCompleted(long containerBookingId) {
|
||||
return cases.completedLoadingDeclaration(containerBookingId) == 1;
|
||||
}
|
||||
public boolean containerCarriesOrder(long containerId, long tenantId, long orderId) {
|
||||
LoadingPlanEntity plan = loadingPlans.selectOne(new LambdaQueryWrapper<LoadingPlanEntity>()
|
||||
|
||||
+3
-5
@@ -1,6 +1,5 @@
|
||||
package com.baiyue.firstleg.customs.service;
|
||||
|
||||
import com.baiyue.firstleg.customs.entity.CustomsCaseEntity;
|
||||
import com.baiyue.firstleg.customs.repository.CustomsRepository;
|
||||
import com.baiyue.firstleg.outbound.dispatch.dto.OutboundDispatchDtos.GateItem;
|
||||
import com.baiyue.firstleg.outbound.dispatch.gate.OutboundDispatchGateContributor;
|
||||
@@ -18,12 +17,11 @@ public class CustomsDispatchGateContributor implements OutboundDispatchGateContr
|
||||
if (context.tenantId() <= 0 || context.customerId() <= 0) {
|
||||
return gate(false, "INVALID_CUSTOMER_SCOPE");
|
||||
}
|
||||
CustomsCaseEntity value = repository.clearedContainerCase(context.containerBookingId());
|
||||
if (value == null) return gate(false, "MISSING");
|
||||
return gate("CLEARANCE_COMPLETED".equals(value.getStatus()), value.getStatus());
|
||||
boolean completed = repository.loadingDeclarationCompleted(context.containerBookingId());
|
||||
return gate(completed, completed ? "COMPLETED" : "MISSING");
|
||||
}
|
||||
|
||||
private static GateItem gate(boolean passed, String actual) {
|
||||
return new GateItem("CUSTOMS_CLEARANCE", "报关完成", passed, actual, "CLEARANCE_COMPLETED");
|
||||
return new GateItem("CUSTOMS_CLEARANCE", "报关完成", passed, actual, "COMPLETED");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,9 +106,13 @@ public class LoadingListRepository {
|
||||
String fromStatus, String toStatus, String beforeSnapshot,
|
||||
String afterSnapshot, long operatorId, String operatorName,
|
||||
String operationReason) {
|
||||
mapper.insertHistory(new HistoryWrite(IdWorker.getId(), planId, operationId, actionType,
|
||||
int changed = mapper.insertHistory(new HistoryWrite(IdWorker.getId(), planId, operationId, actionType,
|
||||
fromStatus, toStatus, beforeSnapshot, afterSnapshot, operatorId, operatorName,
|
||||
operationReason));
|
||||
if (changed != 1) {
|
||||
throw new com.baiyue.common.core.exception.BizException(
|
||||
com.baiyue.common.core.api.ResultCode.CONFLICT, "装柜历史已变化,请刷新后重试");
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Long, List<Customer>> customerMap(List<AggregateRow> rows) {
|
||||
|
||||
@@ -31,12 +31,15 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import feign.FeignException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
@@ -49,6 +52,7 @@ import java.util.Set;
|
||||
|
||||
@Service
|
||||
public class LoadingListService {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoadingListService.class);
|
||||
private static final Set<String> PRELOAD_STATUSES = Set.of("EDITING", "LOADING");
|
||||
public static final String DESTINATION_CLEARANCE = "DESTINATION_CLEARANCE";
|
||||
public static final String CUSTOMS_DECLARATION = "CUSTOMS_DECLARATION";
|
||||
@@ -317,8 +321,16 @@ public class LoadingListService {
|
||||
requireReplaceableDocument(current, expectedVersion);
|
||||
LoadingDocumentFileClient.Metadata metadata = uploadDocumentFile(
|
||||
businessType, businessId, operatorId, file, fileHash);
|
||||
return persistDocument(plan, documentType, current, metadata, operatorId, operatorName,
|
||||
operationId, "UPLOAD_" + documentType, requestHash, operationReason);
|
||||
try {
|
||||
return persistDocument(plan, documentType, current, metadata, operatorId, operatorName,
|
||||
operationId, "UPLOAD_" + documentType, requestHash, operationReason);
|
||||
} catch (RuntimeException exception) {
|
||||
compensateUploadedFile(businessType, businessId, metadata.fileId(), operatorId);
|
||||
if (exception instanceof DataIntegrityViolationException) {
|
||||
throw conflict("资料状态或数据库约束已变化,请刷新后重试");
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
private BusinessDocument persistDocument(AggregateRow plan, String documentType,
|
||||
@@ -337,12 +349,18 @@ public class LoadingListService {
|
||||
if (changed != 1) throw conflict("资料版本已变化,请刷新后重试");
|
||||
} catch (DuplicateKeyException exception) {
|
||||
throw conflict("资料已被其他操作上传,请刷新后重试");
|
||||
} catch (DataIntegrityViolationException exception) {
|
||||
throw conflict("资料状态或数据库约束已变化,请刷新后重试");
|
||||
}
|
||||
ContainerDocumentEntity saved = requireDocumentEntity(plan.getContainerBookingId(), documentType);
|
||||
repository.appendHistory(plan.getPlanId(), operationId, actionType,
|
||||
plan.getPlanStatus(), plan.getPlanStatus(), json(beforeSnapshot),
|
||||
json(values("requestHash", requestHash, "document", documentSnapshot(saved))),
|
||||
operatorId, trim(operatorName), trim(operationReason));
|
||||
try {
|
||||
repository.appendHistory(plan.getPlanId(), operationId, actionType,
|
||||
plan.getPlanStatus(), plan.getPlanStatus(), json(beforeSnapshot),
|
||||
json(values("requestHash", requestHash, "document", documentSnapshot(saved))),
|
||||
operatorId, trim(operatorName), trim(operationReason));
|
||||
} catch (DataIntegrityViolationException exception) {
|
||||
throw conflict("资料历史约束已变化,请刷新后重试");
|
||||
}
|
||||
return document(saved);
|
||||
}
|
||||
|
||||
@@ -414,6 +432,19 @@ public class LoadingListService {
|
||||
}
|
||||
}
|
||||
|
||||
private void compensateUploadedFile(String businessType, String businessId, long fileId, long operatorId) {
|
||||
try {
|
||||
var response = documentFiles.delete(internalToken, operatorId, 0, businessType, businessId, fileId);
|
||||
if (response == null || !response.successful()) {
|
||||
log.error("Business file compensation failed: type={}, businessId={}, fileId={}",
|
||||
businessType, businessId, fileId);
|
||||
}
|
||||
} catch (RuntimeException exception) {
|
||||
log.error("Business file compensation request failed: type={}, businessId={}, fileId={}",
|
||||
businessType, businessId, fileId, exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static void requireReplaceableDocument(ContainerDocumentEntity current, int expectedVersion) {
|
||||
if (current == null && expectedVersion != 0) throw conflict("资料版本已变化,请刷新后重试");
|
||||
if (current != null && !java.util.Objects.equals(current.getVersion(), expectedVersion)) {
|
||||
|
||||
Reference in New Issue
Block a user