101 lines
3.9 KiB
Python
101 lines
3.9 KiB
Python
"""迁移 026:用户产品小册子资料库与海报产品来源快照。"""
|
||
import logging
|
||
|
||
from sqlalchemy import inspect, text
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def _primary_key_sql(dialect: str) -> str:
|
||
if dialect == "postgresql":
|
||
return "BIGSERIAL PRIMARY KEY"
|
||
if dialect in ("mysql", "mariadb"):
|
||
return "BIGINT AUTO_INCREMENT PRIMARY KEY"
|
||
return "INTEGER PRIMARY KEY AUTOINCREMENT"
|
||
|
||
|
||
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 migrate():
|
||
"""幂等创建用户资料表并扩展海报关联字段。"""
|
||
from insurance.db.compat import db
|
||
|
||
dialect = db.engine.dialect.name
|
||
inspector = inspect(db.engine)
|
||
if not inspector.has_table("insurance_user_product_materials"):
|
||
db.session.execute(text(f"""
|
||
CREATE TABLE insurance_user_product_materials (
|
||
id {_primary_key_sql(dialect)},
|
||
owner_user_id VARCHAR(64) NOT NULL,
|
||
tenant_id VARCHAR(64) NOT NULL DEFAULT 'default',
|
||
company_id VARCHAR(50),
|
||
company_name VARCHAR(100),
|
||
product_name VARCHAR(150),
|
||
plan_type VARCHAR(20),
|
||
original_name VARCHAR(200) NOT NULL,
|
||
file_key VARCHAR(500) NOT NULL,
|
||
file_size BIGINT NOT NULL DEFAULT 0,
|
||
page_count INTEGER,
|
||
sha256 VARCHAR(64) NOT NULL,
|
||
parse_status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||
parse_message VARCHAR(500) NOT NULL DEFAULT '',
|
||
parse_error TEXT,
|
||
parse_task_id VARCHAR(200),
|
||
parse_started_at TIMESTAMP,
|
||
parse_finished_at TIMESTAMP,
|
||
parsed_rules TEXT,
|
||
confirmed_rules TEXT,
|
||
confirmed_by VARCHAR(64),
|
||
confirmed_at TIMESTAMP,
|
||
review_status VARCHAR(20) NOT NULL DEFAULT 'private',
|
||
status SMALLINT NOT NULL DEFAULT 1,
|
||
deleted_at TIMESTAMP,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
)
|
||
"""))
|
||
db.session.commit()
|
||
logger.info("[migrate_026] 已创建 insurance_user_product_materials")
|
||
|
||
desired_indexes = {
|
||
"idx_user_material_owner_updated": "owner_user_id, updated_at",
|
||
"idx_user_material_owner_sha256": "owner_user_id, sha256",
|
||
"idx_user_material_parse_status": "parse_status",
|
||
}
|
||
existing_indexes = _index_names(db, "insurance_user_product_materials")
|
||
for index_name, columns in desired_indexes.items():
|
||
if index_name not in existing_indexes:
|
||
db.session.execute(text(
|
||
f"CREATE INDEX {index_name} "
|
||
f"ON insurance_user_product_materials ({columns})"
|
||
))
|
||
|
||
extra_columns = {
|
||
"product_source_type": "VARCHAR(20)",
|
||
"product_source_id": "VARCHAR(64)",
|
||
"product_snapshot_json": "TEXT",
|
||
}
|
||
for table_name in ("poster_case_uploads", "poster_records"):
|
||
current_columns = _column_names(db, table_name)
|
||
for column_name, column_type in extra_columns.items():
|
||
if column_name not in current_columns:
|
||
db.session.execute(text(
|
||
f"ALTER TABLE {table_name} ADD COLUMN {column_name} {column_type}"
|
||
))
|
||
|
||
db.session.execute(text(
|
||
f"UPDATE {table_name} "
|
||
"SET product_source_type = 'library_product', product_source_id = product_id "
|
||
"WHERE product_id IS NOT NULL AND product_id <> '' "
|
||
"AND (product_source_type IS NULL OR product_source_type = '')"
|
||
))
|
||
|
||
db.session.commit()
|
||
logger.info("[migrate_026] 用户产品资料库迁移完成")
|