test: align ocean booking fixtures with direct confirmed flow
This commit is contained in:
@@ -33,22 +33,7 @@ async function createConfirmedUnassignedBooking(context, suffix, master) {
|
||||
`bookingId=${bookingId || 'missing'}, customerId=${id(created?.oceanBooking?.customerId) || 'null'}, customerName=${created?.oceanBooking?.customerName || 'null'}`, OPTIONS)
|
||||
if (!bookingId) return null
|
||||
|
||||
const hiddenResponse = await request(context, 'GET', `${BASE}?page=1&size=20&keyword=${encodeURIComponent(createdBookingNo)}`)
|
||||
const hiddenPage = context.apiSuccess(MODULE, '未确认订舱不进入正式订舱列表', hiddenResponse, '', OPTIONS)
|
||||
context.assert(MODULE, 'DRAFT 未指定客户订舱仅可按详情维护', hiddenResponse,
|
||||
!hiddenPage?.records?.some?.((item) => id(item.id) === bookingId),
|
||||
`bookingId=${bookingId}, records=${hiddenPage?.records?.length ?? 'n/a'}`, OPTIONS)
|
||||
|
||||
const path = `${BASE}/${bookingId}`
|
||||
const submitResponse = await request(context, 'POST', `${path}/submit`, {
|
||||
expectedVersion: Number(created.oceanBooking.version), reason: context.marker,
|
||||
}, { 'Idempotency-Key': `${context.marker}-ocean-unassigned-submit`.slice(0, 128) })
|
||||
const submitted = context.apiSuccess(MODULE, '提交未指定客户订舱', submitResponse, '', OPTIONS)
|
||||
const confirmResponse = await request(context, 'POST', `${path}/confirm`, {
|
||||
expectedVersion: Number(submitted?.oceanBooking?.version), reason: context.marker,
|
||||
}, { 'Idempotency-Key': `${context.marker}-ocean-unassigned-confirm`.slice(0, 128) })
|
||||
context.apiSuccess(MODULE, '确认未指定客户真实订舱', confirmResponse, '', OPTIONS)
|
||||
|
||||
const detailResponse = await request(context, 'GET', path)
|
||||
const detail = context.apiSuccess(MODULE, '回查未指定客户订舱持久化结果', detailResponse, '', OPTIONS)
|
||||
const bookingNo = id(detail?.oceanBooking?.bookingNo || created?.oceanBooking?.bookingNo)
|
||||
@@ -135,29 +120,23 @@ export async function run(context) {
|
||||
const createResponse = await createBooking(context, suffix, key, master)
|
||||
const detail = data(createResponse); const bookingId = id(detail?.oceanBooking?.id)
|
||||
context.apiSuccess(MODULE, '创建隔离海运订舱', createResponse, `key=${key}`, OPTIONS)
|
||||
context.assert(MODULE, '订舱 DTO 字段、DRAFT 和9类关联字段完整', createResponse, Boolean(bookingId) && detail?.oceanBooking?.status === 'DRAFT' && detail?.parties?.length === 3 && detail?.containerRequirements?.length === 1, `bookingId=${bookingId || 'missing'}, parties=${detail?.parties?.length ?? 'n/a'}, requirements=${detail?.containerRequirements?.length ?? 'n/a'}`, OPTIONS)
|
||||
context.assert(MODULE, '线下已确认订舱 DTO、运输快照和关联字段完整', createResponse,
|
||||
Boolean(bookingId) && detail?.oceanBooking?.status === 'CONFIRMED'
|
||||
&& detail?.parties?.length === 3 && detail?.containerRequirements?.length === 1
|
||||
&& ['billOfLadingNo', 'vesselName', 'voyageNo', 'estimatedSailingAt', 'estimatedArrivalAt']
|
||||
.every((field) => Boolean(detail?.oceanBooking?.[field])),
|
||||
`bookingId=${bookingId || 'missing'}, status=${detail?.oceanBooking?.status || 'missing'}, parties=${detail?.parties?.length ?? 'n/a'}, requirements=${detail?.containerRequirements?.length ?? 'n/a'}`, OPTIONS)
|
||||
context.assert(MODULE, '指定客户订舱持久化本轮客户范围快照', createResponse,
|
||||
id(detail?.oceanBooking?.customerId) === id(master.customerId) && detail?.oceanBooking?.customerName === master.customerName,
|
||||
`expectedCustomerId=${id(master.customerId)}, actualCustomerId=${id(detail?.oceanBooking?.customerId) || 'missing'}`, OPTIONS)
|
||||
if (!bookingId) return
|
||||
context.createdResources.oceanBooking = { id: bookingId, customerId: master.customerId, marker: context.marker,
|
||||
containerBookingId: null, loadingPlanId: null, finalStatus: 'DRAFT' }
|
||||
containerBookingId: null, loadingPlanId: null, finalStatus: 'CONFIRMED' }
|
||||
const replay = await createBooking(context, suffix, key, master)
|
||||
context.assert(MODULE, '创建 Idempotency-Key 重放返回同一订舱', replay, String(data(replay)?.oceanBooking?.id) === bookingId, `first=${bookingId}, replay=${id(data(replay)?.oceanBooking?.id)}`, OPTIONS)
|
||||
const path = `${BASE}/${bookingId}`
|
||||
const initialVersion = Number(detail.oceanBooking.version)
|
||||
const edited = { ...oceanBookingDraft(context, suffix, master), shippingCompanyName: `编辑船司-${suffix}` }
|
||||
const update = await request(context, 'PUT', path, { expectedVersion: initialVersion, data: edited }, { 'Idempotency-Key': `${context.marker}-ocean-edit` })
|
||||
context.apiSuccess(MODULE, '编辑 DRAFT 订舱', update, `version=${initialVersion}`, OPTIONS)
|
||||
const stale = await request(context, 'PUT', path, { expectedVersion: initialVersion, data: { ...edited, shippingCompanyName: `STALE-${suffix}` } }, { 'Idempotency-Key': `${context.marker}-ocean-stale` })
|
||||
step(context, '订舱旧版本编辑返回冲突', stale, stale.http === 200 && ['A0409', '409'].includes(codeOf(stale)), `HTTP=${stale.http}, code=${codeOf(stale)}`)
|
||||
const afterStale = await request(context, 'GET', path); const afterData = data(afterStale)
|
||||
context.apiSuccess(MODULE, '冲突后回查订舱', afterStale, '', OPTIONS)
|
||||
context.assert(MODULE, '订舱冲突未部分更新', afterStale, afterData?.oceanBooking?.shippingCompanyName === edited.shippingCompanyName, `shippingCompanyName=${afterData?.oceanBooking?.shippingCompanyName || 'missing'}`, OPTIONS)
|
||||
let version = Number(afterData?.oceanBooking?.version)
|
||||
let version = Number(detail.oceanBooking.version)
|
||||
const action = async (name, endpoint, expected, reason) => { const r = await request(context, 'POST', `${path}/${endpoint}`, { expectedVersion: expected, reason }, { 'Idempotency-Key': `${context.marker}-ocean-${endpoint}` }); const d = data(r); context.apiSuccess(MODULE, name, r, `status=${d?.oceanBooking?.status || 'missing'}`, OPTIONS); version = Number(d?.oceanBooking?.version); return d }
|
||||
await action('提交订舱', 'submit', version, 'marker submit')
|
||||
await action('确认订舱', 'confirm', version, 'marker confirm')
|
||||
const changed = await request(context, 'POST', `${path}/change-request`, { expectedVersion: version, vesselName: `改船-${suffix}`, voyageNo: `CV${suffix}`, reason: context.marker }, { 'Idempotency-Key': `${context.marker}-change` })
|
||||
context.apiSuccess(MODULE, '申请改船', changed, '', OPTIONS); version = Number(data(changed)?.oceanBooking?.version)
|
||||
const changeConfirmed = await action('确认改船', 'change-confirm', version, 'confirm change')
|
||||
@@ -185,7 +164,7 @@ export async function run(context) {
|
||||
const final = await request(context, 'GET', path); const fd = data(final)
|
||||
context.apiSuccess(MODULE, '回查 RELEASED 订舱详情', final, '', OPTIONS)
|
||||
context.assert(MODULE, '独立订舱状态历史、审计操作者和终态完整', final,
|
||||
fd?.oceanBooking?.status === 'RELEASED' && fd.histories?.length >= 5 && fd.histories.every((h) => h.operatorName)
|
||||
fd?.oceanBooking?.status === 'RELEASED' && fd.histories?.length >= 4 && fd.histories.every((h) => h.operatorName)
|
||||
&& fd?.containerAllocations?.length === 0,
|
||||
`status=${fd?.oceanBooking?.status || 'missing'}, histories=${fd?.histories?.length ?? 'n/a'}, allocations=${fd?.containerAllocations?.length ?? 'n/a'}`, OPTIONS)
|
||||
let downstreamBooking = {
|
||||
|
||||
Reference in New Issue
Block a user