This commit is contained in:
2026-09-15 15:24:59 +08:00
parent 90f97e846f
commit 5d2465d1ea
4 changed files with 215 additions and 15 deletions
@@ -28,6 +28,19 @@ describe('UnifiedOrdersView contract', () => {
expect(sendFeeSource).toContain("ElMessage.error(getApiErrorDetails(error, '确认费用发送失败').message)")
})
it('prevents duplicate confirm-and-send chains and reuses one attempt idempotency key set', () => {
const sendFeeSource = source.slice(source.indexOf('async function executeConfirmAndSendFee()'), source.indexOf('function handleOrderSelectionChange'))
expect(sendFeeSource).toContain('if (confirmFeeSending.value) return')
expect(sendFeeSource).toContain('const attempt = currentFeeConfirmAttempt(selectedWeightKg, selectedVolumeCbm, selectedUnitPrice)')
expect(sendFeeSource).toContain('attempt.calculateKey')
expect(sendFeeSource).toContain('attempt.adjustKey')
expect(sendFeeSource).toContain('attempt.confirmKey')
expect(sendFeeSource).toContain('attempt.sendKey')
expect(sendFeeSource).toContain("if (snapshot.feeStatus === 'SENT')")
expect(source).toContain('feeConfirmAttempt = null\n feeConfirmOpen.value = true')
})
it('exposes the product main statuses including dropship palletizing', () => {
expect(unifiedOrderStatusOptions.map((item) => item.label)).toEqual([
'待审核', '待测量数据', '待一件代发组托', '待分柜', '装柜中', '装柜完成', '派送完成',
@@ -248,6 +248,14 @@ const feeConfirmReferenceLoading = ref(false)
const feeConfirmReference = ref<InboundFeeSnapshot | null>(null)
const feeConfirmUnitPrice = ref<number | null>(null)
const feeConfirmPriceReason = ref('')
type FeeConfirmAttempt = {
fingerprint: string
calculateKey: string
adjustKey: string
confirmKey: string
sendKey: string
}
let feeConfirmAttempt: FeeConfirmAttempt | null = null
const feeConfirmPriceChanged = computed(() => {
const reference = Number(feeConfirmReference.value?.unitPrice)
const current = Number(feeConfirmUnitPrice.value)
@@ -1643,6 +1651,7 @@ async function openFeeConfirmDialog() {
feeConfirmReference.value = null
feeConfirmUnitPrice.value = null
feeConfirmPriceReason.value = ''
feeConfirmAttempt = null
feeConfirmOpen.value = true
feeConfirmReferenceLoading.value = true
try {
@@ -1671,7 +1680,31 @@ async function openFeeConfirmDialog() {
}
}
function currentFeeConfirmAttempt(
selectedWeightKg: number,
selectedVolumeCbm: number,
selectedUnitPrice: number,
) {
const fingerprint = JSON.stringify([
selectedWeightKg,
selectedVolumeCbm,
selectedUnitPrice,
feeConfirmPriceReason.value.trim(),
])
if (!feeConfirmAttempt || feeConfirmAttempt.fingerprint !== fingerprint) {
feeConfirmAttempt = {
fingerprint,
calculateKey: createFeeActionIdempotencyKey('calculate'),
adjustKey: createFeeAdjustmentIdempotencyKey(),
confirmKey: createFeeActionIdempotencyKey('confirm'),
sendKey: createFeeActionIdempotencyKey('send'),
}
}
return feeConfirmAttempt
}
async function executeConfirmAndSendFee() {
if (confirmFeeSending.value) return
const summary = detail.value?.summary
if (!summary?.inboundId) return
const selectedWeightKg = Number(feeConfirmWeight.value)
@@ -1689,6 +1722,7 @@ async function executeConfirmAndSendFee() {
ElMessage.warning('人工修改参考单价后,请填写至少 2 个字符的调整原因')
return
}
const attempt = currentFeeConfirmAttempt(selectedWeightKg, selectedVolumeCbm, selectedUnitPrice)
confirmFeeSending.value = true
try {
const tenantId = String(summary.tenantId)
@@ -1698,7 +1732,7 @@ async function executeConfirmAndSendFee() {
selectedVolumeCbm,
weightSource: 'ACTUAL',
volumeSource: 'ACTUAL',
}, createFeeActionIdempotencyKey('calculate'))
}, attempt.calculateKey)
const calculatedUnitPrice = Number(snapshot.unitPrice)
if (Math.abs(selectedUnitPrice - calculatedUnitPrice) > 0.000001) {
snapshot = await adjustPublishedInboundFee(tenantId, inboundId, {
@@ -1708,15 +1742,18 @@ async function executeConfirmAndSendFee() {
additionalAmount: Number(snapshot.additionalAmount || 0),
reason: feeConfirmPriceReason.value.trim() || '推送前按已展示参考单价人工确认',
toleranceConfirmed: true,
}, createFeeAdjustmentIdempotencyKey())
}, attempt.adjustKey)
}
snapshot = await confirmInboundFee(tenantId, inboundId, createFeeActionIdempotencyKey('confirm'))
snapshot = await confirmInboundFee(tenantId, inboundId, attempt.confirmKey)
if (snapshot.feeStatus === 'CONFIRMED') {
const sent = await sendInboundFee(tenantId, inboundId, createFeeActionIdempotencyKey('send'))
automaticFee.value = { feeStatus: sent.feeStatus, totalAmount: Number(sent.totalAmount || 0) }
snapshot = await sendInboundFee(tenantId, inboundId, attempt.sendKey)
}
if (snapshot.feeStatus === 'SENT') {
automaticFee.value = { feeStatus: snapshot.feeStatus, totalAmount: Number(snapshot.totalAmount || 0) }
feePanelRevision.value += 1
ElMessage.success('计费量和单价已确认并发送给客户')
feeConfirmOpen.value = false
feeConfirmAttempt = null
await loadDetail(true)
return
}