打通 T+ 快照、业务、发货、回款和核算准备链路,保留来源差异并提供待补状态。 新增业务自动接入任务、跨平台读取服务托管、权限复核、来源关联和前端核对页面。 补充迁移、隔离集成测试、浏览器模拟验收及角色授权边界修复。
48 lines
2.7 KiB
Python
48 lines
2.7 KiB
Python
"""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)
|