fix: add ocean booking link candidates query
This commit is contained in:
+17
-1
@@ -20,6 +20,7 @@ class PlatformOceanBookingControllerContractTest {
|
||||
.containsExactly("/api/platform/v1/ocean-bookings");
|
||||
Map<String, String> permissions = Map.ofEntries(
|
||||
Map.entry("page", "platform:firstleg:ocean-booking:list"),
|
||||
Map.entry("linkCandidates", "platform:firstleg:ocean-booking:list"),
|
||||
Map.entry("channels", "platform:firstleg:ocean-booking:list"),
|
||||
Map.entry("detail", "platform:firstleg:ocean-booking:list"),
|
||||
Map.entry("create", "platform:firstleg:ocean-booking:create"),
|
||||
@@ -30,7 +31,8 @@ class PlatformOceanBookingControllerContractTest {
|
||||
Method method = method(name);
|
||||
assertThat(method.getAnnotation(PreAuthorize.class).value())
|
||||
.isEqualTo("hasAuthority('" + permission + "')");
|
||||
if (!name.equals("page") && !name.equals("detail") && !name.equals("channels")) {
|
||||
if (!name.equals("page") && !name.equals("detail") && !name.equals("channels")
|
||||
&& !name.equals("linkCandidates")) {
|
||||
assertThat(method.getAnnotation(BusinessAudit.class)).isNotNull();
|
||||
}
|
||||
});
|
||||
@@ -57,6 +59,20 @@ class PlatformOceanBookingControllerContractTest {
|
||||
.doesNotContain("change-request", "change-confirm", "/cancel:", "containers[].containerNo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void linkCandidatesUsesDedicatedGetPathAndStablePageContract() throws Exception {
|
||||
Method method = method("linkCandidates");
|
||||
assertThat(method.getAnnotation(org.springframework.web.bind.annotation.GetMapping.class).value())
|
||||
.containsExactly("/link-candidates");
|
||||
String yaml = Files.readString(Path.of("src/main/resources/openapi/ocean-bookings-v1.yaml"));
|
||||
assertThat(yaml)
|
||||
.contains("/api/platform/v1/ocean-bookings/link-candidates:")
|
||||
.contains("x-permission: platform:firstleg:ocean-booking:list")
|
||||
.contains("warehouseId", "channelCode", "containerType", "capacityCbm", "maxWeightKg")
|
||||
.contains("LinkCandidateResponse", "requiredQuantity", "allocatedQuantity", "remainingQuantity")
|
||||
.contains("booking detail calls are not used");
|
||||
}
|
||||
|
||||
private static Method method(String name) {
|
||||
return Arrays.stream(PlatformOceanBookingController.class.getDeclaredMethods())
|
||||
.filter(method -> method.getName().equals(name)).findFirst().orElseThrow();
|
||||
|
||||
+20
@@ -1,6 +1,7 @@
|
||||
package com.baiyue.firstleg.oceanbooking.repository;
|
||||
|
||||
import com.baiyue.firstleg.oceanbooking.mapper.OceanBookingMapper;
|
||||
import com.baiyue.firstleg.oceanbooking.dto.OceanBookingDtos.LinkCandidateQuery;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -36,4 +37,23 @@ class OceanBookingMapperContractTest {
|
||||
.contains("status='DRAFT' AND version=#{version}")
|
||||
.doesNotContain("CONFIRMED", "CHANGE_PENDING", "CANCELLED", "SUBMITTED", "FAILED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void linkCandidatesUsesOneBoundedSetQueryAndExactRemainingSemantics() throws Exception {
|
||||
String sql = String.join("\n", OceanBookingMapper.class.getDeclaredMethod("selectLinkCandidates",
|
||||
com.baomidou.mybatisplus.extension.plugins.pagination.Page.class, LinkCandidateQuery.class)
|
||||
.getAnnotation(Select.class).value());
|
||||
assertThat(sql)
|
||||
.contains("booking.status='RELEASED'")
|
||||
.contains("booking.warehouse_id=#{query.warehouseId}")
|
||||
.contains("booking.channel_code=#{query.channelCode}")
|
||||
.contains("requirement.container_type=#{query.containerType}")
|
||||
.contains("requirement.capacity_cbm=#{query.capacityCbm}")
|
||||
.contains("requirement.max_weight_kg=#{query.maxWeightKg}")
|
||||
.contains("FROM fl_ocean_booking_container_allocation")
|
||||
.contains("GROUP BY ocean_booking_id,requirement_id")
|
||||
.contains("requirement.quantity-COALESCE(allocated.allocated_quantity,0) remaining_quantity")
|
||||
.contains("requirement.quantity>COALESCE(allocated.allocated_quantity,0)")
|
||||
.doesNotContain("fl_container_booking", "SELECT booking.*");
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -1,6 +1,7 @@
|
||||
package com.baiyue.firstleg.oceanbooking.service;
|
||||
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.baiyue.common.core.api.PageResult;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.firstleg.client.WarehouseMasterDataClient;
|
||||
import com.baiyue.firstleg.client.WarehouseSupplierClient;
|
||||
@@ -170,6 +171,29 @@ class OceanBookingServiceTest {
|
||||
verify(repository, times(2)).page(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void linkCandidatesDefaultsPaginationAndDelegatesOneNormalizedSetQuery() {
|
||||
LinkCandidate candidate = new LinkCandidate(101L, "OB-260818-0001", 201L, "40HC",
|
||||
new BigDecimal("76"), new BigDecimal("28000"), 3, 1, 2,
|
||||
"客户A", "深圳中转仓", "美西海运");
|
||||
when(repository.linkCandidates(any())).thenReturn(new PageResult<>(List.of(candidate), 1, 20, 1, 1));
|
||||
|
||||
PageResult<LinkCandidate> result = service.linkCandidates(new LinkCandidateQuery(701L,
|
||||
" SEA-US ", " 40HC ", new BigDecimal("76.0"), new BigDecimal("28000.00"), null, null));
|
||||
|
||||
assertThat(result.records()).containsExactly(candidate);
|
||||
assertThat(result.records().get(0).remainingQuantity()).isEqualTo(2);
|
||||
ArgumentCaptor<LinkCandidateQuery> query = ArgumentCaptor.forClass(LinkCandidateQuery.class);
|
||||
verify(repository).linkCandidates(query.capture());
|
||||
assertThat(query.getValue().channelCode()).isEqualTo("SEA-US");
|
||||
assertThat(query.getValue().containerType()).isEqualTo("40HC");
|
||||
assertThat(query.getValue().page()).isEqualTo(1L);
|
||||
assertThat(query.getValue().size()).isEqualTo(20L);
|
||||
verify(repository, never()).find(anyLong());
|
||||
verify(repository, never()).requirements(anyLong());
|
||||
verify(repository, never()).containers(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
void releaseRejectsInvalidScheduleWithoutTransition() {
|
||||
OceanBookingEntity draft = completeBooking("DRAFT", 3);
|
||||
|
||||
Reference in New Issue
Block a user