fix(worker): 用户付款金额仅待完善可修改并补后端校验
This commit is contained in:
@@ -308,8 +308,8 @@ export async function updateWorkOrderBasic(
|
||||
/**
|
||||
* 后台修正「用户付款金额」:同时更新 083 派生列与 material_json 来源快照。
|
||||
*
|
||||
* WHERE 里再守一次状态与接单人,避免读完到写入之间被打手接走;
|
||||
* 待抢单(open)还要求没有有效拼单份额,与 capabilities.canEdit 口径一致。
|
||||
* 只允许待完善(pending_material)阶段;WHERE 里再守一次状态与接单人,
|
||||
* 避免读完到写入之间状态已推进或被打手接走。
|
||||
*/
|
||||
export async function updateWorkOrderPaymentAmount(input: {
|
||||
workOrderId: number | string
|
||||
@@ -327,15 +327,6 @@ export async function updateWorkOrderPaymentAmount(input: {
|
||||
WHERE id = $4
|
||||
AND assigned_worker_id IS NULL
|
||||
AND status = ANY($5::text[])
|
||||
AND (
|
||||
status <> 'open'
|
||||
OR NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM work_order_shares wos
|
||||
WHERE wos.work_order_id = work_orders.id
|
||||
AND wos.status <> 'cancelled'
|
||||
)
|
||||
)
|
||||
RETURNING id
|
||||
`,
|
||||
[
|
||||
|
||||
@@ -37,6 +37,7 @@ import { resolveWorkOrderRealtimeWorkerIds } from './admin-work-order-realtime-s
|
||||
import { getWorkerHallConfig } from './worker-hall-config-service.js'
|
||||
import {
|
||||
USER_PAYMENT_AMOUNT_REASON_MAX_LENGTH,
|
||||
canModifyUserPaymentAmountStatus,
|
||||
mergeUserPaymentAmountIntoMaterial,
|
||||
normalizeUserPaymentAmountFen,
|
||||
resolveDisplayedUserPaymentAmountFen,
|
||||
@@ -130,9 +131,9 @@ export async function updateAdminWorkOrder(
|
||||
/**
|
||||
* 后台修正「用户付款金额」。
|
||||
*
|
||||
* 只允许和普通编辑相同的状态(待完善/未分配/待抢单且未指派),
|
||||
* 金额按元提交、按分落库;修改会写入 work_order_events + 后台审计。
|
||||
* 同步 material_json.source 快照,避免列表展示与 083 派生列分叉。
|
||||
* 只允许「待完善(pending_material)」阶段修改:金额进入未分配/待抢单后已参与
|
||||
* 发单与大厅展示,再改会破坏对账口径。金额按元提交、按分落库;修改会写入
|
||||
* work_order_events + 后台审计,并同步 material_json.source 快照。
|
||||
*/
|
||||
export async function updateAdminWorkOrderPaymentAmount(
|
||||
workOrderId: number | string,
|
||||
@@ -140,16 +141,16 @@ export async function updateAdminWorkOrderPaymentAmount(
|
||||
options: { actorName?: string } = {},
|
||||
) {
|
||||
const workOrder = await getRequiredWorkOrder(workOrderId)
|
||||
if (!mapWorkOrderAdmin(workOrder).capabilities.canEdit) {
|
||||
throw createHttpError('只有待完善、未分配或待抢单的工单可以编辑', {
|
||||
if (!canModifyUserPaymentAmountStatus(workOrder.status)) {
|
||||
throw createHttpError('只有待完善的工单可以修改用户付款金额', {
|
||||
statusCode: 409,
|
||||
errorCode: 'work_order_edit_status_invalid',
|
||||
errorCode: 'work_order_payment_amount_status_invalid',
|
||||
})
|
||||
}
|
||||
if (workOrder.assigned_worker_id) {
|
||||
throw createHttpError('工单已被打手接走,不能编辑', {
|
||||
throw createHttpError('工单已被打手接走,不能修改用户付款金额', {
|
||||
statusCode: 409,
|
||||
errorCode: 'work_order_edit_assigned_invalid',
|
||||
errorCode: 'work_order_payment_amount_assigned_invalid',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -184,11 +185,7 @@ export async function updateAdminWorkOrderPaymentAmount(
|
||||
workOrderId: workOrder.id,
|
||||
amountFen,
|
||||
materialJson: mergeUserPaymentAmountIntoMaterial(workOrder.material_json, amountFen),
|
||||
allowedStatuses: [
|
||||
WORK_ORDER_STATUS.PENDING_MATERIAL,
|
||||
WORK_ORDER_STATUS.UNASSIGNED,
|
||||
WORK_ORDER_STATUS.OPEN,
|
||||
],
|
||||
allowedStatuses: [WORK_ORDER_STATUS.PENDING_MATERIAL],
|
||||
now,
|
||||
})
|
||||
if (!updated) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import test from 'node:test'
|
||||
|
||||
import {
|
||||
buildWorkOrderPaymentAmountAuditData,
|
||||
canModifyUserPaymentAmountStatus,
|
||||
mergeUserPaymentAmountIntoMaterial,
|
||||
normalizeUserPaymentAmountFen,
|
||||
resolveDisplayedUserPaymentAmountFen,
|
||||
@@ -21,6 +22,28 @@ test('normalizeUserPaymentAmountFen:0、负数、超上限与非数字都判
|
||||
}
|
||||
})
|
||||
|
||||
test('canModifyUserPaymentAmountStatus:只有待完善(pending_material)可改', () => {
|
||||
assert.equal(canModifyUserPaymentAmountStatus('pending_material'), true)
|
||||
for (const status of [
|
||||
'unassigned',
|
||||
'open',
|
||||
'in_progress',
|
||||
'pending_acceptance',
|
||||
'problem',
|
||||
'accepted',
|
||||
'cancelled',
|
||||
'',
|
||||
null,
|
||||
undefined,
|
||||
]) {
|
||||
assert.equal(
|
||||
canModifyUserPaymentAmountStatus(status),
|
||||
false,
|
||||
`${String(status)} 不应允许修改用户付款金额`,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
test('resolveDisplayedUserPaymentAmountFen:优先送码实付,其次来源金额,最后派生列', () => {
|
||||
assert.equal(
|
||||
resolveDisplayedUserPaymentAmountFen({
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
|
||||
import type { JsonObject } from '../../types/json.js'
|
||||
import { safeParseJson } from '../admin/admin-query-utils.js'
|
||||
|
||||
@@ -29,6 +30,16 @@ export function normalizeUserPaymentAmountFen(value: unknown): number | null {
|
||||
return fen
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户付款金额只允许在「待完善」阶段修改。
|
||||
*
|
||||
* 进入未分配/待抢单后金额已经参与发单与大厅展示,后台再改会破坏对账口径;
|
||||
* 已接单/已验收阶段更不允许改动。
|
||||
*/
|
||||
export function canModifyUserPaymentAmountStatus(status: unknown): boolean {
|
||||
return String(status || '').trim() === WORK_ORDER_STATUS.PENDING_MATERIAL
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取工单当前展示的「用户付款金额」(分)。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user