fix(procurement): align correction actions with shipment state
This commit is contained in:
@@ -1,6 +1,43 @@
|
||||
import type { PlatformProcurement } from './procurementTypes'
|
||||
import type { ProcurementCommand, ProcurementCommandBody, ProcurementPackingCarton } from './api/procurementCommands'
|
||||
export type Leg = 'OVERSEAS' | 'DOMESTIC'
|
||||
const closedStatuses = new Set(['REJECTED', 'CANCELLED', 'EXCEPTION_CLOSED', 'SHIPPED_TO_CUSTOMER'])
|
||||
export function receiptCorrectionReason(detail: PlatformProcurement, leg: Leg): string | null {
|
||||
if (closedStatuses.has(detail.customerView.order.status)) return '订单已结束,只能追加事实说明,不能更正实收数量'
|
||||
if (detail.purchaseFacts[leg === 'OVERSEAS' ? 'overseas_shipped_at' : 'customer_shipped_at']) return '本段已实际交寄,只能追加更正说明,不能改写数量'
|
||||
if (leg === 'OVERSEAS' && detail.physical.packingStatus === 'CONFIRMED') return '须先撤回尚未交寄的确认清单,再更正海外实收'
|
||||
return null
|
||||
}
|
||||
export function dispositionReason(detail: PlatformProcurement, leg: Leg): string | null {
|
||||
if (closedStatuses.has(detail.customerView.order.status)) return '订单已结束,不能修改差异处置'
|
||||
if (detail.purchaseFacts[leg === 'OVERSEAS' ? 'overseas_received_at' : 'domestic_received_at']) return '本段收货已完成,须先受控更正,不能直接改差异结果'
|
||||
if (leg === 'OVERSEAS' && !detail.purchaseFacts.purchased_at) return '尚无本单真实购买来源'
|
||||
if (leg === 'DOMESTIC' && !detail.purchaseFacts.overseas_shipped_at) return '尚无本单国际交寄来源'
|
||||
return null
|
||||
}
|
||||
export const managementOptions: { value: ProcurementCommand; label: string }[] = [
|
||||
{ value: 'dispositions', label: '记录差异处置' }, { value: 'receipts/correct', label: '更正原实收数量' },
|
||||
{ value: 'dispositions/revoke', label: '撤销原差异处置' }, { value: 'packing/withdraw', label: '撤回未交寄的确认清单' },
|
||||
{ value: 'control-notes', label: '追加事实说明或阻断' }, { value: 'control-notes/resolve', label: '解除已处理的阻断' },
|
||||
{ value: 'actual-warehouse/correct', label: '实际仓受控更正' },
|
||||
]
|
||||
export function managementReason(command: ProcurementCommand, detail: PlatformProcurement): string | null {
|
||||
if (command === 'receipts/correct' || command === 'dispositions/revoke') {
|
||||
const records = command === 'receipts/correct' ? detail.physical.receipts : detail.physical.dispositions
|
||||
const active = records.filter(row => row.active)
|
||||
if (!active.length) return command === 'receipts/correct' ? '暂无有效实收记录' : '暂无有效差异处置'
|
||||
return active.some(row => !receiptCorrectionReason(detail, row.leg)) ? null : receiptCorrectionReason(detail, active[0]!.leg)
|
||||
}
|
||||
if (command === 'dispositions') return dispositionReason(detail, 'OVERSEAS') && dispositionReason(detail, 'DOMESTIC')
|
||||
if (command === 'packing/withdraw') {
|
||||
if (closedStatuses.has(detail.customerView.order.status)) return '订单已结束,不能撤回装箱事实'
|
||||
if (detail.purchaseFacts.overseas_shipped_at) return '国际段已交寄,不能撤回装箱事实'
|
||||
if (detail.physical.packingStatus !== 'CONFIRMED') return '暂无已确认清单可撤回'
|
||||
}
|
||||
if (command === 'control-notes/resolve' && !detail.controls.notes.some(row => row.blocking && !row.resolved_at)) return '暂无待处理阻断'
|
||||
if (command === 'actual-warehouse/correct' && !detail.purchaseFacts.actual_warehouse_id) return '尚无实际收货仓,请修改计划仓'
|
||||
return null
|
||||
}
|
||||
export const physicalCommands = new Set<ProcurementCommand>(['overseas-receipts', 'domestic-receipts', 'overseas-receipts/complete', 'domestic-receipts/complete', 'packing', 'packing/confirm', 'packing/withdraw', 'dispositions', 'receipts/correct', 'dispositions/revoke'])
|
||||
export interface PackingDraft { cartonNo: string; lengthCm: string; widthCm: string; heightCm: string; grossWeightKg: string; sources: { receiptId: string; quantity: number | undefined }[] }
|
||||
export interface PhysicalForm { leg: Leg; sourceCartonId: string; receiptId: string; dispositionId: string; goodQuantity: number | undefined; damagedQuantity: number | undefined; extraQuantity: number | undefined; receivedAt: string; kind: 'SHORTAGE' | 'DAMAGED' | 'EXTRA'; quantity: number | undefined; cartons: PackingDraft[] }
|
||||
@@ -28,6 +65,8 @@ export function buildPacking(cartons: PackingDraft[], detail: PlatformProcuremen
|
||||
})
|
||||
}
|
||||
export function buildPhysical(command: ProcurementCommand, form: PhysicalForm, detail: PlatformProcurement, base: ProcurementCommandBody, warehouseId: string, voucherFileId: string): ProcurementCommandBody {
|
||||
const blocked = managementReason(command, detail)
|
||||
if (blocked) throw new Error(blocked)
|
||||
const closed = ['REJECTED', 'CANCELLED', 'EXCEPTION_CLOSED', 'SHIPPED_TO_CUSTOMER'].includes(detail.customerView.order.status)
|
||||
if (closed) throw new Error('订单已结束,不能改写实物记录')
|
||||
if (command === 'packing') return { ...base, cartons: buildPacking(form.cartons, detail) }
|
||||
@@ -40,7 +79,10 @@ export function buildPhysical(command: ProcurementCommand, form: PhysicalForm, d
|
||||
return base
|
||||
}
|
||||
if (command === 'dispositions/revoke') {
|
||||
if (!detail.physical.dispositions.some(row => row.id === form.dispositionId && row.active)) throw new Error('请选择有效差异处置')
|
||||
const row = detail.physical.dispositions.find(row => row.id === form.dispositionId && row.active)
|
||||
if (!row) throw new Error('请选择有效差异处置')
|
||||
const reason = receiptCorrectionReason(detail, row.leg)
|
||||
if (reason) throw new Error(reason)
|
||||
return { ...base, dispositionId: form.dispositionId, voucherFileId }
|
||||
}
|
||||
if (command.endsWith('/complete')) return { ...base, leg: command.startsWith('overseas') ? 'OVERSEAS' : 'DOMESTIC' }
|
||||
@@ -48,6 +90,8 @@ export function buildPhysical(command: ProcurementCommand, form: PhysicalForm, d
|
||||
const old = correction ? detail.physical.receipts.find(row => row.id === form.receiptId && row.active) : undefined
|
||||
if (correction && !old) throw new Error('请选择有效原实收记录')
|
||||
const leg: Leg = old?.leg ?? (command === 'overseas-receipts' ? 'OVERSEAS' : command === 'domestic-receipts' ? 'DOMESTIC' : form.leg)
|
||||
const reason = correction ? receiptCorrectionReason(detail, leg) : command === 'dispositions' ? dispositionReason(detail, leg) : null
|
||||
if (reason) throw new Error(reason)
|
||||
const sourceCartonId = old?.sourceCartonId || form.sourceCartonId
|
||||
if (leg === 'DOMESTIC' && !shippedCartons(detail).some(row => row.id === sourceCartonId)) throw new Error('请选择本单已国际交寄的原箱')
|
||||
if (command === 'dispositions') {
|
||||
|
||||
Reference in New Issue
Block a user