- 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>
89 lines
3.4 KiB
Python
89 lines
3.4 KiB
Python
"""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)
|