feat(lastleg): add direct inventory balance detail
This commit is contained in:
+10
@@ -56,6 +56,16 @@ public class InventoryQueryController {
|
||||
return ApiResponse.success(service.balances(platformScope(user, customerId), query));
|
||||
}
|
||||
|
||||
@GetMapping(BASE_PATH + "/balances/{balanceId}")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.INVENTORY_LIST + "')")
|
||||
@Operation(summary = "Get one inventory balance", description = "Returns one non-zero inventory balance by ID and optional customer scope. Required authority: " + OverseasPermissions.INVENTORY_LIST)
|
||||
public ApiResponse<InventoryBalanceView> balance(
|
||||
@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@PathVariable long balanceId,
|
||||
@RequestParam(required = false) String customerId) {
|
||||
return ApiResponse.success(service.balance(platformScope(user, customerId), balanceId));
|
||||
}
|
||||
|
||||
@GetMapping(BASE_PATH + "/balances/{balanceId}/positions")
|
||||
@PreAuthorize("hasAuthority('" + OverseasPermissions.INVENTORY_LIST + "')")
|
||||
@Operation(summary = "List pallet and batch positions for one inbound-order balance", description = "Required authority: " + OverseasPermissions.INVENTORY_LIST)
|
||||
|
||||
+11
@@ -111,6 +111,17 @@ public interface InventoryQueryMapper {
|
||||
@Select("SELECT * FROM ll_inventory_balance WHERE id=#{balanceId} LIMIT 1")
|
||||
InventoryBalance findBalance(@Param("balanceId") long balanceId);
|
||||
|
||||
@Select("SELECT * FROM ll_inventory_balance WHERE customer_id=#{customerId} AND id=#{balanceId} " +
|
||||
"AND (available_packages+hold_packages+allocated_packages+picked_packages+in_transit_packages+" +
|
||||
"receiving_packages+procurement_packages)>0 LIMIT 1")
|
||||
InventoryBalance ownedVisibleBalance(@Param("customerId") String customerId,
|
||||
@Param("balanceId") long balanceId);
|
||||
|
||||
@Select("SELECT * FROM ll_inventory_balance WHERE id=#{balanceId} " +
|
||||
"AND (available_packages+hold_packages+allocated_packages+picked_packages+in_transit_packages+" +
|
||||
"receiving_packages+procurement_packages)>0 LIMIT 1")
|
||||
InventoryBalance visibleBalance(@Param("balanceId") long balanceId);
|
||||
|
||||
String LEDGER_FILTER = " WHERE 1=1" +
|
||||
"<if test='customerId != null and customerId != \"\"'> AND customer_id=#{customerId}</if>" +
|
||||
"<if test='q.overseasWarehouseId != null and q.overseasWarehouseId != \"\"'> AND overseas_warehouse_id=#{q.overseasWarehouseId}</if>" +
|
||||
|
||||
+10
@@ -57,6 +57,16 @@ public class InventoryQueryService {
|
||||
return page(records, query.page(), query.size(), total);
|
||||
}
|
||||
|
||||
public InventoryBalanceView balance(String customerId, long balanceId) {
|
||||
InventoryBalance balance = customerId == null
|
||||
? mapper.visibleBalance(balanceId)
|
||||
: mapper.ownedVisibleBalance(customerId, balanceId);
|
||||
if (balance == null) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Inventory balance not found");
|
||||
}
|
||||
return balanceView(balance);
|
||||
}
|
||||
|
||||
public List<InventoryPositionView> positions(String customerId, long balanceId,
|
||||
InventoryQueryRequests.PositionQuery query) {
|
||||
validateStatus(query.inventoryStatus(), POSITION_STATUSES);
|
||||
|
||||
@@ -3,6 +3,18 @@ info:
|
||||
title: Lastleg Overseas Business API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/api/platform/v1/last-leg/inventory/balances/{balanceId}:
|
||||
get:
|
||||
summary: 查询单条库存余额详情
|
||||
description: 仅平台且要求 lastleg:inventory:list;按 balanceId 直接查询非零库存余额,不依赖列表分页。可选 customerId 用于精确客户隔离,越权或不存在统一返回404。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { in: path, name: balanceId, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$', description: 长整型ID按字符串传输 } }
|
||||
- { in: query, name: customerId, required: false, schema: { type: string } }
|
||||
responses:
|
||||
'200': { description: 单条库存余额, content: { application/json: { schema: { $ref: '#/components/schemas/InventoryBalanceApiResponse' } } } }
|
||||
'403': { description: 非平台身份或缺少库存查看权限 }
|
||||
'404': { description: 库存余额不存在、已归零或不属于指定客户 }
|
||||
/api/platform/v1/last-leg/inventory/inbound-code-relationships/{inboundCode}:
|
||||
get:
|
||||
summary: 按入仓码查询海外关系摘要
|
||||
@@ -1103,6 +1115,39 @@ paths:
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的换标单详情 }, '409': { description: 非法状态迁移或关联尾程单缺失 } }
|
||||
components:
|
||||
schemas:
|
||||
InventoryBalance:
|
||||
type: object
|
||||
required: [id, customerId, totalPackages, availablePackages, holdPackages, allocatedPackages, pickedPackages, inTransitPackages, receivingPackages, procurementPackages]
|
||||
properties:
|
||||
id: { type: string, pattern: '^[1-9][0-9]*$', description: 库存余额长整型ID,按字符串传输 }
|
||||
customerId: { type: string }
|
||||
customerName: { type: string, nullable: true }
|
||||
overseasWarehouseId: { type: string, nullable: true }
|
||||
overseasWarehouseCode: { type: string, nullable: true }
|
||||
overseasWarehouseName: { type: string, nullable: true }
|
||||
destinationWarehouseId: { type: string, nullable: true }
|
||||
destinationWarehouseCode: { type: string, nullable: true }
|
||||
destinationWarehouseName: { type: string, nullable: true }
|
||||
inboundOrderId: { type: string, nullable: true, pattern: '^[1-9][0-9]*$', description: 长整型ID按字符串传输 }
|
||||
inboundOrderNo: { type: string, nullable: true }
|
||||
inboundCode: { type: string, nullable: true }
|
||||
skuCode: { type: string, nullable: true }
|
||||
productNameZh: { type: string, nullable: true }
|
||||
productNameEn: { type: string, nullable: true }
|
||||
totalPackages: { type: integer, format: int64, minimum: 0 }
|
||||
availablePackages: { type: integer, format: int64, minimum: 0 }
|
||||
holdPackages: { type: integer, format: int64, minimum: 0 }
|
||||
allocatedPackages: { type: integer, format: int64, minimum: 0 }
|
||||
pickedPackages: { type: integer, format: int64, minimum: 0 }
|
||||
inTransitPackages: { type: integer, format: int64, minimum: 0 }
|
||||
receivingPackages: { type: integer, format: int64, minimum: 0 }
|
||||
procurementPackages: { type: integer, format: int64, minimum: 0 }
|
||||
updatedAt: { type: string, format: date-time, nullable: true }
|
||||
InventoryBalanceApiResponse:
|
||||
allOf:
|
||||
- { $ref: '#/components/schemas/ReceivingApiResponseBase' }
|
||||
- type: object
|
||||
properties: { data: { $ref: '#/components/schemas/InventoryBalance' } }
|
||||
InboundCodeRelationship:
|
||||
type: object
|
||||
required: [inboundCode, found, taillegOrders, inboundPlans, palletCodes, inventory]
|
||||
|
||||
Reference in New Issue
Block a user