diff --git a/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs b/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs index b1de24c5f..3d291b9b2 100644 --- a/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs +++ b/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs @@ -91,7 +91,12 @@ test('HTTP regression is self-contained and covers no-customer and idempotency m for (const label of ['自包含创建 DRAFT 订舱', '上传当前有效 BILL_OF_LADING 文件', '放舱自包含订舱', '绑定本轮真实 ISO 柜号', '拖车请求不含客户字段', '同柜第二条非终态预约拒绝且零漂移', '同键同载荷重放', '同键重放版本零漂移', '同键异载荷拒绝', '错误订舱拒绝创建', - '错误柜号归属拒绝创建', '错误提单拒绝创建', '错误承运商拒绝创建']) assert.match(source, new RegExp(label)) + '错误柜号归属拒绝创建', '错误提单拒绝创建', '错误承运商拒绝创建', + '派车命令返回状态身份与版本正确', '派车后回查拖车完整详情', + '详情字段完整且订舱柜号身份无客户字段漂移']) assert.match(source, new RegExp(label)) + assert.match(source, /const detailResponse = await request\(context, 'GET', path\); const detail = data\(detailResponse\)/) + assert.match(source, /const detailGaps = truckAppointmentFieldGaps\(detail\)/) + assert.doesNotMatch(source, /truckAppointmentFieldGaps\(dispatched\)/) assert.doesNotMatch(source, /phase3ContainerLoading|phase3Loading/) const entry = readFileSync(new URL('../admin-test-env-acceptance.mjs', import.meta.url), 'utf8') assert.match(entry, /\['truck-appointments', \['merchant-qualification-fixture'\]\]/) diff --git a/scripts/admin-test-env-modules/truck-appointments.mjs b/scripts/admin-test-env-modules/truck-appointments.mjs index 1c819a1f1..74702a1e9 100644 --- a/scripts/admin-test-env-modules/truck-appointments.mjs +++ b/scripts/admin-test-env-modules/truck-appointments.mjs @@ -196,9 +196,19 @@ export async function run(context) { { expectedVersion: Number(firstData?.version), reason: '派车' }, { 'Idempotency-Key': `${context.marker}-truck-dispatch`.slice(0, 128) }) const dispatched = context.apiSuccess(MODULE, '有效提单后派车', dispatch, '', OPTIONS) - context.assert(MODULE, '派车状态及稳定字段完整', dispatch, - dispatched?.status === 'DISPATCHED' && truckAppointmentFieldGaps(dispatched).length === 0, - `status=${dispatched?.status || 'missing'}`, OPTIONS) + context.assert(MODULE, '派车命令返回状态身份与版本正确', dispatch, + dispatched?.status === 'DISPATCHED' && id(dispatched?.id) === appointmentId + && Number(dispatched?.version) > Number(firstData?.version), + `id=${id(dispatched?.id) || 'missing'}, status=${dispatched?.status || 'missing'}, version=${dispatched?.version ?? 'missing'}`, OPTIONS) + const detailResponse = await request(context, 'GET', path); const detail = data(detailResponse) + context.apiSuccess(MODULE, '派车后回查拖车完整详情', detailResponse, '', OPTIONS) + const detailGaps = truckAppointmentFieldGaps(detail) + context.assert(MODULE, '详情字段完整且订舱柜号身份无客户字段漂移', detailResponse, + detail?.status === 'DISPATCHED' && detailGaps.length === 0 + && !Object.hasOwn(detail || {}, 'customerId') && !Object.hasOwn(detail || {}, 'customerName') + && id(detail?.oceanBookingId) === identity.oceanBookingId + && id(detail?.containerBookingId) === identity.containerBookingId, + `missing=${detailGaps.join(',') || 'none'}, oceanBookingId=${id(detail?.oceanBookingId) || 'missing'}, containerBookingId=${id(detail?.containerBookingId) || 'missing'}`, OPTIONS) context.createdResources.truckAppointment = { id: appointmentId, marker: context.marker, finalStatus: 'DISPATCHED', oceanBookingId: identity.oceanBookingId, containerBookingId: identity.containerBookingId } }