mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 17:13:42 +00:00
feat: add DisclosureRequest model and migration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
00bc92322f
commit
bb13ec80a2
3 changed files with 120 additions and 2 deletions
72
backend/alembic/versions/005_add_disclosure_requests.py
Normal file
72
backend/alembic/versions/005_add_disclosure_requests.py
Normal 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")
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
from app.models.user import AllowedDomain, InvitationLink, RefreshToken, User
|
from app.models.user import AllowedDomain, InvitationLink, RefreshToken, User
|
||||||
from app.models.case import Case, CaseICDCode
|
from app.models.case import Case, CaseICDCode
|
||||||
from app.models.report import WeeklyReport, YearlySummary
|
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__ = [
|
__all__ = [
|
||||||
# User & Auth
|
# User & Auth
|
||||||
|
|
@ -21,4 +21,6 @@ __all__ = [
|
||||||
"ImportLog",
|
"ImportLog",
|
||||||
"AuditLog",
|
"AuditLog",
|
||||||
"Notification",
|
"Notification",
|
||||||
|
# Disclosure / Data Access
|
||||||
|
"DisclosureRequest",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,51 @@ class Notification(Base):
|
||||||
CheckConstraint(
|
CheckConstraint(
|
||||||
"notification_type IN ("
|
"notification_type IN ("
|
||||||
"'new_cases_uploaded','icd_entered','icd_uploaded',"
|
"'new_cases_uploaded','icd_entered','icd_uploaded',"
|
||||||
"'report_ready','coding_completed')",
|
"'report_ready','coding_completed',"
|
||||||
|
"'disclosure_request','disclosure_resolved')",
|
||||||
name="chk_notif",
|
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"),
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue