fix(cost-center): 禁止追溯改价,改价只能当前或未来生效

- 后端统一校验:retroactive 请求直接拒绝,effectiveFrom 早于当前时间拒绝
- 去掉「追溯至历史订单」入口,改价只影响之后的新订单
- 历史订单成本与成交价由快照固化,不再受改价影响
This commit is contained in:
yml2213
2026-11-01 14:53:25 +08:00
parent fed459c7aa
commit ceb786f32e
6 changed files with 46 additions and 47 deletions
@@ -41,7 +41,7 @@ import { useCostCenter } from './CostCenterContext'
interface PriceFormValues {
priceYuan: number
effectiveMode: 'retroactive' | 'now' | 'custom'
effectiveMode: 'now' | 'custom'
customEffectiveDate?: dayjs.Dayjs
changeReason?: string
}
@@ -108,7 +108,7 @@ export function AffiliateSkuPanel() {
priceForm.setFieldsValue({
priceYuan: currentYuan,
effectiveMode: 'retroactive',
effectiveMode: 'now',
changeReason: currentYuan ? '上游采购成本调整' : '首次配置自动发货采购成本',
})
setPriceModalOpen(true)
@@ -123,15 +123,10 @@ export function AffiliateSkuPanel() {
}
let effectiveFrom: string | undefined
let retroactive = false
if (values.effectiveMode === 'retroactive') {
retroactive = true
effectiveFrom = dayjs().subtract(30, 'day').format('YYYY-MM-DDTHH:mm:ss+08:00')
} else if (values.effectiveMode === 'now') {
if (values.effectiveMode === 'now') {
effectiveFrom = new Date().toISOString()
} else if (values.effectiveMode === 'custom' && values.customEffectiveDate) {
effectiveFrom = values.customEffectiveDate.startOf('day').toISOString()
effectiveFrom = values.customEffectiveDate.toISOString()
}
setPriceSubmitting(true)
@@ -139,7 +134,6 @@ export function AffiliateSkuPanel() {
await setAdminAffiliateProductPrice(selectedProduct.id, {
amountFen,
effectiveFrom,
retroactive,
changeReason: values.changeReason,
})
message.success(`「${selectedProduct.canonicalName}」采购单价已设置为 ¥${values.priceYuan}`)
@@ -379,20 +373,16 @@ export function AffiliateSkuPanel() {
>
<Radio.Group>
<Space direction="vertical">
<Radio value="retroactive">
<Radio value="now">
<Space direction="vertical" size={0}>
<Typography.Text strong>追溯至历史订单 (推荐)</Typography.Text>
<Typography.Text strong>自当前时间立即生效</Typography.Text>
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
自近一个月业务起点(30 天前)生效,重算快照后可直接消除近一个月 cost_missing
异常
只影响之后的新订单;历史订单的成本与成交价已固化,不会被本次改价覆盖
</Typography.Text>
</Space>
</Radio>
<Radio value="now">
<span>自当前时间立即生效(仅对后续订单生效)</span>
</Radio>
<Radio value="custom">
<span>指定生效日期</span>
<span>指定生效时间(不能早于当前时间)</span>
</Radio>
</Space>
</Radio.Group>
@@ -352,7 +352,7 @@ export function ProductCatalogPanel() {
async function submitProductPrice(values: {
amountYuan: number | string
effectiveScope: 'retroactive' | 'immediate' | 'custom'
effectiveScope: 'immediate' | 'custom'
effectiveFromCustom?: string
changeReason?: string
syncOpenOrders?: boolean
@@ -365,12 +365,7 @@ export function ProductCatalogPanel() {
}
const amountFen = Math.round(yuan * 100)
let effectiveFrom: string | undefined
let retroactive = false
if (values.effectiveScope === 'retroactive') {
retroactive = true
effectiveFrom = dayjs().subtract(30, 'day').format('YYYY-MM-DDTHH:mm:ss+08:00')
} else if (values.effectiveScope === 'custom' && values.effectiveFromCustom) {
if (values.effectiveScope === 'custom' && values.effectiveFromCustom) {
effectiveFrom = values.effectiveFromCustom
}
@@ -379,7 +374,6 @@ export function ProductCatalogPanel() {
const response = await setAdminProductPrice(pricingProduct.id, {
amountFen,
effectiveFrom,
retroactive,
changeReason: values.changeReason || '在商品与成本中心统一调整价格',
syncOpenOrders: values.syncOpenOrders !== false,
})
@@ -939,19 +933,13 @@ export function ProductCatalogPanel() {
>
<Radio.Group style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<Radio value="immediate">
<strong>自当前时间立即生效(推荐,仅对后续订单生效)</strong>
<strong>自当前时间立即生效(推荐)</strong>
<div style={{ color: '#64748b', fontSize: 12, marginTop: 2 }}>
保留旧版本历史,自新的价格版本创建时刻起计算后续履约结算
</div>
</Radio>
<Radio value="retroactive">
<strong>追溯至历史订单</strong>
<div style={{ color: '#64748b', fontSize: 12, marginTop: 2 }}>
自近一个月业务起点(30 天前)生效,直接更新基线并消除近一个月 cost_missing 异常
只影响之后的新订单;历史订单的成本与成交价已固化,不会被改价覆盖
</div>
</Radio>
<Radio value="custom">
<strong>指定生效日期</strong>
<strong>指定生效时间(不能早于当前时间)</strong>
</Radio>
</Radio.Group>
</Form.Item>
@@ -145,7 +145,6 @@ export function setAdminAffiliateProductPrice(
payload: {
amountFen: number
effectiveFrom?: string
retroactive?: boolean
changeReason?: string
},
) {
@@ -486,7 +485,6 @@ export function setAdminProductPrice(
payload: {
amountFen: number
effectiveFrom?: string
retroactive?: boolean
changeReason?: string
syncOpenOrders?: boolean
},