"""V29 回款独立人工确认及默认开启开关;不自动确认历史回款。""" from pathlib import Path from alembic import op from sqlalchemy import inspect, text revision = "29b0c1d2e3f4" down_revision = "28a9b0c1d2e3" branch_labels = None depends_on = None def upgrade(): sql = Path(__file__).resolve().parents[3] / "db/migration/V29__receipt_manual_confirmation.sql" columns = {column["name"]: column for column in inspect(op.get_bind()).get_columns("receipts")} existing = {name for name in ("confirmation_status", "confirmed_by", "confirmed_at", "confirmed_revision") if name in columns} if existing and len(existing) != 4: raise RuntimeError("回款确认字段不完整,请先核对数据库结构") if existing: expected = {"confirmation_status": ("TINYINT", None, False), "confirmed_by": ("VARCHAR", 64, True), "confirmed_at": ("DATETIME", None, True), "confirmed_revision": ("VARCHAR", 64, True)} for name, (kind, length, nullable) in expected.items(): column = columns[name] actual_type = column["type"] if (actual_type.__visit_name__.upper() != kind or getattr(actual_type, "length", None) != length or column["nullable"] != nullable): raise RuntimeError(f"回款确认字段 {name} 与迁移定义不一致,请先核对数据库结构") if str(columns["confirmation_status"]["default"]).strip("'\"") != "0": raise RuntimeError("回款确认状态默认值不是待确认,请先核对数据库结构") for statement in sql.read_text(encoding="utf-8").split(";\n"): clean = "\n".join(line for line in statement.splitlines() if not line.lstrip().startswith("--")).strip() if clean and not (existing and clean.startswith("ALTER TABLE receipts ADD COLUMN")): op.get_bind().execute(text(clean)) def downgrade(): bind = op.get_bind() if bind.scalar(text("SELECT COUNT(*) FROM receipts WHERE confirmed_at IS NOT NULL OR confirmation_status<>0")): raise RuntimeError("已有回款人工确认记录,禁止删除确认依据;请仅回退应用并保留结构") if bind.scalar(text("SELECT COUNT(*) FROM param_values v JOIN param_definitions d ON d.id=v.param_id WHERE d.param_code='receipt.confirmation.enabled'")): raise RuntimeError("已维护人工确认开关版本,禁止删除历史参数") bind.execute(text("DELETE FROM param_definitions WHERE param_code='receipt.confirmation.enabled'")) bind.execute(text("UPDATE permissions SET status=0 WHERE perm_code='business:receipts:confirm'")) for column in ("confirmed_revision", "confirmed_at", "confirmed_by", "confirmation_status"): op.drop_column("receipts", column)