|
|
|
@@ -183,56 +183,71 @@ async function runRefund(context, routes, fixture) {
|
|
|
|
|
|
|
|
|
|
const documents = frozenSnapshot?.documents || []
|
|
|
|
|
for (const [index, document] of documents.entries()) {
|
|
|
|
|
const completion = await routes.platformUploadCompletion(context, fixture, {
|
|
|
|
|
const receipt = await routes.platformUploadReceipt(context, fixture, {
|
|
|
|
|
documentId: id(document.documentId), expectedVersion: Number(document.source?.version),
|
|
|
|
|
fileName: `${context.marker}-completion-${index + 1}.done`,
|
|
|
|
|
contentType: 'application/x-customs-completion', content: Uint8Array.from([0x43, index + 1]),
|
|
|
|
|
}, key(context, `completion-${index + 1}`))
|
|
|
|
|
context.assert(MODULE, `逐份上传完成文件${index + 1}`, completion,
|
|
|
|
|
success(completion)
|
|
|
|
|
&& zeroDrift(completion.body?.data?.inboundIds, document.inboundIds),
|
|
|
|
|
evidence(completion, `sourceDocumentId=${id(document.documentId)}`), OPTIONS)
|
|
|
|
|
if (index + 1 < documents.length) {
|
|
|
|
|
const beforeEarlyComplete = await platformDetail(context, routes, fixture)
|
|
|
|
|
const early = await routes.platformComplete(context, fixture, {
|
|
|
|
|
expectedVersion: Number(beforeEarlyComplete.body?.data?.version), remark: 'not-last-completion',
|
|
|
|
|
}, key(context, `early-complete-${index + 1}`))
|
|
|
|
|
await assertZeroDrift(context, '最后一份完成文件前禁止整柜完成', routes, fixture, beforeEarlyComplete, early)
|
|
|
|
|
}
|
|
|
|
|
fileName: `${context.marker}-broker-receipt-${index + 1}.pdf`,
|
|
|
|
|
contentType: 'application/pdf', content: Uint8Array.from([0x52, index + 1]),
|
|
|
|
|
}, key(context, `receipt-${index + 1}`))
|
|
|
|
|
context.assert(MODULE, `逐份上传报关行回执${index + 1}`, receipt,
|
|
|
|
|
success(receipt) && zeroDrift(receipt.body?.data?.inboundIds, document.inboundIds),
|
|
|
|
|
evidence(receipt, `sourceDocumentId=${id(document.documentId)}`), OPTIONS)
|
|
|
|
|
}
|
|
|
|
|
const completedReady = await platformDetail(context, routes, fixture)
|
|
|
|
|
const beforeConfirm = await platformDetail(context, routes, fixture)
|
|
|
|
|
const earlyFinal = await routes.platformUploadFinal(context, fixture, {
|
|
|
|
|
documentId: id(documents[0]?.documentId), expectedVersion: 0,
|
|
|
|
|
fileName: `${context.marker}-early-final.pdf`, contentType: 'application/pdf', content: Uint8Array.from([0x45]),
|
|
|
|
|
}, key(context, 'early-final'))
|
|
|
|
|
await assertZeroDrift(context, '回执未确认且未发送执行时禁止上传完税文件', routes, fixture, beforeConfirm, earlyFinal)
|
|
|
|
|
const confirmed = []
|
|
|
|
|
for (const customer of customers) {
|
|
|
|
|
const document = documents.find((item) => (item.inboundIds || []).some((inboundId) =>
|
|
|
|
|
customer.inboundIds.map(id).includes(id(inboundId))))
|
|
|
|
|
if (!document) continue
|
|
|
|
|
const version = Number(document.source?.version || completedReady.body?.data?.documents
|
|
|
|
|
?.find((item) => id(item.documentId) === id(document.documentId))?.source?.version || 0)
|
|
|
|
|
const current = await platformDetail(context, routes, fixture)
|
|
|
|
|
const live = current.body?.data?.documents?.find((item) => id(item.documentId) === id(document.documentId))
|
|
|
|
|
const version = Number(live?.receipt?.version || 0)
|
|
|
|
|
const response = await routes.merchantConfirmReceipt(context, fixture, customer, {
|
|
|
|
|
documentId: id(document.documentId), expectedVersion: version, confirm: true, remark: context.marker,
|
|
|
|
|
}, key(context, `refund-receipt-confirm-${customer.customerId}`))
|
|
|
|
|
confirmed.push(response)
|
|
|
|
|
}
|
|
|
|
|
const afterConfirm = await platformDetail(context, routes, fixture)
|
|
|
|
|
context.assert(MODULE, '客户确认整份回执后仍处于报关中', afterConfirm,
|
|
|
|
|
success(afterConfirm) && afterConfirm.body?.data?.status === 'DECLARING' && confirmed.every(success),
|
|
|
|
|
evidence(afterConfirm), OPTIONS)
|
|
|
|
|
const submitted = await routes.platformSubmitToBroker(context, fixture,
|
|
|
|
|
{ expectedVersion: Number(afterConfirm.body?.data?.version), remark: context.marker }, key(context, 'submit-to-broker'))
|
|
|
|
|
context.assert(MODULE, '平台发送客户确认回执给报关行执行', submitted,
|
|
|
|
|
success(submitted) && submitted.body?.data?.status === 'DECLARING', evidence(submitted), OPTIONS)
|
|
|
|
|
const submitReplay = await routes.platformSubmitToBroker(context, fixture,
|
|
|
|
|
{ expectedVersion: Number(submitted.body?.data?.version), remark: context.marker }, key(context, 'submit-to-broker'))
|
|
|
|
|
context.assert(MODULE, '发送报关行执行同键重放', submitReplay, success(submitReplay), evidence(submitReplay), OPTIONS)
|
|
|
|
|
for (const [index, document] of documents.entries()) {
|
|
|
|
|
const finalDocument = await routes.platformUploadFinal(context, fixture, {
|
|
|
|
|
documentId: id(document.documentId), expectedVersion: 0,
|
|
|
|
|
fileName: `${context.marker}-customs-tax-final-${index + 1}.pdf`,
|
|
|
|
|
contentType: 'application/pdf', content: Uint8Array.from([0x46, index + 1]),
|
|
|
|
|
}, key(context, `final-${index + 1}`))
|
|
|
|
|
context.assert(MODULE, `逐份上传真实报关完税文件${index + 1}`, finalDocument,
|
|
|
|
|
success(finalDocument) && zeroDrift(finalDocument.body?.data?.inboundIds, document.inboundIds),
|
|
|
|
|
evidence(finalDocument), OPTIONS)
|
|
|
|
|
}
|
|
|
|
|
const completed = await platformDetail(context, routes, fixture)
|
|
|
|
|
context.assert(MODULE, '客户确认整份回执后纯退税柜完成', completed,
|
|
|
|
|
success(completed) && completed.body?.data?.status === 'COMPLETED'
|
|
|
|
|
&& confirmed.every(success), evidence(completed), OPTIONS)
|
|
|
|
|
|
|
|
|
|
context.assert(MODULE, '真实报关完税文件齐全后纯退税柜完成', completed,
|
|
|
|
|
success(completed) && completed.body?.data?.status === 'COMPLETED', evidence(completed), OPTIONS)
|
|
|
|
|
const firstDocument = documents[0]
|
|
|
|
|
if (firstDocument) {
|
|
|
|
|
const platformDownload = await routes.platformDownload(context, fixture, {
|
|
|
|
|
documentId: id(firstDocument.documentId), completion: true,
|
|
|
|
|
})
|
|
|
|
|
context.assert(MODULE, 'Admin下载完成文件窗口', platformDownload,
|
|
|
|
|
platformDownload.http === 200 && platformDownload.bytes?.length > 0,
|
|
|
|
|
`HTTP=${platformDownload.http}, bytes=${platformDownload.bytes?.length ?? 0}`, OPTIONS)
|
|
|
|
|
const merchantDownload = await routes.merchantDownload(context, fixture, mutable, {
|
|
|
|
|
documentId: id(firstDocument.documentId), completion: true,
|
|
|
|
|
})
|
|
|
|
|
context.assert(MODULE, 'Client仅下载本客户完成文件窗口', merchantDownload,
|
|
|
|
|
merchantDownload.http === 200 && merchantDownload.bytes?.length > 0,
|
|
|
|
|
`HTTP=${merchantDownload.http}, bytes=${merchantDownload.bytes?.length ?? 0}`, OPTIONS)
|
|
|
|
|
const platformReceipt = await routes.platformDownloadReceipt(context, fixture, { documentId: id(firstDocument.documentId) })
|
|
|
|
|
context.assert(MODULE, 'Admin下载报关行回执', platformReceipt,
|
|
|
|
|
platformReceipt.http === 200 && platformReceipt.bytes?.length > 0, evidence(platformReceipt), OPTIONS)
|
|
|
|
|
const platformFinal = await routes.platformDownloadFinal(context, fixture, { documentId: id(firstDocument.documentId) })
|
|
|
|
|
context.assert(MODULE, 'Admin下载真实报关完税文件', platformFinal,
|
|
|
|
|
platformFinal.http === 200 && platformFinal.bytes?.length > 0, evidence(platformFinal), OPTIONS)
|
|
|
|
|
const merchantFinal = await routes.merchantDownloadFinal(context, fixture, mutable, { documentId: id(firstDocument.documentId) })
|
|
|
|
|
context.assert(MODULE, 'Client仅下载本客户真实报关完税文件', merchantFinal,
|
|
|
|
|
merchantFinal.http === 200 && merchantFinal.bytes?.length > 0, evidence(merchantFinal), OPTIONS)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function runMixedConcurrency(context, routes, fixture) {
|
|
|
|
@@ -320,44 +335,55 @@ async function runMixedConcurrency(context, routes, fixture) {
|
|
|
|
|
}, key(context, 'locked-scope'))
|
|
|
|
|
await assertZeroDrift(context, '开始后资料范围锁定A0409零漂移', routes, fixture, { body: { data: frozen } }, locked)
|
|
|
|
|
|
|
|
|
|
const completionRequest = {
|
|
|
|
|
const receiptRequest = {
|
|
|
|
|
documentId: customer.documentId, expectedVersion: 0,
|
|
|
|
|
finalConfirmation: true, fileName: `${context.marker}-mixed-result.done`,
|
|
|
|
|
contentType: 'application/x-customs-completion', content: Uint8Array.from([0x52, 0x45, 0x53]),
|
|
|
|
|
fileName: `${context.marker}-mixed-broker-receipt.pdf`,
|
|
|
|
|
contentType: 'application/pdf', content: Uint8Array.from([0x52, 0x45, 0x43]),
|
|
|
|
|
}
|
|
|
|
|
const completionKey = key(context, 'mixed-completion')
|
|
|
|
|
const completion = await routes.platformUploadCompletion(context, fixture, completionRequest, completionKey)
|
|
|
|
|
const completionReplay = success(completion)
|
|
|
|
|
? await routes.platformUploadCompletion(context, fixture, completionRequest, completionKey) : null
|
|
|
|
|
const completionConverged = success(completion) && success(completionReplay)
|
|
|
|
|
&& id(completion.body?.data?.documentId) === id(completionReplay.body?.data?.documentId)
|
|
|
|
|
&& id(completion.body?.data?.completion?.fileId) === id(completionReplay.body?.data?.completion?.fileId)
|
|
|
|
|
context.assert(MODULE, '最后一份TAX完成文件二次确认并同键重放', completionReplay || completion,
|
|
|
|
|
completionConverged,
|
|
|
|
|
[completion, completionReplay].filter(Boolean).map((response) => evidence(response)).join('; '), OPTIONS)
|
|
|
|
|
if (!completionConverged) {
|
|
|
|
|
context.addCoverageGap(MODULE, OPTIONS.scenario, '最后一份完成文件二次确认',
|
|
|
|
|
'完成文件未成功或同键重放未收敛,已停止后续自动离仓写入',
|
|
|
|
|
'completion-idempotency', { deploymentBlocker: true })
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const completionDifferent = await routes.platformUploadCompletion(context, fixture,
|
|
|
|
|
{ ...completionRequest, content: Uint8Array.from([0x44, 0x49, 0x46]) }, completionKey)
|
|
|
|
|
context.assert(MODULE, '完成文件同键异载荷A0409', completionDifferent,
|
|
|
|
|
a0409(completionDifferent), evidence(completionDifferent), OPTIONS)
|
|
|
|
|
|
|
|
|
|
const receiptVersion = Number(completion.body?.data?.source?.version || completion.body?.data?.version || 0)
|
|
|
|
|
const receiptKey = key(context, 'mixed-receipt-upload')
|
|
|
|
|
const receipt = await routes.platformUploadReceipt(context, fixture, receiptRequest, receiptKey)
|
|
|
|
|
const receiptReplay = success(receipt)
|
|
|
|
|
? await routes.platformUploadReceipt(context, fixture, receiptRequest, receiptKey) : null
|
|
|
|
|
const receiptConverged = success(receipt) && success(receiptReplay)
|
|
|
|
|
&& id(receipt.body?.data?.documentId) === id(receiptReplay.body?.data?.documentId)
|
|
|
|
|
&& id(receipt.body?.data?.receipt?.fileId) === id(receiptReplay.body?.data?.receipt?.fileId)
|
|
|
|
|
context.assert(MODULE, '报关行回执同键重放收敛', receiptReplay || receipt, receiptConverged,
|
|
|
|
|
[receipt, receiptReplay].filter(Boolean).map((response) => evidence(response)).join('; '), OPTIONS)
|
|
|
|
|
const receiptDifferent = await routes.platformUploadReceipt(context, fixture,
|
|
|
|
|
{ ...receiptRequest, content: Uint8Array.from([0x44, 0x49, 0x46]) }, receiptKey)
|
|
|
|
|
context.assert(MODULE, '回执同键异载荷A0409', receiptDifferent, a0409(receiptDifferent), evidence(receiptDifferent), OPTIONS)
|
|
|
|
|
const receiptVersion = Number(receipt.body?.data?.receipt?.version || 0)
|
|
|
|
|
const receiptConfirm = await routes.merchantConfirmReceipt(context, fixture, customer, {
|
|
|
|
|
documentId: customer.documentId, expectedVersion: receiptVersion, confirm: true, remark: context.marker,
|
|
|
|
|
}, key(context, 'mixed-receipt-confirm'))
|
|
|
|
|
const receiptReplay = await routes.merchantConfirmReceipt(context, fixture, customer, {
|
|
|
|
|
const receiptConfirmReplay = await routes.merchantConfirmReceipt(context, fixture, customer, {
|
|
|
|
|
documentId: customer.documentId, expectedVersion: receiptVersion, confirm: true, remark: context.marker,
|
|
|
|
|
}, key(context, 'mixed-receipt-confirm'))
|
|
|
|
|
context.assert(MODULE, '客户确认整份回执并同键重放', receiptReplay || receiptConfirm,
|
|
|
|
|
success(receiptConfirm) && success(receiptReplay)
|
|
|
|
|
&& receiptConfirm.body?.data?.status === 'COMPLETED'
|
|
|
|
|
&& receiptReplay.body?.data?.status === 'COMPLETED',
|
|
|
|
|
[receiptConfirm, receiptReplay].map((response) => evidence(response)).join('; '), OPTIONS)
|
|
|
|
|
context.assert(MODULE, '客户确认回执后仍未完成整柜', receiptConfirmReplay || receiptConfirm,
|
|
|
|
|
success(receiptConfirm) && success(receiptConfirmReplay)
|
|
|
|
|
&& receiptConfirm.body?.data?.status === 'DECLARING'
|
|
|
|
|
&& receiptConfirmReplay.body?.data?.status === 'DECLARING',
|
|
|
|
|
[receiptConfirm, receiptConfirmReplay].map((response) => evidence(response)).join('; '), OPTIONS)
|
|
|
|
|
const submitted = await routes.platformSubmitToBroker(context, fixture,
|
|
|
|
|
{ expectedVersion: Number(receiptConfirm.body?.data?.version), remark: context.marker }, key(context, 'mixed-submit-to-broker'))
|
|
|
|
|
context.assert(MODULE, '混合柜发送确认回执给报关行执行', submitted,
|
|
|
|
|
success(submitted) && submitted.body?.data?.status === 'DECLARING', evidence(submitted), OPTIONS)
|
|
|
|
|
const finalRequest = {
|
|
|
|
|
documentId: customer.documentId, expectedVersion: 0,
|
|
|
|
|
fileName: `${context.marker}-mixed-customs-tax-final.pdf`,
|
|
|
|
|
contentType: 'application/pdf', content: Uint8Array.from([0x46, 0x49, 0x4e]),
|
|
|
|
|
}
|
|
|
|
|
const finalKey = key(context, 'mixed-final')
|
|
|
|
|
const finalDocument = await routes.platformUploadFinal(context, fixture, finalRequest, finalKey)
|
|
|
|
|
const finalReplay = success(finalDocument)
|
|
|
|
|
? await routes.platformUploadFinal(context, fixture, finalRequest, finalKey) : null
|
|
|
|
|
const finalConverged = success(finalDocument) && success(finalReplay)
|
|
|
|
|
&& id(finalDocument.body?.data?.finalDocument?.fileId) === id(finalReplay.body?.data?.finalDocument?.fileId)
|
|
|
|
|
context.assert(MODULE, '真实报关完税文件同键重放收敛', finalReplay || finalDocument, finalConverged,
|
|
|
|
|
[finalDocument, finalReplay].filter(Boolean).map((response) => evidence(response)).join('; '), OPTIONS)
|
|
|
|
|
const finalDifferent = await routes.platformUploadFinal(context, fixture,
|
|
|
|
|
{ ...finalRequest, content: Uint8Array.from([0x44, 0x49, 0x46]) }, finalKey)
|
|
|
|
|
context.assert(MODULE, '完税文件同键异载荷A0409', finalDifferent, a0409(finalDifferent), evidence(finalDifferent), OPTIONS)
|
|
|
|
|
|
|
|
|
|
let completed = await platformDetail(context, routes, fixture)
|
|
|
|
|
context.assert(MODULE, '混合柜最后一份完成文件后整柜COMPLETED', completed,
|
|
|
|
@@ -396,10 +422,10 @@ async function runMixedConcurrency(context, routes, fixture) {
|
|
|
|
|
evidence(queryDetail), OPTIONS)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const completionDownload = await routes.merchantDownload(context, fixture, customer, {
|
|
|
|
|
documentId: customer.documentId, completion: true,
|
|
|
|
|
const completionDownload = await routes.merchantDownloadFinal(context, fixture, customer, {
|
|
|
|
|
documentId: customer.documentId,
|
|
|
|
|
})
|
|
|
|
|
context.assert(MODULE, '整柜完成后Client可下载自身TAX完成文件', completionDownload,
|
|
|
|
|
context.assert(MODULE, '整柜完成后Client可下载自身真实报关完税文件', completionDownload,
|
|
|
|
|
completionDownload.http === 200 && completionDownload.bytes?.length > 0,
|
|
|
|
|
`HTTP=${completionDownload.http}, bytes=${completionDownload.bytes?.length ?? 0}`, OPTIONS)
|
|
|
|
|
}
|
|
|
|
|