Files
baiyue-firstleg/scripts/admin-test-env-modules/service-center-flow.mjs
T

63 lines
4.8 KiB
JavaScript

const MODULE = 'service-center-flow'
const OPTIONS = { scenario: 'service-center-cross-flow', deploymentBlocker: true }
const OCEAN = '/api/platform/v1/ocean-bookings'
const TRUCK = '/api/platform/v1/truck-appointments'
function id(value) { return value == null ? '' : String(value) }
function codeOf(response) { return response?.body?.code == null ? 'missing' : String(response.body.code) }
export async function run(context) {
const ocean = context.createdResources?.oceanBooking
if (!ocean?.id || ocean.finalStatus !== 'RELEASED') {
context.addStep(MODULE, '跨服务链路前置订舱终态可用', null, false,
'本轮海运订舱模块未返回 RELEASED 隔离记录,未伪造关联拖车预约', OPTIONS)
return
}
const suffix = context.marker.replace(/\D/g, '').slice(-10)
const oceanResponse = await context.request('GET', `${OCEAN}/${ocean.id}`)
const oceanDetail = context.apiSuccess(MODULE, '读取跨服务链路订舱真实客户归属', oceanResponse, `oceanBookingId=${ocean.id}`, OPTIONS)
const customerId = id(oceanDetail?.oceanBooking?.customerId)
context.assert(MODULE, '跨服务链路订舱客户归属有效', oceanResponse, Boolean(customerId), `customerId=${customerId || 'missing'}`, OPTIONS)
if (!customerId) return
const payload = {
outboundOrderId: null, oceanBookingId: ocean.id, containerBookingId: null, loadingPlanId: null,
warehouseId: id(context.createdResources?.warehouse?.id || context.context?.warehouseId || '193000000000000001'),
customerId, customerName: `服务中心链路客户-${suffix}`, carrierId: null, carrierName: `链路承运商-${suffix}`,
fleetContact: '链路车队联系人', fleetPhone: '13800000007', driverName: '链路司机', driverPhone: '13800000008',
driverIdCard: null, vehicleNo: `粤D-${suffix.slice(-6)}`, storeName: `链路门店-${suffix}`, storeContact: '链路联系人',
storePhone: '13800000009', storeAddress: '深圳市南山区链路地址', storeCity: '深圳市', storeZipcode: '518000',
packageCount: 1, grossWeightKg: 1, volumeCbm: 0.1, palletCount: 0, poNo: `FLOW-PO-${suffix}`,
plannedLoadingAt: '2026-09-03T08:00:00', transitMinutes: 60, payableAmount: 1, receivableAmount: 2,
currency: 'RMB', remark: context.marker, expectedVersion: 0,
}
const response = await context.request('POST', TRUCK, payload)
const appointment = context.apiSuccess(MODULE, '创建关联海运订舱的拖车预约', response, `oceanBookingId=${ocean.id}`, OPTIONS)
const appointmentId = id(appointment?.id)
context.assert(MODULE, '拖车预约关联订舱 ID、版本和审计字段完整', response,
Boolean(appointmentId) && id(appointment?.oceanBookingId) === id(ocean.id) && Number.isFinite(Number(appointment?.version))
&& Boolean(appointment?.createdAt || appointment?.createdBy || appointment?.operatorName),
`appointmentId=${appointmentId || 'missing'}, oceanBookingId=${appointment?.oceanBookingId || 'missing'}, version=${appointment?.version ?? 'missing'}`, OPTIONS)
if (!appointmentId) return
context.createdResources.serviceCenterFlow = { appointmentId, oceanBookingId: ocean.id, marker: context.marker, finalStatus: 'CANCELLED' }
const action = await context.request('POST', `${TRUCK}/${appointmentId}/cancel`, { expectedVersion: Number(appointment.version), reason: context.marker })
const cancelled = context.apiSuccess(MODULE, '取消跨服务链路拖车预约', action, '', OPTIONS)
context.assert(MODULE, '跨服务链路安全终态为 CANCELLED', action, cancelled?.status === 'CANCELLED', `status=${cancelled?.status || 'missing'}`, OPTIONS)
const detail = await context.request('GET', `${TRUCK}/${appointmentId}`)
const final = context.apiSuccess(MODULE, '回查跨服务链路安全终态', detail, '', OPTIONS)
context.assert(MODULE, '跨服务链路终态持久化且关联订舱未漂移', detail,
final?.status === 'CANCELLED' && id(final?.oceanBookingId) === id(ocean.id),
`status=${final?.status || 'missing'}, oceanBookingId=${final?.oceanBookingId || 'missing'}`, OPTIONS)
const historyResponse = await context.request('GET', `${TRUCK}/${appointmentId}/history`)
const history = context.apiSuccess(MODULE, '查询跨服务链路拖车预约状态历史', historyResponse, '', OPTIONS)
const cancel = Array.isArray(history) ? history.find((item) => item?.action === 'CANCEL') : null
context.assert(MODULE, '跨服务链路历史包含归属、状态、操作者、时间和备注', historyResponse,
Boolean(cancel) && id(cancel?.appointmentId) === appointmentId
&& cancel?.fromStatus === 'DRAFT' && cancel?.toStatus === 'CANCELLED'
&& Boolean(cancel?.operatorId) && Boolean(cancel?.operatorName) && Boolean(cancel?.createdAt)
&& cancel?.reason === context.marker,
`history=${history?.length ?? 'n/a'}, cancelFrom=${cancel?.fromStatus || 'missing'}, cancelTo=${cancel?.toStatus || 'missing'}`,
OPTIONS)
}