You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
8.9 KiB
171 lines
8.9 KiB
-- ============================================================================
|
|
-- 老「厂家/出货单/授权码」结构 → 新「品牌商/生产批次/授权码(batchno)」结构
|
|
--
|
|
-- 只动 starpivot 库(广州测试环境)。Supabase 源库只读,不受影响。
|
|
-- 全程一个事务;幂等,可重复执行(靠 production_batch.remark 里的老批次号做锚点)。
|
|
--
|
|
-- factory → brand (id 沿用,providerid=0 待后台分配)
|
|
-- factory_deliverynote → production_batch(并上授权码里实际存在的批次)
|
|
-- license_b* → 加 brandid / batchno 并回填(保留 factoryid、probatch 作对照)
|
|
-- product → factoryid 改名 brandid
|
|
-- factory_public_code → factoryid 改名 brandid
|
|
-- 老主表 license 不动(新代码只读分表)
|
|
-- ============================================================================
|
|
\set ON_ERROR_STOP on
|
|
BEGIN;
|
|
|
|
-- ── 批次短码生成:与 comm.GeneratePublicCode 同字符集/长度(6 位,去掉易混字符)──
|
|
CREATE OR REPLACE FUNCTION _mig_gen_batchno() RETURNS varchar(16) AS $fn$
|
|
DECLARE
|
|
charset text := 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
|
code text;
|
|
i int;
|
|
BEGIN
|
|
LOOP
|
|
code := '';
|
|
FOR i IN 1..6 LOOP
|
|
code := code || substr(charset, 1 + floor(random() * 32)::int, 1);
|
|
END LOOP;
|
|
IF NOT EXISTS (SELECT 1 FROM production_batch WHERE batchno = code) THEN
|
|
RETURN code;
|
|
END IF;
|
|
END LOOP;
|
|
END $fn$ LANGUAGE plpgsql;
|
|
|
|
-- ── 1. 方案商:先建三条备用,品牌商暂不关联(providerid=0,后台手工分配)──
|
|
INSERT INTO solution_provider (name, description, contactmails, createtime)
|
|
SELECT v.name, v.descr, '', extract(epoch from now())::bigint
|
|
FROM (VALUES ('jieli', '杰理方案'), ('lanxun', '蓝讯方案'), ('henxuan', '恒玄方案')) AS v(name, descr)
|
|
WHERE NOT EXISTS (SELECT 1 FROM solution_provider s WHERE s.name = v.name);
|
|
|
|
-- ── 2. 厂家 → 品牌商(id 保持不变,这样所有 factoryid 引用无需换值)──
|
|
-- factory.probatch 是老批次计数器,新结构无对应字段,丢弃。
|
|
-- ⚠️ factory.factoryflag 不要丢:它就是方案商 ID(十六进制,如 ABEF/ABF0~ABF4/AB21),
|
|
-- providerid 由它解析而来 —— 见 2026-07-31-solution-provider-vendor.sql,本脚本先置 0。
|
|
INSERT INTO brand (id, brand, providerid, description, contactmails, productlists)
|
|
SELECT f.id, f.factory, 0, COALESCE(f.description, ''), COALESCE(f.contactmails, ''), COALESCE(f.productlists, '')
|
|
FROM factory f
|
|
WHERE NOT EXISTS (SELECT 1 FROM brand b WHERE b.id = f.id);
|
|
SELECT setval('brand_id_seq', GREATEST((SELECT COALESCE(MAX(id), 0) FROM brand), 1));
|
|
|
|
-- ── 3. 汇总历史批次 = 授权码里实际存在的 ∪ 出货单里登记的 ──
|
|
CREATE TEMP TABLE _mig_batch (
|
|
brandid bigint, productid bigint, probatch bigint,
|
|
serialstart bigint, serialend bigint,
|
|
startmac text, endmac text, devicenum bigint, ts bigint,
|
|
src text, batchno varchar(16)
|
|
) ON COMMIT DROP;
|
|
|
|
-- 3a. 来源 A:逐张 license_b* 分表按 (productid, probatch) 聚合 —— 授权码的真实归属。
|
|
-- MAC 区间按 number 排序取首尾(不能用 MIN/MAX:那是字典序,与序号顺序未必一致)。
|
|
DO $$
|
|
DECLARE r record;
|
|
BEGIN
|
|
FOR r IN SELECT table_name t FROM information_schema.tables
|
|
WHERE table_schema = 'public' AND table_name ~ '^license_b' ORDER BY table_name
|
|
LOOP
|
|
EXECUTE format($q$
|
|
INSERT INTO _mig_batch (brandid, productid, probatch, serialstart, serialend, startmac, endmac, devicenum, ts, src)
|
|
SELECT COALESCE(MAX(factoryid), 0), productid, COALESCE(probatch, 0),
|
|
MIN(number), MAX(number),
|
|
COALESCE((array_agg(devicemac ORDER BY number) FILTER (WHERE COALESCE(devicemac,'') <> ''))[1], ''),
|
|
COALESCE((array_agg(devicemac ORDER BY number DESC) FILTER (WHERE COALESCE(devicemac,'') <> ''))[1], ''),
|
|
COUNT(*), COALESCE(MIN(NULLIF(createtime, 0)), 0), 'authcode'
|
|
FROM %I GROUP BY productid, COALESCE(probatch, 0)
|
|
$q$, r.t);
|
|
END LOOP;
|
|
END $$;
|
|
|
|
-- 3b. 来源 B:出货单里有、但授权码里没有的批次(productid=0 是脏数据,跳过)
|
|
INSERT INTO _mig_batch (brandid, productid, probatch, serialstart, serialend, startmac, endmac, devicenum, ts, src)
|
|
SELECT MIN(d.factoryid), d.productid, d.probatch,
|
|
0, 0,
|
|
COALESCE(MIN(NULLIF(d.startmac, '')), ''), COALESCE(MAX(NULLIF(d.endmac, '')), ''),
|
|
SUM(d.devicetnum), MIN(d.ts), 'deliverynote'
|
|
FROM factory_deliverynote d
|
|
WHERE d.productid <> 0
|
|
AND NOT EXISTS (SELECT 1 FROM _mig_batch m WHERE m.productid = d.productid AND m.probatch = d.probatch)
|
|
GROUP BY d.productid, d.probatch;
|
|
|
|
-- 3c. 授权码聚合出的批次,用出货单补齐缺失的 MAC 区间与生产时间
|
|
UPDATE _mig_batch m
|
|
SET startmac = CASE WHEN m.startmac = '' THEN COALESCE(d.startmac, '') ELSE m.startmac END,
|
|
endmac = CASE WHEN m.endmac = '' THEN COALESCE(d.endmac, '') ELSE m.endmac END,
|
|
ts = CASE WHEN m.ts = 0 THEN COALESCE(d.ts, 0) ELSE m.ts END
|
|
FROM (SELECT productid, probatch,
|
|
MIN(NULLIF(startmac, '')) startmac, MAX(NULLIF(endmac, '')) endmac, MIN(ts) ts
|
|
FROM factory_deliverynote WHERE productid <> 0 GROUP BY productid, probatch) d
|
|
WHERE m.productid = d.productid AND m.probatch = d.probatch;
|
|
|
|
-- ── 4. 给每个批次定短码 ──
|
|
-- 重复执行时:已迁过的批次沿用原短码(按 remark 锚点找回),只有新批次才生成。
|
|
UPDATE _mig_batch m SET batchno = p.batchno
|
|
FROM production_batch p
|
|
WHERE p.productid = m.productid
|
|
AND p.remark = format('迁移自老数据(%s):probatch=%s', m.src, m.probatch);
|
|
|
|
UPDATE _mig_batch SET batchno = _mig_gen_batchno() WHERE batchno IS NULL;
|
|
|
|
-- 批内撞码兜底(32^6 概率极低,但唯一索引会直接报错,这里先消掉)
|
|
DO $$
|
|
BEGIN
|
|
WHILE EXISTS (SELECT 1 FROM _mig_batch GROUP BY batchno HAVING count(*) > 1) LOOP
|
|
UPDATE _mig_batch SET batchno = _mig_gen_batchno()
|
|
WHERE ctid IN (SELECT max(ctid) FROM _mig_batch GROUP BY batchno HAVING count(*) > 1);
|
|
END LOOP;
|
|
END $$;
|
|
|
|
-- ── 5. 写入 production_batch;remark 留老批次号,便于对账与重跑 ──
|
|
INSERT INTO production_batch (ts, brandid, productid, serialstart, serialend, startmac, endmac, devicenum, batchno, remark)
|
|
SELECT m.ts, m.brandid, m.productid, m.serialstart, m.serialend, m.startmac, m.endmac, m.devicenum, m.batchno,
|
|
format('迁移自老数据(%s):probatch=%s', m.src, m.probatch)
|
|
FROM _mig_batch m
|
|
WHERE NOT EXISTS (SELECT 1 FROM production_batch p WHERE p.batchno = m.batchno);
|
|
|
|
-- ── 6. 各 license 分表:加 brandid / batchno 并回填 ──
|
|
-- factoryid、probatch 原样保留,作为对账依据、也留回滚余地。
|
|
DO $$
|
|
DECLARE r record;
|
|
BEGIN
|
|
FOR r IN SELECT table_name t FROM information_schema.tables
|
|
WHERE table_schema = 'public' AND table_name ~ '^license_b' ORDER BY table_name
|
|
LOOP
|
|
EXECUTE format('ALTER TABLE %I ADD COLUMN IF NOT EXISTS brandid bigint', r.t);
|
|
EXECUTE format('ALTER TABLE %I ADD COLUMN IF NOT EXISTS batchno varchar(16)', r.t);
|
|
-- brandid 直接取老的 factoryid(品牌商 id 沿用了厂家 id,值不变)
|
|
EXECUTE format('UPDATE %I SET brandid = factoryid WHERE brandid IS DISTINCT FROM factoryid', r.t);
|
|
-- batchno 按 (productid, probatch) 从临时表关联(不依赖 remark 文本)
|
|
EXECUTE format($q$
|
|
UPDATE %I l SET batchno = m.batchno
|
|
FROM _mig_batch m
|
|
WHERE m.productid = l.productid
|
|
AND m.probatch = COALESCE(l.probatch, 0)
|
|
AND l.batchno IS DISTINCT FROM m.batchno
|
|
$q$, r.t);
|
|
EXECUTE format('CREATE INDEX IF NOT EXISTS %I ON %I (brandid)', 'idx_' || r.t || '_brandid', r.t);
|
|
EXECUTE format('CREATE INDEX IF NOT EXISTS %I ON %I (batchno)', 'idx_' || r.t || '_batchno', r.t);
|
|
END LOOP;
|
|
END $$;
|
|
|
|
-- ── 7. product / factory_public_code:factoryid 改名 brandid(值不变)──
|
|
DO $$
|
|
BEGIN
|
|
IF EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema='public' AND table_name='product' AND column_name='factoryid')
|
|
AND NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema='public' AND table_name='product' AND column_name='brandid') THEN
|
|
ALTER TABLE product RENAME COLUMN factoryid TO brandid;
|
|
CREATE INDEX IF NOT EXISTS idx_product_brandid ON product (brandid);
|
|
END IF;
|
|
|
|
IF EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema='public' AND table_name='factory_public_code' AND column_name='factoryid')
|
|
AND NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema='public' AND table_name='factory_public_code' AND column_name='brandid') THEN
|
|
ALTER TABLE factory_public_code RENAME COLUMN factoryid TO brandid;
|
|
CREATE INDEX IF NOT EXISTS idx_factory_public_code_brandid ON factory_public_code (brandid);
|
|
END IF;
|
|
END $$;
|
|
|
|
DROP FUNCTION IF EXISTS _mig_gen_batchno();
|
|
COMMIT;
|
|
|