优化打手订单结算和大厅加载

This commit is contained in:
yml2213
2026-08-17 13:06:40 +08:00
parent 1d9e102527
commit bca2e4a801
8 changed files with 306 additions and 74 deletions
@@ -48,6 +48,14 @@ const WORK_ORDER_SHARE_SELECT = `
LEFT JOIN worker_users wu ON wu.id = wos.worker_id
`
type WorkerOrderOverviewRow = {
status: string
order_count: number
settlement_amount: number
vip_evidence_pending_count: number
vip_evidence_pending_settlement_amount: number
}
export async function listWorkOrderShares(
workOrderId: number | string,
): Promise<WorkOrderShareRow[]> {
@@ -820,6 +828,81 @@ export async function listWorkOrders({
return { items: itemsResult.rows, total: Number(totalResult.rows[0]?.total || 0) }
}
/** 汇总打手本人各订单状态的可结算金额,拼单按个人份额计算。 */
export async function getWorkerOrderOverview(workerId: number | string): Promise<
Array<{
status: string
orderCount: number
settlementAmount: number
vipEvidencePendingCount: number
vipEvidencePendingSettlementAmount: number
}>
> {
const normalizedWorkerId = Number(workerId)
const result = await query<WorkerOrderOverviewRow>(
`
WITH worker_orders AS (
SELECT
wo.status,
wo.acceptance_json,
wos.id IS NOT NULL AS is_worker_share,
CASE
WHEN wos.id IS NOT NULL THEN wos.share_reward
WHEN wo.assigned_worker_id = $1 THEN wo.reward_amount
ELSE 0
END AS worker_settlement_amount
FROM work_orders wo
LEFT JOIN work_order_shares wos
ON wos.work_order_id = wo.id
AND wos.worker_id = $1
AND wos.status != 'cancelled'
WHERE wo.assigned_worker_id = $1
OR wo.last_assigned_worker_id = $1
OR wos.id IS NOT NULL
)
SELECT
status,
COUNT(*)::int AS order_count,
COALESCE(
SUM(
CASE
WHEN status IN ('in_progress', 'pending_acceptance', 'problem', 'accepted')
OR (status = 'open' AND is_worker_share)
THEN worker_settlement_amount
ELSE 0
END
),
0
)::int AS settlement_amount,
COUNT(*) FILTER (
WHERE status = 'accepted'
AND acceptance_json->>'reviewMode' = 'vip_auto'
AND acceptance_json->>'evidenceStatus' = 'pending'
AND NULLIF(acceptance_json->>'evidenceDueAt', '')::timestamptz > NOW()
)::int AS vip_evidence_pending_count,
COALESCE(
SUM(worker_settlement_amount) FILTER (
WHERE status = 'accepted'
AND acceptance_json->>'reviewMode' = 'vip_auto'
AND acceptance_json->>'evidenceStatus' = 'pending'
AND NULLIF(acceptance_json->>'evidenceDueAt', '')::timestamptz > NOW()
),
0
)::int AS vip_evidence_pending_settlement_amount
FROM worker_orders
GROUP BY status
`,
[normalizedWorkerId],
)
return result.rows.map((row) => ({
status: row.status,
orderCount: Number(row.order_count || 0),
settlementAmount: Number(row.settlement_amount || 0),
vipEvidencePendingCount: Number(row.vip_evidence_pending_count || 0),
vipEvidencePendingSettlementAmount: Number(row.vip_evidence_pending_settlement_amount || 0),
}))
}
export async function updateWorkOrder(
workOrderId: number | string,
patch: Partial<
+11
View File
@@ -11,6 +11,7 @@ import {
getWorkerProfile,
getWorkerSessionSummary,
getWorkerHallLeaderboard,
getWorkerMyOrderOverview,
grabWorkerHallOrder,
joinWorkerSharingOrder,
listWorkerProfileFinanceRequests,
@@ -268,6 +269,16 @@ router.get(
}),
)
router.get(
'/orders/overview',
requireActiveWorker,
createRouteHandler((req) => getWorkerMyOrderOverview(getRequiredWorkerSession(req)), {
successMessage: 'ok',
errorMessage: '读取我的订单概览失败',
scope: '[worker/orders/overview]',
}),
)
router.get(
'/orders/:workOrderId/events',
requireActiveWorker,
@@ -28,6 +28,7 @@ import {
getWorkerUserByDisplayName,
getWorkOrderById,
getWorkOrderShare,
getWorkerOrderOverview,
grabWorkOrder,
incrementWorkerSessionVersion,
joinWorkOrderShare,
@@ -1148,6 +1149,40 @@ export async function listWorkerMyOrders(query: JsonObject = {}, session: Worker
}
}
/** 打手订单标签概览:订单数与预计/已结算金额。 */
export async function getWorkerMyOrderOverview(session: WorkerSession) {
requireActiveWorkerSession(session)
const worker = await getRequiredWorker(session.workerId)
await settleOverdueWorkOrders({ workerId: worker.id, limit: 50 })
const rows = await getWorkerOrderOverview(worker.id)
const items = rows.map((row) => ({
status: row.status,
orderCount: row.orderCount,
settlementAmount: row.settlementAmount,
}))
const vipEvidencePending = rows.reduce(
(summary, row) => ({
orderCount: summary.orderCount + row.vipEvidencePendingCount,
settlementAmount: summary.settlementAmount + row.vipEvidencePendingSettlementAmount,
}),
{ orderCount: 0, settlementAmount: 0 },
)
const all = items.reduce(
(summary, item) => ({
orderCount: summary.orderCount + item.orderCount,
settlementAmount: summary.settlementAmount + item.settlementAmount,
}),
{ orderCount: 0, settlementAmount: 0 },
)
return {
items: [
...items,
{ status: 'vip_evidence_pending', ...vipEvidencePending },
{ status: 'all', ...all },
],
}
}
export async function getWorkerMyOrderEvents(workOrderId: number | string, session: WorkerSession) {
requireActiveWorkerSession(session)
if (runtimeConfig.worker.orderTimelineVisible !== true) {