refactor(finance)!: 强制渠道模型,移除旧履约方式与同步链路

- 删除 fulfillment_mode 相关的旧同步/回填链路与定时任务
- 删除 cost_finance_sync、成本快照同步、人工商品归一等遗留服务
- 迁移 113 直接删除 order_items.fulfillment_mode 及其索引约束
- 断代脚本自带归档步骤,不再依赖独立回填脚本
- 退款/事实/总账统一走渠道版销售事实
This commit is contained in:
yml2213
2026-10-31 19:52:03 +08:00
parent 808949f3b8
commit 65b7f4f9dc
25 changed files with 156 additions and 2383 deletions
-91
View File
@@ -1,91 +0,0 @@
import process from 'node:process'
import { closeDb } from '../src/db/client.js'
import {
syncActualWorkOrderCostSnapshots,
syncEstimatedOrderItemCostSnapshots,
} from '../src/services/cost-center/cost-snapshot-sync-service.js'
import { rebuildSalesDailyFacts } from '../src/services/finance/sales-facts-service.js'
import { resolveFinanceDateRange, shiftDate } from '../src/utils/finance-date-range.js'
import { nowIso } from '../src/utils/time.js'
type Mode = 'estimated' | 'actual' | 'facts' | 'all'
const options = parseOptions(process.argv.slice(2))
const mode = normalizeMode(options.mode)
const days = normalizeDays(options.days)
const fallbackTo = options.to || formatShanghaiDate(new Date())
const fallbackFrom = options.from || shiftDate(fallbackTo, -(days - 1))
async function main() {
const input = { dateFrom: fallbackFrom, dateTo: fallbackTo }
const range = resolveFinanceDateRange(input, { defaultDays: days, maxDays: 400 })
const startedAt = Date.now()
const result: Record<string, unknown> = { mode, range }
if (mode === 'estimated' || mode === 'all') {
result.estimated = await syncEstimatedOrderItemCostSnapshots(input)
}
if (mode === 'actual' || mode === 'all') {
result.actual = await syncActualWorkOrderCostSnapshots(input)
}
if (mode === 'facts' || mode === 'all') {
result.facts = await rebuildSalesDailyFacts(input)
}
result.durationMs = Date.now() - startedAt
result.finishedAt = nowIso()
console.log(JSON.stringify(result, null, 2))
}
main()
.catch((error) => {
console.error(error instanceof Error ? error.message : error)
process.exitCode = 1
})
.finally(async () => {
await closeDb()
})
function parseOptions(args: string[]) {
const result: Record<string, string> = {}
for (const arg of args) {
if (!arg.startsWith('--')) continue
const body = arg.slice(2)
const index = body.indexOf('=')
if (index === -1) {
result[body] = 'true'
} else {
result[body.slice(0, index)] = body.slice(index + 1)
}
}
return result
}
function normalizeMode(value: unknown): Mode {
const mode = String(value || 'all').trim()
if (mode === 'estimated' || mode === 'actual' || mode === 'facts' || mode === 'all') {
return mode
}
throw new Error('--mode 只能是 estimated / actual / facts / all')
}
function normalizeDays(value: unknown) {
const parsed = Number(value || 7)
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 400) {
throw new Error('--days 必须是 1-400 的整数')
}
return parsed
}
/** 模块级只构造一次:`new Intl.DateTimeFormat()` 每次约 0.5ms,逐条调用会线性放大。 */
const SHANGHAI_DATE_FORMATTER = new Intl.DateTimeFormat('en-CA', {
timeZone: 'Asia/Shanghai',
year: 'numeric',
month: '2-digit',
day: '2-digit',
})
function formatShanghaiDate(value: Date) {
return SHANGHAI_DATE_FORMATTER.format(value)
}