baodan/api/insurance/db/migrate_027.py

125 lines
4.5 KiB
Python
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.

"""迁移 027PPT/海报品牌策略与后台对象软删除字段。"""
import logging
from sqlalchemy import inspect, text
logger = logging.getLogger(__name__)
def _column_names(db, table_name: str) -> set[str]:
return {item["name"] for item in inspect(db.engine).get_columns(table_name)}
def _index_names(db, table_name: str) -> set[str]:
return {item["name"] for item in inspect(db.engine).get_indexes(table_name)}
def _add_columns(db, table_name: str, columns: dict[str, str]):
existing = _column_names(db, table_name)
for name, definition in columns.items():
if name not in existing:
db.session.execute(text(
f"ALTER TABLE {table_name} ADD COLUMN {name} {definition}"
))
def _add_index(db, table_name: str, index_name: str, columns: str):
if index_name not in _index_names(db, table_name):
db.session.execute(text(
f"CREATE INDEX {index_name} ON {table_name} ({columns})"
))
def migrate():
"""幂等增加品牌策略和软删除字段。"""
from insurance.db.compat import db
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS insurance_ppt_scenarios (
code VARCHAR(50) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
base_scenario VARCHAR(50),
generation_mode VARCHAR(20) NOT NULL DEFAULT 'single',
description TEXT,
status SMALLINT NOT NULL DEFAULT 1,
sort_order INTEGER NOT NULL DEFAULT 0,
is_builtin BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
)
"""))
# 先提交新表,确保后续 inspector 使用的独立连接能够看到它。
db.session.commit()
_add_columns(db, "insurance_ppt_companies", {
"masking_enabled": "BOOLEAN NOT NULL DEFAULT FALSE",
"logo_enabled": "BOOLEAN NOT NULL DEFAULT TRUE",
"deleted_at": "TIMESTAMP",
})
_add_columns(db, "insurance_ppt_products", {
"masking_enabled": "BOOLEAN NOT NULL DEFAULT FALSE",
"deleted_at": "TIMESTAMP",
})
_add_columns(db, "insurance_ppt_templates", {
"deleted_at": "TIMESTAMP",
})
_add_columns(db, "poster_copy_templates", {
"deleted_at": "TIMESTAMP",
})
# 新增字段提交后再检查并创建索引,避免 DDL 对其他连接不可见。
db.session.commit()
_add_index(
db, "insurance_ppt_companies",
"idx_ppt_companies_status_deleted", "status, deleted_at",
)
_add_index(
db, "insurance_ppt_scenarios",
"idx_ppt_scenarios_status_deleted", "status, deleted_at",
)
builtins = [
("single_savings", "单份储蓄计划", "single_savings", "single", 10),
("multi_savings_comparison", "双/多储蓄险对比", "multi_savings_comparison", "compare", 20),
("savings_iul_comprehensive", "储蓄险 + IUL 综合方案", "savings_iul_comprehensive", "portfolio", 30),
("generic_single", "通用单产品", "generic_single", "single", 40),
("generic_compare", "通用同险种对比", "generic_compare", "compare", 50),
("generic_portfolio", "通用组合方案", "generic_portfolio", "portfolio", 60),
]
for code, name, base_scenario, generation_mode, sort_order in builtins:
db.session.execute(text("""
INSERT INTO insurance_ppt_scenarios
(code, name, base_scenario, generation_mode, status, sort_order, is_builtin)
SELECT :code, :name, :base_scenario, :generation_mode, 1, :sort_order, TRUE
WHERE NOT EXISTS (
SELECT 1 FROM insurance_ppt_scenarios WHERE code = :code
)
"""), {
"code": code,
"name": name,
"base_scenario": base_scenario,
"generation_mode": generation_mode,
"sort_order": sort_order,
})
_add_index(
db, "insurance_ppt_products",
"idx_ppt_products_status_deleted", "status, deleted_at",
)
_add_index(
db, "insurance_ppt_products",
"idx_ppt_products_company_deleted", "company_id, deleted_at",
)
_add_index(
db, "insurance_ppt_templates",
"idx_ppt_templates_status_deleted", "status, deleted_at",
)
_add_index(
db, "poster_copy_templates",
"idx_copy_templates_status_deleted", "status, deleted_at",
)
db.session.commit()
logger.info("[migrate_027] 品牌策略与软删除字段迁移完成")