baodan/api/insurance/db/migrate_015.py

221 lines
8.1 KiB
Python
Raw Normal View History

2026-07-23 15:04:16 +08:00
"""迁移 015: PPT/海报功能扩展 — 扩展现有表 + 创建新表。
覆盖
- 扩展 insurance_ppt_companies+3 字段
- 扩展 insurance_ppt_products+16 字段
- 扩展 insurance_ppt_templates+6 字段
- 创建 insurance_ppt_history
- 创建 poster_case_uploads
- 创建 poster_templates
- 创建 poster_copy_templates
- 创建 poster_records
- 创建 system_settings + 种子数据
"""
import logging
logger = logging.getLogger(__name__)
def _add_column(table, column_def, db):
"""安全添加列(已存在则跳过)。"""
from sqlalchemy import text
try:
db.session.execute(text(f"ALTER TABLE {table} ADD COLUMN {column_def}"))
except Exception as e:
# 仅忽略"列已存在"错误,其他错误记录日志
err_msg = str(e).lower()
if "already exists" not in err_msg and "duplicate column" not in err_msg:
logger.warning(f"添加列 {table}.{column_def} 失败: {e}")
def migrate():
"""迁移入口。"""
from insurance.db.compat import db
from sqlalchemy import text
# ========== 1. 扩展 insurance_ppt_companies ==========
logger.info("[migrate_015] 扩展 insurance_ppt_companies ...")
for col in [
"logo_url VARCHAR(500)",
"status SMALLINT DEFAULT 1",
"sort_order INTEGER DEFAULT 0",
]:
_add_column("insurance_ppt_companies", col, db)
db.session.execute(text(
"UPDATE insurance_ppt_companies SET status = 1 WHERE status IS NULL"
))
db.session.commit()
logger.info("[migrate_015] insurance_ppt_companies 扩展完成")
# ========== 2. 扩展 insurance_ppt_products ==========
logger.info("[migrate_015] 扩展 insurance_ppt_products ...")
for col in [
"product_code VARCHAR(50)",
"product_type VARCHAR(20)",
"coverage_period VARCHAR(50)",
"payment_period VARCHAR(50)",
"insured_age_range VARCHAR(50)",
"waiting_period VARCHAR(50)",
"highlights TEXT",
"extra_fields TEXT",
"status SMALLINT DEFAULT 1",
"sort_order INTEGER DEFAULT 0",
"updated_at TIMESTAMP DEFAULT NOW()",
"manual_file_url VARCHAR(500)",
"manual_parse_status VARCHAR(20) DEFAULT 'none'",
"manual_parsed_rules TEXT",
"manual_reviewed_by VARCHAR(50)",
"manual_reviewed_at TIMESTAMP",
]:
_add_column("insurance_ppt_products", col, db)
db.session.execute(text(
"UPDATE insurance_ppt_products SET status = 1 WHERE status IS NULL"
))
db.session.commit()
logger.info("[migrate_015] insurance_ppt_products 扩展完成")
# ========== 3. 扩展 insurance_ppt_templates ==========
logger.info("[migrate_015] 扩展 insurance_ppt_templates ...")
for col in [
"name VARCHAR(100)",
"scenario_tag VARCHAR(50)",
"preview_image VARCHAR(500)",
"applicable_company_ids TEXT",
"applicable_product_ids TEXT",
"status SMALLINT DEFAULT 1",
]:
_add_column("insurance_ppt_templates", col, db)
db.session.commit()
logger.info("[migrate_015] insurance_ppt_templates 扩展完成")
# ========== 4. 创建 insurance_ppt_history ==========
logger.info("[migrate_015] 创建 insurance_ppt_history ...")
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS insurance_ppt_history (
id BIGSERIAL PRIMARY KEY,
user_id VARCHAR(50) NOT NULL,
session_id VARCHAR(50),
action_type VARCHAR(20) NOT NULL,
company_id VARCHAR(50),
product_id VARCHAR(50),
template_id VARCHAR(50),
content_snapshot TEXT,
file_url VARCHAR(500),
ip VARCHAR(50),
user_agent VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW()
)
"""))
db.session.execute(text(
"CREATE INDEX IF NOT EXISTS idx_ppt_history_user ON insurance_ppt_history(user_id, created_at DESC)"
))
db.session.commit()
logger.info("[migrate_015] insurance_ppt_history 创建完成")
# ========== 5. 创建 poster_case_uploads ==========
logger.info("[migrate_015] 创建 poster_case_uploads ...")
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS poster_case_uploads (
id BIGSERIAL PRIMARY KEY,
user_id VARCHAR(50) NOT NULL,
product_id VARCHAR(50) NOT NULL,
source_file_url VARCHAR(500) NOT NULL,
parse_status VARCHAR(20) DEFAULT 'pending',
parsed_data TEXT,
confirmed_data TEXT,
confirmed_by VARCHAR(50),
confirmed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
)
"""))
db.session.commit()
logger.info("[migrate_015] poster_case_uploads 创建完成")
# ========== 6. 创建 poster_templates ==========
logger.info("[migrate_015] 创建 poster_templates ...")
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS poster_templates (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
scenario_tag VARCHAR(50),
style_description TEXT NOT NULL,
color_scheme TEXT,
reference_image VARCHAR(500),
preview_image VARCHAR(500),
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
)
"""))
db.session.commit()
logger.info("[migrate_015] poster_templates 创建完成")
# ========== 7. 创建 poster_copy_templates ==========
logger.info("[migrate_015] 创建 poster_copy_templates ...")
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS poster_copy_templates (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
scenario_tag VARCHAR(50),
content TEXT NOT NULL,
variables TEXT,
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW()
)
"""))
db.session.commit()
logger.info("[migrate_015] poster_copy_templates 创建完成")
# ========== 8. 创建 poster_records ==========
logger.info("[migrate_015] 创建 poster_records ...")
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS poster_records (
id BIGSERIAL PRIMARY KEY,
user_id VARCHAR(50) NOT NULL,
product_id VARCHAR(50),
case_upload_id BIGINT,
template_id BIGINT,
copy_mode VARCHAR(20),
copy_content TEXT,
ai_raw_content TEXT,
export_url VARCHAR(500),
export_format VARCHAR(10),
export_size VARCHAR(20),
reference_image_used VARCHAR(500),
prompt_used TEXT,
created_at TIMESTAMP DEFAULT NOW()
)
"""))
db.session.execute(text(
"CREATE INDEX IF NOT EXISTS idx_poster_records_user ON poster_records(user_id, created_at DESC)"
))
db.session.commit()
logger.info("[migrate_015] poster_records 创建完成")
# ========== 9. 创建 system_settings + 种子数据 ==========
logger.info("[migrate_015] 创建 system_settings ...")
db.session.execute(text("""
CREATE TABLE IF NOT EXISTS system_settings (
id BIGSERIAL PRIMARY KEY,
key VARCHAR(100) UNIQUE NOT NULL,
value TEXT NOT NULL,
description VARCHAR(500),
updated_by VARCHAR(50),
updated_at TIMESTAMP DEFAULT NOW()
)
"""))
# 种子数据(幂等:已存在则跳过)
for key, value, desc in [
("ppt_history_retention_days", "365", "PPT 历史记录保留天数0=永久保留)"),
("poster_history_retention_days", "365", "海报历史记录保留天数0=永久保留)"),
]:
db.session.execute(text(
"INSERT INTO system_settings (key, value, description) "
"SELECT :key, :value, :desc "
"WHERE NOT EXISTS (SELECT 1 FROM system_settings WHERE key = :key)"
), {"key": key, "value": value, "desc": desc})
db.session.commit()
logger.info("[migrate_015] system_settings 创建完成")
logger.info("[migrate_015] 全部迁移完成")