好友赠送单确认加好友后取消扣押金覆盖撤单撤回取消指派撤单申请与超时问题单处置

This commit is contained in:
yml2213
2026-08-23 11:23:17 +08:00
parent 70b31f4874
commit 360c5ea20e
6 changed files with 170 additions and 25 deletions
@@ -1,4 +1,5 @@
import { withTransaction } from '../../db/client.js'
import { isWorkOrderGiftDepositForfeitable } from '../../domain/work-order-acceptance-mode.js'
import { ensureWorkerWalletWithClient, getWorkerWalletWithClient } from './shared.js'
import { createWorkOrderEventWithClient } from './work-order-event-repo.js'
import { getWorkOrderByIdWithClient } from './work-order-query-repo.js'
@@ -124,6 +125,7 @@ export async function unassignWorkOrder(input: {
return { order: null, failureReason: 'work_order_no_worker' }
}
const forfeitGiftDeposit = isWorkOrderGiftDepositForfeitable(workOrder)
await ensureWorkerWalletWithClient(client, workerId, input.now)
const wallet = await getWorkerWalletWithClient(client, workerId)
const releaseAmount = Math.min(
@@ -147,7 +149,8 @@ export async function unassignWorkOrder(input: {
)
if (releaseAmount > 0) {
const nextAvailable = Number(wallet?.available_amount || 0) + releaseAmount
const nextAvailable =
Number(wallet?.available_amount || 0) + (forfeitGiftDeposit ? 0 : releaseAmount)
const nextFrozen = Math.max(0, Number(wallet?.frozen_deposit_amount || 0) - releaseAmount)
await client.query(
`
@@ -162,9 +165,19 @@ export async function unassignWorkOrder(input: {
INSERT INTO worker_wallet_ledgers (
worker_id, ledger_type, amount, balance_after, frozen_after,
related_work_order_id, note, payload_json, created_at
) VALUES ($1, 'deposit_release', $2, $3, $4, $5, '后台取消指派退还押金', '{}'::jsonb, $6)
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9)
`,
[workerId, releaseAmount, nextAvailable, nextFrozen, input.workOrderId, input.now],
[
workerId,
forfeitGiftDeposit ? 'deposit_deduction' : 'deposit_release',
forfeitGiftDeposit ? -releaseAmount : releaseAmount,
nextAvailable,
nextFrozen,
input.workOrderId,
forfeitGiftDeposit ? '后台取消指派扣除押金(已确认加好友)' : '后台取消指派退还押金',
JSON.stringify(forfeitGiftDeposit ? { giftDepositForfeited: true } : {}),
input.now,
],
)
}
@@ -175,7 +188,11 @@ export async function unassignWorkOrder(input: {
eventType: 'unassigned_by_admin',
fromStatus: 'in_progress',
toStatus: 'unassigned',
payloadJson: JSON.stringify({ workerId, releaseAmount }),
payloadJson: JSON.stringify({
workerId,
releaseAmount: forfeitGiftDeposit ? 0 : releaseAmount,
forfeitedAmount: forfeitGiftDeposit ? releaseAmount : 0,
}),
now: input.now,
})
@@ -214,6 +231,7 @@ export async function returnAssignedWorkOrderToHall(input: {
return { order: null, failureReason: 'work_order_no_worker' }
}
const forfeitGiftDeposit = isWorkOrderGiftDepositForfeitable(workOrder)
await ensureWorkerWalletWithClient(client, workerId, input.now)
const wallet = await getWorkerWalletWithClient(client, workerId)
const releaseAmount = Math.min(
@@ -239,7 +257,8 @@ export async function returnAssignedWorkOrderToHall(input: {
)
if (releaseAmount > 0) {
const nextAvailable = Number(wallet?.available_amount || 0) + releaseAmount
const nextAvailable =
Number(wallet?.available_amount || 0) + (forfeitGiftDeposit ? 0 : releaseAmount)
const nextFrozen = Math.max(0, Number(wallet?.frozen_deposit_amount || 0) - releaseAmount)
await client.query(
`
@@ -254,9 +273,19 @@ export async function returnAssignedWorkOrderToHall(input: {
INSERT INTO worker_wallet_ledgers (
worker_id, ledger_type, amount, balance_after, frozen_after,
related_work_order_id, note, payload_json, created_at
) VALUES ($1, 'deposit_release', $2, $3, $4, $5, '后台退回大厅退还押金', '{}'::jsonb, $6)
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9)
`,
[workerId, releaseAmount, nextAvailable, nextFrozen, input.workOrderId, input.now],
[
workerId,
forfeitGiftDeposit ? 'deposit_deduction' : 'deposit_release',
forfeitGiftDeposit ? -releaseAmount : releaseAmount,
nextAvailable,
nextFrozen,
input.workOrderId,
forfeitGiftDeposit ? '后台退回大厅扣除押金(已确认加好友)' : '后台退回大厅退还押金',
JSON.stringify(forfeitGiftDeposit ? { giftDepositForfeited: true } : {}),
input.now,
],
)
}
@@ -269,7 +298,8 @@ export async function returnAssignedWorkOrderToHall(input: {
toStatus: 'open',
payloadJson: JSON.stringify({
workerId,
releaseAmount,
releaseAmount: forfeitGiftDeposit ? 0 : releaseAmount,
forfeitedAmount: forfeitGiftDeposit ? releaseAmount : 0,
reason: String(input.reason || '').trim(),
}),
now: input.now,
@@ -310,6 +340,7 @@ export async function cancelAssignedWorkOrder(input: {
return { order: null, failureReason: 'work_order_no_worker' }
}
const forfeitGiftDeposit = isWorkOrderGiftDepositForfeitable(workOrder)
await ensureWorkerWalletWithClient(client, workerId, input.now)
const wallet = await getWorkerWalletWithClient(client, workerId)
const releaseAmount = Math.min(
@@ -326,6 +357,7 @@ export async function cancelAssignedWorkOrder(input: {
assigned_at = NULL,
deadline_at = NULL,
published_at = NULL,
${RESET_GIFT_FLOW_SQL},
updated_at = $1
WHERE id = $2
`,
@@ -333,7 +365,8 @@ export async function cancelAssignedWorkOrder(input: {
)
if (releaseAmount > 0) {
const nextAvailable = Number(wallet?.available_amount || 0) + releaseAmount
const nextAvailable =
Number(wallet?.available_amount || 0) + (forfeitGiftDeposit ? 0 : releaseAmount)
const nextFrozen = Math.max(0, Number(wallet?.frozen_deposit_amount || 0) - releaseAmount)
await client.query(
`
@@ -348,9 +381,19 @@ export async function cancelAssignedWorkOrder(input: {
INSERT INTO worker_wallet_ledgers (
worker_id, ledger_type, amount, balance_after, frozen_after,
related_work_order_id, note, payload_json, created_at
) VALUES ($1, 'deposit_release', $2, $3, $4, $5, '后台撤单退还押金', '{}'::jsonb, $6)
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9)
`,
[workerId, releaseAmount, nextAvailable, nextFrozen, input.workOrderId, input.now],
[
workerId,
forfeitGiftDeposit ? 'deposit_deduction' : 'deposit_release',
forfeitGiftDeposit ? -releaseAmount : releaseAmount,
nextAvailable,
nextFrozen,
input.workOrderId,
forfeitGiftDeposit ? '后台撤单扣除押金(已确认加好友)' : '后台撤单退还押金',
JSON.stringify(forfeitGiftDeposit ? { giftDepositForfeited: true } : {}),
input.now,
],
)
}
@@ -363,7 +406,8 @@ export async function cancelAssignedWorkOrder(input: {
toStatus: 'cancelled',
payloadJson: JSON.stringify({
workerId,
releaseAmount,
releaseAmount: forfeitGiftDeposit ? 0 : releaseAmount,
forfeitedAmount: forfeitGiftDeposit ? releaseAmount : 0,
reason: String(input.reason || '').trim(),
}),
now: input.now,
@@ -1,4 +1,5 @@
import { withTransaction } from '../../db/client.js'
import { isWorkOrderGiftDepositForfeitable } from '../../domain/work-order-acceptance-mode.js'
import { ensureWorkerWalletWithClient, getWorkerWalletWithClient } from './shared.js'
import { createWorkOrderEventWithClient } from './work-order-event-repo.js'
import { getWorkOrderByIdWithClient } from './work-order-query-repo.js'
@@ -57,8 +58,15 @@ export async function resolveProblemWorkOrder(input: {
restoreStatus = resolveProblemReturnToWorkerStatus(fromStatus)
}
const shouldReleaseDeposit = ['reopen', 'cancel_release'].includes(input.action)
const shouldDeductDeposit = input.action === 'cancel_deduct'
// 赠送单已确认加好友后不再退押金:释放类处置转为扣除,事件类型按实际资金动作记录。
const forfeitGiftDeposit = isWorkOrderGiftDepositForfeitable(workOrder)
const releaseActions = ['reopen', 'cancel_release']
const shouldReleaseDeposit = releaseActions.includes(input.action) && !forfeitGiftDeposit
const shouldDeductDeposit =
input.action === 'cancel_deduct' ||
(releaseActions.includes(input.action) && forfeitGiftDeposit)
const effectiveAction =
input.action === 'cancel_release' && forfeitGiftDeposit ? 'cancel_deduct' : input.action
const workerId = Number(workOrder.assigned_worker_id || 0)
let resolvedDepositAmount = 0
@@ -173,11 +181,12 @@ export async function resolveProblemWorkOrder(input: {
workOrderId: input.workOrderId,
actorType: 'admin',
actorId: input.actorName || '',
eventType: `problem_${input.action}`,
eventType: `problem_${effectiveAction}`,
fromStatus: 'problem',
toStatus: targetStatus,
payloadJson: JSON.stringify({
action: input.action,
giftDepositForfeited: forfeitGiftDeposit || undefined,
note: input.note,
depositAmount: resolvedDepositAmount,
}),
@@ -226,8 +235,15 @@ export async function settleOverdueWorkOrder(input: {
return { order: null, failureReason: 'work_order_has_active_shares' }
}
const shouldReleaseDeposit = ['reopen', 'cancel_release'].includes(input.policy)
const shouldDeductDeposit = input.policy === 'cancel_deduct'
// 赠送单已确认加好友后不再退押金:释放类处置转为扣除,事件类型按实际资金动作记录。
const forfeitGiftDeposit = isWorkOrderGiftDepositForfeitable(workOrder)
const releasePolicies = ['reopen', 'cancel_release']
const shouldReleaseDeposit = releasePolicies.includes(input.policy) && !forfeitGiftDeposit
const shouldDeductDeposit =
input.policy === 'cancel_deduct' ||
(releasePolicies.includes(input.policy) && forfeitGiftDeposit)
const effectivePolicy =
input.policy === 'cancel_release' && forfeitGiftDeposit ? 'cancel_deduct' : input.policy
const workerId = Number(workOrder.assigned_worker_id || 0)
let resolvedDepositAmount = 0
@@ -306,11 +322,12 @@ export async function settleOverdueWorkOrder(input: {
workOrderId: input.workOrderId,
actorType: 'system',
actorId: '',
eventType: `timeout_${input.policy}`,
eventType: `timeout_${effectivePolicy}`,
fromStatus: 'in_progress',
toStatus: targetStatus,
payloadJson: JSON.stringify({
policy: input.policy,
giftDepositForfeited: forfeitGiftDeposit || undefined,
depositAmount: resolvedDepositAmount,
workerId: workerId > 0 ? workerId : null,
}),
@@ -1,6 +1,7 @@
import type { PoolClient } from 'pg'
import { query, withTransaction } from '../../db/client.js'
import { isWorkOrderGiftDepositForfeitable } from '../../domain/work-order-acceptance-mode.js'
import {
ensureWorkerWalletWithClient,
getWorkerWalletWithClient,
@@ -458,6 +459,8 @@ export async function reviewWorkerCancelRequest(input: {
}
let releasedDepositAmount = 0
// 赠送单与拼单互斥,拼单份额分支不会命中赠送单;整单分支按确认加好友判定扣押金。
const forfeitGiftDeposit = isWorkOrderGiftDepositForfeitable(workOrder)
if (request.work_order_share_id) {
const shareResult = await client.query<WorkOrderShareRow>(
`SELECT * FROM work_order_shares WHERE id = $1 AND work_order_id = $2 FOR UPDATE`,
@@ -555,7 +558,8 @@ export async function reviewWorkerCancelRequest(input: {
[input.now, workOrder.id],
)
if (releasedDepositAmount > 0) {
const nextAvailable = Number(wallet?.available_amount || 0) + releasedDepositAmount
const nextAvailable =
Number(wallet?.available_amount || 0) + (forfeitGiftDeposit ? 0 : releasedDepositAmount)
const nextFrozen = Math.max(
0,
Number(wallet?.frozen_deposit_amount || 0) - releasedDepositAmount,
@@ -570,14 +574,22 @@ export async function reviewWorkerCancelRequest(input: {
`INSERT INTO worker_wallet_ledgers (
worker_id, ledger_type, amount, balance_after, frozen_after,
related_work_order_id, note, payload_json, created_at
) VALUES ($1, 'deposit_release', $2, $3, $4, $5, '撤单申请审核通过退还押金', $6::jsonb, $7)`,
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9)`,
[
request.worker_id,
releasedDepositAmount,
forfeitGiftDeposit ? 'deposit_deduction' : 'deposit_release',
forfeitGiftDeposit ? -releasedDepositAmount : releasedDepositAmount,
nextAvailable,
nextFrozen,
request.work_order_id,
JSON.stringify({ requestId: request.id, reason: request.reason }),
forfeitGiftDeposit
? '撤单申请审核通过扣除押金(已确认加好友)'
: '撤单申请审核通过退还押金',
JSON.stringify({
requestId: request.id,
reason: request.reason,
giftDepositForfeited: forfeitGiftDeposit || undefined,
}),
input.now,
],
)
@@ -607,7 +619,8 @@ export async function reviewWorkerCancelRequest(input: {
payloadJson: JSON.stringify({
requestId: request.id,
shareId: request.work_order_share_id,
releasedDepositAmount,
releasedDepositAmount: forfeitGiftDeposit ? 0 : releasedDepositAmount,
forfeitedDepositAmount: forfeitGiftDeposit ? releasedDepositAmount : 0,
levelChanged: penalty.levelChanged,
accountDisabled: penalty.accountDisabled,
note: input.reviewNote,
@@ -617,7 +630,7 @@ export async function reviewWorkerCancelRequest(input: {
return {
request: await getWorkerCancelRequestByIdWithClient(client, request.id),
order: updatedOrder,
releasedDepositAmount,
releasedDepositAmount: forfeitGiftDeposit ? 0 : releasedDepositAmount,
levelChanged: penalty.levelChanged,
accountDisabled: penalty.accountDisabled,
failureReason: null,