This commit is contained in:
2026-08-05 13:50:37 +08:00
parent 487f398eb8
commit 264458920b
7 changed files with 41 additions and 16 deletions
+1 -1
View File
@@ -34,7 +34,7 @@
## 修改与验证
- 商户只看到可用且符合租户/服务范围的数据;平台启停必须检查业务约束,不能只改状态字段。
- 平台仓库管理接口必须同时校验平台访问域和按钮权限:列表/详情使用 `platform:warehouse:list`,新增使用 `platform:warehouse:create`,编辑使用 `platform:warehouse:edit`,启停使用 `platform:warehouse:status`;OpenAPI 的 403 响应说明必须与权限码同步。
- 平台仓库是平台公共主数据:列表接口默认查询全部仓库,并可用兼容字段 `tenantId` 做可选客户范围筛选;不得要求 Admin 先选择客户才能取得仓库候选。详情和写操作现阶段仍按数据表兼容字段校验范围。接口同时校验平台访问域和按钮权限:列表/详情使用 `platform:warehouse:list`,新增使用 `platform:warehouse:create`,编辑使用 `platform:warehouse:edit`,启停使用 `platform:warehouse:status`;OpenAPI 的 403 响应说明必须与权限码同步。
- 往来单位与仓库查询供 Order 使用,DTO 或有效性语义变化需同步检查 `order/client/` 和订单快照逻辑。
- 往来单位类型以 `types` 多值集合和 `wh_partner_type` 为准,允许同一单位同时作为客户、供应商等;`wh_partner.partner_type` 与 DTO 的 `partnerType` 仅保留旧数据兼容。写入时 Entity、Mapper、Repository、平台保存/导入和 Order 客户端必须一起核对。
- 往来单位与快递公司导入只接收标准 XLSX 模板,文件上限 5MB、最多 1000 行;先完成整表头、字段、文件内重复和数据库重复校验,再原子写入,任一行失败整批不落库。权限分别是 `platform:counterparty:import` 与 `platform:express:import`。
@@ -89,8 +89,8 @@ public class PlatformWarehouseController {
}
@Operation(
summary = "List tenant warehouses / 查询租户仓库",
description = "Returns a tenant-scoped warehouse page with optional country, capability and status filters. / 按租户分页查询仓库,可按国家、能力和状态筛选。"
summary = "List platform warehouses / 查询平台仓库",
description = "Returns all platform warehouses by default; customer ID is an optional compatibility filter. / 默认分页查询平台全部仓库,客户 ID 仅作为兼容筛选条件。"
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "Query succeeded / 查询成功"),
@@ -101,11 +101,11 @@ public class PlatformWarehouseController {
@PreAuthorize("hasAuthority('platform:warehouse:list')")
public ApiResponse<PageResult<WarehouseEntity>> page(
@AuthenticationPrincipal AuthenticatedUser user,
@Parameter(description = "Target tenant ID / 目标租户 ID", example = "10001", required = true)
@RequestParam @NotNull Long tenantId,
@Parameter(description = "Optional customer ID / 可选客户 ID", example = "10001")
@RequestParam(required = false) Long tenantId,
@Valid WarehouseRequests.QueryRequest request) {
requirePlatform(user);
requireTenant(tenantId);
if (tenantId != null) requireTenant(tenantId);
return ApiResponse.success(service.page(tenantId, request));
}
@@ -169,4 +169,3 @@ public class PlatformWarehouseController {
}
}
}
@@ -56,9 +56,9 @@ public class WarehouseRepository {
.ne(excludedId != null, WarehouseEntity::getId, excludedId)) > 0;
}
public PageResult<WarehouseEntity> page(long tenantId, WarehouseRequests.QueryRequest query) {
public PageResult<WarehouseEntity> page(Long tenantId, WarehouseRequests.QueryRequest query) {
LambdaQueryWrapper<WarehouseEntity> wrapper = new LambdaQueryWrapper<WarehouseEntity>()
.eq(WarehouseEntity::getTenantId, tenantId)
.eq(tenantId != null, WarehouseEntity::getTenantId, tenantId)
.eq(StringUtils.hasText(query.status()), WarehouseEntity::getStatus, query.status())
.eq(StringUtils.hasText(query.warehouseType()), WarehouseEntity::getWarehouseType, query.warehouseType())
.eq(StringUtils.hasText(query.countryCode()), WarehouseEntity::getCountryCode, query.countryCode())
@@ -67,7 +67,7 @@ public class WarehouseRepository {
if (StringUtils.hasText(query.capabilityCode())) {
List<Long> ids = capabilities.selectList(new LambdaQueryWrapper<ServiceCapabilityEntity>()
.select(ServiceCapabilityEntity::getWarehouseId)
.eq(ServiceCapabilityEntity::getTenantId, tenantId)
.eq(tenantId != null, ServiceCapabilityEntity::getTenantId, tenantId)
.eq(ServiceCapabilityEntity::getCapabilityCode, query.capabilityCode())
.eq(ServiceCapabilityEntity::getEnabled, true))
.stream()
@@ -63,7 +63,7 @@ public class WarehouseApplicationService {
insertChildren(tenantId, id, request.address(), request.capabilities());
}
public PageResult<WarehouseEntity> page(long tenantId, WarehouseRequests.QueryRequest query) {
public PageResult<WarehouseEntity> page(Long tenantId, WarehouseRequests.QueryRequest query) {
return repository.page(tenantId, query);
}
@@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.lang.reflect.Method;
@@ -45,6 +46,13 @@ class PlatformMasterDataControllerContractTest {
assertWarehouseMethod("create", PostMapping.class, "platform:warehouse:create");
assertWarehouseMethod("update", PutMapping.class, "platform:warehouse:edit");
assertWarehouseMethod("status", PatchMapping.class, "platform:warehouse:status");
Method page = java.util.Arrays.stream(PlatformWarehouseController.class.getDeclaredMethods())
.filter(candidate -> candidate.getName().equals("page"))
.findFirst()
.orElseThrow();
assertThat(page.getParameterTypes()[1]).isEqualTo(Long.class);
assertThat(page.getParameters()[1].getAnnotation(RequestParam.class).required()).isFalse();
}
@Test
@@ -4,6 +4,8 @@ import com.baiyue.common.core.exception.BizException;
import com.baiyue.common.core.api.ResultCode;
import com.baiyue.warehouse.entity.WarehouseEntity;
import com.baiyue.warehouse.repository.WarehouseRepository;
import com.baiyue.warehouse.dto.WarehouseRequests;
import com.baiyue.common.core.api.PageResult;
import org.junit.jupiter.api.Test;
import jakarta.annotation.Resource;
import org.springframework.boot.test.mock.mockito.MockBean;
@@ -36,4 +38,12 @@ class WarehouseApplicationServiceTest {
assertThatThrownBy(() -> service.activeDetail(10001,1)).isInstanceOf(BizException.class)
.extracting(exception -> ((BizException) exception).getResultCode()).isEqualTo(ResultCode.CONFLICT);
}
@Test
void pagesAllPlatformWarehousesWithoutCustomerFilter() {
WarehouseRequests.QueryRequest query = new WarehouseRequests.QueryRequest(1, 200, null, null, null, null);
when(repository.page(null, query)).thenReturn(new PageResult<>(java.util.List.of(), 1, 200, 0, 0));
assertThat(service.page(null, query).records()).isEmpty();
verify(repository).page(null, query);
}
}