feat: add DisclosureRequest model and migration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
CCS Admin 2026-02-26 16:02:52 +00:00
parent 00bc92322f
commit bb13ec80a2
3 changed files with 120 additions and 2 deletions

View file

@ -0,0 +1,72 @@
"""add disclosure_requests table
Revision ID: 005_disclosure
Revises: 5717043d0f9d
Create Date: 2026-02-26 14:00:00.000000
"""
from typing import Sequence, Union
from alembic import op
# revision identifiers, used by Alembic.
revision: str = "005_disclosure"
down_revision: Union[str, None] = "5717043d0f9d"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.execute(
"""
CREATE TABLE disclosure_requests (
id INT AUTO_INCREMENT PRIMARY KEY,
case_id INT NOT NULL,
requester_id INT NOT NULL,
reason VARCHAR(500) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
reviewed_by INT NULL,
reviewed_at DATETIME NULL,
expires_at DATETIME NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_dr_case FOREIGN KEY (case_id) REFERENCES cases(id),
CONSTRAINT fk_dr_requester FOREIGN KEY (requester_id) REFERENCES users(id),
CONSTRAINT fk_dr_reviewer FOREIGN KEY (reviewed_by) REFERENCES users(id),
CONSTRAINT chk_dr_status CHECK (status IN ('pending', 'approved', 'rejected')),
INDEX idx_dr_case_status (case_id, status),
INDEX idx_dr_requester (requester_id),
INDEX idx_dr_status (status)
)
"""
)
# Update Notification CHECK constraint to include disclosure types
op.execute("ALTER TABLE notifications DROP CONSTRAINT chk_notif")
op.execute(
"""
ALTER TABLE notifications ADD CONSTRAINT chk_notif CHECK (
notification_type IN (
'new_cases_uploaded','icd_entered','icd_uploaded',
'report_ready','coding_completed','disclosure_request','disclosure_resolved'
)
)
"""
)
def downgrade() -> None:
# Restore original Notification CHECK constraint
op.execute("ALTER TABLE notifications DROP CONSTRAINT chk_notif")
op.execute(
"""
ALTER TABLE notifications ADD CONSTRAINT chk_notif CHECK (
notification_type IN (
'new_cases_uploaded','icd_entered','icd_uploaded',
'report_ready','coding_completed'
)
)
"""
)
op.execute("DROP TABLE disclosure_requests")

View file

@ -3,7 +3,7 @@
from app.models.user import AllowedDomain, InvitationLink, RefreshToken, User
from app.models.case import Case, CaseICDCode
from app.models.report import WeeklyReport, YearlySummary
from app.models.audit import AuditLog, ImportLog, Notification
from app.models.audit import AuditLog, DisclosureRequest, ImportLog, Notification
__all__ = [
# User & Auth
@ -21,4 +21,6 @@ __all__ = [
"ImportLog",
"AuditLog",
"Notification",
# Disclosure / Data Access
"DisclosureRequest",
]

View file

@ -124,7 +124,51 @@ class Notification(Base):
CheckConstraint(
"notification_type IN ("
"'new_cases_uploaded','icd_entered','icd_uploaded',"
"'report_ready','coding_completed')",
"'report_ready','coding_completed',"
"'disclosure_request','disclosure_resolved')",
name="chk_notif",
),
)
class DisclosureRequest(Base):
__tablename__ = "disclosure_requests"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
case_id: Mapped[int] = mapped_column(
Integer, ForeignKey("cases.id"), nullable=False
)
requester_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id"), nullable=False
)
reason: Mapped[str] = mapped_column(String(500), nullable=False)
status: Mapped[str] = mapped_column(
String(20), nullable=False, server_default="pending"
)
reviewed_by: Mapped[Optional[int]] = mapped_column(
Integer, ForeignKey("users.id"), nullable=True
)
reviewed_at: Mapped[Optional[dt.datetime]] = mapped_column(
DateTime, nullable=True
)
expires_at: Mapped[Optional[dt.datetime]] = mapped_column(
DateTime, nullable=True
)
created_at: Mapped[dt.datetime] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
# Relationships
case: Mapped["Case"] = relationship(foreign_keys=[case_id])
requester: Mapped["User"] = relationship(foreign_keys=[requester_id])
reviewer: Mapped[Optional["User"]] = relationship(foreign_keys=[reviewed_by])
__table_args__ = (
CheckConstraint(
"status IN ('pending','approved','rejected')",
name="chk_dr_status",
),
Index("idx_dr_case_status", "case_id", "status"),
Index("idx_dr_requester", "requester_id"),
Index("idx_dr_status", "status"),
)