dak.c2s/backend/app/services/coding_service.py
CCS Admin d6fb04d5a7 feat: coding queue, reports API, Excel sync
- Add coding_service.py with queue retrieval, single + batch coding updates
- Add report schemas (DashboardKPIs, WeeklyDataPoint, ReportMeta)
- Add coding API router with /queue, PUT /{case_id}, POST /batch endpoints
- Add reports API router with /dashboard, /weekly, /generate, /download, /list
- Add excel_sync.py for bidirectional Abrechnung DB<->XLSX sync
- Register coding and reports routers in main.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 08:03:17 +00:00

109 lines
3.2 KiB
Python

"""Coding queue and batch coding operations for Gutachten classification."""
from datetime import datetime, timezone
from sqlalchemy.orm import Session
from app.core.exceptions import CaseNotFoundError
from app.models.case import Case
def get_coding_queue(
db: Session,
fallgruppe: str | None = None,
page: int = 1,
per_page: int = 50,
) -> tuple[list[Case], int]:
"""Get cases with gutachten=True but no gutachten_typ yet.
These cases have received a Gutachten but still need classification
(Bestaetigung/Alternative) and therapy-change coding.
Returns:
Tuple of (cases, total_count) for pagination.
"""
query = db.query(Case).filter(
Case.gutachten == True, # noqa: E712
Case.gutachten_typ == None, # noqa: E711
)
if fallgruppe:
query = query.filter(Case.fallgruppe == fallgruppe)
total = query.count()
cases = (
query.order_by(Case.datum.desc())
.offset((page - 1) * per_page)
.limit(per_page)
.all()
)
return cases, total
def update_coding(
db: Session,
case_id: int,
gutachten_typ: str,
therapieaenderung: str,
ta_diagnosekorrektur: bool = False,
ta_unterversorgung: bool = False,
ta_uebertherapie: bool = False,
user_id: int | None = None,
) -> Case:
"""Set coding for a single case.
Validates gutachten_typ and therapieaenderung values, then persists the
coding classification along with the user and timestamp.
Raises:
CaseNotFoundError: If no case with the given ID exists.
ValueError: If gutachten_typ or therapieaenderung have invalid values.
"""
case = db.query(Case).filter(Case.id == case_id).first()
if not case:
raise CaseNotFoundError()
if gutachten_typ not in ("Bestätigung", "Alternative"):
raise ValueError(f"Invalid gutachten_typ: {gutachten_typ}")
if therapieaenderung not in ("Ja", "Nein"):
raise ValueError(f"Invalid therapieaenderung: {therapieaenderung}")
case.gutachten_typ = gutachten_typ
case.therapieaenderung = therapieaenderung
case.ta_diagnosekorrektur = ta_diagnosekorrektur
case.ta_unterversorgung = ta_unterversorgung
case.ta_uebertherapie = ta_uebertherapie
case.coding_completed_by = user_id
case.coding_completed_at = datetime.now(timezone.utc)
db.commit()
db.refresh(case)
return case
def batch_update_coding(
db: Session,
updates: list[dict],
user_id: int | None = None,
) -> dict:
"""Batch update coding for multiple cases.
Each dict in *updates* must contain at minimum:
- ``case_id`` (int)
- ``gutachten_typ`` (str)
- ``therapieaenderung`` (str)
and optionally the ``ta_*`` boolean flags.
Returns:
Dict with ``updated`` count and ``errors`` list of error messages.
"""
updated = 0
errors: list[str] = []
for item in updates:
case_id = item.get("case_id")
try:
params = {k: v for k, v in item.items() if k != "case_id"}
update_coding(db, case_id, user_id=user_id, **params)
updated += 1
except Exception as exc:
errors.append(f"Case {case_id}: {exc}")
return {"updated": updated, "errors": errors}