优化
This commit is contained in:
+1
-1
@@ -46,7 +46,7 @@ public class DeliveryTransferController {
|
|||||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.OUTBOUND_CREATE + "')")
|
@PreAuthorize("hasAuthority('" + OverseasPermissions.OUTBOUND_CREATE + "')")
|
||||||
@Operation(summary = "List server-authoritative one-click dropship outbound candidates")
|
@Operation(summary = "List server-authoritative one-click dropship outbound candidates")
|
||||||
public ApiResponse<java.util.List<DeliveryResponses.OneClickCandidate>> oneClickCandidates(
|
public ApiResponse<java.util.List<DeliveryResponses.OneClickCandidate>> oneClickCandidates(
|
||||||
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam String customerId,
|
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId,
|
||||||
@RequestParam(required = false) String warehouseId) {
|
@RequestParam(required = false) String warehouseId) {
|
||||||
requirePlatform(user);
|
requirePlatform(user);
|
||||||
return ApiResponse.success(service.oneClickCandidates(customerId, warehouseId));
|
return ApiResponse.success(service.oneClickCandidates(customerId, warehouseId));
|
||||||
|
|||||||
@@ -665,10 +665,10 @@ paths:
|
|||||||
/api/platform/v1/last-leg/outbound-orders/one-click-dropship/candidates:
|
/api/platform/v1/last-leg/outbound-orders/one-click-dropship/candidates:
|
||||||
get:
|
get:
|
||||||
summary: 查询一件代发出库候选库存
|
summary: 查询一件代发出库候选库存
|
||||||
description: 权限 platform:overseas-warehouse:outbound:create;按客户及可选海外仓一次查询服务端权威候选,仅返回 ACTIVE 一件代发档案、OCCUPIED 正可用库存、AVAILABLE 箱唛与 SKU 余额共同覆盖且未被排车、转仓或待执行出库占用的维度。创建命令会再次校验,不信任前端候选快照。
|
description: 权限 platform:overseas-warehouse:outbound:create;仅平台身份可查询,customerId 为可选客户筛选条件,未传时跨客户查询,可按海外仓筛选。仅返回 ACTIVE 一件代发档案、OCCUPIED 正可用库存、AVAILABLE 箱唛与 SKU 余额共同覆盖且未被排车、转仓或待执行出库占用的维度。创建命令仍必须指定唯一客户并再次校验客户与仓库,不信任前端候选快照。
|
||||||
security: [{ bearerAuth: [] }]
|
security: [{ bearerAuth: [] }]
|
||||||
parameters:
|
parameters:
|
||||||
- { name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
- { name: customerId, in: query, required: false, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
||||||
- { name: warehouseId, in: query, required: false, schema: { type: string } }
|
- { name: warehouseId, in: query, required: false, schema: { type: string } }
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
|
|||||||
+1
@@ -19,6 +19,7 @@ class DropshipOutboundCandidateMapperContractTest {
|
|||||||
assertTrue(sql.contains(token), token);
|
assertTrue(sql.contains(token), token);
|
||||||
}
|
}
|
||||||
assertTrue(sql.contains("LEAST(pos.available_packages,s.package_count"));
|
assertTrue(sql.contains("LEAST(pos.available_packages,s.package_count"));
|
||||||
|
assertTrue(sql.contains("#{customerId} IS NULL OR #{customerId}='' OR p.customer_id=#{customerId}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+33
-2
@@ -36,6 +36,37 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
|
|||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
class PlatformDispatchOutboundContractTest {
|
class PlatformDispatchOutboundContractTest {
|
||||||
|
@Test
|
||||||
|
void candidateHttpQueryAcceptsWarehouseWithoutCustomerAndPreservesExplicitFilter() throws Exception {
|
||||||
|
DeliveryTransferController controller = new DeliveryTransferController();
|
||||||
|
var service = mock(com.baiyue.lastleg.delivery.service.DeliveryTransferService.class);
|
||||||
|
ReflectionTestUtils.setField(controller, "service", service);
|
||||||
|
MockMvc mvc = MockMvcBuilders.standaloneSetup(controller)
|
||||||
|
.setCustomArgumentResolvers(new AuthenticationPrincipalArgumentResolver()).build();
|
||||||
|
AuthenticatedUser platform = new AuthenticatedUser(1000001L, 0L, 0L, 1L, "platform_admin",
|
||||||
|
"PLATFORM", "WEB", Set.of(OverseasPermissions.OUTBOUND_CREATE));
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(
|
||||||
|
new UsernamePasswordAuthenticationToken(platform, null, Set.of()));
|
||||||
|
String path = "/api/platform/v1/last-leg/outbound-orders/one-click-dropship/candidates";
|
||||||
|
try {
|
||||||
|
mvc.perform(get(path).param("warehouseId", "WH-1")).andExpect(status().isOk());
|
||||||
|
org.mockito.Mockito.verify(service).oneClickCandidates(null, "WH-1");
|
||||||
|
mvc.perform(get(path).param("customerId", "101").param("warehouseId", "WH-1"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
org.mockito.Mockito.verify(service).oneClickCandidates("101", "WH-1");
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
mvc.perform(get(path).param("warehouseId", "WH-1")).andExpect(status().isUnauthorized());
|
||||||
|
AuthenticatedUser merchant = new AuthenticatedUser(7L, 100L, 100L, 8L, "merchant",
|
||||||
|
"MERCHANT", "WEB", Set.of(OverseasPermissions.OUTBOUND_CREATE));
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(
|
||||||
|
new UsernamePasswordAuthenticationToken(merchant, null, Set.of()));
|
||||||
|
mvc.perform(get(path).param("warehouseId", "WH-1")).andExpect(status().isForbidden());
|
||||||
|
org.mockito.Mockito.verifyNoMoreInteractions(service);
|
||||||
|
} finally {
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void outboundDetailAcceptsTheDocumentUrlWithoutPagingParameters() throws Exception {
|
void outboundDetailAcceptsTheDocumentUrlWithoutPagingParameters() throws Exception {
|
||||||
DeliveryTransferController controller = new DeliveryTransferController();
|
DeliveryTransferController controller = new DeliveryTransferController();
|
||||||
@@ -87,7 +118,7 @@ class PlatformDispatchOutboundContractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void oneClickRequiresCustomerWhileOutboundListKeepsOptionalFilter() throws Exception {
|
void oneClickCreationRequiresCustomerWhileCandidateAndListFiltersAreOptional() throws Exception {
|
||||||
Method create = DeliveryTransferController.class.getMethod("createOneClick", AuthenticatedUser.class,
|
Method create = DeliveryTransferController.class.getMethod("createOneClick", AuthenticatedUser.class,
|
||||||
String.class, DeliveryRequests.OneClickOutbound.class);
|
String.class, DeliveryRequests.OneClickOutbound.class);
|
||||||
Method candidates = DeliveryTransferController.class.getMethod("oneClickCandidates", AuthenticatedUser.class,
|
Method candidates = DeliveryTransferController.class.getMethod("oneClickCandidates", AuthenticatedUser.class,
|
||||||
@@ -102,7 +133,7 @@ class PlatformDispatchOutboundContractTest {
|
|||||||
RequestParam pageCustomer = page.getParameters()[1].getAnnotation(RequestParam.class);
|
RequestParam pageCustomer = page.getParameters()[1].getAnnotation(RequestParam.class);
|
||||||
assertNotNull(createCustomer);
|
assertNotNull(createCustomer);
|
||||||
assertTrue(createCustomer.required());
|
assertTrue(createCustomer.required());
|
||||||
assertTrue(candidates.getParameters()[1].getAnnotation(RequestParam.class).required());
|
assertFalse(candidates.getParameters()[1].getAnnotation(RequestParam.class).required());
|
||||||
assertFalse(candidates.getParameters()[2].getAnnotation(RequestParam.class).required());
|
assertFalse(candidates.getParameters()[2].getAnnotation(RequestParam.class).required());
|
||||||
assertNotNull(pageCustomer);
|
assertNotNull(pageCustomer);
|
||||||
assertFalse(pageCustomer.required());
|
assertFalse(pageCustomer.required());
|
||||||
|
|||||||
+14
@@ -557,6 +557,20 @@ class DeliveryTransferServiceTest {
|
|||||||
verify(inventoryPositions, never()).selectById(any());
|
verify(inventoryPositions, never()).selectById(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void oneClickCandidatesAllowPlatformWarehouseQueryWithoutCustomer() {
|
||||||
|
DropshipOutboundCandidate first = dropshipCandidate(901L, 1001L, "WH-1", "DS-A001", "SKU-1", 1L);
|
||||||
|
DropshipOutboundCandidate second = dropshipCandidate(902L, 1002L, "WH-1", "DS-A002", "SKU-1", 3L);
|
||||||
|
when(dropshipProfiles.listOutboundCandidates(null, "WH-1")).thenReturn(List.of(first, second));
|
||||||
|
|
||||||
|
var result = service.oneClickCandidates(null, " WH-1 ");
|
||||||
|
|
||||||
|
assertEquals(2, result.size());
|
||||||
|
assertEquals("DS-A001", result.get(0).palletNo());
|
||||||
|
assertEquals("DS-A002", result.get(1).palletNo());
|
||||||
|
verify(dropshipProfiles).listOutboundCandidates(null, "WH-1");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void oneClickCreationRejectsOrdinaryInventoryBeforeAnyWrite() {
|
void oneClickCreationRejectsOrdinaryInventoryBeforeAnyWrite() {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user