71 lines
4.4 KiB
JavaScript
71 lines
4.4 KiB
JavaScript
import { readFile } from 'node:fs/promises'
|
|
import { resolve } from 'node:path'
|
|
|
|
const MODULE = 'manual-preload-push-fixture'
|
|
const OPTIONS = { scenario: 'manual-preload-push-fixture', deploymentBlocker: true }
|
|
const SMART = '/api/platform/v1/first-leg/smart-loading'
|
|
const CONTAINERS = '/api/platform/v1/containers'
|
|
|
|
function id(value) { return value == null ? '' : String(value) }
|
|
function rows(value) { return Array.isArray(value) ? value : [] }
|
|
function itemSnapshot(items) {
|
|
return rows(items).map((item) => ({ id: id(item.id), inboundId: id(item.inboundId),
|
|
packageCount: Number(item.packageCount) }))
|
|
.sort((left, right) => left.inboundId.localeCompare(right.inboundId) || left.id.localeCompare(right.id))
|
|
}
|
|
|
|
async function loadSource(context) {
|
|
const report = JSON.parse(await readFile(resolve(context.options.manualPreloadSourceReport), 'utf8'))
|
|
const verification = report?.createdResources?.manualOrderSplittingVerification
|
|
const sourceGateway = String(report?.gateway || '').replace(/\/$/, '')
|
|
const valid = sourceGateway === context.options.gateway && verification?.loadingPlanId
|
|
&& verification?.containerBookingId && Array.isArray(verification?.verifiedAssignments)
|
|
context.assert(MODULE, '读取同环境人工分柜核验报告', null, valid,
|
|
`sourceMarker=${report?.marker || 'missing'}, sameGateway=${sourceGateway === context.options.gateway}, loadingPlanId=${id(verification?.loadingPlanId) || 'missing'}`,
|
|
OPTIONS)
|
|
return valid ? verification : null
|
|
}
|
|
|
|
export async function run(context) {
|
|
const source = await loadSource(context)
|
|
if (!source) return
|
|
const planId = id(source.loadingPlanId)
|
|
const containerId = id(source.containerBookingId)
|
|
|
|
const planResponse = await context.request('GET', `${SMART}/plans/${encodeURIComponent(planId)}`)
|
|
const plan = context.apiSuccess(MODULE, '推送前读取智能装柜计划', planResponse, '', OPTIONS)
|
|
const items = itemSnapshot(plan?.items)
|
|
context.assert(MODULE, '计划仍处于未推送 EDITING 且分柜明细完整', planResponse,
|
|
id(plan?.id) === planId && id(plan?.bookingId || plan?.containerBookingId) === containerId
|
|
&& plan?.status === 'EDITING' && Number.isInteger(Number(plan?.version)) && items.length > 0,
|
|
`planId=${id(plan?.id) || 'missing'}, status=${plan?.status || 'missing'}, version=${plan?.version ?? 'missing'}, items=${items.length}`,
|
|
OPTIONS)
|
|
if (!plan || plan.status !== 'EDITING' || items.length === 0) return
|
|
|
|
const linksResponse = await context.request('GET', `${SMART}/plans/${encodeURIComponent(planId)}/preloads`)
|
|
const links = context.apiSuccess(MODULE, '推送前回查尚未建立预装 bridge', linksResponse, '', OPTIONS)
|
|
context.assert(MODULE, '未点击推送前不存在预装 bridge', linksResponse,
|
|
rows(links).length === 0, `linkCount=${rows(links).length}`, OPTIONS)
|
|
|
|
const containerResponse = await context.request('GET', `${CONTAINERS}/domestic/${encodeURIComponent(containerId)}`)
|
|
const container = context.apiSuccess(MODULE, '推送前读取内部模拟柜', containerResponse, '', OPTIONS)?.container
|
|
context.assert(MODULE, '当前仍是无真实柜号且未关联订舱的内部模拟柜', containerResponse,
|
|
id(container?.id) === containerId && container?.containerNo == null && container?.oceanBookingId == null
|
|
&& id(container?.warehouseId) === id(source.warehouseId) && container?.channelCode === source.channelCode,
|
|
`containerId=${id(container?.id) || 'missing'}, cabinetNo=${container?.cabinetNo || 'missing'}, containerNo=${container?.containerNo || 'null'}, oceanBookingId=${id(container?.oceanBookingId) || 'null'}`,
|
|
OPTIONS)
|
|
|
|
context.createdResources.manualPreloadPushFixture = {
|
|
schemaVersion: 1, sourceMarker: source.sourceMarker, preparedAt: new Date().toISOString(),
|
|
stage: 'MANUAL_PUSH_PRELOAD_READY', loadingPlanId: planId, containerBookingId: containerId,
|
|
cabinetNo: container?.cabinetNo || null, tenantId: id(source.tenantId), warehouseId: id(source.warehouseId),
|
|
channelCode: source.channelCode, beforePlanVersion: Number(plan.version), beforeItems: items,
|
|
expectedAssignments: source.verifiedAssignments,
|
|
instructions: [
|
|
'在智能装柜计划页面点击推送预装。',
|
|
'本节点保持无真实集装箱号、无订舱关联,不执行计划确认。',
|
|
'推送成功后不要继续录入柜号或创建 PDA 任务,立即运行 manual-preload-push-verify。',
|
|
],
|
|
}
|
|
}
|