Add client acceptance controls for AQMM and peer review workflow
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
"""phase_2_client_acceptance_controls
|
||||
|
||||
Revision ID: 20260622_phase_2_client_acceptance_controls
|
||||
Revises: 20260621_phase_1_udin_final_documents
|
||||
Create Date: 2026-06-22
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import inspect, text
|
||||
|
||||
revision = "20260622_phase_2_client_acceptance_controls"
|
||||
down_revision = "20260621_phase_1_udin_final_documents"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
CLIENT_TABLE = "clients"
|
||||
|
||||
|
||||
def _columns(table_name: str) -> set[str]:
|
||||
bind = op.get_bind()
|
||||
inspector = inspect(bind)
|
||||
if table_name not in inspector.get_table_names():
|
||||
return set()
|
||||
return {col["name"] for col in inspector.get_columns(table_name)}
|
||||
|
||||
|
||||
def _add_column_if_missing(existing: set[str], column: sa.Column) -> None:
|
||||
if column.name in existing:
|
||||
return
|
||||
op.add_column(CLIENT_TABLE, column)
|
||||
existing.add(column.name)
|
||||
|
||||
|
||||
def _create_index_if_missing(index_name: str, columns: list[str]) -> None:
|
||||
bind = op.get_bind()
|
||||
inspector = inspect(bind)
|
||||
existing_indexes = {idx["name"] for idx in inspector.get_indexes(CLIENT_TABLE)}
|
||||
if index_name not in existing_indexes:
|
||||
op.create_index(index_name, CLIENT_TABLE, columns)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
existing = _columns(CLIENT_TABLE)
|
||||
|
||||
_add_column_if_missing(existing, sa.Column("acceptance_status", sa.String(length=30), nullable=False, server_default="pending_review"))
|
||||
_add_column_if_missing(existing, sa.Column("acceptance_required", sa.Boolean(), nullable=False, server_default=sa.true()))
|
||||
_add_column_if_missing(existing, sa.Column("independence_check_completed", sa.Boolean(), nullable=False, server_default=sa.false()))
|
||||
_add_column_if_missing(existing, sa.Column("conflict_check_completed", sa.Boolean(), nullable=False, server_default=sa.false()))
|
||||
_add_column_if_missing(existing, sa.Column("kyc_completed", sa.Boolean(), nullable=False, server_default=sa.false()))
|
||||
_add_column_if_missing(existing, sa.Column("engagement_letter_required", sa.Boolean(), nullable=False, server_default=sa.true()))
|
||||
_add_column_if_missing(existing, sa.Column("engagement_letter_received", sa.Boolean(), nullable=False, server_default=sa.false()))
|
||||
_add_column_if_missing(existing, sa.Column("acceptance_approved_by_user_id", sa.Integer(), nullable=True))
|
||||
_add_column_if_missing(existing, sa.Column("acceptance_approved_at_utc", sa.DateTime(timezone=True), nullable=True))
|
||||
_add_column_if_missing(existing, sa.Column("acceptance_review_notes", sa.Text(), nullable=True))
|
||||
_add_column_if_missing(existing, sa.Column("acceptance_rejection_reason", sa.Text(), nullable=True))
|
||||
|
||||
bind = op.get_bind()
|
||||
dialect = bind.dialect.name
|
||||
if dialect == "postgresql":
|
||||
op.execute(text("UPDATE clients SET acceptance_status = 'pending_review' WHERE acceptance_status IS NULL"))
|
||||
op.execute(text("UPDATE clients SET acceptance_required = TRUE WHERE acceptance_required IS NULL"))
|
||||
op.execute(text("UPDATE clients SET independence_check_completed = FALSE WHERE independence_check_completed IS NULL"))
|
||||
op.execute(text("UPDATE clients SET conflict_check_completed = FALSE WHERE conflict_check_completed IS NULL"))
|
||||
op.execute(text("UPDATE clients SET kyc_completed = FALSE WHERE kyc_completed IS NULL"))
|
||||
op.execute(text("UPDATE clients SET engagement_letter_required = TRUE WHERE engagement_letter_required IS NULL"))
|
||||
op.execute(text("UPDATE clients SET engagement_letter_received = FALSE WHERE engagement_letter_received IS NULL"))
|
||||
else:
|
||||
op.execute(text("UPDATE clients SET acceptance_status = 'pending_review' WHERE acceptance_status IS NULL"))
|
||||
op.execute(text("UPDATE clients SET acceptance_required = 1 WHERE acceptance_required IS NULL"))
|
||||
op.execute(text("UPDATE clients SET independence_check_completed = 0 WHERE independence_check_completed IS NULL"))
|
||||
op.execute(text("UPDATE clients SET conflict_check_completed = 0 WHERE conflict_check_completed IS NULL"))
|
||||
op.execute(text("UPDATE clients SET kyc_completed = 0 WHERE kyc_completed IS NULL"))
|
||||
op.execute(text("UPDATE clients SET engagement_letter_required = 1 WHERE engagement_letter_required IS NULL"))
|
||||
op.execute(text("UPDATE clients SET engagement_letter_received = 0 WHERE engagement_letter_received IS NULL"))
|
||||
|
||||
_create_index_if_missing("ix_clients_acceptance_status", ["acceptance_status"])
|
||||
_create_index_if_missing("ix_clients_acceptance_approved_by_user_id", ["acceptance_approved_by_user_id"])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
bind = op.get_bind()
|
||||
inspector = inspect(bind)
|
||||
if CLIENT_TABLE not in inspector.get_table_names():
|
||||
return
|
||||
|
||||
existing_indexes = {idx["name"] for idx in inspector.get_indexes(CLIENT_TABLE)}
|
||||
if "ix_clients_acceptance_approved_by_user_id" in existing_indexes:
|
||||
op.drop_index("ix_clients_acceptance_approved_by_user_id", table_name=CLIENT_TABLE)
|
||||
if "ix_clients_acceptance_status" in existing_indexes:
|
||||
op.drop_index("ix_clients_acceptance_status", table_name=CLIENT_TABLE)
|
||||
|
||||
existing = _columns(CLIENT_TABLE)
|
||||
for col in [
|
||||
"acceptance_rejection_reason",
|
||||
"acceptance_review_notes",
|
||||
"acceptance_approved_at_utc",
|
||||
"acceptance_approved_by_user_id",
|
||||
"engagement_letter_received",
|
||||
"engagement_letter_required",
|
||||
"kyc_completed",
|
||||
"conflict_check_completed",
|
||||
"independence_check_completed",
|
||||
"acceptance_required",
|
||||
"acceptance_status",
|
||||
]:
|
||||
if col in existing:
|
||||
op.drop_column(CLIENT_TABLE, col)
|
||||
Reference in New Issue
Block a user