From 32127c30c36c93e175a5826a4afd1432c01739dd Mon Sep 17 00:00:00 2001 From: CCS Admin Date: Thu, 26 Feb 2026 10:20:33 +0000 Subject: [PATCH] fix: filter all case queries to DAK insurance only Add VERSICHERUNG_FILTER="DAK" to config and apply it to all case queries: list, detail, pending-icd, pending-coding, coding queue, dashboard KPIs, all 5 report sheets, and excel sync export. Co-Authored-By: Claude Opus 4.6 --- backend/app/api/cases.py | 8 +++++-- backend/app/config.py | 1 + backend/app/services/coding_service.py | 4 ++++ backend/app/services/excel_sync.py | 5 ++++- backend/app/services/icd_service.py | 8 ++++++- backend/app/services/report_service.py | 30 ++++++++++++++++---------- 6 files changed, 41 insertions(+), 15 deletions(-) diff --git a/backend/app/api/cases.py b/backend/app/api/cases.py index 53bc153..54aacdf 100644 --- a/backend/app/api/cases.py +++ b/backend/app/api/cases.py @@ -20,9 +20,12 @@ from app.schemas.case import ( CodingUpdate, ICDUpdate, ) +from app.config import get_settings from app.services.audit_service import log_action from app.services.icd_service import generate_coding_template, get_pending_icd_cases, save_icd_for_case +settings = get_settings() + logger = logging.getLogger(__name__) router = APIRouter() @@ -73,6 +76,7 @@ def list_pending_coding( (Bestätigung/Alternative) and therapy-change coding. """ query = db.query(Case).filter( + Case.versicherung == settings.VERSICHERUNG_FILTER, Case.gutachten == True, # noqa: E712 Case.gutachten_typ == None, # noqa: E711 ) @@ -172,7 +176,7 @@ def list_cases( - ``has_coding``: True = only with gutachten_typ; False = only without - ``search``: free-text search across nachname, vorname, fall_id, kvnr """ - query = db.query(Case) + query = db.query(Case).filter(Case.versicherung == settings.VERSICHERUNG_FILTER) if jahr is not None: query = query.filter(Case.jahr == jahr) @@ -227,7 +231,7 @@ def get_case( user: User = Depends(get_current_user), ): """Return a single case by its database ID.""" - case = db.query(Case).filter(Case.id == case_id).first() + case = db.query(Case).filter(Case.id == case_id, Case.versicherung == settings.VERSICHERUNG_FILTER).first() if not case: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, diff --git a/backend/app/config.py b/backend/app/config.py index 828f684..7e872aa 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -30,6 +30,7 @@ class Settings(BaseSettings): APP_NAME: str = "DAK Zweitmeinungs-Portal" CORS_ORIGINS: str = "http://localhost:5173,https://dak.complexcaresolutions.de" MAX_UPLOAD_SIZE: int = 20971520 # 20MB + VERSICHERUNG_FILTER: str = "DAK" @property def database_url(self) -> str: diff --git a/backend/app/services/coding_service.py b/backend/app/services/coding_service.py index b266d0b..5b802b2 100644 --- a/backend/app/services/coding_service.py +++ b/backend/app/services/coding_service.py @@ -4,9 +4,12 @@ from datetime import datetime, timezone from sqlalchemy.orm import Session +from app.config import get_settings from app.core.exceptions import CaseNotFoundError from app.models.case import Case +settings = get_settings() + def get_coding_queue( db: Session, @@ -23,6 +26,7 @@ def get_coding_queue( Tuple of (cases, total_count) for pagination. """ query = db.query(Case).filter( + Case.versicherung == settings.VERSICHERUNG_FILTER, Case.gutachten == True, # noqa: E712 Case.gutachten_typ == None, # noqa: E711 ) diff --git a/backend/app/services/excel_sync.py b/backend/app/services/excel_sync.py index e887393..be36ea6 100644 --- a/backend/app/services/excel_sync.py +++ b/backend/app/services/excel_sync.py @@ -12,8 +12,11 @@ from typing import Any from openpyxl import Workbook, load_workbook from sqlalchemy.orm import Session +from app.config import get_settings from app.models.case import Case +settings = get_settings() + logger = logging.getLogger(__name__) # Columns in the Abrechnung export, matching the expected DAK format @@ -48,7 +51,7 @@ def sync_db_to_excel(db: Session, filepath: str | None = None) -> bytes: Returns: The Excel file as bytes. """ - cases = db.query(Case).order_by(Case.jahr.desc(), Case.datum.desc()).all() + cases = db.query(Case).filter(Case.versicherung == settings.VERSICHERUNG_FILTER).order_by(Case.jahr.desc(), Case.datum.desc()).all() # Group cases by year by_year: dict[int, list[Case]] = {} diff --git a/backend/app/services/icd_service.py b/backend/app/services/icd_service.py index c665c01..09ec0ff 100644 --- a/backend/app/services/icd_service.py +++ b/backend/app/services/icd_service.py @@ -8,9 +8,12 @@ from typing import Optional from openpyxl import Workbook, load_workbook from sqlalchemy.orm import Session +from app.config import get_settings from app.models.case import Case, CaseICDCode from app.utils.validators import normalize_icd_hauptgruppe, split_icd_codes, validate_icd +settings = get_settings() + logger = logging.getLogger(__name__) @@ -76,7 +79,10 @@ def get_pending_icd_cases( per_page: int = 50, ) -> tuple[list[Case], int]: """Get cases without ICD codes.""" - query = db.query(Case).filter(Case.icd == None) # noqa: E711 + query = db.query(Case).filter( + Case.versicherung == settings.VERSICHERUNG_FILTER, + Case.icd == None, # noqa: E711 + ) if jahr: query = query.filter(Case.jahr == jahr) diff --git a/backend/app/services/report_service.py b/backend/app/services/report_service.py index fb0f80b..9ea1923 100644 --- a/backend/app/services/report_service.py +++ b/backend/app/services/report_service.py @@ -17,8 +17,11 @@ from typing import Any from sqlalchemy import Integer, and_, func from sqlalchemy.orm import Session +from app.config import get_settings from app.models.case import Case, CaseICDCode +settings = get_settings() + logger = logging.getLogger(__name__) # Canonical Fallgruppen in display order @@ -128,7 +131,7 @@ def calculate_sheet1_data(db: Session, jahr: int) -> dict: func.sum(Case.ablehnung.cast(Integer)).label("ablehnungen"), func.sum(Case.gutachten.cast(Integer)).label("gutachten"), ) - .filter(Case.jahr == jahr) + .filter(Case.versicherung == settings.VERSICHERUNG_FILTER, Case.jahr == jahr) .group_by(Case.kw) .all() ) @@ -205,7 +208,7 @@ def calculate_sheet2_data(db: Session, jahr: int) -> dict: func.count(Case.id).label("anzahl"), func.sum(Case.gutachten.cast(Integer)).label("gutachten"), ) - .filter(Case.jahr == jahr) + .filter(Case.versicherung == settings.VERSICHERUNG_FILTER, Case.jahr == jahr) .group_by(Case.kw, Case.fallgruppe) .all() ) @@ -276,7 +279,7 @@ def calculate_sheet3_data(db: Session, jahr: int) -> dict: (Case.gutachten_typ == "Alternative").cast(Integer) ).label("alternative"), ) - .filter(Case.jahr == jahr, Case.gutachten == True) # noqa: E712 + .filter(Case.versicherung == settings.VERSICHERUNG_FILTER, Case.jahr == jahr, Case.gutachten == True) # noqa: E712 .group_by(Case.kw, Case.fallgruppe) .all() ) @@ -356,7 +359,7 @@ def calculate_sheet4_data(db: Session, jahr: int) -> dict: func.sum(Case.ta_unterversorgung.cast(Integer)).label("unterversorgung"), func.sum(Case.ta_uebertherapie.cast(Integer)).label("uebertherapie"), ) - .filter(Case.jahr == jahr, Case.gutachten == True) # noqa: E712 + .filter(Case.versicherung == settings.VERSICHERUNG_FILTER, Case.jahr == jahr, Case.gutachten == True) # noqa: E712 .group_by(Case.kw) .all() ) @@ -413,6 +416,7 @@ def calculate_sheet5_data(db: Session, jahr: int) -> dict: .join(Case, CaseICDCode.case_id == Case.id) .filter( and_( + Case.versicherung == settings.VERSICHERUNG_FILTER, Case.fallgruppe == "onko", Case.jahr == jahr, ) @@ -446,15 +450,18 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: "gutachten_typen": {"alternative": X, "bestaetigung": X, "uncodiert": X}, } """ + # Base filter for this portal's insurance + v_filter = Case.versicherung == settings.VERSICHERUNG_FILTER + # Total cases for the year total_cases = ( - db.query(func.count(Case.id)).filter(Case.jahr == jahr).scalar() or 0 + db.query(func.count(Case.id)).filter(v_filter, Case.jahr == jahr).scalar() or 0 ) # Cases without ICD codes entered pending_icd = ( db.query(func.count(Case.id)) - .filter(Case.jahr == jahr, Case.icd == None) # noqa: E711 + .filter(v_filter, Case.jahr == jahr, Case.icd == None) # noqa: E711 .scalar() or 0 ) @@ -463,6 +470,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: pending_coding = ( db.query(func.count(Case.id)) .filter( + v_filter, Case.jahr == jahr, Case.gutachten == True, # noqa: E712 Case.gutachten_typ == None, # noqa: E711 @@ -474,7 +482,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Gutachten totals total_gutachten = ( db.query(func.count(Case.id)) - .filter(Case.jahr == jahr, Case.gutachten == True) # noqa: E712 + .filter(v_filter, Case.jahr == jahr, Case.gutachten == True) # noqa: E712 .scalar() or 0 ) @@ -482,7 +490,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Ablehnungen total_ablehnungen = ( db.query(func.count(Case.id)) - .filter(Case.jahr == jahr, Case.ablehnung == True) # noqa: E712 + .filter(v_filter, Case.jahr == jahr, Case.ablehnung == True) # noqa: E712 .scalar() or 0 ) @@ -490,7 +498,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Unterlagen total_unterlagen = ( db.query(func.count(Case.id)) - .filter(Case.jahr == jahr, Case.unterlagen == True) # noqa: E712 + .filter(v_filter, Case.jahr == jahr, Case.unterlagen == True) # noqa: E712 .scalar() or 0 ) @@ -498,7 +506,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Per-Fallgruppe counts fg_rows = ( db.query(Case.fallgruppe, func.count(Case.id).label("cnt")) - .filter(Case.jahr == jahr) + .filter(v_filter, Case.jahr == jahr) .group_by(Case.fallgruppe) .all() ) @@ -510,7 +518,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Gutachten type breakdown typ_rows = ( db.query(Case.gutachten_typ, func.count(Case.id).label("cnt")) - .filter(Case.jahr == jahr, Case.gutachten == True) # noqa: E712 + .filter(v_filter, Case.jahr == jahr, Case.gutachten == True) # noqa: E712 .group_by(Case.gutachten_typ) .all() )