展示打手提现统计
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
-- 支持资金申请列表按打手快速统计提现次数和已提现金额。
|
||||
CREATE INDEX IF NOT EXISTS idx_worker_finance_requests_worker_withdraw_stats
|
||||
ON worker_finance_requests(worker_id, request_type)
|
||||
INCLUDE (status, amount);
|
||||
@@ -154,6 +154,11 @@ export type WorkerFinanceRequestRow = {
|
||||
worker_username?: string
|
||||
worker_display_name?: string
|
||||
worker_phone?: string
|
||||
worker_type?: string
|
||||
worker_level_key?: string
|
||||
worker_level_name?: string
|
||||
worker_withdraw_request_count?: number
|
||||
worker_total_withdraw_amount?: number
|
||||
}
|
||||
|
||||
export type WorkerWithdrawalAccountRow = {
|
||||
|
||||
@@ -39,9 +39,23 @@ const WORKER_FINANCE_REQUEST_SELECT = `
|
||||
wfr.*,
|
||||
wu.username AS worker_username,
|
||||
wu.display_name AS worker_display_name,
|
||||
wu.phone AS worker_phone
|
||||
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 type CreateWorkerSessionInput = {
|
||||
|
||||
@@ -392,6 +392,11 @@ export function mapFinanceRequest(request: WorkerFinanceRequestRow | null | unde
|
||||
username: request.worker_username || '',
|
||||
displayName: request.worker_display_name || request.worker_username || '',
|
||||
phone: request.worker_phone || '',
|
||||
workerType: normalizeWorkerType(request.worker_type),
|
||||
levelKey: request.worker_level_key || '',
|
||||
levelName: request.worker_level_name || '',
|
||||
withdrawRequestCount: Number(request.worker_withdraw_request_count || 0),
|
||||
totalWithdrawAmount: Number(request.worker_total_withdraw_amount || 0),
|
||||
}
|
||||
: null,
|
||||
}
|
||||
|
||||
@@ -525,6 +525,11 @@ test('支付宝提现申请保留收款二维码快照', () => {
|
||||
created_at: '2026-08-20T00:00:00.000Z',
|
||||
updated_at: '2026-08-20T00:00:00.000Z',
|
||||
reviewed_at: null,
|
||||
worker_type: 'internal',
|
||||
worker_level_key: 'vip5',
|
||||
worker_level_name: 'VIP5',
|
||||
worker_withdraw_request_count: 3,
|
||||
worker_total_withdraw_amount: 28_800,
|
||||
}
|
||||
|
||||
const mapped = mapFinanceRequest(request)
|
||||
@@ -532,6 +537,17 @@ test('支付宝提现申请保留收款二维码快照', () => {
|
||||
(mapped?.payload.alipayQrCodeImage as { url?: string }).url,
|
||||
'https://example.com/alipay-qr.png',
|
||||
)
|
||||
assert.deepEqual(mapped?.worker, {
|
||||
workerId: 1,
|
||||
username: '',
|
||||
displayName: '',
|
||||
phone: '',
|
||||
workerType: 'internal',
|
||||
levelKey: 'vip5',
|
||||
levelName: 'VIP5',
|
||||
withdrawRequestCount: 3,
|
||||
totalWithdrawAmount: 28_800,
|
||||
})
|
||||
})
|
||||
|
||||
test('提现渠道仅支持支付宝和微信', () => {
|
||||
|
||||
@@ -201,13 +201,25 @@ export default function FinancePanel() {
|
||||
const requestColumns: TableColumnsType<WorkerFinanceRequest> = [
|
||||
{
|
||||
title: '打手',
|
||||
minWidth: 180,
|
||||
minWidth: 250,
|
||||
render: (_, row) => (
|
||||
<div className="cell-stack">
|
||||
<Typography.Text strong>
|
||||
{row.worker?.displayName || row.worker?.username || '-'}
|
||||
</Typography.Text>
|
||||
<Typography.Text type="secondary">{row.worker?.username || '-'}</Typography.Text>
|
||||
{row.worker ? (
|
||||
<Space size={[4, 4]} wrap>
|
||||
<Tag color={row.worker.workerType === 'internal' ? 'blue' : 'default'}>
|
||||
{row.worker.workerType === 'internal' ? '内部打手' : '外部打手'}
|
||||
</Tag>
|
||||
<Tag>{row.worker.levelName || row.worker.levelKey || '未分级'}</Tag>
|
||||
<Typography.Text type="secondary">
|
||||
提现 {row.worker.withdrawRequestCount} 次,累计
|
||||
{formatMoney(row.worker.totalWithdrawAmount)}
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
) : null}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -99,6 +99,11 @@ export type WorkerFinanceRequest = {
|
||||
username: string
|
||||
displayName: string
|
||||
phone: string
|
||||
workerType: 'internal' | 'external'
|
||||
levelKey: string
|
||||
levelName: string
|
||||
withdrawRequestCount: number
|
||||
totalWithdrawAmount: number
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user