后端: - 删除 services/admin/admin-cost-center-service.ts(4,248 行),拆为 services/cost-center/ 下 5 个模块: cost-center-shared(类型/枚举/归一化/映射/costModelScopeSql)、 cost-center-overview(总览与选项)、 product-catalog(商品与渠道映射)、 template-bootstrap(模板引导、自动发货同步、工单证据回填)、 cost-definition(成本项/版本/异常/预览/快照) - cost_items.carrier_type / cost_type 改为单一 cost_model;专属模型只对 对应履约方式生效,通用模型对所有履约方式生效 - cost_snapshots / cost_exceptions 删除载体列;按履约方式筛异常改用 IN 半连接(248k 异常下 EXISTS 逐行回表 2.7s -> 170ms) - sales_daily_facts.carrier_type -> fulfillment_mode - 人工支出按 cost_model 归类;履约方式只读 order_items.fulfillment_mode - 移除 syncOpenCostExceptionCarrierTypes:异常表已无载体列可同步 前端: - AdminCostCenterPage.tsx(2,887 行 -> 18 行转发),拆为 pages/admin/cost-center/ 下 8 个 Panel + shared + CostCenterContext - CostCarrierType 删除;新增 FulfillmentMode / ProductSource / CostModel - 销售毛利页 carrierType -> fulfillmentMode 同步补两个索引:idx_order_items_fulfillment_id(异常半连接)、 idx_work_categories_name(商品目录分类 lateral join)。
139 lines
6.8 KiB
PL/PgSQL
139 lines
6.8 KiB
PL/PgSQL
-- ============================================================================
|
||
-- 原地改造脚本(本地库专用,2026-10-23 财务重写)
|
||
--
|
||
-- 目的:把本地库的旧派生表结构(carrier_type / cost_type)改造成新 schema
|
||
-- (cost_model / fulfillment_mode),不重建整库、不动源表。
|
||
--
|
||
-- 改造矩阵(列级 ALTER,不重建表):
|
||
-- product_catalog 删 carrier_type(来源改由 canonical_sku 前缀推导)
|
||
-- cost_items cost_type + carrier_type -> cost_model
|
||
-- cost_snapshots 删 carrier_type(履约方式 join order_items)
|
||
-- cost_exceptions 删 carrier_type(同上)
|
||
-- sales_daily_facts carrier_type -> fulfillment_mode(改名)
|
||
-- manual_expense_records cost_item_id 改 NOT NULL
|
||
-- work_product_rules 删 legacy_cost_source
|
||
-- order_items 不动(履约事实、收入固化、商品指向全部保留)
|
||
--
|
||
-- 约束:
|
||
-- 1. 源表(orders / order_items / work_orders / work_product_rules /
|
||
-- fulfillment_tasks / fund_accounts)一律不动;
|
||
-- 2. 派生表按新 schema 就地改造,历史快照与异常不重建(不丢审计痕迹);
|
||
-- 3. 执行前必须已有备份 backups/postgres/order_site_pre_rewrite_20261023.dump。
|
||
--
|
||
-- 执行:
|
||
-- docker exec -i order_site-postgres-1 psql -U postgres -d order_site \
|
||
-- -v ON_ERROR_STOP=1 < scripts/rewrite-local-db-2026-10-23.sql
|
||
-- ============================================================================
|
||
|
||
\set ON_ERROR_STOP on
|
||
BEGIN;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 1. 清掉旧迁移记录(103–114),让新迁移 103–107 重新执行
|
||
-- ---------------------------------------------------------------------------
|
||
DELETE FROM schema_migrations
|
||
WHERE name IN (
|
||
'103_product_catalog',
|
||
'104_cost_center',
|
||
'105_cost_center_bootstrap_fix',
|
||
'106_product_mapping_match_keys',
|
||
'107_product_catalog_carrier',
|
||
'108_cost_snapshot_runtime',
|
||
'109_sales_daily_facts',
|
||
'110_system_cost_items',
|
||
'111_manual_expense_records',
|
||
'112_cost_reporting_indexes',
|
||
'113_fund_account_no_readable',
|
||
'114_order_item_fulfillment_mode'
|
||
);
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 2. product_catalog:删履约载体列
|
||
-- 来源改由 canonical_sku 前缀表达(aff: / tpl: / wo: / man:)。
|
||
-- ---------------------------------------------------------------------------
|
||
DROP INDEX IF EXISTS idx_product_catalog_status_carrier;
|
||
ALTER TABLE product_catalog DROP COLUMN IF EXISTS carrier_type;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 3. cost_items:cost_type + carrier_type -> cost_model
|
||
-- 成本模型只表达「成本怎么算」,与履约方式正交。
|
||
-- ---------------------------------------------------------------------------
|
||
-- 3.1 先把编码统一到新口径,避免迁移 104 再插一条同义成本项。
|
||
UPDATE cost_items SET code = 'sys_affiliate_purchase' WHERE code = 'auto_purchase';
|
||
|
||
-- 3.2 新增 cost_model 并按旧 cost_type 映射。
|
||
ALTER TABLE cost_items ADD COLUMN IF NOT EXISTS cost_model TEXT;
|
||
UPDATE cost_items
|
||
SET cost_model = CASE cost_type
|
||
WHEN 'auto_purchase' THEN 'affiliate_purchase'
|
||
WHEN 'work_order_reward' THEN 'work_order_reward'
|
||
WHEN 'manual_service' THEN 'manual_actual'
|
||
WHEN 'platform_fee' THEN 'platform_fee'
|
||
WHEN 'payment_fee' THEN 'payment_fee'
|
||
WHEN 'after_sales_loss' THEN 'after_sales_loss'
|
||
WHEN 'shipping_other' THEN 'other'
|
||
WHEN 'other' THEN 'other'
|
||
ELSE 'other'
|
||
END
|
||
WHERE cost_model IS NULL;
|
||
|
||
-- 3.3 删旧列(CHECK 约束随列一起消失)。
|
||
ALTER TABLE cost_items DROP COLUMN IF EXISTS cost_type;
|
||
ALTER TABLE cost_items DROP COLUMN IF EXISTS carrier_type;
|
||
|
||
-- 3.4 删旧 CHECK,让迁移 104 按新枚举重建。
|
||
ALTER TABLE cost_items DROP CONSTRAINT IF EXISTS chk_cost_items_cost_type;
|
||
ALTER TABLE cost_items DROP CONSTRAINT IF EXISTS chk_cost_items_carrier_type;
|
||
ALTER TABLE cost_items DROP CONSTRAINT IF EXISTS chk_cost_items_pricing_mode;
|
||
|
||
-- 3.5 cost_model 必填。
|
||
-- 迁移 104 用 CREATE TABLE IF NOT EXISTS 建表,表已存在时不会补 NOT NULL,
|
||
-- 所以这里先补上,迁移 104 再补 CHECK 枚举。
|
||
ALTER TABLE cost_items ALTER COLUMN cost_model SET NOT NULL;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 4. cost_snapshots:删履约载体列与未被使用的 manual_case_id
|
||
-- 履约方式由 order_items.fulfillment_mode 提供,join 即可。
|
||
-- ---------------------------------------------------------------------------
|
||
ALTER TABLE cost_snapshots DROP COLUMN IF EXISTS carrier_type;
|
||
ALTER TABLE cost_snapshots DROP COLUMN IF EXISTS manual_case_id;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 5. cost_exceptions:删履约载体列
|
||
-- ---------------------------------------------------------------------------
|
||
ALTER TABLE cost_exceptions DROP COLUMN IF EXISTS carrier_type;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 6. sales_daily_facts:carrier_type -> fulfillment_mode
|
||
-- ---------------------------------------------------------------------------
|
||
ALTER TABLE sales_daily_facts DROP CONSTRAINT IF EXISTS chk_sales_daily_facts_carrier;
|
||
DROP INDEX IF EXISTS uq_sales_daily_facts_key;
|
||
ALTER TABLE sales_daily_facts RENAME COLUMN carrier_type TO fulfillment_mode;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 7. manual_expense_records:成本项必填
|
||
-- ---------------------------------------------------------------------------
|
||
ALTER TABLE manual_expense_records
|
||
ALTER COLUMN cost_item_id SET NOT NULL;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 8. work_product_rules:删旧成本回退标记
|
||
-- ---------------------------------------------------------------------------
|
||
ALTER TABLE work_product_rules DROP COLUMN IF EXISTS legacy_cost_source;
|
||
|
||
-- ---------------------------------------------------------------------------
|
||
-- 9. 让迁移 104 按新定义重建同名索引
|
||
-- 旧 112 的两个覆盖索引定义与新 104 不同,先删后建。
|
||
-- ---------------------------------------------------------------------------
|
||
DROP INDEX IF EXISTS idx_work_orders_rule_cover;
|
||
DROP INDEX IF EXISTS idx_order_items_revenue_cover;
|
||
|
||
COMMIT;
|
||
|
||
-- ============================================================================
|
||
-- 以上是结构改造;接下来执行:
|
||
-- 1. npm run db:migrate —— 应用新迁移 103–107
|
||
-- 2. npm run fulfillment:backfill —— 重跑履约回填(幂等,NULL=0 时无操作)
|
||
-- 3. 回填脚本 / 同步脚本 —— 重跑商品、成本版本、快照与销售事实
|
||
-- ============================================================================
|