优化
This commit is contained in:
+1
-1
@@ -84,7 +84,7 @@ class PlatformSmartLoadingControllerContractTest {
|
||||
.contains("成功响应中的 version 是递增后的 planVersion")
|
||||
.contains("items[].version 是递增后的 itemVersion")
|
||||
.contains("数量调整或动态增量不会覆盖已有协作备注")
|
||||
.contains("柜内总容积和总重量分别允许达到柜型额定值的150%")
|
||||
.contains("柜内总容积和总重量分别允许达到柜型基准值的150%")
|
||||
.contains("人工分配不限制订单国内仓及渠道与柜次一致")
|
||||
.contains("智能推荐允许跨国内仓,但仍只选择柜次渠道")
|
||||
.contains("canAssign: {type: boolean}")
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
package com.baiyue.firstleg.domain;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class ContainerSpecificationCatalogTest {
|
||||
@Test
|
||||
void exposesCanonicalSpecificationsAndRejectsAliases() {
|
||||
var specification = ContainerSpecificationCatalog.requireMatch(
|
||||
"40HC", new BigDecimal("76.000"), new BigDecimal("28000.000"));
|
||||
|
||||
assertThat(specification.containerType()).isEqualTo("40HC");
|
||||
assertThatThrownBy(() -> ContainerSpecificationCatalog.require("40HQ"))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("固定规格");
|
||||
assertThatThrownBy(() -> ContainerSpecificationCatalog.requireMatch(
|
||||
"40HC", new BigDecimal("68"), new BigDecimal("28000")))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("容量和限重");
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -23,8 +23,8 @@ class OceanBookingSqlContractTest {
|
||||
.contains("customer_name VARCHAR(128) NULL COMMENT '可选客户名称快照'")
|
||||
.contains("MODIFY COLUMN customer_id BIGINT UNSIGNED NULL COMMENT '可选客户ID快照'")
|
||||
.contains("MODIFY COLUMN customer_name VARCHAR(128) NULL COMMENT '可选客户名称快照'")
|
||||
.contains("service_term VARCHAR(32) NULL COMMENT '运输服务条款快照;发布前必填'")
|
||||
.contains("freight_term VARCHAR(32) NULL COMMENT '海运费支付条款快照;发布前必填'")
|
||||
.doesNotContain("service_term")
|
||||
.doesNotContain("freight_term")
|
||||
.contains("carrier_code VARCHAR(16) NULL COMMENT '船司标准编码")
|
||||
.contains("carrier_code IS NULL OR carrier_code IN ('MATSON','SML','ZIM','COSCO','EMC','HEDE','OTHER')")
|
||||
.contains("container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '明确引用现有柜次ID'")
|
||||
|
||||
+2
-5
@@ -67,8 +67,6 @@ class OceanBookingPrintServiceTest {
|
||||
Detail detail = detail("DRAFT");
|
||||
detail.oceanBooking().setBillOfLadingNo(null);
|
||||
detail.oceanBooking().setPlaceOfDelivery(null);
|
||||
detail.oceanBooking().setServiceTerm(null);
|
||||
detail.oceanBooking().setFreightTerm(null);
|
||||
detail = new Detail(detail.oceanBooking(), List.of(detail.parties().get(0)),
|
||||
detail.containerRequirements(), List.of(), List.of(), List.of());
|
||||
when(bookings.detail(10L)).thenReturn(detail);
|
||||
@@ -102,8 +100,7 @@ class OceanBookingPrintServiceTest {
|
||||
booking.setId(10L); booking.setBookingNo("OB-1"); booking.setStatus(status);
|
||||
booking.setBillOfLadingNo("BL-1"); booking.setVesselName("Vessel"); booking.setVoyageNo("V001");
|
||||
booking.setDeparturePortName("Ningbo"); booking.setDestinationPortName("LA");
|
||||
booking.setPlaceOfDelivery("LA DC"); booking.setServiceTerm("CY-CY");
|
||||
booking.setFreightTerm("PREPAID"); booking.setBookingAgentName("Agent");
|
||||
booking.setPlaceOfDelivery("LA DC"); booking.setBookingAgentName("Agent");
|
||||
booking.setEstimatedSailingAt(LocalDateTime.of(2026, 9, 1, 0, 0));
|
||||
OceanBookingPartyEntity shipper = new OceanBookingPartyEntity();
|
||||
shipper.setPartyType("SHIPPER"); shipper.setPartyName("Shipper"); shipper.setAddress("Address");
|
||||
@@ -113,7 +110,7 @@ class OceanBookingPrintServiceTest {
|
||||
notify.setPartyType("NOTIFY_PARTY"); notify.setPartyName("Notify");
|
||||
OceanBookingContainerRequirementEntity requirement = new OceanBookingContainerRequirementEntity();
|
||||
requirement.setContainerType("40HQ"); requirement.setContainerKind("DRY"); requirement.setQuantity(2);
|
||||
requirement.setCapacityCbm(new BigDecimal("68")); requirement.setMaxWeightKg(new BigDecimal("28000"));
|
||||
requirement.setCapacityCbm(new BigDecimal("68")); requirement.setMaxWeightKg(new BigDecimal("19500"));
|
||||
return new Detail(booking, List.of(shipper, consignee, notify), List.of(requirement), List.of(), List.of(), List.of());
|
||||
}
|
||||
}
|
||||
|
||||
+13
-14
@@ -160,7 +160,7 @@ class OceanBookingServiceTest {
|
||||
ArgumentCaptor<List<OceanBookingContainerRequirementEntity>> captor = ArgumentCaptor.forClass(List.class);
|
||||
verify(repository).replaceRequirements(eq(inserted.get().getId()), captor.capture());
|
||||
assertThat(captor.getValue()).singleElement().satisfies(value -> {
|
||||
assertThat(value.getContainerType()).isEqualTo("40HC");
|
||||
assertThat(value.getContainerType()).isEqualTo("40HQ");
|
||||
assertThat(value.getQuantity()).isEqualTo(2);
|
||||
});
|
||||
verify(repository, never()).insertContainer(any());
|
||||
@@ -326,13 +326,13 @@ class OceanBookingServiceTest {
|
||||
|
||||
@Test
|
||||
void linkCandidatesDefaultsPaginationAndDelegatesOneNormalizedSetQuery() {
|
||||
LinkCandidate candidate = new LinkCandidate(101L, "OB-260818-0001", 201L, "40HC",
|
||||
new BigDecimal("76"), new BigDecimal("28000"), 3, 1, 2,
|
||||
LinkCandidate candidate = new LinkCandidate(101L, "OB-260818-0001", 201L, "40HQ",
|
||||
new BigDecimal("68"), new BigDecimal("19500"), 3, 1, 2,
|
||||
"客户A", "深圳中转仓", "美西海运");
|
||||
when(repository.linkCandidates(any(), anySet())).thenReturn(new PageResult<>(List.of(candidate), 1, 20, 1, 1));
|
||||
|
||||
PageResult<LinkCandidate> result = service.linkCandidates(new LinkCandidateQuery(701L,
|
||||
" MATSON_CLX ", " 40HC ", null, null));
|
||||
" MATSON_CLX ", " 40HQ ", null, null));
|
||||
|
||||
assertThat(result.records()).containsExactly(candidate);
|
||||
assertThat(result.records().get(0).remainingQuantity()).isEqualTo(2);
|
||||
@@ -340,7 +340,7 @@ class OceanBookingServiceTest {
|
||||
@SuppressWarnings("unchecked") ArgumentCaptor<java.util.Set<String>> channels = ArgumentCaptor.forClass(java.util.Set.class);
|
||||
verify(repository).linkCandidates(query.capture(), channels.capture());
|
||||
assertThat(query.getValue().channelGroupCode()).isEqualTo("MATSON_CLX");
|
||||
assertThat(query.getValue().containerType()).isEqualTo("40HC");
|
||||
assertThat(query.getValue().containerType()).isEqualTo("40HQ");
|
||||
assertThat(query.getValue().page()).isEqualTo(1L);
|
||||
assertThat(query.getValue().size()).isEqualTo(20L);
|
||||
assertThat(channels.getValue()).contains("MATSON_CLX_TRUCK", "MATSON_CLX_PARCEL", "ZBYHK");
|
||||
@@ -354,7 +354,7 @@ class OceanBookingServiceTest {
|
||||
when(repository.linkCandidates(any(), anySet())).thenReturn(new PageResult<>(List.of(), 1, 20, 0, 0));
|
||||
|
||||
PageResult<LinkCandidate> result = service.linkCandidates(
|
||||
new LinkCandidateQuery(701L, "MATSON_CLX", "45HC", null, null));
|
||||
new LinkCandidateQuery(701L, "MATSON_CLX", "45HQ", null, null));
|
||||
|
||||
assertThat(result.records()).isEmpty();
|
||||
assertThat(result.total()).isZero();
|
||||
@@ -402,19 +402,19 @@ class OceanBookingServiceTest {
|
||||
|
||||
private static DraftData partialDraft(String remark) {
|
||||
return new DraftData(null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, remark, null, null);
|
||||
null, null, null, null, null, null, null, null, null, remark, null, null);
|
||||
}
|
||||
|
||||
private static DraftData completeDraft() {
|
||||
return new DraftData(100L, "客户", "SEA-US", 701L, "BL-001", 71L, "船公司", "MATSON",
|
||||
81L, null, "VESSEL", "V001", "CNSZX", "深圳", "USLAX", "洛杉矶",
|
||||
"LAX", "CY-CY", "PREPAID", LocalDateTime.of(2026, 9, 1, 0, 0),
|
||||
"LAX", LocalDateTime.of(2026, 9, 1, 0, 0),
|
||||
LocalDateTime.of(2026, 9, 20, 0, 0), null,
|
||||
List.of(new PartyRequest("SHIPPER", "发货人", null, null, null),
|
||||
new PartyRequest("CONSIGNEE", "收货人", null, null, null),
|
||||
new PartyRequest("NOTIFY_PARTY", "通知人", null, null, null)),
|
||||
List.of(new ContainerRequirementRequest("40HC", "DRY", 2,
|
||||
new BigDecimal("76"), new BigDecimal("28000"))));
|
||||
List.of(new ContainerRequirementRequest("40HQ", "DRY", 2,
|
||||
new BigDecimal("68"), new BigDecimal("19500"))));
|
||||
}
|
||||
|
||||
private static OceanBookingEntity completeBooking(String status, int version) {
|
||||
@@ -426,7 +426,6 @@ class OceanBookingServiceTest {
|
||||
value.setDeparturePortCode("CNSZX"); value.setDeparturePortName("深圳");
|
||||
value.setDestinationPortCode("USLAX"); value.setDestinationPortName("洛杉矶");
|
||||
value.setPlaceOfDelivery("LAX");
|
||||
value.setServiceTerm("CY-CY"); value.setFreightTerm("PREPAID");
|
||||
value.setEstimatedSailingAt(LocalDateTime.of(2026, 9, 1, 0, 0));
|
||||
value.setEstimatedArrivalAt(LocalDateTime.of(2026, 9, 20, 0, 0));
|
||||
return value;
|
||||
@@ -447,9 +446,9 @@ class OceanBookingServiceTest {
|
||||
|
||||
private static OceanBookingContainerRequirementEntity requirement() {
|
||||
var value = new OceanBookingContainerRequirementEntity();
|
||||
value.setId(11L); value.setContainerType("40HC"); value.setContainerKind("DRY");
|
||||
value.setQuantity(1); value.setCapacityCbm(new BigDecimal("76"));
|
||||
value.setMaxWeightKg(new BigDecimal("28000")); return value;
|
||||
value.setId(11L); value.setContainerType("40HQ"); value.setContainerKind("DRY");
|
||||
value.setQuantity(1); value.setCapacityCbm(new BigDecimal("68"));
|
||||
value.setMaxWeightKg(new BigDecimal("19500")); return value;
|
||||
}
|
||||
|
||||
private String hash(String action, Long id, Object request) throws Exception {
|
||||
|
||||
@@ -85,7 +85,7 @@ class ContainerServiceTest {
|
||||
assertThat(saved.getChannelName()).isNull();
|
||||
assertThat(saved.getWarehouseId()).isEqualTo(101L);
|
||||
assertThat(saved.getWarehouseName()).isEqualTo("上海中转仓");
|
||||
assertThat(saved.getCapacityCbm()).isEqualByComparingTo("76.0000");
|
||||
assertThat(saved.getCapacityCbm()).isEqualByComparingTo("68.0000");
|
||||
assertThat(saved.getPlanId()).isEqualTo(501L);
|
||||
assertThat(saved.getPlanNo()).isEqualTo("LP-260818-0001");
|
||||
assertThat(saved.getPlanStatus()).isEqualTo("EDITING");
|
||||
@@ -96,11 +96,11 @@ class ContainerServiceTest {
|
||||
@DisplayName("新增模拟柜拒绝柜型与固定规格不匹配")
|
||||
void rejectsSimulationWithNonCanonicalSpecification() {
|
||||
SimulationCreateRequest invalid = new SimulationCreateRequest(
|
||||
"MATSON_CLX", 101L, "40HC", new BigDecimal("100"), new BigDecimal("28000"));
|
||||
"MATSON_CLX", 101L, "40HQ", new BigDecimal("100"), new BigDecimal("19500"));
|
||||
|
||||
assertThatThrownBy(() -> service.createSimulation(9L, "admin", invalid))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("容量和限重");
|
||||
.hasMessageContaining("容量和货重上限");
|
||||
verify(repository, never()).insert(any());
|
||||
}
|
||||
|
||||
@@ -204,12 +204,12 @@ class ContainerServiceTest {
|
||||
container.setPlanId(501L);
|
||||
container.setPlanNo("LP-260818-0001");
|
||||
container.setContainerNo(null);
|
||||
container.setWarehouseId(101L); container.setChannelGroupCode("EXX"); container.setChannelCode(null); container.setContainerType("40HC");
|
||||
container.setWarehouseId(101L); container.setChannelGroupCode("EXX"); container.setChannelCode(null); container.setContainerType("40HQ");
|
||||
container.setCapacityCbm(new BigDecimal("85.5000")); container.setMaxWeightKg(new BigDecimal("27500.000"));
|
||||
OceanBookingEntity booking = new OceanBookingEntity();
|
||||
booking.setId(21L); booking.setStatus("RELEASED"); booking.setWarehouseId(101L); booking.setChannelCode("EXX_RAIL_NY");
|
||||
OceanBookingContainerRequirementEntity requirement = new OceanBookingContainerRequirementEntity();
|
||||
requirement.setId(31L); requirement.setQuantity(1); requirement.setContainerType("40HC"); requirement.setCapacityCbm(new BigDecimal("76.0000")); requirement.setMaxWeightKg(new BigDecimal("28000.000"));
|
||||
requirement.setId(31L); requirement.setQuantity(1); requirement.setContainerType("40HQ"); requirement.setCapacityCbm(new BigDecimal("68.0000")); requirement.setMaxWeightKg(new BigDecimal("19500.000"));
|
||||
when(repository.find(11L)).thenReturn(container, container);
|
||||
when(oceanBookings.find(21L)).thenReturn(booking);
|
||||
when(oceanBookings.requirement(21L, 31L)).thenReturn(requirement);
|
||||
@@ -313,15 +313,15 @@ class ContainerServiceTest {
|
||||
void linksMultipleRealContainersToTheSameReleasedBookingRequirement() {
|
||||
ContainerBookingEntity first = booking("WAIT_LOADING", 2);
|
||||
first.setId(11L); first.setContainerNo(null); first.setWarehouseId(101L);
|
||||
first.setChannelGroupCode("MATSON_CLX"); first.setChannelCode(null); first.setContainerType("40HC");
|
||||
first.setChannelGroupCode("MATSON_CLX"); first.setChannelCode(null); first.setContainerType("40HQ");
|
||||
ContainerBookingEntity second = booking("WAIT_LOADING", 4);
|
||||
second.setId(12L); second.setContainerNo(null); second.setWarehouseId(101L);
|
||||
second.setChannelGroupCode("MATSON_CLX"); second.setChannelCode(null); second.setContainerType("40HC");
|
||||
second.setChannelGroupCode("MATSON_CLX"); second.setChannelCode(null); second.setContainerType("40HQ");
|
||||
OceanBookingEntity oceanBooking = new OceanBookingEntity();
|
||||
oceanBooking.setId(21L); oceanBooking.setStatus("RELEASED");
|
||||
oceanBooking.setWarehouseId(101L); oceanBooking.setChannelCode("MATSON_CLX_TRUCK");
|
||||
OceanBookingContainerRequirementEntity requirement = new OceanBookingContainerRequirementEntity();
|
||||
requirement.setId(31L); requirement.setQuantity(2); requirement.setContainerType("40HC");
|
||||
requirement.setId(31L); requirement.setQuantity(2); requirement.setContainerType("40HQ");
|
||||
when(repository.find(11L)).thenReturn(first);
|
||||
when(repository.find(12L)).thenReturn(second);
|
||||
when(oceanBookings.find(21L)).thenReturn(oceanBooking);
|
||||
@@ -362,19 +362,19 @@ class ContainerServiceTest {
|
||||
@Test
|
||||
@DisplayName("首次关联拒绝装柜仓库不一致")
|
||||
void rejectsLinkWhenWarehouseDiffers() {
|
||||
assertThreeFieldMismatch(102L, "MATSON_CLX_TRUCK", "40HC");
|
||||
assertThreeFieldMismatch(102L, "MATSON_CLX_TRUCK", "40HQ");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("首次关联拒绝物流渠道不一致")
|
||||
void rejectsLinkWhenChannelDiffers() {
|
||||
assertThreeFieldMismatch(101L, "HEDE_TRUCK", "40HC");
|
||||
assertThreeFieldMismatch(101L, "HEDE_TRUCK", "40HQ");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("首次关联拒绝柜型不一致")
|
||||
void rejectsLinkWhenContainerTypeDiffers() {
|
||||
assertThreeFieldMismatch(101L, "MATSON_CLX_TRUCK", "45HC");
|
||||
assertThreeFieldMismatch(101L, "MATSON_CLX_TRUCK", "45HQ");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -418,7 +418,7 @@ class ContainerServiceTest {
|
||||
ContainerBookingEntity container = booking("WAIT_LOADING", 2);
|
||||
container.setContainerNo(null);
|
||||
container.setWarehouseId(101L); container.setChannelGroupCode("MATSON_CLX"); container.setChannelCode(null);
|
||||
container.setContainerType("40HC");
|
||||
container.setContainerType("40HQ");
|
||||
OceanBookingEntity oceanBooking = new OceanBookingEntity();
|
||||
oceanBooking.setId(21L); oceanBooking.setStatus("RELEASED");
|
||||
oceanBooking.setWarehouseId(bookingWarehouseId); oceanBooking.setChannelCode(bookingChannel);
|
||||
@@ -440,12 +440,12 @@ class ContainerServiceTest {
|
||||
ContainerBookingEntity container = booking("WAIT_LOADING", 2);
|
||||
container.setContainerNo(null);
|
||||
container.setWarehouseId(101L); container.setChannelGroupCode("MATSON_CLX"); container.setChannelCode(null);
|
||||
container.setContainerType("40HC");
|
||||
container.setContainerType("40HQ");
|
||||
OceanBookingEntity oceanBooking = new OceanBookingEntity();
|
||||
oceanBooking.setId(21L); oceanBooking.setStatus("RELEASED");
|
||||
oceanBooking.setWarehouseId(101L); oceanBooking.setChannelCode("MATSON_CLX_TRUCK");
|
||||
OceanBookingContainerRequirementEntity requirement = new OceanBookingContainerRequirementEntity();
|
||||
requirement.setId(31L); requirement.setQuantity(2); requirement.setContainerType("40HC");
|
||||
requirement.setId(31L); requirement.setQuantity(2); requirement.setContainerType("40HQ");
|
||||
when(repository.find(11L)).thenReturn(container);
|
||||
when(oceanBookings.find(21L)).thenReturn(oceanBooking);
|
||||
when(oceanBookings.requirement(21L, 31L)).thenReturn(requirement);
|
||||
@@ -485,15 +485,15 @@ class ContainerServiceTest {
|
||||
|
||||
private static SaveRequest request() {
|
||||
return new SaveRequest(101L, "上海仓", "BOL-001", "柏悦轮",
|
||||
"V001", "40HC", 201L, "船司A", "CNSHA", "上海港", "USLAX", "洛杉矶港",
|
||||
"ONT8", "ONT8", new BigDecimal("76.0000"), new BigDecimal("28000.000"), 202L, "拖车公司A",
|
||||
"V001", "40HQ", 201L, "船司A", "CNSHA", "上海港", "USLAX", "洛杉矶港",
|
||||
"ONT8", "ONT8", new BigDecimal("68.0000"), new BigDecimal("19500.000"), 202L, "拖车公司A",
|
||||
LocalDateTime.of(2026, 8, 10, 8, 0), LocalDateTime.of(2026, 8, 12, 8, 0), null,
|
||||
LocalDateTime.of(2026, 8, 25, 8, 0), null,
|
||||
LocalDateTime.of(2026, 8, 27, 8, 0), null);
|
||||
}
|
||||
|
||||
private static SimulationCreateRequest simulation() {
|
||||
return new SimulationCreateRequest("MATSON_CLX", 101L, "40HC", new BigDecimal("76.0000"), new BigDecimal("28000.000"));
|
||||
return new SimulationCreateRequest("MATSON_CLX", 101L, "40HQ", new BigDecimal("68.0000"), new BigDecimal("19500.000"));
|
||||
}
|
||||
|
||||
private static ChannelRow channel() {
|
||||
|
||||
@@ -552,8 +552,8 @@ class SmartLoadingServiceTest {
|
||||
@Test
|
||||
void pagesWorkbenchContainersWithTheSameGlobalFilters() {
|
||||
WorkbenchContainer container = new WorkbenchContainer(99L, "CB-1", "CAB-1", null,
|
||||
100L, "义乌仓", "MATSON_CLX", null, null, "40HC",
|
||||
new BigDecimal("68"), new BigDecimal("28000"),
|
||||
100L, "义乌仓", "MATSON_CLX", null, null, "40HQ",
|
||||
new BigDecimal("68"), new BigDecimal("19500"),
|
||||
1L, "LP-1", "EDITING", 2);
|
||||
WorkbenchContainerQuery query = new WorkbenchContainerQuery(List.of("MATSON_CLX"), 100L,
|
||||
9L, "IN-10", LocalDate.parse("2026-09-01"), LocalDate.parse("2026-09-30"),
|
||||
|
||||
Reference in New Issue
Block a user