优化
This commit is contained in:
@@ -26,7 +26,7 @@ async function request(context, method, path, body, headers = {}) {
|
||||
}
|
||||
|
||||
async function uploadAttachment(context, appointmentId) {
|
||||
const path = `${BASE}/${appointmentId}/attachments/upload?attachmentType=ACCEPTANCE_EVIDENCE`
|
||||
const path = `${BASE}/${appointmentId}/attachments/upload?attachmentType=BILL_OF_LADING`
|
||||
const form = new FormData()
|
||||
const png = Uint8Array.from([137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,1,0,0,0,1,8,6,0,0,0,31,21,196,137,0,0,0,13,73,68,65,84,8,215,99,248,207,192,240,31,0,5,0,1,255,137,153,61,29,0,0,0,0,73,69,78,68,174,66,96,130])
|
||||
form.append('file', new Blob([png], { type: 'image/png' }), `${context.marker}-truck.png`)
|
||||
@@ -89,6 +89,8 @@ export function truckAppointmentPayload(context, suffix, identity, version = 0,
|
||||
loadingPlanId: associations.loadingPlanId || null, warehouseId: associations.warehouseId || null,
|
||||
customerId: identity.customerId, customerName: identity.customerName || null,
|
||||
carrierId: supplierId || null, carrierName: supplierName || null,
|
||||
billOfLadingNo: Object.hasOwn(associations, 'billOfLadingNo')
|
||||
? associations.billOfLadingNo : `BL-TRUCK-${suffix}`.slice(0, 128),
|
||||
fleetContact: '车队联系人', fleetPhone: '13800000004',
|
||||
driverName: '司机验收', driverPhone: '13800000005', driverIdCard: null, vehicleNo: `粤B-${suffix.slice(-6)}`,
|
||||
storeName: `门店-${suffix}`, storeContact: '门店联系人', storePhone: '13800000006', storeAddress: '深圳市南山区验收地址',
|
||||
@@ -155,6 +157,21 @@ export async function run(context) {
|
||||
`HTTP=${rejected.http}, code=${codeOf(rejected)}, requestId=${rejected.requestId || 'missing'}, traceId=${rejected.traceId || 'missing'}`, OPTIONS)
|
||||
}
|
||||
|
||||
const missingBillCreate = await request(context, 'POST', BASE,
|
||||
truckAppointmentPayload(context, `${suffix}B`, customerIdentity, 0, { billOfLadingNo: null }))
|
||||
const missingBill = data(missingBillCreate)
|
||||
if (missingBill?.id) {
|
||||
const missingBillSubmit = await request(context, 'POST', `${BASE}/${id(missingBill.id)}/submit`,
|
||||
{ expectedVersion: Number(missingBill.version), reason: context.marker },
|
||||
{ 'Idempotency-Key': `${context.marker}-truck-no-bill-submit`.slice(0, 128) })
|
||||
const submitted = data(missingBillSubmit)
|
||||
const rejectedDispatch = await request(context, 'POST', `${BASE}/${id(missingBill.id)}/dispatch`,
|
||||
{ expectedVersion: Number(submitted?.version), reason: context.marker },
|
||||
{ 'Idempotency-Key': `${context.marker}-truck-no-bill-dispatch`.slice(0, 128) })
|
||||
context.addStep(MODULE, '拖车 DRAFT 可无提单但 DISPATCH 缺提单号与文件明确拒绝', rejectedDispatch,
|
||||
failure(rejectedDispatch), `HTTP=${rejectedDispatch.http}, code=${codeOf(rejectedDispatch)}`, OPTIONS)
|
||||
}
|
||||
|
||||
const linkedFlow = [context.createdResources?.phase3Loading, context.createdResources?.phase3ContainerLoading]
|
||||
.find((item) => item?.marker === context.marker && id(item.containerBookingId) && id(item.loadingPlanId))
|
||||
if (linkedFlow) {
|
||||
@@ -204,20 +221,14 @@ export async function run(context) {
|
||||
|
||||
const upload = await uploadAttachment(context, appointmentId); const attachment = context.apiSuccess(MODULE, '上传本轮拖车预约图片附件', upload, `fileName=${context.marker}-truck.png`, OPTIONS)
|
||||
const attachmentId = id(attachment?.id)
|
||||
context.assert(MODULE, '附件引用归属、类型和哈希元数据完整', upload, Boolean(attachmentId) && id(attachment?.appointmentId) === appointmentId && attachment?.attachmentType === 'ACCEPTANCE_EVIDENCE' && Boolean(attachment?.fileId) && Boolean(attachment?.fileHash), `attachmentId=${attachmentId || 'missing'}, fileId=${attachment?.fileId || 'missing'}`, OPTIONS)
|
||||
context.assert(MODULE, '提单附件归属、类型和哈希元数据完整', upload, Boolean(attachmentId) && id(attachment?.appointmentId) === appointmentId && attachment?.attachmentType === 'BILL_OF_LADING' && Boolean(attachment?.fileId) && Boolean(attachment?.fileHash), `attachmentId=${attachmentId || 'missing'}, fileId=${attachment?.fileId || 'missing'}`, OPTIONS)
|
||||
const attachments = await request(context, 'GET', `${path}/attachments`); const attachmentList = context.apiSuccess(MODULE, '查询拖车预约附件列表', attachments, '', OPTIONS)
|
||||
context.assert(MODULE, '附件列表包含本轮上传引用', attachments, Array.isArray(attachmentList) && attachmentList.some((item) => id(item.id) === attachmentId), `attachments=${attachmentList?.length ?? 'n/a'}`, OPTIONS)
|
||||
const forged = await request(context, 'POST', `${path}/attachments`, { fileId: '999999999999999999', attachmentType: 'ACCEPTANCE_EVIDENCE', fileName: `${context.marker}-forged.txt`, fileHash: 'forged' })
|
||||
const forged = await request(context, 'POST', `${path}/attachments`, { fileId: '999999999999999999', attachmentType: 'BILL_OF_LADING', fileName: `${context.marker}-forged.txt`, fileHash: 'forged' })
|
||||
context.addStep(MODULE, '伪造附件 fileId 安全拒绝', forged, failure(forged), `HTTP=${forged.http}, code=${codeOf(forged)}`, OPTIONS)
|
||||
if (attachmentId) {
|
||||
const removed = await request(context, 'DELETE', `${path}/attachments/${attachmentId}`)
|
||||
context.apiSuccess(MODULE, '删除本轮拖车预约附件引用', removed, `attachmentId=${attachmentId}`, OPTIONS)
|
||||
const afterRemoval = await request(context, 'GET', `${path}/attachments`)
|
||||
const remainingAttachments = context.apiSuccess(MODULE, '删除后回查拖车预约附件列表', afterRemoval, '', OPTIONS)
|
||||
context.assert(MODULE, '删除后附件引用不再返回', afterRemoval,
|
||||
Array.isArray(remainingAttachments) && !remainingAttachments.some((item) => id(item.id) === attachmentId),
|
||||
`attachmentId=${attachmentId}, remaining=${remainingAttachments?.length ?? 'n/a'}`, OPTIONS)
|
||||
}
|
||||
context.assert(MODULE, '派车前保留有效 BILL_OF_LADING 提单附件', attachments,
|
||||
Boolean(attachmentId) && attachmentList.some((item) => id(item.id) === attachmentId && item.attachmentType === 'BILL_OF_LADING'),
|
||||
`attachmentId=${attachmentId || 'missing'}`, OPTIONS)
|
||||
|
||||
let version = Number(appointment.version)
|
||||
const edit = await request(context, 'PUT', path, { ...truckAppointmentPayload(context, suffix, customerIdentity, version), vehicleNo: `粤C-${suffix.slice(-6)}` }); const edited = context.apiSuccess(MODULE, '编辑独立拖车预约且关联身份保持为空', edit, `version=${version}`, OPTIONS); version = Number(edited?.version)
|
||||
|
||||
Reference in New Issue
Block a user