Files
finance/backend/alembic/versions/20260923_0005_optional_hold_reason.py
T
k1nq 63d065011b Update manifest.json and infra README
- Updated timestamps and AST hashes in manifest.json for various backend and frontend files to reflect recent changes.
- Added new files related to MCC categories and optional hold reasons in the manifest.
- Modified the README in the infra directory to correct the linting tool from 'mypy' to 'ty' for type checking in the backend project.
2026-09-23 10:57:27 +05:00

49 lines
1.4 KiB
Python

"""Allow manual HOLD resolutions without a reason."""
import sqlalchemy as sa
from alembic import op
revision = "0005"
down_revision = "0004"
branch_labels = None
depends_on = None
def _reason_constraint_name() -> str | None:
return next(
(
name
for item in sa.inspect(op.get_bind()).get_check_constraints("hold_resolutions")
if (name := item.get("name")) and name.endswith("manual_reason_required")
),
None,
)
def upgrade() -> None:
if name := _reason_constraint_name():
with op.batch_alter_table("hold_resolutions") as batch_op:
batch_op.drop_constraint(op.f(name), type_="check")
def downgrade() -> None:
if _reason_constraint_name():
return
bind = op.get_bind()
missing_reason = bind.execute(
sa.text(
"SELECT 1 FROM hold_resolutions WHERE resolution IN "
"('confirmed_as_posted', 'discarded_as_cancelled') "
"AND (reason IS NULL OR reason = '') LIMIT 1"
)
).first()
if missing_reason:
raise RuntimeError("Cannot require reasons while reasonless HOLD resolutions exist")
with op.batch_alter_table("hold_resolutions") as batch_op:
batch_op.create_check_constraint(
op.f("ck_hold_resolutions_manual_reason_required"),
"NOT (resolution IN ('confirmed_as_posted', 'discarded_as_cancelled') "
"AND (reason IS NULL OR reason = ''))",
)