baodan/api/insurance/db/migrate_027.py

125 lines
4.5 KiB
Python
Raw Normal View History

主要完成内容: 修复 PPT 异步任务无法生成的问题,包括任务变量引用错误、失败状态回写、心跳缺失任务恢复。 脱敏改为保司/产品后台统一配置,生成端不再让用户选择;任务创建时保存策略快照。 保司支持独立控制 PPT、海报 Logo 显示。 PPT 核验新增吸烟状态、币种及三个条件字段。 利益演示、退保提取调整为警告,不再阻止生成。 PPT 生成完成后可以直接返回数据核验页修改。 建立不同险种、单图/长图共六套海报字段画像。 PPT“生成场景”支持后台新增、启停和删除。 保司、产品、PPT 模板、文案模板均支持安全删除。 内置模板禁止删除,只允许停用;存在关联数据时拒绝危险删除。 补充策略变更及删除审计日志。 更新 API 文档、部署文档及修复计划实施记录。 关键交付文件: [数据库迁移 migrate_027.py](D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_027.py) [海报字段画像 field_profiles.py](D:/work/code/python/coding/baodanagent/api/insurance/poster/field_profiles.py) [动态场景服务 scenarios.py](D:/work/code/python/coding/baodanagent/api/insurance/ppt/scenarios.py) [新增回归测试](D:/work/code/python/coding/baodanagent/tests/ppt_poster_optimization_test.py) [优化修复计划书](D:/work/code/python/coding/baodanagent/docs/保险智能客服系统_PPT与海报优化修复计划书_20260731.md) 验证结果: 核心链路测试:37 passed,1 skipped 扩展回归测试:140 passed PPT 渲染器测试:6 passed 前端生产构建:通过 Python 编译检查:通过 完整测试集:190 passed,1 failed 唯一失败为 tests/test_chat_save.py::test_chat_logs_query 未建立 Flask application context,与本次 PPT/海报链路无关。
2026-07-31 14:10:24 +08:00
"""迁移 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()
主要完成内容: 修复 PPT 异步任务无法生成的问题,包括任务变量引用错误、失败状态回写、心跳缺失任务恢复。 脱敏改为保司/产品后台统一配置,生成端不再让用户选择;任务创建时保存策略快照。 保司支持独立控制 PPT、海报 Logo 显示。 PPT 核验新增吸烟状态、币种及三个条件字段。 利益演示、退保提取调整为警告,不再阻止生成。 PPT 生成完成后可以直接返回数据核验页修改。 建立不同险种、单图/长图共六套海报字段画像。 PPT“生成场景”支持后台新增、启停和删除。 保司、产品、PPT 模板、文案模板均支持安全删除。 内置模板禁止删除,只允许停用;存在关联数据时拒绝危险删除。 补充策略变更及删除审计日志。 更新 API 文档、部署文档及修复计划实施记录。 关键交付文件: [数据库迁移 migrate_027.py](D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_027.py) [海报字段画像 field_profiles.py](D:/work/code/python/coding/baodanagent/api/insurance/poster/field_profiles.py) [动态场景服务 scenarios.py](D:/work/code/python/coding/baodanagent/api/insurance/ppt/scenarios.py) [新增回归测试](D:/work/code/python/coding/baodanagent/tests/ppt_poster_optimization_test.py) [优化修复计划书](D:/work/code/python/coding/baodanagent/docs/保险智能客服系统_PPT与海报优化修复计划书_20260731.md) 验证结果: 核心链路测试:37 passed,1 skipped 扩展回归测试:140 passed PPT 渲染器测试:6 passed 前端生产构建:通过 Python 编译检查:通过 完整测试集:190 passed,1 failed 唯一失败为 tests/test_chat_save.py::test_chat_logs_query 未建立 Flask application context,与本次 PPT/海报链路无关。
2026-07-31 14:10:24 +08:00
_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()
主要完成内容: 修复 PPT 异步任务无法生成的问题,包括任务变量引用错误、失败状态回写、心跳缺失任务恢复。 脱敏改为保司/产品后台统一配置,生成端不再让用户选择;任务创建时保存策略快照。 保司支持独立控制 PPT、海报 Logo 显示。 PPT 核验新增吸烟状态、币种及三个条件字段。 利益演示、退保提取调整为警告,不再阻止生成。 PPT 生成完成后可以直接返回数据核验页修改。 建立不同险种、单图/长图共六套海报字段画像。 PPT“生成场景”支持后台新增、启停和删除。 保司、产品、PPT 模板、文案模板均支持安全删除。 内置模板禁止删除,只允许停用;存在关联数据时拒绝危险删除。 补充策略变更及删除审计日志。 更新 API 文档、部署文档及修复计划实施记录。 关键交付文件: [数据库迁移 migrate_027.py](D:/work/code/python/coding/baodanagent/api/insurance/db/migrate_027.py) [海报字段画像 field_profiles.py](D:/work/code/python/coding/baodanagent/api/insurance/poster/field_profiles.py) [动态场景服务 scenarios.py](D:/work/code/python/coding/baodanagent/api/insurance/ppt/scenarios.py) [新增回归测试](D:/work/code/python/coding/baodanagent/tests/ppt_poster_optimization_test.py) [优化修复计划书](D:/work/code/python/coding/baodanagent/docs/保险智能客服系统_PPT与海报优化修复计划书_20260731.md) 验证结果: 核心链路测试:37 passed,1 skipped 扩展回归测试:140 passed PPT 渲染器测试:6 passed 前端生产构建:通过 Python 编译检查:通过 完整测试集:190 passed,1 failed 唯一失败为 tests/test_chat_save.py::test_chat_logs_query 未建立 Flask application context,与本次 PPT/海报链路无关。
2026-07-31 14:10:24 +08:00
_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] 品牌策略与软删除字段迁移完成")