This commit is contained in:
2026-10-20 18:44:53 +08:00
parent 20858dbe33
commit 78893f1144
4 changed files with 33 additions and 5 deletions
+1 -1
View File
@@ -25,7 +25,7 @@
- 头程订单只用当前正式读写契约;不得扩展 `LEGACY_MANUAL`、旧系统入仓码、C02 不可用回退旧 API、历史部分响应兼容或其他新旧并跑逻辑。触及该链路时同步删除生产分支、类型、文案、Mock 和测试。
- 快速下单只创建草稿,不提交、不审核;逐行失败必须回填原因与入仓码,不用内部 ID 代替业务编号。
- 入库费用确认携带 `expectedFeeVersion` 与幂等键,金额与冻结状态只认服务端结果;所有订单行都可进入费用确认弹框,不按行类型隐藏。
- 入库费用确认携带 `expectedFeeVersion` 与幂等键,金额与冻结状态只认服务端结果;列表“确认计费重”仅在具备确认权限且服务端 `customerFeeConfirmationRequired=true` 时显示,已确认或未推送费用的订单不显示;详情保留费用查看入口。
- 报关资料在开始后只读冻结资料,未装柜或无资格时不展示入口;`utils/customsEligibility.ts` 是唯一资格判断入口。
- 模块间协作只能从本模块 `public.ts` 导入,不穿透其他模块的 `views/` 或内部目录。
@@ -642,15 +642,41 @@ test('opens billing-weight confirmation independently from order details', () =>
assert.match(source, /unavailable-message="未推送费用"/)
})
test('uses one published-fee dialog for billing-weight confirmation on every order row', () => {
test('only offers published-fee confirmation for pending orders with confirmation permission', () => {
const actions = source.slice(source.indexOf('function getOrderRowActions'), source.indexOf('function getOrderRowActions') + 1800)
assert.match(actions, /actions\.push\(\{ key: 'fee', label: '确认计费重', run: \(\) => openFeeConfirmation\(order\) \}\)/)
assert.doesNotMatch(actions, /customerFeeConfirmationRequired|label: '确认费用'|key: 'weight'/)
assert.match(actions, /if \(canConfirmInboundFee\.value && order\.businessSummary\.customerFeeConfirmationRequired\) \{\s*actions\.push\(\{ key: 'fee'/)
assert.doesNotMatch(actions, /label: '确认费用'|key: 'weight'/)
assert.doesNotMatch(source, /ChargeableWeightDialog|weightConfirmationOrderId/)
assert.match(source, /:row-actions="getOrderRowActions"/)
assert.match(orderStoreSource, /customerFeeConfirmationRequired: summary\?\.customerFeeConfirmationRequired \?\? false/)
})
test('hides confirmation for confirmed, unpushed and unauthorized orders and refreshes after confirmation', () => {
const start = source.indexOf('function getOrderRowActions')
const end = source.indexOf('\nasync function copyOrder', start)
const body = source.slice(start, end)
.replace('function getOrderRowActions(row: object): TableAction[]', 'function getOrderRowActions(row)')
.replace('const order = row as FirstLegOrder', 'const order = row')
.replace('const actions: TableAction[]', 'const actions')
const actionsFor = new Function('canConfirmInboundFee', 'canCreateOrder', 'canEditOrder',
'canOfferCancellation', 'eligibleCustomsDetail', 'openFeeConfirmation',
`${body}; return getOrderRowActions`)
for (const [permitted, pending] of [[true, true], [true, false], [false, true], [false, false]]) {
const opened = []
const order = { id: 'order-1', businessSummary: { customerFeeConfirmationRequired: pending } }
const getActions = actionsFor({ value: permitted }, { value: false }, { value: false },
() => false, () => false, row => opened.push(row.id))
const confirm = getActions(order).filter(action => action.key === 'fee')
assert.equal(confirm.length, permitted && pending ? 1 : 0)
if (confirm.length) {
confirm[0].run()
assert.deepEqual(opened, ['order-1'])
}
}
assert.match(source, /function handleInboundFeeConfirmed\(\) \{\s*if \(!isCreatePage\.value && !isDetailPage\.value\) void loadOrderPage\(\)/)
})
test('submits only selected draft orders in one batch action', () => {
assert.match(source, /selectedDraftOrders = computed\(\(\) => selectedOrders\.value\.filter\(\(order\) => order\.status === 'DRAFT'\)\)/)
assert.match(source, /Promise\.allSettled\(ids\.map\(id => store\.submitSaved/)
@@ -1361,7 +1361,9 @@ function getOrderRowActions(row: object): TableAction[] {
if (canCreateOrder.value) {
actions.push({ key: 'copy', label: '复制下单', loading: copyingOrderId.value === order.id, run: () => copyOrder(order) })
}
actions.push({ key: 'fee', label: '确认计费重', run: () => openFeeConfirmation(order) })
if (canConfirmInboundFee.value && order.businessSummary.customerFeeConfirmationRequired) {
actions.push({ key: 'fee', label: '确认计费重', run: () => openFeeConfirmation(order) })
}
if (canEditOrder.value && canClientEditFirstLegOrder(order.status)) {
actions.push({ key: 'edit', label: '编辑', loading: openingEditor.value, run: () => openEdit(order) })
}