diff --git a/scripts/admin-test-env-modules/phase3-container-regression-contract.test.mjs b/scripts/admin-test-env-modules/phase3-container-regression-contract.test.mjs index 743ca33d8..4445e2f2b 100644 --- a/scripts/admin-test-env-modules/phase3-container-regression-contract.test.mjs +++ b/scripts/admin-test-env-modules/phase3-container-regression-contract.test.mjs @@ -71,9 +71,13 @@ test('truck attachment API and Admin upload-reference-delete flow are frozen', ( assert.match(truckAttachmentDialog, /uploadTruckAppointmentAttachment/) assert.match(truckAttachmentDialog, /上传并关联/) assert.match(truckAttachmentDialog, /confirmButtonText: '确认', cancelButtonText: '取消'/) - assert.match(truckAcceptance, /attachmentType=BILL_OF_LADING/) - assert.match(truckAcceptance, /派车前保留有效 BILL_OF_LADING 提单附件/) - assert.match(truckAcceptance, /缺提单号与文件明确拒绝/) + for (const type of ['DISPATCH_ORDER', 'DRIVER_DOCUMENT', 'VEHICLE_DOCUMENT', 'OTHER']) + assert.match(truckAttachmentDialog, new RegExp(type)) + assert.doesNotMatch(truckAttachmentDialog, /BILL_OF_LADING/) + for (const label of ['上传并关联DISPATCH_ORDER拖车附件', '删除首次上传的拖车附件引用', + '重新引用平台归属拖车附件', '附件列表包含重新引用的DISPATCH_ORDER', '删除重新引用的拖车附件']) + assert.match(truckAcceptance, new RegExp(label)) + assert.doesNotMatch(truckAcceptance, /attachmentType=BILL_OF_LADING|派车前保留有效 BILL_OF_LADING 提单附件/) assert.match(matrix, /拖车附件闭环[\s\S]*`LANDED`/) }) @@ -113,10 +117,9 @@ test('PDA task opens only after no-number push, release, four-field link and pla }) test('customer public display uses tenantName without a legalName fallback', () => { - for (const source of [truckList, containerList]) { - assert.match(source, /label: customer\.tenantName/) - } - assert.match(truckForm, /return customer\.tenantName/) + assert.match(containerList, /label: customer\.tenantName/) + for (const source of [truckList, truckForm]) + assert.doesNotMatch(source, /customer\.(?:tenantName|legalName)/) for (const source of [truckList, containerList, truckForm]) assert.doesNotMatch(source, /customer\.legalName\?\.trim\(\) \|\| customer\.tenantName/) assert.match(matrix, /客户公开名称一致性[\s\S]*已统一 `tenantName`[\s\S]*`LANDED`/) 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 bfdd18387..3eeaab7a3 100644 --- a/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs +++ b/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs @@ -94,6 +94,9 @@ test('HTTP regression is self-contained and covers no-customer and idempotency m '同键同载荷重放', '同键重放版本零漂移', '同键异载荷拒绝', '错误订舱拒绝创建', '错误柜号归属拒绝创建', '错误提单拒绝创建', '错误承运商拒绝创建', '非法拖车币种拒绝创建', 'RMB应付费用响应无客户及应收字段', '编辑为USD应付费用', 'USD应付费用保存且无应收字段', + '上传并关联DISPATCH_ORDER拖车附件', '拖车附件类型仅使用运营附件而非订舱提单', + '删除首次上传的拖车附件引用', '重新引用平台归属拖车附件', '附件列表包含重新引用的DISPATCH_ORDER', + '删除重新引用的拖车附件', '派车命令返回状态身份与版本正确', '派车后回查拖车完整详情', '详情字段完整且订舱柜号身份无客户字段漂移']) assert.match(source, new RegExp(label)) assert.match(source, /const detailResponse = await request\(context, 'GET', path\); const detail = data\(detailResponse\)/) diff --git a/scripts/admin-test-env-modules/truck-appointments.mjs b/scripts/admin-test-env-modules/truck-appointments.mjs index 077376ab9..3fc3fae36 100644 --- a/scripts/admin-test-env-modules/truck-appointments.mjs +++ b/scripts/admin-test-env-modules/truck-appointments.mjs @@ -185,6 +185,29 @@ export async function run(context) { && !Object.hasOwn(appointment, 'receivableAmount') && !Object.hasOwn(appointment, 'customerId') && !Object.hasOwn(appointment, 'customerName'), '', OPTIONS) const path = `${TRUCKS}/${appointmentId}` + const attachmentForm = new FormData(); attachmentForm.append('attachmentType', 'DISPATCH_ORDER') + attachmentForm.append('file', new Blob([`${context.marker}-DISPATCH_ORDER`], { type: 'application/pdf' }), + `dispatch-order-${identity.suffix}.pdf`) + const uploadAttachmentResponse = await context.requestMultipart('POST', `${path}/attachments/upload`, + attachmentForm, context.token) + const uploadedAttachment = context.apiSuccess(MODULE, '上传并关联DISPATCH_ORDER拖车附件', uploadAttachmentResponse, '', OPTIONS) + const uploadedAttachmentId = id(uploadedAttachment?.id); const uploadedFileId = id(uploadedAttachment?.fileId) + context.assert(MODULE, '拖车附件类型仅使用运营附件而非订舱提单', uploadAttachmentResponse, + Boolean(uploadedAttachmentId && uploadedFileId) && uploadedAttachment?.attachmentType === 'DISPATCH_ORDER', + `attachmentId=${uploadedAttachmentId || 'missing'}, fileId=${uploadedFileId || 'missing'}`, OPTIONS) + const deleteUploadedResponse = await request(context, 'DELETE', `${path}/attachments/${uploadedAttachmentId}`) + context.apiSuccess(MODULE, '删除首次上传的拖车附件引用', deleteUploadedResponse, '', OPTIONS) + const referenceResponse = await request(context, 'POST', `${path}/attachments`, + { fileId: uploadedFileId, attachmentType: 'DISPATCH_ORDER' }) + const referencedAttachment = context.apiSuccess(MODULE, '重新引用平台归属拖车附件', referenceResponse, '', OPTIONS) + const referencedAttachmentId = id(referencedAttachment?.id) + const attachmentListResponse = await request(context, 'GET', `${path}/attachments`) + const attachmentList = context.apiSuccess(MODULE, '查询拖车运营附件列表', attachmentListResponse, '', OPTIONS) + context.assert(MODULE, '附件列表包含重新引用的DISPATCH_ORDER', attachmentListResponse, + Array.isArray(attachmentList) && attachmentList.some((item) => id(item?.id) === referencedAttachmentId + && item?.attachmentType === 'DISPATCH_ORDER'), `attachmentId=${referencedAttachmentId || 'missing'}`, OPTIONS) + const deleteReferencedResponse = await request(context, 'DELETE', `${path}/attachments/${referencedAttachmentId}`) + context.apiSuccess(MODULE, '删除重新引用的拖车附件', deleteReferencedResponse, '', OPTIONS) const usdResponse = await request(context, 'PUT', path, { ...base, currency: 'USD', payableAmount: 12.34, expectedVersion: Number(appointment.version) }) const usdAppointment = context.apiSuccess(MODULE, '编辑为USD应付费用', usdResponse, '', OPTIONS)