Files
order_site/apps/backend/scripts/backfill-fulfillment-mode.ts
T

90 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import process from 'node:process'
import { closeDb, query } from '../src/db/client.js'
import {
getFulfillmentModeCounts,
reconcilePendingFulfillmentModes,
syncOpenCostExceptionCarrierTypes,
} from '../src/services/fulfillment/fulfillment-mode-service.js'
const options = parseOptions(process.argv.slice(2))
const batchSize = normalizeInteger(options.batchSize, 5000, 1, 50_000)
const maxBatches = normalizeInteger(options.maxBatches, 1000, 1, 10_000)
async function main() {
const column = await query<{ exists: boolean }>(
`
SELECT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'order_items'
AND column_name = 'fulfillment_mode'
) AS exists
`,
)
if (!column.rows[0]?.exists) {
throw new Error('order_items.fulfillment_mode 不存在,请先执行 npm run db:migrate(迁移 114)')
}
const startedAt = Date.now()
const result = await reconcilePendingFulfillmentModes({
batchSize,
maxBatches,
reason: 'backfill_2026_10_23',
})
const exceptions = await syncOpenCostExceptionCarrierTypes()
const counts = await getFulfillmentModeCounts()
console.log(
JSON.stringify(
{
...result,
exceptionCarrierUpdated: exceptions.updatedCount,
batchSize,
maxBatches,
counts,
durationMs: Date.now() - startedAt,
},
null,
2,
),
)
if (result.remainingCount > 0) {
console.error(`仍有 ${result.remainingCount} 个订单项未回填;请增大 --max-batches 或检查数据。`)
process.exitCode = 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 normalizeInteger(value: unknown, fallback: number, min: number, max: number) {
const parsed = Number(value)
if (!Number.isInteger(parsed)) return fallback
return Math.min(max, Math.max(min, parsed))
}