-- Лицевые счета домов: отдельная таблица, чтобы не терять их при обновлении buildings.data CREATE TABLE IF NOT EXISTS building_personal_accounts ( id VARCHAR(255) PRIMARY KEY, building_id VARCHAR(255) NOT NULL REFERENCES buildings(id) ON DELETE CASCADE, data JSONB NOT NULL ); CREATE INDEX IF NOT EXISTS idx_building_personal_accounts_building_id ON building_personal_accounts(building_id); COMMENT ON TABLE building_personal_accounts IS 'Лицевые счета (собственники, прописанные, приборы учёта) — вынесены из buildings.data для защиты от перезаписи'; -- Перенос существующих счетов из buildings.data->accounts в новую таблицу (идемпотентно: ON CONFLICT DO NOTHING) INSERT INTO building_personal_accounts (id, building_id, data) SELECT COALESCE(acc->>'id', b.id || '-acc-migrated-' || t.ord), b.id, CASE WHEN (acc ? 'id') AND (acc->>'id' IS NOT NULL) AND (acc->>'id' <> '') THEN acc ELSE acc || jsonb_build_object('id', COALESCE(acc->>'id', b.id || '-acc-migrated-' || t.ord)) END FROM buildings b, LATERAL jsonb_array_elements( CASE WHEN jsonb_typeof(COALESCE(b.data->'accounts', '[]'::jsonb)) = 'array' THEN COALESCE(b.data->'accounts', '[]'::jsonb) ELSE '[]'::jsonb END ) WITH ORDINALITY AS t(acc, ord) ON CONFLICT (id) DO NOTHING;