This commit is contained in:
2026-08-20 18:02:38 +08:00
parent b55b049e77
commit 1cd8b6a473
210 changed files with 6974 additions and 825 deletions
@@ -9,6 +9,7 @@ import com.baiyue.warehouse.dto.WarehouseDetailResponse;
import com.baiyue.warehouse.dto.WarehouseRequests;
import com.baiyue.warehouse.entity.WarehouseEntity;
import com.baiyue.warehouse.service.WarehouseApplicationService;
import com.baiyue.warehouse.security.OverseasWarehousePermissions;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
@@ -17,6 +18,7 @@ import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
@@ -44,7 +46,7 @@ public class PlatformWarehouseController {
@Operation(
summary = "Create warehouse / 新建仓库",
description = "Creates a warehouse, address and service capabilities for the target tenant. / 为目标租户创建仓库、地址和服务能力。"
description = "Required authority: " + OverseasWarehousePermissions.WAREHOUSE_CREATE + ". Creates a warehouse, address and service capabilities for the target customer."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "Created successfully / 创建成功"),
@@ -53,6 +55,7 @@ public class PlatformWarehouseController {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "409", description = "Warehouse code already exists / 仓库编码已存在")
})
@PostMapping
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.WAREHOUSE_CREATE + "')")
public ApiResponse<Long> create(@AuthenticationPrincipal AuthenticatedUser user,
@Valid @RequestBody WarehouseRequests.SaveRequest request) {
requirePlatform(user);
@@ -62,7 +65,7 @@ public class PlatformWarehouseController {
@Operation(
summary = "Update warehouse / 更新仓库",
description = "Updates the warehouse and replaces its address and capabilities. / 更新仓库,并整体替换地址和服务能力。"
description = "Required authority: " + OverseasWarehousePermissions.WAREHOUSE_EDIT + ". Updates the warehouse and replaces its address and capabilities."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "Updated successfully / 更新成功"),
@@ -72,6 +75,7 @@ public class PlatformWarehouseController {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "409", description = "Warehouse code already exists / 仓库编码已存在")
})
@PutMapping("/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.WAREHOUSE_EDIT + "')")
public ApiResponse<Void> update(
@AuthenticationPrincipal AuthenticatedUser user,
@Parameter(description = "Target tenant ID / 目标租户 ID", example = "10001", required = true)
@@ -87,7 +91,7 @@ public class PlatformWarehouseController {
@Operation(
summary = "List tenant warehouses / 查询租户仓库",
description = "Returns a tenant-scoped warehouse page with optional country, capability and status filters. / 按租户分页查询仓库,可按国家、能力和状态筛选。"
description = "Required authority: " + OverseasWarehousePermissions.WAREHOUSE_LIST + ". Returns a customer-scoped warehouse page with optional filters."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "Query succeeded / 查询成功"),
@@ -95,6 +99,7 @@ public class PlatformWarehouseController {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "403", description = "Platform access required / 需要平台端权限")
})
@GetMapping
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.WAREHOUSE_LIST + "')")
public ApiResponse<PageResult<WarehouseEntity>> page(
@AuthenticationPrincipal AuthenticatedUser user,
@Parameter(description = "Target tenant ID / 目标租户 ID", example = "10001", required = true)
@@ -107,7 +112,7 @@ public class PlatformWarehouseController {
@Operation(
summary = "Get tenant warehouse details / 查询租户仓库详情",
description = "Returns the warehouse, addresses and service capabilities in the target tenant. / 返回目标租户下的仓库、地址及服务能力。"
description = "Required authority: " + OverseasWarehousePermissions.WAREHOUSE_LIST + ". Returns the warehouse, addresses and service capabilities for the target customer."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "Query succeeded / 查询成功"),
@@ -115,6 +120,7 @@ public class PlatformWarehouseController {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "Warehouse not found / 仓库不存在")
})
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.WAREHOUSE_LIST + "')")
public ApiResponse<WarehouseDetailResponse> detail(
@AuthenticationPrincipal AuthenticatedUser user,
@Parameter(description = "Target tenant ID / 目标租户 ID", example = "10001", required = true)
@@ -128,7 +134,7 @@ public class PlatformWarehouseController {
@Operation(
summary = "Enable or disable warehouse / 启用或停用仓库",
description = "Changes warehouse status to ACTIVE or INACTIVE. / 将仓库状态切换为 ACTIVE 或 INACTIVE。"
description = "Required authority: " + OverseasWarehousePermissions.WAREHOUSE_STATUS + ". Changes warehouse status to ACTIVE or INACTIVE."
)
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "Status changed / 状态变更成功"),
@@ -137,6 +143,7 @@ public class PlatformWarehouseController {
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "Warehouse not found / 仓库不存在")
})
@PatchMapping("/{id}/status")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.WAREHOUSE_STATUS + "')")
public ApiResponse<Void> status(
@AuthenticationPrincipal AuthenticatedUser user,
@Parameter(description = "Target tenant ID / 目标租户 ID", example = "10001", required = true)
@@ -152,7 +159,7 @@ public class PlatformWarehouseController {
}
private static void requirePlatform(AuthenticatedUser user) {
if (user == null || !"PLATFORM".equals(user.appCode())) {
if (user == null || !"PLATFORM".equals(user.appCode()) || user.tenantId() == null || user.tenantId() != 0L) {
throw new BizException(ResultCode.FORBIDDEN, "Platform application required / 仅允许平台端访问");
}
}
@@ -163,4 +170,3 @@ public class PlatformWarehouseController {
}
}
}
@@ -10,10 +10,13 @@ import com.baiyue.warehouse.dto.PalletRequests;
import com.baiyue.warehouse.entity.WarehouseLocationEntity;
import com.baiyue.warehouse.entity.WarehousePalletEntity;
import com.baiyue.warehouse.service.WarehouseResourceService;
import com.baiyue.warehouse.security.OverseasWarehousePermissions;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@@ -28,104 +31,114 @@ import org.springframework.web.bind.annotation.RestController;
@Validated
@RestController
@RequestMapping("/api/platform/v1/warehouse-admin/{warehouseId}")
@Tag(name = "Platform overseas warehouse resources")
public class PlatformWarehouseResourceController {
@Resource private WarehouseResourceService service;
@PostMapping("/locations")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.LOCATION_CREATE + "')")
@Operation(summary = "Create a warehouse location", description = "Required authority: " + OverseasWarehousePermissions.LOCATION_CREATE)
public ApiResponse<Long> createLocation(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId,
@Valid @RequestBody LocationRequests.SaveRequest request) {
requirePlatform(user, customerId);
return ApiResponse.success(service.createLocation(customerId, warehouseId, request));
requirePlatform(user);
return ApiResponse.success(service.createLocation(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, request));
}
@PutMapping("/locations/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.LOCATION_EDIT + "')")
@Operation(summary = "Update a warehouse location", description = "Required authority: " + OverseasWarehousePermissions.LOCATION_EDIT)
public ApiResponse<Void> updateLocation(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId, @PathVariable long id,
@Valid @RequestBody LocationRequests.SaveRequest request) {
requirePlatform(user, customerId);
service.updateLocation(customerId, warehouseId, id, request);
requirePlatform(user);
service.updateLocation(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, id, request);
return ApiResponse.success(null);
}
@GetMapping("/locations")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.LOCATION_LIST + "')")
@Operation(summary = "Page warehouse locations", description = "Required authority: " + OverseasWarehousePermissions.LOCATION_LIST)
public ApiResponse<PageResult<WarehouseLocationEntity>> locations(
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam @NotNull Long customerId,
@AuthenticationPrincipal AuthenticatedUser user,
@PathVariable long warehouseId, @Valid LocationRequests.QueryRequest query) {
requirePlatform(user, customerId);
return ApiResponse.success(service.locations(customerId, warehouseId, query));
requirePlatform(user);
return ApiResponse.success(service.locations(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, query));
}
@GetMapping("/locations/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.LOCATION_LIST + "')")
@Operation(summary = "Get a warehouse location", description = "Required authority: " + OverseasWarehousePermissions.LOCATION_LIST)
public ApiResponse<WarehouseLocationEntity> location(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId,
@PathVariable long id) {
requirePlatform(user, customerId);
return ApiResponse.success(service.location(customerId, warehouseId, id));
requirePlatform(user);
return ApiResponse.success(service.location(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, id));
}
@DeleteMapping("/locations/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.LOCATION_DELETE + "')")
@Operation(summary = "Delete a warehouse location", description = "Required authority: " + OverseasWarehousePermissions.LOCATION_DELETE)
public ApiResponse<Void> deleteLocation(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId, @PathVariable long id) {
requirePlatform(user, customerId);
service.deleteLocation(customerId, warehouseId, id);
requirePlatform(user);
service.deleteLocation(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, id);
return ApiResponse.success(null);
}
@PostMapping("/pallets")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.PALLET_CREATE + "')")
@Operation(summary = "Create a warehouse pallet", description = "Required authority: " + OverseasWarehousePermissions.PALLET_CREATE)
public ApiResponse<Long> createPallet(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId,
@Valid @RequestBody PalletRequests.SaveRequest request) {
requirePlatform(user, customerId);
return ApiResponse.success(service.createPallet(customerId, warehouseId, request));
requirePlatform(user);
return ApiResponse.success(service.createPallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, request));
}
@PutMapping("/pallets/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.PALLET_EDIT + "')")
@Operation(summary = "Update a warehouse pallet", description = "Required authority: " + OverseasWarehousePermissions.PALLET_EDIT)
public ApiResponse<Void> updatePallet(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId, @PathVariable long id,
@Valid @RequestBody PalletRequests.SaveRequest request) {
requirePlatform(user, customerId);
service.updatePallet(customerId, warehouseId, id, request);
requirePlatform(user);
service.updatePallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, id, request);
return ApiResponse.success(null);
}
@GetMapping("/pallets")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.PALLET_LIST + "')")
@Operation(summary = "Page warehouse pallets", description = "Required authority: " + OverseasWarehousePermissions.PALLET_LIST)
public ApiResponse<PageResult<WarehousePalletEntity>> pallets(
@AuthenticationPrincipal AuthenticatedUser user, @RequestParam @NotNull Long customerId,
@AuthenticationPrincipal AuthenticatedUser user,
@PathVariable long warehouseId, @Valid PalletRequests.QueryRequest query) {
requirePlatform(user, customerId);
return ApiResponse.success(service.pallets(customerId, warehouseId, query));
requirePlatform(user);
return ApiResponse.success(service.pallets(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, query));
}
@GetMapping("/pallets/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.PALLET_LIST + "')")
@Operation(summary = "Get a warehouse pallet", description = "Required authority: " + OverseasWarehousePermissions.PALLET_LIST)
public ApiResponse<WarehousePalletEntity> pallet(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId, @PathVariable long id) {
requirePlatform(user, customerId);
return ApiResponse.success(service.pallet(customerId, warehouseId, id));
requirePlatform(user);
return ApiResponse.success(service.pallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, id));
}
@DeleteMapping("/pallets/{id}")
@PreAuthorize("hasAuthority('" + OverseasWarehousePermissions.PALLET_DELETE + "')")
@Operation(summary = "Delete a warehouse pallet", description = "Required authority: " + OverseasWarehousePermissions.PALLET_DELETE)
public ApiResponse<Void> deletePallet(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam @NotNull Long customerId,
@PathVariable long warehouseId, @PathVariable long id) {
requirePlatform(user, customerId);
service.deletePallet(customerId, warehouseId, id);
requirePlatform(user);
service.deletePallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, warehouseId, id);
return ApiResponse.success(null);
}
private static void requirePlatform(AuthenticatedUser user, Long customerId) {
if (user == null || !"PLATFORM".equals(user.appCode())) {
private static void requirePlatform(AuthenticatedUser user) {
if (user == null || !"PLATFORM".equals(user.appCode()) || user.tenantId() == null || user.tenantId() != 0L) {
throw new BizException(ResultCode.FORBIDDEN, "仅允许平台端访问");
}
if (customerId == null || customerId <= 0) {
throw new BizException(ResultCode.BAD_REQUEST, "必须指定有效目标租户");
}
}
}
@@ -7,11 +7,13 @@ import com.baiyue.warehouse.entity.WarehouseResourceLockEntity;
import com.baiyue.warehouse.mapper.WarehouseLocationMapper;
import com.baiyue.warehouse.mapper.WarehousePalletMapper;
import com.baiyue.warehouse.mapper.WarehouseResourceLockMapper;
import com.baiyue.warehouse.service.WarehouseResourceService;
import org.springframework.stereotype.Repository;
import jakarta.annotation.Resource;
@Repository
public class WarehouseResourceLockRepository {
private static final long PUBLIC_RESOURCE_SCOPE = WarehouseResourceService.PUBLIC_RESOURCE_SCOPE;
@Resource private WarehouseResourceLockMapper locks;
@Resource private WarehousePalletMapper pallets;
@Resource private WarehouseLocationMapper locations;
@@ -32,58 +34,58 @@ public class WarehouseResourceLockRepository {
public WarehousePalletEntity findPallet(long customerId, long palletId) {
return pallets.selectOne(new LambdaQueryWrapper<WarehousePalletEntity>()
.eq(WarehousePalletEntity::getCustomerId, customerId)
.eq(WarehousePalletEntity::getCustomerId, PUBLIC_RESOURCE_SCOPE)
.eq(WarehousePalletEntity::getId, palletId));
}
public WarehousePalletEntity findPallet(long customerId, long warehouseId, long palletId) {
return pallets.selectOne(new LambdaQueryWrapper<WarehousePalletEntity>()
.eq(WarehousePalletEntity::getCustomerId, customerId)
.eq(WarehousePalletEntity::getCustomerId, PUBLIC_RESOURCE_SCOPE)
.eq(WarehousePalletEntity::getWarehouseId, warehouseId)
.eq(WarehousePalletEntity::getId, palletId));
}
public WarehouseLocationEntity findLocation(long customerId, long warehouseId, long locationId) {
return locations.selectOne(new LambdaQueryWrapper<WarehouseLocationEntity>()
.eq(WarehouseLocationEntity::getCustomerId, customerId)
.eq(WarehouseLocationEntity::getCustomerId, PUBLIC_RESOURCE_SCOPE)
.eq(WarehouseLocationEntity::getWarehouseId, warehouseId)
.eq(WarehouseLocationEntity::getId, locationId));
}
public int occupyPallet(long customerId, long warehouseId, long palletId, long locationId) {
return locks.occupyPallet(customerId, warehouseId, palletId, locationId);
return locks.occupyPallet(PUBLIC_RESOURCE_SCOPE, warehouseId, palletId, locationId);
}
public int occupyLocation(long customerId, long warehouseId, long locationId) {
return locks.occupyLocation(customerId, warehouseId, locationId);
return locks.occupyLocation(PUBLIC_RESOURCE_SCOPE, warehouseId, locationId);
}
public void insert(WarehouseResourceLockEntity lock) { locks.insert(lock); }
public int releasePallet(WarehouseResourceLockEntity lock) {
return locks.releasePallet(lock.getCustomerId(), lock.getWarehouseId(), lock.getPalletId(), lock.getLocationId());
return locks.releasePallet(PUBLIC_RESOURCE_SCOPE, lock.getWarehouseId(), lock.getPalletId(), lock.getLocationId());
}
public int releasePalletAtVirtualLocation(WarehouseResourceLockEntity lock) {
return locks.releasePalletAtVirtualLocation(lock.getCustomerId(), lock.getWarehouseId(),
return locks.releasePalletAtVirtualLocation(PUBLIC_RESOURCE_SCOPE, lock.getWarehouseId(),
lock.getPalletId(), lock.getLocationId());
}
public int scrapPallet(WarehouseResourceLockEntity lock) {
return locks.scrapPallet(lock.getCustomerId(), lock.getWarehouseId(), lock.getPalletId(), lock.getLocationId());
return locks.scrapPallet(PUBLIC_RESOURCE_SCOPE, lock.getWarehouseId(), lock.getPalletId(), lock.getLocationId());
}
public int scrapPalletWithoutLock(long customerId, long palletId) {
return locks.scrapPalletWithoutLock(customerId, palletId);
return locks.scrapPalletWithoutLock(PUBLIC_RESOURCE_SCOPE, palletId);
}
public int scrapPalletAtVirtualLocation(WarehouseResourceLockEntity lock) {
return locks.scrapPalletAtVirtualLocation(lock.getCustomerId(), lock.getWarehouseId(),
return locks.scrapPalletAtVirtualLocation(PUBLIC_RESOURCE_SCOPE, lock.getWarehouseId(),
lock.getPalletId(), lock.getLocationId());
}
public int releaseLocation(WarehouseResourceLockEntity lock) {
return locks.releaseLocation(lock.getCustomerId(), lock.getWarehouseId(), lock.getLocationId());
return locks.releaseLocation(PUBLIC_RESOURCE_SCOPE, lock.getWarehouseId(), lock.getLocationId());
}
public int close(WarehouseResourceLockEntity lock, String status) { return locks.closeLock(lock.getId(), status); }
@@ -45,6 +45,10 @@ public class WarehouseResourceRepository {
.eq(WarehouseEntity::getId, warehouseId));
}
public WarehouseEntity findWarehouseById(long warehouseId) {
return warehouses.selectById(warehouseId);
}
public WarehouseLocationEntity findDefaultVirtualLocation(long customerId, long warehouseId) {
return locations.selectOne(new LambdaQueryWrapper<WarehouseLocationEntity>()
.eq(WarehouseLocationEntity::getCustomerId, customerId)
@@ -0,0 +1,19 @@
package com.baiyue.warehouse.security;
/** Canonical Admin authorities for overseas warehouse resources. */
public final class OverseasWarehousePermissions {
public static final String WAREHOUSE_LIST = "platform:overseas-warehouse:warehouse:list";
public static final String WAREHOUSE_CREATE = "platform:overseas-warehouse:warehouse:create";
public static final String WAREHOUSE_EDIT = "platform:overseas-warehouse:warehouse:edit";
public static final String WAREHOUSE_STATUS = "platform:overseas-warehouse:warehouse:status";
public static final String LOCATION_LIST = "platform:overseas-warehouse:location:list";
public static final String LOCATION_CREATE = "platform:overseas-warehouse:location:create";
public static final String LOCATION_EDIT = "platform:overseas-warehouse:location:edit";
public static final String LOCATION_DELETE = "platform:overseas-warehouse:location:delete";
public static final String PALLET_LIST = "platform:overseas-warehouse:pallet:list";
public static final String PALLET_CREATE = "platform:overseas-warehouse:pallet:create";
public static final String PALLET_EDIT = "platform:overseas-warehouse:pallet:edit";
public static final String PALLET_DELETE = "platform:overseas-warehouse:pallet:delete";
private OverseasWarehousePermissions() { }
}
@@ -22,6 +22,7 @@ import org.springframework.util.StringUtils;
@Service
public class WarehouseResourceService {
public static final long PUBLIC_RESOURCE_SCOPE = 0L;
private static final Set<String> LOCATION_STATUSES = Set.of("ACTIVE", "IDLE", "OCCUPIED", "INACTIVE");
private static final Set<String> PALLET_STATUSES = Set.of("IDLE", "OCCUPIED", "SCRAPPED");
@@ -187,13 +188,20 @@ public class WarehouseResourceService {
}
private void requireWarehouse(long customerId, long warehouseId) {
if (customerId == PUBLIC_RESOURCE_SCOPE) {
if (repository.findWarehouseById(warehouseId) == null) {
throw new BizException(ResultCode.NOT_FOUND, "Warehouse not found");
}
return;
}
if (!repository.warehouseOwned(customerId, warehouseId)) {
throw new BizException(ResultCode.NOT_FOUND, "当前租户下仓库不存在");
}
}
private WarehouseEntity requireWarehouseEntity(long customerId, long warehouseId) {
WarehouseEntity warehouse = repository.findWarehouse(customerId, warehouseId);
WarehouseEntity warehouse = customerId == PUBLIC_RESOURCE_SCOPE
? repository.findWarehouseById(warehouseId) : repository.findWarehouse(customerId, warehouseId);
if (warehouse == null) {
throw new BizException(ResultCode.NOT_FOUND, "Tenant warehouse not found");
}