Files

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。',
],
}
}