完善个人中心资金功能
This commit is contained in:
@@ -31,6 +31,8 @@ export type WorkerUserRow = {
|
||||
level_permission_json?: string | Record<string, unknown>
|
||||
available_amount?: number
|
||||
frozen_deposit_amount?: number
|
||||
total_credited_amount?: number
|
||||
total_settled_amount?: number
|
||||
}
|
||||
|
||||
export type WorkerWalletRow = {
|
||||
@@ -43,6 +45,37 @@ export type WorkerWalletRow = {
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export type WorkerWalletLedgerRow = {
|
||||
id: number
|
||||
worker_id: number
|
||||
ledger_type: string
|
||||
amount: number
|
||||
balance_after: number
|
||||
frozen_after: number
|
||||
related_work_order_id: number | null
|
||||
audit_status: string
|
||||
note: string
|
||||
payload_json: string | Record<string, unknown>
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export type WorkerFinanceRequestRow = {
|
||||
id: number
|
||||
worker_id: number
|
||||
request_type: string
|
||||
status: string
|
||||
amount: number
|
||||
account_channel: string
|
||||
account_name: string
|
||||
account_no: string
|
||||
note: string
|
||||
reviewed_note: string
|
||||
payload_json: string | Record<string, unknown>
|
||||
created_at: string
|
||||
updated_at: string
|
||||
reviewed_at: string | null
|
||||
}
|
||||
|
||||
export type WorkCategoryRow = {
|
||||
id: number
|
||||
category_key: string
|
||||
@@ -133,6 +166,21 @@ type ProductRuleListInput = {
|
||||
keyword?: string
|
||||
}
|
||||
|
||||
type WalletLedgerListInput = {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
workerId?: number
|
||||
ledgerType?: string
|
||||
}
|
||||
|
||||
type FinanceRequestListInput = {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
workerId?: number
|
||||
status?: string
|
||||
requestType?: string
|
||||
}
|
||||
|
||||
type CreateWorkerInput = {
|
||||
username: string
|
||||
passwordHash: string
|
||||
@@ -167,7 +215,9 @@ const WORKER_USER_SELECT = `
|
||||
wl.name AS level_name,
|
||||
wl.permission_json AS level_permission_json,
|
||||
ww.available_amount,
|
||||
ww.frozen_deposit_amount
|
||||
ww.frozen_deposit_amount,
|
||||
ww.total_credited_amount,
|
||||
ww.total_settled_amount
|
||||
FROM worker_users wu
|
||||
LEFT JOIN worker_levels wl ON wl.id = wu.level_id
|
||||
LEFT JOIN worker_wallets ww ON ww.worker_id = wu.id
|
||||
@@ -333,6 +383,30 @@ export async function updateWorkerUser(
|
||||
return getWorkerUserById(workerId)
|
||||
}
|
||||
|
||||
export async function updateWorkerPassword(input: {
|
||||
workerId: number
|
||||
passwordHash: string
|
||||
sessionVersion: number
|
||||
now: string
|
||||
}): Promise<WorkerUserRow | null> {
|
||||
const result = await query<{ id: number }>(
|
||||
`
|
||||
UPDATE worker_users
|
||||
SET
|
||||
password_hash = $1,
|
||||
session_version = $2,
|
||||
updated_at = $3
|
||||
WHERE id = $4
|
||||
RETURNING id
|
||||
`,
|
||||
[input.passwordHash, input.sessionVersion, input.now, input.workerId],
|
||||
)
|
||||
if (!result.rows[0]) {
|
||||
return null
|
||||
}
|
||||
return getWorkerUserById(input.workerId)
|
||||
}
|
||||
|
||||
export async function incrementWorkerSessionVersion(
|
||||
workerId: number | string,
|
||||
now: string,
|
||||
@@ -394,6 +468,38 @@ export async function getWorkerWallet(workerId: number | string): Promise<Worker
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function listWorkerWalletLedgers({
|
||||
page = 1,
|
||||
pageSize = 20,
|
||||
workerId = 0,
|
||||
ledgerType = '',
|
||||
}: WalletLedgerListInput = {}): Promise<{ items: WorkerWalletLedgerRow[]; total: number }> {
|
||||
const { whereClause, params } = buildWorkerWalletLedgerWhere({
|
||||
workerId,
|
||||
ledgerType,
|
||||
})
|
||||
const totalResult = await query<{ total: number }>(
|
||||
`SELECT COUNT(*)::int AS total FROM worker_wallet_ledgers wwl ${whereClause}`,
|
||||
params,
|
||||
)
|
||||
const offset = (page - 1) * pageSize
|
||||
params.push(pageSize, offset)
|
||||
const itemsResult = await query<WorkerWalletLedgerRow>(
|
||||
`
|
||||
SELECT *
|
||||
FROM worker_wallet_ledgers wwl
|
||||
${whereClause}
|
||||
ORDER BY wwl.created_at DESC, wwl.id DESC
|
||||
LIMIT $${params.length - 1} OFFSET $${params.length}
|
||||
`,
|
||||
params,
|
||||
)
|
||||
return {
|
||||
items: itemsResult.rows,
|
||||
total: Number(totalResult.rows[0]?.total || 0),
|
||||
}
|
||||
}
|
||||
|
||||
export async function addWorkerWalletCredit(input: {
|
||||
workerId: number
|
||||
amount: number
|
||||
@@ -438,6 +544,121 @@ export async function addWorkerWalletCredit(input: {
|
||||
})
|
||||
}
|
||||
|
||||
export async function createWorkerFinanceRequest(input: {
|
||||
workerId: number
|
||||
requestType: string
|
||||
amount: number
|
||||
accountChannel: string
|
||||
accountName: string
|
||||
accountNo: string
|
||||
note: string
|
||||
payloadJson: string
|
||||
now: string
|
||||
}): Promise<WorkerFinanceRequestRow | null> {
|
||||
const result = await query<WorkerFinanceRequestRow>(
|
||||
`
|
||||
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 listWorkerFinanceRequests({
|
||||
page = 1,
|
||||
pageSize = 20,
|
||||
workerId = 0,
|
||||
status = '',
|
||||
requestType = '',
|
||||
}: FinanceRequestListInput = {}): Promise<{ items: WorkerFinanceRequestRow[]; total: number }> {
|
||||
const { whereClause, params } = buildWorkerFinanceRequestWhere({
|
||||
workerId,
|
||||
status,
|
||||
requestType,
|
||||
})
|
||||
const totalResult = await query<{ total: number }>(
|
||||
`SELECT COUNT(*)::int AS total FROM worker_finance_requests wfr ${whereClause}`,
|
||||
params,
|
||||
)
|
||||
const offset = (page - 1) * pageSize
|
||||
params.push(pageSize, offset)
|
||||
const itemsResult = await query<WorkerFinanceRequestRow>(
|
||||
`
|
||||
SELECT *
|
||||
FROM worker_finance_requests wfr
|
||||
${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 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 async function countWorkerAcceptedOrders(workerId: number | string): Promise<number> {
|
||||
const result = await query<{ total: number }>(
|
||||
`
|
||||
SELECT COUNT(*)::int AS total
|
||||
FROM work_orders
|
||||
WHERE assigned_worker_id = $1
|
||||
AND status = 'accepted'
|
||||
`,
|
||||
[Number(workerId)],
|
||||
)
|
||||
return Number(result.rows[0]?.total || 0)
|
||||
}
|
||||
|
||||
export async function getWorkCategoryByKey(categoryKey: string): Promise<WorkCategoryRow | null> {
|
||||
const result = await query<WorkCategoryRow>(
|
||||
'SELECT * FROM work_categories WHERE category_key = $1 LIMIT 1',
|
||||
@@ -1255,6 +1476,51 @@ function buildWorkOrderWhere({ status = '', keyword = '', workerId = 0 }: ListIn
|
||||
}
|
||||
}
|
||||
|
||||
function buildWorkerWalletLedgerWhere({
|
||||
workerId = 0,
|
||||
ledgerType = '',
|
||||
}: WalletLedgerListInput) {
|
||||
const filters: string[] = []
|
||||
const params: unknown[] = []
|
||||
if (workerId) {
|
||||
params.push(workerId)
|
||||
filters.push(`wwl.worker_id = $${params.length}`)
|
||||
}
|
||||
if (ledgerType) {
|
||||
params.push(ledgerType)
|
||||
filters.push(`wwl.ledger_type = $${params.length}`)
|
||||
}
|
||||
return {
|
||||
whereClause: filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '',
|
||||
params,
|
||||
}
|
||||
}
|
||||
|
||||
function buildWorkerFinanceRequestWhere({
|
||||
workerId = 0,
|
||||
status = '',
|
||||
requestType = '',
|
||||
}: FinanceRequestListInput) {
|
||||
const filters: string[] = []
|
||||
const params: unknown[] = []
|
||||
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}`)
|
||||
}
|
||||
return {
|
||||
whereClause: filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '',
|
||||
params,
|
||||
}
|
||||
}
|
||||
|
||||
function buildWorkProductRuleWhere({ enabled = null, keyword = '' }: ProductRuleListInput) {
|
||||
const filters: string[] = []
|
||||
const params: unknown[] = []
|
||||
|
||||
Reference in New Issue
Block a user