dak.c2s/backend/app/models/report.py
CCS Admin e7befe78b6 feat: SQLAlchemy models for users, cases, reports, audit
11 models across 4 files matching the MariaDB schema:
- user.py: User, RefreshToken, InvitationLink, AllowedDomain
- case.py: Case, CaseICDCode
- report.py: WeeklyReport, YearlySummary
- audit.py: ImportLog, AuditLog, Notification

All CHECK constraints, indexes (incl. prefix index), foreign keys,
and server defaults match the SQL DDL specification exactly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 07:28:33 +00:00

189 lines
5.7 KiB
Python

"""Weekly report and yearly summary models."""
from __future__ import annotations
import datetime as dt
from typing import Optional
from sqlalchemy import (
Date,
DateTime,
ForeignKey,
Index,
Integer,
SmallInteger,
String,
UniqueConstraint,
func,
)
from sqlalchemy.dialects.mysql import JSON
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database import Base
class WeeklyReport(Base):
__tablename__ = "weekly_reports"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
jahr: Mapped[int] = mapped_column(SmallInteger, nullable=False)
kw: Mapped[int] = mapped_column(SmallInteger, nullable=False)
report_date: Mapped[dt.date] = mapped_column(Date, nullable=False)
report_file_path: Mapped[Optional[str]] = mapped_column(
String(500), nullable=True
)
report_data: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
generated_by: Mapped[Optional[int]] = mapped_column(
Integer, ForeignKey("users.id"), nullable=True
)
generated_at: Mapped[dt.datetime] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
# Relationships
generated_by_user: Mapped[Optional["User"]] = relationship(
foreign_keys=[generated_by]
)
__table_args__ = (
UniqueConstraint("jahr", "kw", name="uk_jahr_kw"),
)
class YearlySummary(Base):
__tablename__ = "yearly_summary"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
jahr: Mapped[int] = mapped_column(SmallInteger, nullable=False)
kw: Mapped[int] = mapped_column(SmallInteger, nullable=False)
# Overall counts
erstberatungen: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
ablehnungen: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
unterlagen: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
keine_rueckmeldung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
gutachten_gesamt: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
gutachten_alternative: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
gutachten_bestaetigung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
# Per-Fallgruppe counts: onko
onko_anzahl: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
onko_gutachten: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
onko_keine_rm: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
# Per-Fallgruppe counts: kardio
kardio_anzahl: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
kardio_gutachten: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
kardio_keine_rm: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
# Per-Fallgruppe counts: intensiv
intensiv_anzahl: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
intensiv_gutachten: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
intensiv_keine_rm: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
# Per-Fallgruppe counts: galle
galle_anzahl: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
galle_gutachten: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
galle_keine_rm: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
# Per-Fallgruppe counts: sd
sd_anzahl: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
sd_gutachten: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
sd_keine_rm: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
# Gutachten-Typ per Fallgruppe
onko_alternative: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
onko_bestaetigung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
kardio_alternative: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
kardio_bestaetigung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
intensiv_alternative: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
intensiv_bestaetigung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
galle_alternative: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
galle_bestaetigung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
sd_alternative: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
sd_bestaetigung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
# Therapieaenderung counts
ta_ja: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
ta_nein: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
ta_diagnosekorrektur: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
ta_unterversorgung: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
ta_uebertherapie: Mapped[Optional[int]] = mapped_column(
Integer, server_default="0"
)
__table_args__ = (
UniqueConstraint("jahr", "kw", name="uk_jahr_kw"),
)