From 2f0a556371e022502dd32f80ff8d0aa1aa3d1341 Mon Sep 17 00:00:00 2001 From: CCS Admin Date: Sat, 28 Feb 2026 13:23:03 +0000 Subject: [PATCH] fix: use same KW range for year-over-year KPI comparison The previous implementation compared a partial current year against a full previous year, producing misleading percentages. Now determines the max KW with data in the selected year and filters the previous year to the same KW range for a fair comparison. Co-Authored-By: Claude Opus 4.6 --- backend/app/api/reports.py | 17 +++++++++++++++- backend/app/services/report_service.py | 27 +++++++++++++++----------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/backend/app/api/reports.py b/backend/app/api/reports.py index 5c15826..c33afa6 100644 --- a/backend/app/api/reports.py +++ b/backend/app/api/reports.py @@ -19,6 +19,7 @@ from app.schemas.report import ( ReportListResponse, ReportMeta, ) +from app.config import get_settings from app.services.audit_service import log_action logger = logging.getLogger(__name__) @@ -43,13 +44,27 @@ def dashboard( jahr = date_to_jahr(date.today()) try: + from sqlalchemy import func as sa_func + + from app.models.case import Case from app.services.report_service import ( calculate_dashboard_kpis, calculate_sheet1_data, ) + # Determine the highest KW with data in the selected year so + # the previous-year comparison covers the same calendar-week range. + max_kw = ( + db.query(sa_func.max(Case.kw)) + .filter( + Case.versicherung == get_settings().VERSICHERUNG_FILTER, + Case.jahr == jahr, + ) + .scalar() + ) + kpis = calculate_dashboard_kpis(db, jahr) - prev_kpis = calculate_dashboard_kpis(db, jahr - 1) + prev_kpis = calculate_dashboard_kpis(db, jahr - 1, max_kw=max_kw) sheet1 = calculate_sheet1_data(db, jahr) return DashboardResponse(kpis=kpis, prev_kpis=prev_kpis, weekly=sheet1.get("weekly", [])) except ImportError: diff --git a/backend/app/services/report_service.py b/backend/app/services/report_service.py index 43a06e1..b22c181 100644 --- a/backend/app/services/report_service.py +++ b/backend/app/services/report_service.py @@ -497,9 +497,12 @@ def calculate_sheet5_data(db: Session, jahr: int, max_kw: int | None = None, fal # Dashboard KPIs # --------------------------------------------------------------------------- -def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: +def calculate_dashboard_kpis(db: Session, jahr: int, max_kw: int | None = None) -> dict: """Calculate live KPIs for the dashboard. + If *max_kw* is given, only cases up to and including that calendar week + are counted. This is used for fair year-over-year comparisons. + Returns:: { @@ -513,18 +516,21 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: "gutachten_typen": {"alternative": X, "bestaetigung": X, "uncodiert": X}, } """ - # Base filter for this portal's insurance + # Base filters for this portal's insurance + year (+ optional KW cutoff) v_filter = Case.versicherung == settings.VERSICHERUNG_FILTER + base_filters = [v_filter, Case.jahr == jahr] + if max_kw is not None: + base_filters.append(Case.kw <= max_kw) # Total cases for the year total_cases = ( - db.query(func.count(Case.id)).filter(v_filter, Case.jahr == jahr).scalar() or 0 + db.query(func.count(Case.id)).filter(*base_filters).scalar() or 0 ) # Cases without ICD codes entered pending_icd = ( db.query(func.count(Case.id)) - .filter(v_filter, Case.jahr == jahr, Case.icd == None) # noqa: E711 + .filter(*base_filters, Case.icd == None) # noqa: E711 .scalar() or 0 ) @@ -533,8 +539,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: pending_coding = ( db.query(func.count(Case.id)) .filter( - v_filter, - Case.jahr == jahr, + *base_filters, Case.gutachten == True, # noqa: E712 Case.gutachten_typ == None, # noqa: E711 ) @@ -545,7 +550,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Gutachten totals total_gutachten = ( db.query(func.count(Case.id)) - .filter(v_filter, Case.jahr == jahr, Case.gutachten == True) # noqa: E712 + .filter(*base_filters, Case.gutachten == True) # noqa: E712 .scalar() or 0 ) @@ -553,7 +558,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Ablehnungen total_ablehnungen = ( db.query(func.count(Case.id)) - .filter(v_filter, Case.jahr == jahr, Case.ablehnung == True) # noqa: E712 + .filter(*base_filters, Case.ablehnung == True) # noqa: E712 .scalar() or 0 ) @@ -561,7 +566,7 @@ def calculate_dashboard_kpis(db: Session, jahr: int) -> dict: # Unterlagen total_unterlagen = ( db.query(func.count(Case.id)) - .filter(v_filter, Case.jahr == jahr, Case.unterlagen == True) # noqa: E712 + .filter(*base_filters, Case.unterlagen == True) # noqa: E712 .scalar() or 0 ) @@ -569,7 +574,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(v_filter, Case.jahr == jahr) + .filter(*base_filters) .group_by(Case.fallgruppe) .all() ) @@ -581,7 +586,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(v_filter, Case.jahr == jahr, Case.gutachten == True) # noqa: E712 + .filter(*base_filters, Case.gutachten == True) # noqa: E712 .group_by(Case.gutachten_typ) .all() )