fix(firstleg): map broker submission fields in customs container
This commit is contained in:
+2
-1
@@ -441,7 +441,8 @@ public interface ContainerCustomsMapper {
|
||||
String cabinetNo,String containerNo) {}
|
||||
record ContainerRow(Long id,Long loadingPlanId,Long containerBookingId,String status,Long startedBy,
|
||||
String startedByName,LocalDateTime startedAt,Long completedBy,String completedByName,
|
||||
LocalDateTime completedAt,LocalDateTime createdAt,LocalDateTime updatedAt,Integer version) {}
|
||||
LocalDateTime completedAt,Long brokerSubmittedBy,String brokerSubmittedByName,
|
||||
LocalDateTime brokerSubmittedAt,LocalDateTime createdAt,LocalDateTime updatedAt,Integer version) {}
|
||||
record DocumentRow(Long id,Long customsContainerId,Long tenantId,Long fileId,String fileName,String fileHash,
|
||||
String contentType,Long sizeBytes,String status,Long uploadedBy,LocalDateTime uploadedAt,
|
||||
Integer frozenVersion,LocalDateTime frozenAt,Integer version) {}
|
||||
|
||||
@@ -49,8 +49,8 @@ test('mixed fixture producer is registered and uses only public HTTP composition
|
||||
|
||||
test('coverage matrix freezes every requested product boundary', () => {
|
||||
const text = CONTAINER_CUSTOMS_MATRIX.map((item) => `${item.scenario}:${item.expected}`).join('\n')
|
||||
for (const token of ['买单XLSX', '多对多', '覆盖', '改关联', '删除', '冻结', '逐份完成文件',
|
||||
'最后一份', '混合', '缺资料', '开始后锁定', '客户隔离', '买单隐藏', '50MiB', '任意格式',
|
||||
for (const token of ['买单XLSX', '多对多', '覆盖', '改关联', '删除', '冻结', '回执确认', '报关行执行', '完税文件',
|
||||
'最后上传', '混合', '缺资料', '开始后锁定', '客户隔离', '买单隐藏', '50MiB', '任意格式',
|
||||
'幂等', '并发', 'A0409', '零漂移', '自动离仓', 'Outbox', '历史', 'Admin与Client权限']) {
|
||||
assert.match(text, new RegExp(token))
|
||||
}
|
||||
@@ -69,7 +69,7 @@ test('HTTP scenario contains file, state, idempotency, concurrency and zero-drif
|
||||
for (const token of ['EXACT_50_MB + 1', '.customblob', 'application/octet-stream',
|
||||
'缺退税资料禁止开始且零漂移', '开始后资料范围锁定A0409零漂移',
|
||||
"['上传'", "['覆盖'", "['改关联'", "['删除'", '开始后${label}锁定A0409零漂移',
|
||||
'最后一份完成文件前禁止整柜完成', '客户确认整份回执后纯退税柜完成', '客户确认整份回执并同键重放',
|
||||
'回执未确认且未发送执行时禁止上传完税文件', '客户确认整份回执后仍处于报关中', '真实报关完税文件齐全后纯退税柜完成', '客户确认回执后仍未完成整柜',
|
||||
'混合柜平台详情精确包含BUY与TAX长ID票', 'Client只见本客户TAX票且完全隐藏BUY票',
|
||||
'买单导出只处理实际装柜BUY行', '混合柜最后一份完成文件后整柜COMPLETED',
|
||||
'自动离仓只写一次SYSTEM历史', '自动离仓只创建一个OUTBOUND_CONFIRM长ID任务',
|
||||
@@ -87,7 +87,7 @@ test('HTTP scenario contains file, state, idempotency, concurrency and zero-drif
|
||||
|
||||
test('database evidence list covers atomicity, history, dispatch and outbox without embedding SQL writes', () => {
|
||||
for (const table of ['fl_customs_container', 'fl_customs_customer_document_inbound',
|
||||
'fl_customs_completion_document', 'fl_customs_command', 'fl_customs_container_history',
|
||||
'fl_customs_completion_document', 'fl_customs_final_document', 'fl_customs_command', 'fl_customs_container_history',
|
||||
'fl_outbound_dispatch', 'fl_event_outbox']) assert.ok(READ_ONLY_DB_EVIDENCE.includes(table), table)
|
||||
assert.doesNotMatch(source, /\b(?:INSERT|UPDATE|DELETE)\s+(?:INTO|FROM|[a-z_])/i)
|
||||
})
|
||||
|
||||
@@ -58,12 +58,12 @@ async function runAllBuy(context, routes, fixture) {
|
||||
xlsx.http === 200 && xlsxMagic(xlsx.bytes),
|
||||
`HTTP=${xlsx.http}, bytes=${xlsx.bytes?.length ?? 0}, contentType=${xlsx.contentType || 'missing'}`, OPTIONS)
|
||||
|
||||
const startBody = { expectedVersion: Number(detail.body?.data?.version), remark: context.marker }
|
||||
const startBody = { expectedVersion: Number(detail.body?.data?.version), confirm: true, remark: context.marker }
|
||||
const started = await routes.platformStart(context, fixture, startBody, key(context, 'all-buy-start'))
|
||||
context.assert(MODULE, '全买单柜开始报关', started,
|
||||
success(started) && started.body?.data?.status === 'DECLARING', evidence(started), OPTIONS)
|
||||
|
||||
const completeBody = { expectedVersion: Number(started.body?.data?.version), remark: context.marker }
|
||||
const completeBody = { expectedVersion: Number(started.body?.data?.version), confirm: true, remark: context.marker }
|
||||
const completed = await routes.platformComplete(context, fixture, completeBody, key(context, 'all-buy-complete'))
|
||||
context.assert(MODULE, '全买单柜完成并触发自动离仓意图', completed,
|
||||
success(completed) && completed.body?.data?.status === 'COMPLETED', evidence(completed), OPTIONS)
|
||||
@@ -153,7 +153,7 @@ async function runRefund(context, routes, fixture) {
|
||||
|
||||
const ready = await platformDetail(context, routes, fixture)
|
||||
const started = await routes.platformStart(context, fixture, {
|
||||
expectedVersion: Number(ready.body?.data?.version), remark: context.marker,
|
||||
expectedVersion: Number(ready.body?.data?.version), confirm: true, remark: context.marker,
|
||||
}, key(context, 'refund-start'))
|
||||
context.assert(MODULE, '纯退税柜资料齐全后开始并冻结', started,
|
||||
success(started) && started.body?.data?.status === 'DECLARING'
|
||||
@@ -184,7 +184,7 @@ async function runRefund(context, routes, fixture) {
|
||||
const documents = frozenSnapshot?.documents || []
|
||||
for (const [index, document] of documents.entries()) {
|
||||
const receipt = await routes.platformUploadReceipt(context, fixture, {
|
||||
documentId: id(document.documentId), expectedVersion: Number(document.source?.version),
|
||||
documentId: id(document.documentId), expectedVersion: 0,
|
||||
fileName: `${context.marker}-broker-receipt-${index + 1}.pdf`,
|
||||
contentType: 'application/pdf', content: Uint8Array.from([0x52, index + 1]),
|
||||
}, key(context, `receipt-${index + 1}`))
|
||||
@@ -216,11 +216,11 @@ async function runRefund(context, routes, fixture) {
|
||||
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'))
|
||||
{ expectedVersion: Number(afterConfirm.body?.data?.version), confirm: true, 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'))
|
||||
{ expectedVersion: Number(afterConfirm.body?.data?.version), confirm: true, 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, {
|
||||
@@ -365,7 +365,7 @@ async function runMixedConcurrency(context, routes, fixture) {
|
||||
&& 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'))
|
||||
{ expectedVersion: Number(receiptConfirm.body?.data?.version), confirm: true, 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 = {
|
||||
@@ -381,6 +381,9 @@ async function runMixedConcurrency(context, routes, fixture) {
|
||||
&& 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)
|
||||
if (!finalConverged) {
|
||||
blocker(context, '完税文件幂等收敛', '完成文件未成功或同键重放未收敛,已停止后续自动离仓写入')
|
||||
}
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user