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 <noreply@anthropic.com>
This commit is contained in:
CCS Admin 2026-02-26 10:20:33 +00:00
parent e0b2d1e01d
commit 32127c30c3
6 changed files with 41 additions and 15 deletions

View file

@ -20,9 +20,12 @@ from app.schemas.case import (
CodingUpdate, CodingUpdate,
ICDUpdate, ICDUpdate,
) )
from app.config import get_settings
from app.services.audit_service import log_action 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 from app.services.icd_service import generate_coding_template, get_pending_icd_cases, save_icd_for_case
settings = get_settings()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
router = APIRouter() router = APIRouter()
@ -73,6 +76,7 @@ def list_pending_coding(
(Bestätigung/Alternative) and therapy-change coding. (Bestätigung/Alternative) and therapy-change coding.
""" """
query = db.query(Case).filter( query = db.query(Case).filter(
Case.versicherung == settings.VERSICHERUNG_FILTER,
Case.gutachten == True, # noqa: E712 Case.gutachten == True, # noqa: E712
Case.gutachten_typ == None, # noqa: E711 Case.gutachten_typ == None, # noqa: E711
) )
@ -172,7 +176,7 @@ def list_cases(
- ``has_coding``: True = only with gutachten_typ; False = only without - ``has_coding``: True = only with gutachten_typ; False = only without
- ``search``: free-text search across nachname, vorname, fall_id, kvnr - ``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: if jahr is not None:
query = query.filter(Case.jahr == jahr) query = query.filter(Case.jahr == jahr)
@ -227,7 +231,7 @@ def get_case(
user: User = Depends(get_current_user), user: User = Depends(get_current_user),
): ):
"""Return a single case by its database ID.""" """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: if not case:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, status_code=status.HTTP_404_NOT_FOUND,

View file

@ -30,6 +30,7 @@ class Settings(BaseSettings):
APP_NAME: str = "DAK Zweitmeinungs-Portal" APP_NAME: str = "DAK Zweitmeinungs-Portal"
CORS_ORIGINS: str = "http://localhost:5173,https://dak.complexcaresolutions.de" CORS_ORIGINS: str = "http://localhost:5173,https://dak.complexcaresolutions.de"
MAX_UPLOAD_SIZE: int = 20971520 # 20MB MAX_UPLOAD_SIZE: int = 20971520 # 20MB
VERSICHERUNG_FILTER: str = "DAK"
@property @property
def database_url(self) -> str: def database_url(self) -> str:

View file

@ -4,9 +4,12 @@ from datetime import datetime, timezone
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.config import get_settings
from app.core.exceptions import CaseNotFoundError from app.core.exceptions import CaseNotFoundError
from app.models.case import Case from app.models.case import Case
settings = get_settings()
def get_coding_queue( def get_coding_queue(
db: Session, db: Session,
@ -23,6 +26,7 @@ def get_coding_queue(
Tuple of (cases, total_count) for pagination. Tuple of (cases, total_count) for pagination.
""" """
query = db.query(Case).filter( query = db.query(Case).filter(
Case.versicherung == settings.VERSICHERUNG_FILTER,
Case.gutachten == True, # noqa: E712 Case.gutachten == True, # noqa: E712
Case.gutachten_typ == None, # noqa: E711 Case.gutachten_typ == None, # noqa: E711
) )

View file

@ -12,8 +12,11 @@ from typing import Any
from openpyxl import Workbook, load_workbook from openpyxl import Workbook, load_workbook
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.config import get_settings
from app.models.case import Case from app.models.case import Case
settings = get_settings()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Columns in the Abrechnung export, matching the expected DAK format # 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: Returns:
The Excel file as bytes. 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 # Group cases by year
by_year: dict[int, list[Case]] = {} by_year: dict[int, list[Case]] = {}

View file

@ -8,9 +8,12 @@ from typing import Optional
from openpyxl import Workbook, load_workbook from openpyxl import Workbook, load_workbook
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.config import get_settings
from app.models.case import Case, CaseICDCode from app.models.case import Case, CaseICDCode
from app.utils.validators import normalize_icd_hauptgruppe, split_icd_codes, validate_icd from app.utils.validators import normalize_icd_hauptgruppe, split_icd_codes, validate_icd
settings = get_settings()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -76,7 +79,10 @@ def get_pending_icd_cases(
per_page: int = 50, per_page: int = 50,
) -> tuple[list[Case], int]: ) -> tuple[list[Case], int]:
"""Get cases without ICD codes.""" """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: if jahr:
query = query.filter(Case.jahr == jahr) query = query.filter(Case.jahr == jahr)

View file

@ -17,8 +17,11 @@ from typing import Any
from sqlalchemy import Integer, and_, func from sqlalchemy import Integer, and_, func
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.config import get_settings
from app.models.case import Case, CaseICDCode from app.models.case import Case, CaseICDCode
settings = get_settings()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Canonical Fallgruppen in display order # 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.ablehnung.cast(Integer)).label("ablehnungen"),
func.sum(Case.gutachten.cast(Integer)).label("gutachten"), 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) .group_by(Case.kw)
.all() .all()
) )
@ -205,7 +208,7 @@ def calculate_sheet2_data(db: Session, jahr: int) -> dict:
func.count(Case.id).label("anzahl"), func.count(Case.id).label("anzahl"),
func.sum(Case.gutachten.cast(Integer)).label("gutachten"), 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) .group_by(Case.kw, Case.fallgruppe)
.all() .all()
) )
@ -276,7 +279,7 @@ def calculate_sheet3_data(db: Session, jahr: int) -> dict:
(Case.gutachten_typ == "Alternative").cast(Integer) (Case.gutachten_typ == "Alternative").cast(Integer)
).label("alternative"), ).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) .group_by(Case.kw, Case.fallgruppe)
.all() .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_unterversorgung.cast(Integer)).label("unterversorgung"),
func.sum(Case.ta_uebertherapie.cast(Integer)).label("uebertherapie"), 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) .group_by(Case.kw)
.all() .all()
) )
@ -413,6 +416,7 @@ def calculate_sheet5_data(db: Session, jahr: int) -> dict:
.join(Case, CaseICDCode.case_id == Case.id) .join(Case, CaseICDCode.case_id == Case.id)
.filter( .filter(
and_( and_(
Case.versicherung == settings.VERSICHERUNG_FILTER,
Case.fallgruppe == "onko", Case.fallgruppe == "onko",
Case.jahr == jahr, Case.jahr == jahr,
) )
@ -446,15 +450,18 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict:
"gutachten_typen": {"alternative": X, "bestaetigung": X, "uncodiert": X}, "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 for the year
total_cases = ( 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 # Cases without ICD codes entered
pending_icd = ( pending_icd = (
db.query(func.count(Case.id)) 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() .scalar()
or 0 or 0
) )
@ -463,6 +470,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict:
pending_coding = ( pending_coding = (
db.query(func.count(Case.id)) db.query(func.count(Case.id))
.filter( .filter(
v_filter,
Case.jahr == jahr, Case.jahr == jahr,
Case.gutachten == True, # noqa: E712 Case.gutachten == True, # noqa: E712
Case.gutachten_typ == None, # noqa: E711 Case.gutachten_typ == None, # noqa: E711
@ -474,7 +482,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict:
# Gutachten totals # Gutachten totals
total_gutachten = ( total_gutachten = (
db.query(func.count(Case.id)) 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() .scalar()
or 0 or 0
) )
@ -482,7 +490,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict:
# Ablehnungen # Ablehnungen
total_ablehnungen = ( total_ablehnungen = (
db.query(func.count(Case.id)) 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() .scalar()
or 0 or 0
) )
@ -490,7 +498,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict:
# Unterlagen # Unterlagen
total_unterlagen = ( total_unterlagen = (
db.query(func.count(Case.id)) 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() .scalar()
or 0 or 0
) )
@ -498,7 +506,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict:
# Per-Fallgruppe counts # Per-Fallgruppe counts
fg_rows = ( fg_rows = (
db.query(Case.fallgruppe, func.count(Case.id).label("cnt")) db.query(Case.fallgruppe, func.count(Case.id).label("cnt"))
.filter(Case.jahr == jahr) .filter(v_filter, Case.jahr == jahr)
.group_by(Case.fallgruppe) .group_by(Case.fallgruppe)
.all() .all()
) )
@ -510,7 +518,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict:
# Gutachten type breakdown # Gutachten type breakdown
typ_rows = ( typ_rows = (
db.query(Case.gutachten_typ, func.count(Case.id).label("cnt")) 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) .group_by(Case.gutachten_typ)
.all() .all()
) )