fix(consignment): 复核修复——占库撞 080 CHECK 必 500、指派非卖家双付货款、手动匹配权限门控
- 占库默认 allocation_status 从自由文本改为「已安排」,不再撞 080 的
CHECK ('待安排','已安排');加静态守卫测试(剥注释断言枚举内默认值)
- resolveConsignmentAssignRewardFen 加 assigneeIsSupplier:指派供货卖家本人
→ 报酬=结算价(货款走报酬渠道);指派别的打手 → 报酬保持原值(货款走
供货货款渠道),两条渠道互斥,封住平台双付;补行为级测试 + 调用点钉住
- 手动匹配两处入口(库存面板行内按钮、拦截弹窗 footer)统一按
consignment.fulfill 门控,编辑/作废仍为 manage,与后端权限一一对应
- docs/寄卖系统优化方案.md 记录批次 U
后端 473(+3)/ 前端 49(+1)测试全绿,typecheck / lint / format / check:sql / build 通过
This commit is contained in:
@@ -553,7 +553,13 @@ export async function fulfillWorkOrderWithConsignment(input: {
|
||||
* 选用内部寄售库存并走接单平台指派打手(冻结押金担保履约)
|
||||
*/
|
||||
/**
|
||||
* 指派打手线里工单报酬要改成"货的结算价":卖家拿结算价、平台赚差价。
|
||||
* 指派打手线里工单报酬的口径:
|
||||
*
|
||||
* - 指派对象 = 供货卖家本人(常规玩法):报酬改成"货的结算价",卖家通过工单报酬渠道拿货款;
|
||||
* 验收结算会因"接单人===卖家"跳过供货货款(consignment-deposit-repo),不会双付。
|
||||
* - 指派对象 ≠ 供货卖家(API 层允许传任意打手,界面不会主动构造):报酬保持工单原值给打手,
|
||||
* 卖家的货款由验收结算的 settleConsignmentSupplierPayout 单独支付 —— 两条渠道互斥。
|
||||
* 以前这里无条件改写成结算价:打手按结算价拿一份 + 卖家再拿一份供货货款 = 平台双付。
|
||||
*
|
||||
* 单位必须是**分**(与钱包、流水、其它工单报酬一致)。这里以前多除了 100,
|
||||
* 会把 ¥124 写成 ¥1.24 —— 卖家只拿到结算价的百分之一。
|
||||
@@ -561,10 +567,14 @@ export async function fulfillWorkOrderWithConsignment(input: {
|
||||
export function resolveConsignmentAssignRewardFen(input: {
|
||||
costPriceFen: unknown
|
||||
orderRewardFen: unknown
|
||||
/** 指派对象是否供货卖家本人;缺省视为 true(保持旧行为,调用方应显式传) */
|
||||
assigneeIsSupplier?: boolean
|
||||
}): number {
|
||||
const orderRewardFen = Math.round(Number(input.orderRewardFen || 0))
|
||||
if (input.assigneeIsSupplier === false) return orderRewardFen
|
||||
const costPriceFen = Math.round(Number(input.costPriceFen || 0))
|
||||
if (costPriceFen > 0) return costPriceFen
|
||||
return Math.round(Number(input.orderRewardFen || 0))
|
||||
return orderRewardFen
|
||||
}
|
||||
|
||||
export async function assignWorkOrderWithConsignmentWorker(input: {
|
||||
@@ -687,6 +697,9 @@ export async function assignWorkOrderWithConsignmentWorker(input: {
|
||||
const rewardAmountFen = resolveConsignmentAssignRewardFen({
|
||||
costPriceFen: claimed.cost_price_fen,
|
||||
orderRewardFen: workOrder.reward_amount,
|
||||
// 指派对象是供货卖家本人 → 报酬改写为结算价(货款走工单报酬渠道);
|
||||
// 指派了别的打手 → 报酬保持原值(货款走验收结算的供货货款渠道),两条渠道互斥防双付
|
||||
assigneeIsSupplier: Number(targetWorkerId) === Number(inventory.worker_id || 0),
|
||||
})
|
||||
|
||||
await updateWorkOrder(workOrder.id, {
|
||||
|
||||
@@ -71,3 +71,39 @@ test('"从工单找供货卖家"只有一处实现,货款与售后共用', asy
|
||||
// 取卖家那段 SQL(含 UNION ALL 兜底)只应存在于共享查询里,别处不要再抄一份
|
||||
assert.equal(depositSource.includes('UNION ALL'), false)
|
||||
})
|
||||
|
||||
test('指派对象不是供货卖家时,工单报酬必须保持原值(货款走供货货款渠道,防止双付)', () => {
|
||||
// 成本价 12400 分、工单原报酬 14500 分:指派了别的打手时不能把报酬改写成 12400 ——
|
||||
// 否则打手按 12400 拿一份 + 卖家再拿 12400 供货货款(settleConsignmentSupplierPayout
|
||||
// 只在“接单人===卖家”时跳过)= 平台双付
|
||||
assert.equal(
|
||||
resolveConsignmentAssignRewardFen({
|
||||
costPriceFen: 12400,
|
||||
orderRewardFen: 14500,
|
||||
assigneeIsSupplier: false,
|
||||
}),
|
||||
14500,
|
||||
)
|
||||
// 卖家本人履约:报酬仍是结算价(供货货款渠道会因“接单人===卖家”跳过,不双付)
|
||||
assert.equal(
|
||||
resolveConsignmentAssignRewardFen({
|
||||
costPriceFen: 12400,
|
||||
orderRewardFen: 14500,
|
||||
assigneeIsSupplier: true,
|
||||
}),
|
||||
12400,
|
||||
)
|
||||
})
|
||||
|
||||
test('指派链路必须按“指派对象===供货卖家”判定报酬渠道,不能静默丢掉判定', async () => {
|
||||
const source = await readFile(
|
||||
new URL('./consignment-fulfillment-service.ts', import.meta.url),
|
||||
'utf8',
|
||||
)
|
||||
assert.ok(
|
||||
source.includes(
|
||||
'assigneeIsSupplier: Number(targetWorkerId) === Number(inventory.worker_id || 0)',
|
||||
),
|
||||
'指派报酬必须传 assigneeIsSupplier,且与供货卖家(inventory.worker_id)比对',
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user