diff --git a/apps/backend/src/repositories/worker-platform/work-order-repo.ts b/apps/backend/src/repositories/worker-platform/work-order-repo.ts index b4bf9a45..4bdfafaa 100644 --- a/apps/backend/src/repositories/worker-platform/work-order-repo.ts +++ b/apps/backend/src/repositories/worker-platform/work-order-repo.ts @@ -2402,13 +2402,16 @@ export async function acceptWorkOrderShareAndSettle(input: { ], ) } - await maybeUpgradeWorkerLevelWithClient(client, workerId, input.now) } await client.query( `UPDATE work_order_shares SET status = 'accepted', accepted_at = $1, updated_at = $1 WHERE id = $2`, [input.now, input.shareId], ) + if (workerId > 0) { + // 先落库份额已验收状态,再按去重后的订单数计算等级进度。 + await maybeUpgradeWorkerLevelWithClient(client, workerId, input.now) + } const progressResult = await client.query<{ joined_quantity: number unfinished_count: number diff --git a/apps/backend/src/repositories/worker-platform/worker-repo.ts b/apps/backend/src/repositories/worker-platform/worker-repo.ts index e596197f..ca966671 100644 --- a/apps/backend/src/repositories/worker-platform/worker-repo.ts +++ b/apps/backend/src/repositories/worker-platform/worker-repo.ts @@ -942,16 +942,33 @@ export async function getWorkerFinanceRequestSummary(workerId: number | string) } } +/** 完成单数按源订单去重,拼单份数只影响收益,不增加完成单数。 */ export async function countWorkerAcceptedOrders(workerId: number | string): Promise { const result = await query<{ total: number }>( ` - SELECT - (SELECT COUNT(*)::int FROM work_orders WHERE assigned_worker_id = $1 AND status = 'accepted') - + - COALESCE( - (SELECT SUM(quantity)::int FROM work_order_shares WHERE worker_id = $1 AND status = 'accepted'), - 0 - ) AS total + SELECT COUNT(DISTINCT order_key)::int AS total + FROM ( + SELECT + COALESCE( + 'order:' || NULLIF(wo.order_id::text, ''), + 'platform_order:' || NULLIF(BTRIM(wo.platform_order_id), ''), + 'work_order:' || wo.id::text + ) AS order_key + FROM work_orders wo + WHERE wo.assigned_worker_id = $1 AND wo.status = 'accepted' + + UNION + + SELECT + COALESCE( + 'order:' || NULLIF(wo.order_id::text, ''), + 'platform_order:' || NULLIF(BTRIM(wo.platform_order_id), ''), + 'work_order:' || wo.id::text + ) AS order_key + FROM work_order_shares wos + INNER JOIN work_orders wo ON wo.id = wos.work_order_id + WHERE wos.worker_id = $1 AND wos.status = 'accepted' + ) AS completed_orders `, [Number(workerId)], ) @@ -989,12 +1006,16 @@ export async function listWorkerCompletionLeaderboard(input: { accepted_totals AS ( SELECT worker_id, - SUM(accepted_order_count)::int AS accepted_order_count, + COUNT(DISTINCT order_key)::int AS accepted_order_count, MAX(last_accepted_at) AS last_accepted_at FROM ( SELECT assigned_worker_id AS worker_id, - COUNT(*)::int AS accepted_order_count, + COALESCE( + 'order:' || NULLIF(order_id::text, ''), + 'platform_order:' || NULLIF(BTRIM(platform_order_id), ''), + 'work_order:' || id::text + ) AS order_key, MAX(accepted_at) AS last_accepted_at FROM work_orders CROSS JOIN leaderboard_day @@ -1004,22 +1025,27 @@ export async function listWorkerCompletionLeaderboard(input: { $3::boolean = false OR (accepted_at >= leaderboard_day.starts_at AND accepted_at < leaderboard_day.starts_at + INTERVAL '1 day') ) - GROUP BY assigned_worker_id + GROUP BY assigned_worker_id, order_key UNION ALL SELECT - worker_id, - COALESCE(SUM(quantity), 0)::int AS accepted_order_count, - MAX(accepted_at) AS last_accepted_at - FROM work_order_shares + wos.worker_id, + COALESCE( + 'order:' || NULLIF(wo.order_id::text, ''), + 'platform_order:' || NULLIF(BTRIM(wo.platform_order_id), ''), + 'work_order:' || wo.id::text + ) AS order_key, + MAX(wos.accepted_at) AS last_accepted_at + FROM work_order_shares wos + INNER JOIN work_orders wo ON wo.id = wos.work_order_id CROSS JOIN leaderboard_day - WHERE status = 'accepted' + WHERE wos.status = 'accepted' AND ( $3::boolean = false - OR (accepted_at >= leaderboard_day.starts_at AND accepted_at < leaderboard_day.starts_at + INTERVAL '1 day') + OR (wos.accepted_at >= leaderboard_day.starts_at AND wos.accepted_at < leaderboard_day.starts_at + INTERVAL '1 day') ) - GROUP BY worker_id + GROUP BY wos.worker_id, order_key ) AS accepted_records GROUP BY worker_id ), @@ -1081,13 +1107,29 @@ export async function maybeUpgradeWorkerLevelWithClient( const acceptedResult = await client.query<{ total: number }>( ` - SELECT - (SELECT COUNT(*)::int FROM work_orders WHERE assigned_worker_id = $1 AND status = 'accepted') - + - COALESCE( - (SELECT SUM(quantity)::int FROM work_order_shares WHERE worker_id = $1 AND status = 'accepted'), - 0 - ) AS total + SELECT COUNT(DISTINCT order_key)::int AS total + FROM ( + SELECT + COALESCE( + 'order:' || NULLIF(wo.order_id::text, ''), + 'platform_order:' || NULLIF(BTRIM(wo.platform_order_id), ''), + 'work_order:' || wo.id::text + ) AS order_key + FROM work_orders wo + WHERE wo.assigned_worker_id = $1 AND wo.status = 'accepted' + + UNION + + SELECT + COALESCE( + 'order:' || NULLIF(wo.order_id::text, ''), + 'platform_order:' || NULLIF(BTRIM(wo.platform_order_id), ''), + 'work_order:' || wo.id::text + ) AS order_key + FROM work_order_shares wos + INNER JOIN work_orders wo ON wo.id = wos.work_order_id + WHERE wos.worker_id = $1 AND wos.status = 'accepted' + ) AS completed_orders `, [workerId], )