Files

50 lines
3.2 KiB
JavaScript

const id = value => value == null ? '' : String(value)
const positive = value => /^[1-9][0-9]*$/.test(id(value)) && Number.isSafeInteger(Number(value))
/** 仅组合本轮已收货入仓单的权威箱、SKU 和实际托盘位置,不生成箱号或推算每箱件数。 */
export async function readCurrentBoxedInventory(context, token, warehouseId, module) {
const pda = context.createdResources?.phase4OverseasPda
if (pda?.marker !== context.marker || pda.finalStatus !== 'COMPLETED'
|| id(pda.overseasWarehouseId) !== id(warehouseId)) throw Error('真实箱来源缺少本轮已收货仓库事实')
const inbounds = Object.keys(pda.generatedPalletsByInbound || {})
if (!inbounds.length) throw Error('真实箱来源缺少本轮入仓单')
const get = async path => {
const response = await context.request('GET', path, undefined, token, {})
const data = context.apiSuccess(module, '核对本轮库存真实箱与SKU来源', response)
if (response?.http !== 200 || String(response?.body?.code) !== '200' || !Array.isArray(data))
throw Error('真实箱来源接口未返回完整列表')
return data
}
const physical = await get('/api/merchant/v1/last-leg/cargo-discards/inventory-candidates')
const result = []
for (const inboundCode of inbounds) {
const scope = { operatingWarehouseId: id(warehouseId), inboundCode }
const cartons = await get('/api/merchant/v1/last-leg/warehouse-transfers/inventory-source-cartons?' + new URLSearchParams(scope))
if (!cartons.length) continue
const inventory = await get('/api/merchant/v1/last-leg/relabel-applications/inventory-candidates?'
+ new URLSearchParams({ operationWarehouseId: id(warehouseId), inboundCode }))
for (const source of inventory.filter(row => row.sourceType === 'INBOUND' && row.inboundCode === inboundCode
&& id(row.overseasWarehouseId) === id(warehouseId) && id(row.inventoryBalanceId) && id(row.inboundOrderId))) {
const boxes = physical.filter(row => row.inboundCode === inboundCode && id(row.overseasWarehouseId) === id(warehouseId)
&& id(row.orderId) === id(source.inboundOrderId)).flatMap(row => row.cartons || [])
const seen = new Set()
const actual = []
for (const carton of cartons) {
if (!carton.cartonMark || seen.has(carton.cartonMark)) throw Error('权威来源箱号缺失或重复')
seen.add(carton.cartonMark)
const matches = boxes.filter(box => box.cartonMark === carton.cartonMark)
if (matches.length !== 1) continue
const box = matches[0]
const positions = (source.positions || []).filter(position => position.palletNo === box.palletNo
&& box.palletNo && box.palletNo.toUpperCase() !== 'UNBOUND' && Number(position.availablePackages) > 0)
const items = carton.items || []
if (positions.length !== 1 || !items.length || items.some(item => !item.skuCode || !positive(item.quantity))
|| !items.some(item => item.skuCode === source.skuCode)) continue
actual.push({ ...carton, cartonId: id(box.cartonId), positionId: id(positions[0].positionId), palletNo: box.palletNo })
}
if (actual.length) result.push({ ...source, cartons: actual })
}
}
return result
}