fix(worker-platform): 修复售后欠款抵扣导致验收失败,并支持余额偿还
有待还欠款时结算写入 settled_at 发生 timestamptz/text 类型错误会整单 500;顺带支持充值/解冻自动偿还与后台手动偿还。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
listAfterSalesCaseEvents,
|
||||
listAfterSalesCases,
|
||||
listWorkerAfterSalesCases,
|
||||
repayAfterSalesCaseDebt,
|
||||
resolveAfterSalesCase,
|
||||
submitWorkerAfterSalesResponse,
|
||||
} from '../../repositories/worker-platform/after-sales-repo.js'
|
||||
@@ -230,6 +231,80 @@ export async function resolveAdminAfterSalesCase(
|
||||
}
|
||||
}
|
||||
|
||||
export async function repayAdminAfterSalesCaseDebt(
|
||||
caseId: number | string,
|
||||
payload: JsonObject = {},
|
||||
actorName = '',
|
||||
) {
|
||||
const afterSalesCase = await getAfterSalesCaseById(caseId)
|
||||
if (!afterSalesCase) {
|
||||
throw createHttpError('售后问题单不存在', {
|
||||
statusCode: 404,
|
||||
errorCode: 'after_sales_case_not_found',
|
||||
})
|
||||
}
|
||||
const note = String(payload.note || payload.resolutionNote || '后台手动偿还售后欠款').trim()
|
||||
if (!note) {
|
||||
throw createHttpError('请填写偿还备注', {
|
||||
statusCode: 400,
|
||||
errorCode: 'after_sales_case_repay_note_required',
|
||||
})
|
||||
}
|
||||
if (note.length > 2_000) {
|
||||
throw createHttpError('偿还备注不能超过 2000 个字符', {
|
||||
statusCode: 400,
|
||||
errorCode: 'after_sales_case_repay_note_too_long',
|
||||
})
|
||||
}
|
||||
const amountRaw = payload.amount ?? payload.repayAmount
|
||||
const amount =
|
||||
amountRaw === undefined || amountRaw === null || String(amountRaw).trim() === ''
|
||||
? null
|
||||
: normalizeAmountFen(amountRaw, 0)
|
||||
if (amount !== null && amount <= 0) {
|
||||
throw createHttpError('偿还金额必须大于 0', {
|
||||
statusCode: 400,
|
||||
errorCode: 'after_sales_case_repay_amount_invalid',
|
||||
})
|
||||
}
|
||||
const result = await repayAfterSalesCaseDebt({
|
||||
caseId: Number(caseId),
|
||||
amount,
|
||||
note,
|
||||
repaidBy: actorName,
|
||||
now: nowIso(),
|
||||
})
|
||||
if (result.failureReason === 'not_found' || !result.case) {
|
||||
throw createHttpError('售后问题单不存在', {
|
||||
statusCode: 404,
|
||||
errorCode: 'after_sales_case_not_found',
|
||||
})
|
||||
}
|
||||
if (result.failureReason === 'no_open_debt') {
|
||||
throw createHttpError('该售后问题单没有待还欠款', {
|
||||
statusCode: 409,
|
||||
errorCode: 'after_sales_case_no_open_debt',
|
||||
})
|
||||
}
|
||||
if (result.failureReason === 'insufficient_balance') {
|
||||
throw createHttpError('打手可用余额不足,无法偿还欠款', {
|
||||
statusCode: 409,
|
||||
errorCode: 'after_sales_case_repay_insufficient_balance',
|
||||
})
|
||||
}
|
||||
const workerId = Number(result.case.worker_id)
|
||||
publishWorkOrderRealtimeChange({
|
||||
workOrderId: Number(result.case.work_order_id),
|
||||
workerIds: workerId > 0 ? [workerId] : [],
|
||||
})
|
||||
if (workerId > 0) publishWorkerWalletRealtimeChange(workerId)
|
||||
return {
|
||||
case: mapWorkerAfterSalesCase(result.case),
|
||||
repaidAmount: result.repaidAmount,
|
||||
availableAfter: result.availableAfter,
|
||||
}
|
||||
}
|
||||
|
||||
export async function getWorkerAfterSalesCaseSummary(session: WorkerSession) {
|
||||
requireActiveWorkerSession(session)
|
||||
return { items: (await listWorkerAfterSalesCases(session.workerId)).map(mapWorkerAfterSalesCase) }
|
||||
|
||||
Reference in New Issue
Block a user