From ec29469fcb825149444628473c58a466993c4ca2 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Fri, 21 Aug 2026 18:09:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=86=E5=88=86=E6=89=93=E6=89=8B=E8=B5=84?= =?UTF-8?q?=E9=87=91=E4=BB=93=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/repositories/worker-platform/index.ts | 1 + .../worker-platform/worker-finance-repo.ts | 451 +++++++++++++++++ .../worker-platform/worker-repo.ts | 469 +----------------- 3 files changed, 465 insertions(+), 456 deletions(-) create mode 100644 apps/backend/src/repositories/worker-platform/worker-finance-repo.ts diff --git a/apps/backend/src/repositories/worker-platform/index.ts b/apps/backend/src/repositories/worker-platform/index.ts index fe86b937..94efc081 100644 --- a/apps/backend/src/repositories/worker-platform/index.ts +++ b/apps/backend/src/repositories/worker-platform/index.ts @@ -4,6 +4,7 @@ export * from './worker-repo.js' export * from './worker-session-repo.js' export * from './worker-level-repo.js' export * from './worker-wallet-repo.js' +export * from './worker-finance-repo.js' export * from './work-order-repo.js' export * from './work-order-event-repo.js' export * from './work-order-share-repo.js' diff --git a/apps/backend/src/repositories/worker-platform/worker-finance-repo.ts b/apps/backend/src/repositories/worker-platform/worker-finance-repo.ts new file mode 100644 index 00000000..34f97822 --- /dev/null +++ b/apps/backend/src/repositories/worker-platform/worker-finance-repo.ts @@ -0,0 +1,451 @@ +import { query, withTransaction } from '../../db/client.js' +import { ensureWorkerWalletWithClient, getWorkerWalletWithClient } from './shared.js' +import type { + FinanceRequestListInput, + WorkerFinanceRequestRow, + WorkerWithdrawalAccountRow, +} from './types.js' +import type { PoolClient } from 'pg' + +const WORKER_FINANCE_REQUEST_SELECT = ` + SELECT + wfr.*, + wu.username AS worker_username, + wu.display_name AS worker_display_name, + wu.phone AS worker_phone, + wu.worker_type, + wl.level_key AS worker_level_key, + wl.name AS worker_level_name, + withdraw_stats.withdraw_request_count AS worker_withdraw_request_count, + withdraw_stats.total_withdraw_amount AS worker_total_withdraw_amount + FROM worker_finance_requests wfr + LEFT JOIN worker_users wu ON wu.id = wfr.worker_id + LEFT JOIN worker_levels wl ON wl.id = wu.level_id + LEFT JOIN LATERAL ( + SELECT + COUNT(*)::int AS withdraw_request_count, + COALESCE(SUM(amount) FILTER (WHERE status = 'approved'), 0)::bigint AS total_withdraw_amount + FROM worker_finance_requests history_request + WHERE history_request.worker_id = wfr.worker_id + AND history_request.request_type = 'withdraw' + ) withdraw_stats ON TRUE +` + +export async function createWorkerFinanceRequest(input: { + workerId: number + requestType: string + amount: number + accountChannel: string + accountName: string + accountNo: string + note: string + payloadJson: string + now: string +}): Promise { + const result = await query( + ` + INSERT INTO worker_finance_requests ( + worker_id, request_type, status, amount, + account_channel, account_name, account_no, + note, reviewed_note, payload_json, created_at, updated_at + ) VALUES ($1, $2, 'pending', $3, $4, $5, $6, $7, '', $8::jsonb, $9, $10) + RETURNING * + `, + [ + input.workerId, + input.requestType, + input.amount, + input.accountChannel, + input.accountName, + input.accountNo, + input.note, + input.payloadJson, + input.now, + input.now, + ], + ) + return result.rows[0] || null +} + +export async function getWorkerWithdrawalAccount( + workerId: number | string, + accountChannel: string, +): Promise { + const result = await query( + ` + SELECT * + FROM worker_withdrawal_accounts + WHERE worker_id = $1 AND account_channel = $2 + LIMIT 1 + `, + [Number(workerId), accountChannel], + ) + return result.rows[0] || null +} + +export async function listWorkerWithdrawalAccounts( + workerId: number | string, +): Promise { + const result = await query( + ` + SELECT * + FROM worker_withdrawal_accounts + WHERE worker_id = $1 + ORDER BY account_channel ASC + `, + [Number(workerId)], + ) + return result.rows +} + +export async function createWorkerWithdrawalAccount(input: { + workerId: number + accountChannel: string + accountName: string + accountNo: string + alipayQrCodeJson: string + wechatQrCodeJson: string + now: string +}): Promise { + const result = await query( + ` + INSERT INTO worker_withdrawal_accounts ( + worker_id, account_channel, account_name, account_no, + alipay_qr_code_json, wechat_qr_code_json, created_at + ) VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7) + ON CONFLICT (worker_id, account_channel) DO NOTHING + RETURNING * + `, + [ + input.workerId, + input.accountChannel, + input.accountName, + input.accountNo, + input.alipayQrCodeJson, + input.wechatQrCodeJson, + input.now, + ], + ) + return result.rows[0] || null +} + +export async function upsertWorkerWithdrawalAccount(input: { + workerId: number + accountChannel: string + accountName: string + accountNo: string + alipayQrCodeJson: string + wechatQrCodeJson: string + now: string +}): Promise { + const result = await query( + ` + INSERT INTO worker_withdrawal_accounts ( + worker_id, account_channel, account_name, account_no, + alipay_qr_code_json, wechat_qr_code_json, created_at + ) VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7) + ON CONFLICT (worker_id, account_channel) DO UPDATE + SET + account_name = EXCLUDED.account_name, + account_no = EXCLUDED.account_no, + alipay_qr_code_json = EXCLUDED.alipay_qr_code_json, + wechat_qr_code_json = EXCLUDED.wechat_qr_code_json + RETURNING * + `, + [ + input.workerId, + input.accountChannel, + input.accountName, + input.accountNo, + input.alipayQrCodeJson, + input.wechatQrCodeJson, + input.now, + ], + ) + return result.rows[0] || null +} + +export async function getWorkerFinanceRequestById( + requestId: number | string, +): Promise { + const result = await query( + `${WORKER_FINANCE_REQUEST_SELECT} WHERE wfr.id = $1 LIMIT 1`, + [Number(requestId)], + ) + return result.rows[0] || null +} + +export async function countWorkerWithdrawRequestsOnDay( + workerId: number | string, + dayStartIso: string, + dayEndIso: string, +): Promise { + const result = await query<{ total: number }>( + ` + SELECT COUNT(*)::int AS total + FROM worker_finance_requests + WHERE worker_id = $1 + AND request_type = 'withdraw' + AND status != 'cancelled' + AND created_at >= $2 + AND created_at < $3 + `, + [Number(workerId), dayStartIso, dayEndIso], + ) + return Number(result.rows[0]?.total || 0) +} + +export async function listWorkerFinanceRequests({ + page = 1, + pageSize = 20, + requestId = 0, + workerId = 0, + status = '', + requestType = '', + keyword = '', +}: FinanceRequestListInput = {}): Promise<{ items: WorkerFinanceRequestRow[]; total: number }> { + const { whereClause, params } = buildWorkerFinanceRequestWhere({ + requestId, + workerId, + status, + requestType, + keyword, + }) + const totalResult = await query<{ total: number }>( + `SELECT COUNT(*)::int AS total FROM worker_finance_requests wfr + LEFT JOIN worker_users wu ON wu.id = wfr.worker_id + ${whereClause}`, + params, + ) + const offset = (page - 1) * pageSize + params.push(pageSize, offset) + const itemsResult = await query( + `${WORKER_FINANCE_REQUEST_SELECT} + ${whereClause} + ORDER BY wfr.created_at DESC, wfr.id DESC + LIMIT $${params.length - 1} OFFSET $${params.length}`, + params, + ) + return { + items: itemsResult.rows, + total: Number(totalResult.rows[0]?.total || 0), + } +} + +export async function reviewWorkerFinanceRequest(input: { + requestId: number + status: string + reviewedNote: string + now: string +}): Promise<{ + request: WorkerFinanceRequestRow | null + failureReason: 'request_not_pending' | 'withdraw_insufficient' | null +}> { + return withTransaction(async (client) => { + const currentResult = await client.query( + ` + SELECT * + FROM worker_finance_requests + WHERE id = $1 + LIMIT 1 + FOR UPDATE + `, + [input.requestId], + ) + const current = currentResult.rows[0] || null + if (!current) return { request: null, failureReason: null } + + if (current.status !== 'pending') { + return { + request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), + failureReason: 'request_not_pending', + } + } + + if (input.status === 'approved') { + await ensureWorkerWalletWithClient(client, Number(current.worker_id), input.now) + const wallet = await getWorkerWalletWithClient(client, Number(current.worker_id)) + const availableAmount = Number(wallet?.available_amount || 0) + const frozenAmount = Number(wallet?.frozen_deposit_amount || 0) + const amount = Number(current.amount || 0) + const note = + input.reviewedNote || + (current.request_type === 'withdraw' ? '提现申请审核通过' : '充值申请审核通过') + + if (current.request_type === 'withdraw') { + if (availableAmount < amount) { + return { + request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), + failureReason: 'withdraw_insufficient', + } + } + const nextAvailable = availableAmount - amount + await client.query( + ` + UPDATE worker_wallets + SET available_amount = $1, updated_at = $2 + WHERE worker_id = $3 + `, + [nextAvailable, input.now, Number(current.worker_id)], + ) + await client.query( + ` + INSERT INTO worker_wallet_ledgers ( + worker_id, ledger_type, amount, balance_after, frozen_after, + audit_status, note, payload_json, created_at + ) VALUES ($1, 'withdraw_paid', $2, $3, $4, 'approved', $5, $6::jsonb, $7) + `, + [ + Number(current.worker_id), + -amount, + nextAvailable, + frozenAmount, + note, + JSON.stringify({ + requestId: Number(current.id), + requestType: current.request_type, + source: 'admin_finance_review', + }), + input.now, + ], + ) + } else { + const nextAvailable = availableAmount + amount + await client.query( + ` + UPDATE worker_wallets + SET + available_amount = $1, + total_credited_amount = total_credited_amount + $2, + updated_at = $3 + WHERE worker_id = $4 + `, + [nextAvailable, amount, input.now, Number(current.worker_id)], + ) + await client.query( + ` + INSERT INTO worker_wallet_ledgers ( + worker_id, ledger_type, amount, balance_after, frozen_after, + audit_status, note, payload_json, created_at + ) VALUES ($1, 'manual_credit', $2, $3, $4, 'approved', $5, $6::jsonb, $7) + `, + [ + Number(current.worker_id), + amount, + nextAvailable, + frozenAmount, + note, + JSON.stringify({ + requestId: Number(current.id), + requestType: current.request_type, + source: 'admin_finance_review', + }), + input.now, + ], + ) + } + } + + await client.query( + ` + UPDATE worker_finance_requests + SET + status = $1, + reviewed_note = $2, + reviewed_at = $3, + updated_at = $3 + WHERE id = $4 + `, + [input.status, input.reviewedNote, input.now, input.requestId], + ) + + return { + request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), + failureReason: null, + } + }) +} + +export async function getWorkerFinanceRequestSummary(workerId: number | string) { + const result = await query<{ + pending_withdraw_amount: number + approved_withdraw_amount: number + pending_recharge_amount: number + }>( + ` + SELECT + COALESCE( + SUM(CASE WHEN request_type = 'withdraw' AND status = 'pending' THEN amount ELSE 0 END), + 0 + )::int AS pending_withdraw_amount, + COALESCE( + SUM(CASE WHEN request_type = 'withdraw' AND status = 'approved' THEN amount ELSE 0 END), + 0 + )::int AS approved_withdraw_amount, + COALESCE( + SUM(CASE WHEN request_type = 'recharge' AND status = 'pending' THEN amount ELSE 0 END), + 0 + )::int AS pending_recharge_amount + FROM worker_finance_requests + WHERE worker_id = $1 + `, + [Number(workerId)], + ) + return { + pendingWithdrawAmount: Number(result.rows[0]?.pending_withdraw_amount || 0), + approvedWithdrawAmount: Number(result.rows[0]?.approved_withdraw_amount || 0), + pendingRechargeAmount: Number(result.rows[0]?.pending_recharge_amount || 0), + } +} + +async function getWorkerFinanceRequestByIdWithClient( + client: PoolClient, + requestId: number | string, +): Promise { + const result = await client.query( + `${WORKER_FINANCE_REQUEST_SELECT} WHERE wfr.id = $1 LIMIT 1`, + [Number(requestId)], + ) + return result.rows[0] || null +} + +function buildWorkerFinanceRequestWhere({ + requestId = 0, + workerId = 0, + status = '', + requestType = '', + keyword = '', +}: FinanceRequestListInput) { + const filters: string[] = [] + const params: unknown[] = [] + if (requestId) { + params.push(requestId) + filters.push(`wfr.id = $${params.length}`) + } + if (workerId) { + params.push(workerId) + filters.push(`wfr.worker_id = $${params.length}`) + } + if (status) { + params.push(status) + filters.push(`wfr.status = $${params.length}`) + } + if (requestType) { + params.push(requestType) + filters.push(`wfr.request_type = $${params.length}`) + } + if (keyword) { + params.push(`%${keyword}%`) + filters.push( + `(wu.username ILIKE $${params.length} + OR wu.display_name ILIKE $${params.length} + OR wu.phone ILIKE $${params.length} + OR wfr.account_name ILIKE $${params.length} + OR wfr.account_no ILIKE $${params.length})`, + ) + } + return { + whereClause: filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '', + params, + } +} diff --git a/apps/backend/src/repositories/worker-platform/worker-repo.ts b/apps/backend/src/repositories/worker-platform/worker-repo.ts index 974d9b3d..f4fe8b74 100644 --- a/apps/backend/src/repositories/worker-platform/worker-repo.ts +++ b/apps/backend/src/repositories/worker-platform/worker-repo.ts @@ -1,13 +1,6 @@ import { query, withTransaction } from '../../db/client.js' import { ensureWorkerWalletWithClient, getWorkerWalletWithClient } from './shared.js' -import type { - CreateWorkerInput, - FinanceRequestListInput, - ListInput, - WorkerFinanceRequestRow, - WorkerUserRow, - WorkerWithdrawalAccountRow, -} from './types.js' +import type { CreateWorkerInput, ListInput, WorkerUserRow } from './types.js' import type { PoolClient } from 'pg' const WORKER_USER_SELECT = ` @@ -29,30 +22,6 @@ const WORKER_USER_SELECT = ` LEFT JOIN worker_wallets ww ON ww.worker_id = wu.id ` -const WORKER_FINANCE_REQUEST_SELECT = ` - SELECT - wfr.*, - wu.username AS worker_username, - wu.display_name AS worker_display_name, - wu.phone AS worker_phone, - wu.worker_type, - wl.level_key AS worker_level_key, - wl.name AS worker_level_name, - withdraw_stats.withdraw_request_count AS worker_withdraw_request_count, - withdraw_stats.total_withdraw_amount AS worker_total_withdraw_amount - FROM worker_finance_requests wfr - LEFT JOIN worker_users wu ON wu.id = wfr.worker_id - LEFT JOIN worker_levels wl ON wl.id = wu.level_id - LEFT JOIN LATERAL ( - SELECT - COUNT(*)::int AS withdraw_request_count, - COALESCE(SUM(amount) FILTER (WHERE status = 'approved'), 0)::bigint AS total_withdraw_amount - FROM worker_finance_requests history_request - WHERE history_request.worker_id = wfr.worker_id - AND history_request.request_type = 'withdraw' - ) withdraw_stats ON TRUE -` - export { createWorkerSessionRecord, getWorkerSessionBySessionId, @@ -293,378 +262,18 @@ export { listWorkerWalletLedgers, } from './worker-wallet-repo.js' -export async function createWorkerFinanceRequest(input: { - workerId: number - requestType: string - amount: number - accountChannel: string - accountName: string - accountNo: string - note: string - payloadJson: string - now: string -}): Promise { - const result = await query( - ` - INSERT INTO worker_finance_requests ( - worker_id, request_type, status, amount, - account_channel, account_name, account_no, - note, reviewed_note, payload_json, created_at, updated_at - ) VALUES ($1, $2, 'pending', $3, $4, $5, $6, $7, '', $8::jsonb, $9, $10) - RETURNING * - `, - [ - input.workerId, - input.requestType, - input.amount, - input.accountChannel, - input.accountName, - input.accountNo, - input.note, - input.payloadJson, - input.now, - input.now, - ], - ) - return result.rows[0] || null -} - -export async function getWorkerWithdrawalAccount( - workerId: number | string, - accountChannel: string, -): Promise { - const result = await query( - ` - SELECT * - FROM worker_withdrawal_accounts - WHERE worker_id = $1 AND account_channel = $2 - LIMIT 1 - `, - [Number(workerId), accountChannel], - ) - return result.rows[0] || null -} - -export async function listWorkerWithdrawalAccounts( - workerId: number | string, -): Promise { - const result = await query( - ` - SELECT * - FROM worker_withdrawal_accounts - WHERE worker_id = $1 - ORDER BY account_channel ASC - `, - [Number(workerId)], - ) - return result.rows -} - -export async function createWorkerWithdrawalAccount(input: { - workerId: number - accountChannel: string - accountName: string - accountNo: string - alipayQrCodeJson: string - wechatQrCodeJson: string - now: string -}): Promise { - const result = await query( - ` - INSERT INTO worker_withdrawal_accounts ( - worker_id, account_channel, account_name, account_no, - alipay_qr_code_json, wechat_qr_code_json, created_at - ) VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7) - ON CONFLICT (worker_id, account_channel) DO NOTHING - RETURNING * - `, - [ - input.workerId, - input.accountChannel, - input.accountName, - input.accountNo, - input.alipayQrCodeJson, - input.wechatQrCodeJson, - input.now, - ], - ) - return result.rows[0] || null -} - -export async function upsertWorkerWithdrawalAccount(input: { - workerId: number - accountChannel: string - accountName: string - accountNo: string - alipayQrCodeJson: string - wechatQrCodeJson: string - now: string -}): Promise { - const result = await query( - ` - INSERT INTO worker_withdrawal_accounts ( - worker_id, account_channel, account_name, account_no, - alipay_qr_code_json, wechat_qr_code_json, created_at - ) VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7) - ON CONFLICT (worker_id, account_channel) DO UPDATE - SET - account_name = EXCLUDED.account_name, - account_no = EXCLUDED.account_no, - alipay_qr_code_json = EXCLUDED.alipay_qr_code_json, - wechat_qr_code_json = EXCLUDED.wechat_qr_code_json - RETURNING * - `, - [ - input.workerId, - input.accountChannel, - input.accountName, - input.accountNo, - input.alipayQrCodeJson, - input.wechatQrCodeJson, - input.now, - ], - ) - return result.rows[0] || null -} - -export async function getWorkerFinanceRequestById( - requestId: number | string, -): Promise { - const result = await query( - `${WORKER_FINANCE_REQUEST_SELECT} WHERE wfr.id = $1 LIMIT 1`, - [Number(requestId)], - ) - return result.rows[0] || null -} - -export async function countWorkerWithdrawRequestsOnDay( - workerId: number | string, - dayStartIso: string, - dayEndIso: string, -): Promise { - const result = await query<{ total: number }>( - ` - SELECT COUNT(*)::int AS total - FROM worker_finance_requests - WHERE worker_id = $1 - AND request_type = 'withdraw' - AND status != 'cancelled' - AND created_at >= $2 - AND created_at < $3 - `, - [Number(workerId), dayStartIso, dayEndIso], - ) - return Number(result.rows[0]?.total || 0) -} - -export async function listWorkerFinanceRequests({ - page = 1, - pageSize = 20, - requestId = 0, - workerId = 0, - status = '', - requestType = '', - keyword = '', -}: FinanceRequestListInput = {}): Promise<{ items: WorkerFinanceRequestRow[]; total: number }> { - const { whereClause, params } = buildWorkerFinanceRequestWhere({ - requestId, - workerId, - status, - requestType, - keyword, - }) - const totalResult = await query<{ total: number }>( - `SELECT COUNT(*)::int AS total FROM worker_finance_requests wfr - LEFT JOIN worker_users wu ON wu.id = wfr.worker_id - ${whereClause}`, - params, - ) - const offset = (page - 1) * pageSize - params.push(pageSize, offset) - const itemsResult = await query( - `${WORKER_FINANCE_REQUEST_SELECT} - ${whereClause} - ORDER BY wfr.created_at DESC, wfr.id DESC - LIMIT $${params.length - 1} OFFSET $${params.length}`, - params, - ) - return { - items: itemsResult.rows, - total: Number(totalResult.rows[0]?.total || 0), - } -} - -export async function reviewWorkerFinanceRequest(input: { - requestId: number - status: string - reviewedNote: string - now: string -}): Promise<{ - request: WorkerFinanceRequestRow | null - failureReason: 'request_not_pending' | 'withdraw_insufficient' | null -}> { - return withTransaction(async (client) => { - const currentResult = await client.query( - ` - SELECT * - FROM worker_finance_requests - WHERE id = $1 - LIMIT 1 - FOR UPDATE - `, - [input.requestId], - ) - const current = currentResult.rows[0] || null - if (!current) { - return { - request: null, - failureReason: null, - } - } - - if (current.status !== 'pending') { - return { - request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), - failureReason: 'request_not_pending', - } - } - - if (input.status === 'approved') { - await ensureWorkerWalletWithClient(client, Number(current.worker_id), input.now) - const wallet = await getWorkerWalletWithClient(client, Number(current.worker_id)) - const availableAmount = Number(wallet?.available_amount || 0) - const frozenAmount = Number(wallet?.frozen_deposit_amount || 0) - const amount = Number(current.amount || 0) - const note = - input.reviewedNote || - (current.request_type === 'withdraw' ? '提现申请审核通过' : '充值申请审核通过') - - if (current.request_type === 'withdraw') { - if (availableAmount < amount) { - return { - request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), - failureReason: 'withdraw_insufficient', - } - } - - const nextAvailable = availableAmount - amount - await client.query( - ` - UPDATE worker_wallets - SET available_amount = $1, updated_at = $2 - WHERE worker_id = $3 - `, - [nextAvailable, input.now, Number(current.worker_id)], - ) - await client.query( - ` - INSERT INTO worker_wallet_ledgers ( - worker_id, ledger_type, amount, balance_after, frozen_after, - audit_status, note, payload_json, created_at - ) VALUES ($1, 'withdraw_paid', $2, $3, $4, 'approved', $5, $6::jsonb, $7) - `, - [ - Number(current.worker_id), - -amount, - nextAvailable, - frozenAmount, - note, - JSON.stringify({ - requestId: Number(current.id), - requestType: current.request_type, - source: 'admin_finance_review', - }), - input.now, - ], - ) - } else { - const nextAvailable = availableAmount + amount - await client.query( - ` - UPDATE worker_wallets - SET - available_amount = $1, - total_credited_amount = total_credited_amount + $2, - updated_at = $3 - WHERE worker_id = $4 - `, - [nextAvailable, amount, input.now, Number(current.worker_id)], - ) - await client.query( - ` - INSERT INTO worker_wallet_ledgers ( - worker_id, ledger_type, amount, balance_after, frozen_after, - audit_status, note, payload_json, created_at - ) VALUES ($1, 'manual_credit', $2, $3, $4, 'approved', $5, $6::jsonb, $7) - `, - [ - Number(current.worker_id), - amount, - nextAvailable, - frozenAmount, - note, - JSON.stringify({ - requestId: Number(current.id), - requestType: current.request_type, - source: 'admin_finance_review', - }), - input.now, - ], - ) - } - } - - await client.query( - ` - UPDATE worker_finance_requests - SET - status = $1, - reviewed_note = $2, - reviewed_at = $3, - updated_at = $3 - WHERE id = $4 - `, - [input.status, input.reviewedNote, input.now, input.requestId], - ) - - return { - request: await getWorkerFinanceRequestByIdWithClient(client, input.requestId), - failureReason: null, - } - }) -} - -export async function getWorkerFinanceRequestSummary(workerId: number | string) { - const result = await query<{ - pending_withdraw_amount: number - approved_withdraw_amount: number - pending_recharge_amount: number - }>( - ` - SELECT - COALESCE( - SUM(CASE WHEN request_type = 'withdraw' AND status = 'pending' THEN amount ELSE 0 END), - 0 - )::int AS pending_withdraw_amount, - COALESCE( - SUM(CASE WHEN request_type = 'withdraw' AND status = 'approved' THEN amount ELSE 0 END), - 0 - )::int AS approved_withdraw_amount, - COALESCE( - SUM(CASE WHEN request_type = 'recharge' AND status = 'pending' THEN amount ELSE 0 END), - 0 - )::int AS pending_recharge_amount - FROM worker_finance_requests - WHERE worker_id = $1 - `, - [Number(workerId)], - ) - return { - pendingWithdrawAmount: Number(result.rows[0]?.pending_withdraw_amount || 0), - approvedWithdrawAmount: Number(result.rows[0]?.approved_withdraw_amount || 0), - pendingRechargeAmount: Number(result.rows[0]?.pending_recharge_amount || 0), - } -} +export { + countWorkerWithdrawRequestsOnDay, + createWorkerFinanceRequest, + createWorkerWithdrawalAccount, + getWorkerFinanceRequestById, + getWorkerFinanceRequestSummary, + getWorkerWithdrawalAccount, + listWorkerFinanceRequests, + listWorkerWithdrawalAccounts, + reviewWorkerFinanceRequest, + upsertWorkerWithdrawalAccount, +} from './worker-finance-repo.js' /** 完成单数按源订单去重,拼单份数只影响收益,不增加完成单数。 */ export async function countWorkerAcceptedOrders(workerId: number | string): Promise { @@ -939,17 +548,6 @@ async function getWorkerUserByIdWithClient( return result.rows[0] || null } -async function getWorkerFinanceRequestByIdWithClient( - client: PoolClient, - requestId: number | string, -): Promise { - const result = await client.query( - `${WORKER_FINANCE_REQUEST_SELECT} WHERE wfr.id = $1 LIMIT 1`, - [Number(requestId)], - ) - return result.rows[0] || null -} - function buildWorkerUserWhere({ status = '', keyword = '', @@ -981,44 +579,3 @@ function buildWorkerUserWhere({ params, } } - -function buildWorkerFinanceRequestWhere({ - requestId = 0, - workerId = 0, - status = '', - requestType = '', - keyword = '', -}: FinanceRequestListInput) { - const filters: string[] = [] - const params: unknown[] = [] - if (requestId) { - params.push(requestId) - filters.push(`wfr.id = $${params.length}`) - } - if (workerId) { - params.push(workerId) - filters.push(`wfr.worker_id = $${params.length}`) - } - if (status) { - params.push(status) - filters.push(`wfr.status = $${params.length}`) - } - if (requestType) { - params.push(requestType) - filters.push(`wfr.request_type = $${params.length}`) - } - if (keyword) { - params.push(`%${keyword}%`) - filters.push( - `(wu.username ILIKE $${params.length} - OR wu.display_name ILIKE $${params.length} - OR wu.phone ILIKE $${params.length} - OR wfr.account_name ILIKE $${params.length} - OR wfr.account_no ILIKE $${params.length})`, - ) - } - return { - whereClause: filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '', - params, - } -}