优化
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { ensureMatsonCarrierPartner } from './carrier-partner-fixture.mjs'
|
||||
import { oceanBookingDraft } from './ocean-booking-fixture.mjs'
|
||||
import { truckAppointmentFieldGaps } from './fulfillment-list-field-contract.mjs'
|
||||
|
||||
const MODULE = 'truck-appointments'
|
||||
const OPTIONS = { scenario: 'booking-level-truck-appointment-lifecycle', deploymentBlocker: true }
|
||||
@@ -9,6 +10,9 @@ const FORBIDDEN_TRUCK_FIELDS = ['containerBookingId', 'loadingPlanId', 'containe
|
||||
|
||||
function id(value) { return value == null ? '' : String(value) }
|
||||
function codeOf(response) { return response?.body?.code == null ? 'missing' : String(response.body.code) }
|
||||
function responseEvidence(response) {
|
||||
return `HTTP=${response?.http ?? 'missing'}, code=${codeOf(response)}, requestId=${response?.requestId || 'missing'}, traceId=${response?.traceId || 'missing'}`
|
||||
}
|
||||
function data(response) { return codeOf(response) === '200' ? response.body.data : null }
|
||||
function failure(response) { return response?.http === 0 || response?.http >= 400 || (response?.http === 200 && codeOf(response) !== '200') }
|
||||
function records(value) { return Array.isArray(value) ? value : value?.records || [] }
|
||||
@@ -201,8 +205,10 @@ export async function run(context) {
|
||||
const appointmentId = id(appointment?.id); if (!appointmentId) return
|
||||
const path = `${TRUCKS}/${appointmentId}`
|
||||
context.assert(MODULE, '创建响应完全无柜次协议且费用正确', createdResponse,
|
||||
!hasForbiddenTruckFields(appointment) && appointment?.currency === 'RMB' && Number(appointment?.payableAmount) === 0,
|
||||
`appointmentNo=${appointment?.appointmentNo || 'missing'}`, OPTIONS)
|
||||
truckAppointmentFieldGaps(appointment).length === 0
|
||||
&& !hasForbiddenTruckFields(appointment) && appointment?.currency === 'RMB'
|
||||
&& Number(appointment?.payableAmount) === 0,
|
||||
`appointmentNo=${appointment?.appointmentNo || 'missing'}, fieldGaps=${truckAppointmentFieldGaps(appointment).join('|') || 'none'}`, OPTIONS)
|
||||
const afterCreateCandidate = await candidate(context, identity)
|
||||
context.assert(MODULE, '创建后订舱立即退出候选', afterCreateCandidate.response, !afterCreateCandidate.item,
|
||||
`appointmentNo=${appointment.appointmentNo}`, OPTIONS)
|
||||
@@ -219,12 +225,45 @@ export async function run(context) {
|
||||
`dispatch-order-${identity.suffix}.pdf`)
|
||||
const uploadAttachmentResponse = await context.requestMultipart('POST', `${path}/attachments/upload`,
|
||||
attachmentForm, context.token)
|
||||
const attachment = context.apiSuccess(MODULE, '上传DISPATCH_ORDER拖车附件', uploadAttachmentResponse, '', OPTIONS)
|
||||
const attachment = context.apiSuccess(MODULE, '上传并关联DISPATCH_ORDER拖车附件', uploadAttachmentResponse, '', OPTIONS)
|
||||
const attachmentListResponse = await request(context, 'GET', `${path}/attachments`)
|
||||
const attachmentList = context.apiSuccess(MODULE, '查询拖车附件列表', attachmentListResponse, '', OPTIONS)
|
||||
context.assert(MODULE, '附件列表包含本轮运营附件', attachmentListResponse,
|
||||
records(attachmentList).some((item) => id(item?.id) === id(attachment?.id) && item?.attachmentType === 'DISPATCH_ORDER'),
|
||||
`attachmentId=${id(attachment?.id) || 'missing'}`, OPTIONS)
|
||||
if (!attachment?.id || !attachment?.fileId) return
|
||||
const deleteUploadedResponse = await request(context, 'DELETE',
|
||||
`${path}/attachments/${encodeURIComponent(id(attachment?.id))}`)
|
||||
context.addStep(MODULE, '删除首次上传的拖车附件引用', deleteUploadedResponse,
|
||||
deleteUploadedResponse.http === 200 && codeOf(deleteUploadedResponse) === '200',
|
||||
responseEvidence(deleteUploadedResponse), OPTIONS)
|
||||
const referencedResponse = await request(context, 'POST', `${path}/attachments`, {
|
||||
fileId: id(attachment?.fileId), attachmentType: 'DISPATCH_ORDER',
|
||||
fileName: attachment?.fileName || `dispatch-order-${identity.suffix}.pdf`,
|
||||
fileHash: attachment?.fileHash || null,
|
||||
})
|
||||
const referenced = context.apiSuccess(MODULE, '重新引用平台归属拖车附件', referencedResponse, '', OPTIONS)
|
||||
const referencedListResponse = await request(context, 'GET', `${path}/attachments`)
|
||||
const referencedList = context.apiSuccess(MODULE, '回查重新引用的拖车附件', referencedListResponse, '', OPTIONS)
|
||||
context.assert(MODULE, '附件列表包含重新引用的DISPATCH_ORDER', referencedListResponse,
|
||||
records(referencedList).some((item) => id(item?.id) === id(referenced?.id)
|
||||
&& id(item?.fileId) === id(attachment?.fileId) && item?.attachmentType === 'DISPATCH_ORDER'),
|
||||
`attachmentId=${id(referenced?.id) || 'missing'}, fileId=${id(attachment?.fileId) || 'missing'}`, OPTIONS)
|
||||
const deleteReferencedResponse = await request(context, 'DELETE',
|
||||
`${path}/attachments/${encodeURIComponent(id(referenced?.id))}`)
|
||||
context.addStep(MODULE, '删除重新引用的拖车附件', deleteReferencedResponse,
|
||||
deleteReferencedResponse.http === 200 && codeOf(deleteReferencedResponse) === '200',
|
||||
responseEvidence(deleteReferencedResponse), OPTIONS)
|
||||
const replacementForm = new FormData(); replacementForm.append('attachmentType', 'DISPATCH_ORDER')
|
||||
replacementForm.append('file', new Blob([minimalPdfBytes(`${context.marker}-DISPATCH_ORDER-REPLACEMENT`)],
|
||||
{ type: 'application/pdf' }), `dispatch-order-replacement-${identity.suffix}.pdf`)
|
||||
const replacementResponse = await context.requestMultipart('POST', `${path}/attachments/upload`,
|
||||
replacementForm, context.token)
|
||||
const replacement = context.apiSuccess(MODULE, '恢复一份DISPATCH_ORDER拖车附件供后续状态流转',
|
||||
replacementResponse, '', OPTIONS)
|
||||
context.assert(MODULE, '恢复附件使用新引用且仍指向平台文件', replacementResponse,
|
||||
Boolean(id(replacement?.id) && id(replacement?.fileId)) && id(replacement?.id) !== id(attachment?.id),
|
||||
`attachmentId=${id(replacement?.id) || 'missing'}, fileId=${id(replacement?.fileId) || 'missing'}`, OPTIONS)
|
||||
|
||||
const editedResponse = await request(context, 'PUT', path,
|
||||
truckAppointmentPayload(context, identity.suffix, identity, Number(appointment.version), { currency: 'USD', payableAmount: 12.34 }))
|
||||
@@ -254,9 +293,10 @@ export async function run(context) {
|
||||
const finalDetailResponse = await request(context, 'GET', path)
|
||||
const finalDetail = context.apiSuccess(MODULE, '回查COMPLETED订舱级拖车详情', finalDetailResponse, '', OPTIONS)
|
||||
context.assert(MODULE, '完整生命周期完成且详情无柜次协议', finalDetailResponse,
|
||||
finalDetail?.status === 'COMPLETED' && !hasForbiddenTruckFields(finalDetail)
|
||||
finalDetail?.status === 'COMPLETED' && truckAppointmentFieldGaps(finalDetail).length === 0
|
||||
&& !hasForbiddenTruckFields(finalDetail)
|
||||
&& id(finalDetail?.oceanBookingId) === identity.oceanBookingId,
|
||||
`appointmentNo=${finalDetail?.appointmentNo || 'missing'}, status=${finalDetail?.status || 'missing'}`, OPTIONS)
|
||||
`appointmentNo=${finalDetail?.appointmentNo || 'missing'}, status=${finalDetail?.status || 'missing'}, fieldGaps=${truckAppointmentFieldGaps(finalDetail).join('|') || 'none'}`, OPTIONS)
|
||||
const afterCompleteCandidate = await candidate(context, identity)
|
||||
context.assert(MODULE, 'COMPLETED后订舱恢复候选', afterCompleteCandidate.response, Boolean(afterCompleteCandidate.item),
|
||||
`oceanBookingNo=${identity.oceanBookingNo}`, OPTIONS)
|
||||
|
||||
Reference in New Issue
Block a user