feat(worker-platform): 支持客户退款冲正并关闭订单

This commit is contained in:
yml2213
2026-11-05 17:15:41 +08:00
parent b72d5877da
commit fc928c6b18
15 changed files with 2129 additions and 6 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,67 @@
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import test from 'node:test'
test('客户退款第一版覆盖范围与原子关闭动作已声明', async () => {
const source = await readFile(new URL('./customer-refund-service.ts', import.meta.url), 'utf8')
for (const status of [
'pending_material',
'unassigned',
'open',
'in_progress',
'pending_acceptance',
'problem',
]) {
assert.ok(source.includes(`'${status}'`), `缺少工单状态 ${status}`)
}
assert.ok(source.includes("pay_status = 'refunded'"))
assert.ok(source.includes("order_status = 'refunded'"))
assert.ok(source.includes('work_order_shares'))
assert.ok(source.includes('voucher_consume_jobs'))
assert.ok(source.includes('redeem_certificates'))
assert.ok(source.includes('findResumableRefundCancelOperation'))
assert.ok(source.includes('customer_refund_processing'))
assert.ok(source.includes("status: 'platform_approved'"))
assert.ok(source.includes('refundFee'))
assert.ok(source.includes('queryType: 2'))
assert.ok(
source.includes('afterSale.operate') || source.includes('approveDouyinMashidaAfterSale'),
)
})
test('抖音退款创建和关闭消息会进入自动发现白名单', async () => {
const [configSource, notifySource] = await Promise.all([
readFile(
new URL('../platforms/douyin-mashida/source-config-service.ts', import.meta.url),
'utf8',
),
readFile(new URL('../platforms/douyin-mashida/notify-service.ts', import.meta.url), 'utf8'),
])
assert.ok(configSource.includes('refund_RefundCreated'))
assert.ok(configSource.includes('refund_RefundClosed'))
assert.ok(notifySource.includes('bindPlatformAfterSalesToLocalOrder'))
})
test('客户退款操作表和平台售后表具备幂等唯一键', async () => {
const migration = await readFile(
new URL('../../db/migrations/134_customer_refund_operations.sql', import.meta.url),
'utf8',
)
assert.ok(migration.includes('uq_platform_after_sales_external'))
assert.ok(migration.includes('uq_refund_cancel_operations_external'))
assert.ok(migration.includes('afterSale.operate') || migration.includes('平台售后'))
assert.ok(migration.includes('平台同意、本地退款、业务关闭'))
})
test('客户退款使用独立权限,客服默认可用且可由管理员收回', async () => {
const [routeSource, migration] = await Promise.all([
readFile(new URL('../../routes/admin/worker-platform/orders.ts', import.meta.url), 'utf8'),
readFile(
new URL('../../db/migrations/134_customer_refund_operations.sql', import.meta.url),
'utf8',
),
])
assert.ok(routeSource.includes("requireAdminPermission('worker_order.customer_refund')"))
assert.ok(migration.includes("'worker_order.customer_refund'"))
assert.ok(migration.includes("('support')"))
})
@@ -635,6 +635,8 @@ export async function approveAndRecordKuaishouRefund(
refundedAt?: string | undefined
sellerId?: string | undefined
refundHandingWay?: unknown
status?: unknown
negotiateStatus?: unknown
desc?: string | undefined
},
session: AdminSession | null,
@@ -770,6 +772,8 @@ export async function approveAndRecordKuaishouRefund(
refundAmount: amountFen,
desc: input.desc || input.note || '',
refundHandingWay: input.refundHandingWay,
status: input.status,
negotiateStatus: input.negotiateStatus,
...(input.sellerId ? { sellerId: input.sellerId } : {}),
})
await updatePlatformRefundIntent(intent.id, 'platform_approved')