feat: Phase 4 — viewer enrichi, non-cumul CCAM, fusion multi-PDFs + rebuild FAISS (21 141 vecteurs)
- Viewer : badges compteurs (DAS, actes, alertes, CMA), raisonnement LLM pliable, regroupement CCAM, navigation patient, alertes NON-CUMUL en rouge - Non-cumul CCAM : 3 règles heuristiques (même base, même regroupement/jour, paires incompatibles) - Fusion multi-PDFs : merge_dossiers() avec priorité Trackare, spécificité CIM-10, déduplication, champ source_files - Index FAISS reconstruit : 21 141 vecteurs (CCAM dict 8 257 + CIM-10 alpha 306) - 192 tests unitaires passent Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
88
tests/test_ccam_noncumul.py
Normal file
88
tests/test_ccam_noncumul.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""Tests pour le module de détection de non-cumul CCAM."""
|
||||
|
||||
import pytest
|
||||
|
||||
from src.config import ActeCCAM
|
||||
from src.medical.ccam_noncumul import check_noncumul
|
||||
|
||||
|
||||
class TestCheckNoncumul:
|
||||
def test_no_actes_no_alerts(self):
|
||||
assert check_noncumul([]) == []
|
||||
|
||||
def test_single_acte_no_alert(self):
|
||||
actes = [ActeCCAM(texte="Cholécystectomie", code_ccam_suggestion="HMFC004")]
|
||||
assert check_noncumul(actes) == []
|
||||
|
||||
def test_same_base_code_different_activity(self):
|
||||
"""Deux codes avec les 7 premiers caractères identiques déclenchent une alerte."""
|
||||
actes = [
|
||||
ActeCCAM(texte="Acte 1", code_ccam_suggestion="HMFC004"),
|
||||
ActeCCAM(texte="Acte 2", code_ccam_suggestion="HMFC005"),
|
||||
]
|
||||
alertes = check_noncumul(actes)
|
||||
assert any("NON-CUMUL" in a and "HMFC0" in a for a in alertes)
|
||||
|
||||
def test_different_base_codes_no_alert(self):
|
||||
"""Codes de bases différentes : pas d'alerte de base identique."""
|
||||
actes = [
|
||||
ActeCCAM(texte="Acte 1", code_ccam_suggestion="HMFC004"),
|
||||
ActeCCAM(texte="Acte 2", code_ccam_suggestion="ZCQK002"),
|
||||
]
|
||||
alertes = check_noncumul(actes)
|
||||
# Pas d'alerte sur la règle 1 (même base)
|
||||
assert not any("même base" in a for a in alertes)
|
||||
|
||||
def test_same_regroupement_same_day(self, monkeypatch):
|
||||
"""Même regroupement chirurgical le même jour déclenche une alerte."""
|
||||
# Monkeypatch pour simuler le regroupement
|
||||
def mock_get_regroup(acte):
|
||||
return "ADC"
|
||||
|
||||
monkeypatch.setattr(
|
||||
"src.medical.ccam_noncumul._get_regroupement", mock_get_regroup
|
||||
)
|
||||
|
||||
actes = [
|
||||
ActeCCAM(texte="Acte 1", code_ccam_suggestion="ABCD001", date="01/03/2023"),
|
||||
ActeCCAM(texte="Acte 2", code_ccam_suggestion="EFGH002", date="01/03/2023"),
|
||||
]
|
||||
alertes = check_noncumul(actes)
|
||||
assert any("NON-CUMUL" in a and "ADC" in a for a in alertes)
|
||||
|
||||
def test_different_regroupement_no_alert(self, monkeypatch):
|
||||
"""Regroupements différents non incompatibles : pas d'alerte."""
|
||||
regroup_map = {"ABCD001": "ATM", "EFGH002": "ACI"}
|
||||
|
||||
def mock_get_regroup(acte):
|
||||
return regroup_map.get(acte.code_ccam_suggestion)
|
||||
|
||||
monkeypatch.setattr(
|
||||
"src.medical.ccam_noncumul._get_regroupement", mock_get_regroup
|
||||
)
|
||||
|
||||
actes = [
|
||||
ActeCCAM(texte="Acte 1", code_ccam_suggestion="ABCD001", date="01/03/2023"),
|
||||
ActeCCAM(texte="Acte 2", code_ccam_suggestion="EFGH002", date="01/03/2023"),
|
||||
]
|
||||
alertes = check_noncumul(actes)
|
||||
# Pas d'alerte de regroupement unique ni d'incompatibilité
|
||||
assert not any("regroupement" in a.lower() for a in alertes)
|
||||
|
||||
def test_incompatible_regroupement_pairs(self, monkeypatch):
|
||||
"""Paire de regroupements incompatibles déclenche une alerte."""
|
||||
regroup_map = {"ABCD001": "ADC", "EFGH002": "ADE"}
|
||||
|
||||
def mock_get_regroup(acte):
|
||||
return regroup_map.get(acte.code_ccam_suggestion)
|
||||
|
||||
monkeypatch.setattr(
|
||||
"src.medical.ccam_noncumul._get_regroupement", mock_get_regroup
|
||||
)
|
||||
|
||||
actes = [
|
||||
ActeCCAM(texte="Acte 1", code_ccam_suggestion="ABCD001"),
|
||||
ActeCCAM(texte="Acte 2", code_ccam_suggestion="EFGH002"),
|
||||
]
|
||||
alertes = check_noncumul(actes)
|
||||
assert any("incompatibles" in a and "ADC" in a and "ADE" in a for a in alertes)
|
||||
Reference in New Issue
Block a user