fix(firstleg): allow optional ocean booking customer
This commit is contained in:
+5
-10
@@ -34,6 +34,7 @@ import com.baiyue.firstleg.oceanbooking.entity.OceanBookingOperationEntity;
|
||||
@Service
|
||||
public class OceanBookingDocumentService {
|
||||
public static final String BUSINESS_TYPE = "OCEAN_BOOKING_DOCUMENT";
|
||||
private static final long FILE_TENANT_ID = 0L;
|
||||
private static final Set<String> DOCUMENT_TYPES = Set.of("BOOKING_CONFIRMATION", "BILL_OF_LADING");
|
||||
|
||||
@Resource private OceanBookingRepository repository;
|
||||
@@ -54,7 +55,7 @@ public class OceanBookingDocumentService {
|
||||
OceanBookingEntity booking = lockDraft(oceanBookingId, expectedVersion);
|
||||
OceanBookingFileClient.Metadata metadata;
|
||||
try {
|
||||
var response = files.upload(internalToken, operatorId, booking.getCustomerId(), BUSINESS_TYPE,
|
||||
var response = files.upload(internalToken, operatorId, FILE_TENANT_ID, BUSINESS_TYPE,
|
||||
Long.toString(oceanBookingId), file);
|
||||
if (response == null || !response.successful() || response.data() == null) {
|
||||
throw bad("订舱文件上传失败");
|
||||
@@ -115,7 +116,7 @@ public class OceanBookingDocumentService {
|
||||
}
|
||||
metadata(booking, document.getFileId());
|
||||
try {
|
||||
ResponseEntity<byte[]> response = files.download(internalToken, booking.getCustomerId(), BUSINESS_TYPE,
|
||||
ResponseEntity<byte[]> response = files.download(internalToken, FILE_TENANT_ID, BUSINESS_TYPE,
|
||||
Long.toString(oceanBookingId), document.getFileId());
|
||||
byte[] content = response.getBody();
|
||||
if (!response.getStatusCode().is2xxSuccessful() || content == null || content.length == 0) {
|
||||
@@ -132,9 +133,6 @@ public class OceanBookingDocumentService {
|
||||
}
|
||||
|
||||
public void requireActiveValidDocument(OceanBookingEntity booking) {
|
||||
if (booking.getCustomerId() == null || booking.getCustomerId() <= 0) {
|
||||
throw conflict("订舱缺少客户归属,无法校验文件");
|
||||
}
|
||||
boolean valid = false;
|
||||
for (OceanBookingDocumentEntity document : repository.activeDocuments(booking.getId())) {
|
||||
if (!DOCUMENT_TYPES.contains(document.getDocumentType())) continue;
|
||||
@@ -178,9 +176,6 @@ public class OceanBookingDocumentService {
|
||||
if (booking == null) throw new BizException(ResultCode.NOT_FOUND, "订舱单不存在");
|
||||
if (!Integer.valueOf(expectedVersion).equals(booking.getVersion())) throw concurrent();
|
||||
if (!"DRAFT".equals(booking.getStatus())) throw conflict("已放舱订舱文件永久只读");
|
||||
if (booking.getCustomerId() == null || booking.getCustomerId() <= 0) {
|
||||
throw bad("请先保存订舱客户后再上传文件");
|
||||
}
|
||||
return booking;
|
||||
}
|
||||
|
||||
@@ -192,7 +187,7 @@ public class OceanBookingDocumentService {
|
||||
|
||||
private OceanBookingFileClient.Metadata metadata(OceanBookingEntity booking, long fileId) {
|
||||
try {
|
||||
var response = files.metadata(internalToken, booking.getCustomerId(), BUSINESS_TYPE,
|
||||
var response = files.metadata(internalToken, FILE_TENANT_ID, BUSINESS_TYPE,
|
||||
Long.toString(booking.getId()), fileId);
|
||||
if (response == null || !response.successful() || response.data() == null) {
|
||||
throw new BizException(ResultCode.NOT_FOUND, "订舱文件不存在或归属不匹配");
|
||||
@@ -207,7 +202,7 @@ public class OceanBookingDocumentService {
|
||||
}
|
||||
|
||||
private static void validateMetadata(OceanBookingEntity booking, OceanBookingFileClient.Metadata metadata) {
|
||||
if (metadata.fileId() == null || !Objects.equals(metadata.tenantId(), booking.getCustomerId())
|
||||
if (metadata.fileId() == null || !Objects.equals(metadata.tenantId(), FILE_TENANT_ID)
|
||||
|| !BUSINESS_TYPE.equals(metadata.businessType())
|
||||
|| !Long.toString(booking.getId()).equals(metadata.businessId())) {
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED, "订舱文件归属不匹配");
|
||||
|
||||
+17
-6
@@ -50,6 +50,7 @@ public class OceanBookingService {
|
||||
@Resource private WarehousePartnerClient partners;
|
||||
@Resource private FirstlegDocumentNumberGenerator documentNumbers;
|
||||
@Resource private OceanBookingDocumentService documents;
|
||||
@Resource private com.baiyue.firstleg.service.IamCustomerSnapshotService customers;
|
||||
@Value("${baiyue.security.internal-service-token:}") private String internalToken;
|
||||
@Value("${baiyue.warehouse.public-tenant-id:0}") private long publicWarehouseTenantId;
|
||||
|
||||
@@ -200,7 +201,7 @@ public class OceanBookingService {
|
||||
private void validateDraftStructure(DraftData data) {
|
||||
boolean hasCustomerId = data.customerId() != null;
|
||||
boolean hasCustomerName = StringUtils.hasText(data.customerName());
|
||||
if (hasCustomerId != hasCustomerName) throw badRequest("客户ID和客户名称必须同时填写或同时为空");
|
||||
if (!hasCustomerId && hasCustomerName) throw badRequest("客户名称不能脱离客户ID提交");
|
||||
if (data.parties() != null) {
|
||||
Set<String> types = new HashSet<>();
|
||||
for (PartyRequest party : data.parties()) {
|
||||
@@ -221,8 +222,7 @@ public class OceanBookingService {
|
||||
private static void validateRange(LocalDateTime from, LocalDateTime to) { if (from != null && to != null && to.isBefore(from)) throw badRequest("预计到港时间不能早于预计开船时间"); }
|
||||
private static void validateRelease(OceanBookingEntity booking, List<OceanBookingPartyEntity> parties,
|
||||
List<OceanBookingContainerRequirementEntity> requirements) {
|
||||
if (booking.getCustomerId() == null || !StringUtils.hasText(booking.getCustomerName())
|
||||
|| !StringUtils.hasText(booking.getChannelCode()) || booking.getWarehouseId() == null
|
||||
if (!StringUtils.hasText(booking.getChannelCode()) || booking.getWarehouseId() == null
|
||||
|| !StringUtils.hasText(booking.getBillOfLadingNo()) || !StringUtils.hasText(booking.getVesselName())
|
||||
|| !StringUtils.hasText(booking.getVoyageNo()) || !StringUtils.hasText(booking.getServiceTerm())
|
||||
|| !StringUtils.hasText(booking.getFreightTerm()) || booking.getEstimatedSailingAt() == null
|
||||
@@ -258,8 +258,9 @@ public class OceanBookingService {
|
||||
}
|
||||
|
||||
private record ResolvedDraft(String warehouseName, String channelName, String shippingCompanyName,
|
||||
String carrierCode, String bookingAgentName) {}
|
||||
String carrierCode, String bookingAgentName, String customerName) {}
|
||||
private ResolvedDraft resolveDraft(DraftData d) {
|
||||
String customerName = resolveCustomer(d.customerId(), d.customerName());
|
||||
String warehouseName = null; String channelName = null;
|
||||
if (d.warehouseId() != null && StringUtils.hasText(d.channelCode())) {
|
||||
WarehouseMasterDataClient.Warehouse warehouse = requireDomesticTransitWarehouse(d.warehouseId());
|
||||
@@ -269,10 +270,10 @@ public class OceanBookingService {
|
||||
var carrier = resolveCarrier(d.shippingCompanyId(), d.shippingCompanyName(), d.carrierCode());
|
||||
var agent = resolveBookingAgent(d.bookingAgentId(), d.bookingAgentName(), carrier == null ? null : carrier.carrierCode());
|
||||
return new ResolvedDraft(warehouseName, channelName, carrier == null ? null : carrier.partnerName(),
|
||||
carrier == null ? null : carrier.carrierCode(), agent == null ? null : agent.name());
|
||||
carrier == null ? null : carrier.carrierCode(), agent == null ? null : agent.name(), customerName);
|
||||
}
|
||||
private static void copy(OceanBookingEntity v, DraftData d, ResolvedDraft resolved) {
|
||||
v.setCustomerId(d.customerId()); v.setCustomerName(trim(d.customerName()));
|
||||
v.setCustomerId(d.customerId()); v.setCustomerName(resolved.customerName());
|
||||
v.setChannelCode(trim(d.channelCode())); v.setChannelName(resolved.channelName());
|
||||
v.setWarehouseId(d.warehouseId()); v.setWarehouseName(resolved.warehouseName());
|
||||
v.setBillOfLadingNo(trim(d.billOfLadingNo()));
|
||||
@@ -288,10 +289,20 @@ public class OceanBookingService {
|
||||
}
|
||||
|
||||
private void validateMasterData(OceanBookingEntity booking) {
|
||||
resolveCustomer(booking.getCustomerId(), booking.getCustomerName());
|
||||
resolveCarrier(booking.getShippingCompanyId(), booking.getShippingCompanyName(), booking.getCarrierCode());
|
||||
resolveBookingAgent(booking.getBookingAgentId(), booking.getBookingAgentName(), booking.getCarrierCode());
|
||||
}
|
||||
|
||||
private String resolveCustomer(Long id, String name) {
|
||||
if (id == null) {
|
||||
if (StringUtils.hasText(name)) throw badRequest("客户名称不能脱离客户ID提交");
|
||||
return null;
|
||||
}
|
||||
if (id <= 0) throw badRequest("请选择有效客户");
|
||||
return customers.active(id, name).tenantName();
|
||||
}
|
||||
|
||||
private WarehousePartnerClient.Snapshot resolveCarrier(Long id, String suppliedName, String suppliedCode) {
|
||||
if (id == null) {
|
||||
if (StringUtils.hasText(suppliedName) || StringUtils.hasText(suppliedCode)) throw badRequest("船公司名称和编码不能脱离shippingCompanyId提交");
|
||||
|
||||
Reference in New Issue
Block a user