Fix bolus/basal insulin categorization: split SMB from manual corrections, add basal calc

AndroidAPS records an automatic SMB micro-bolus as eventType "Correction
Bolus" with type "SMB", not as its own eventType. bolus_stats() was
grouping by eventType alone, so every SMB was silently counted as a manual
correction bolus. Verified against production data: 100% of "Correction
Bolus" treatments over 90 days were actually type=SMB.

Also adds basal_stats(), computing delivered basal directly from Temp
Basal treatments (rate x duration) without needing the pump profile.

Closes gitea #20.
This commit is contained in:
2026-08-01 22:52:54 +02:00
parent 441bb84212
commit 9e11dd8d73
5 changed files with 184 additions and 26 deletions
+32
View File
@@ -90,6 +90,38 @@ def test_fetch_treatments_fills_missing_columns(monkeypatch):
assert result.iloc[0]["eventType"] == "Site Change"
assert pd_isna(result.iloc[0]["insulin"])
assert pd_isna(result.iloc[0]["carbs"])
assert result.iloc[0]["type"] == ""
assert pd_isna(result.iloc[0]["absolute"])
assert pd_isna(result.iloc[0]["duration"])
def test_fetch_treatments_passes_through_type_and_temp_basal_fields(monkeypatch):
"""SMB-classificatie (reporting.bolus_stats) en basaalberekening
(reporting.basal_stats) hebben deze velden nodig — zie gitea #20."""
monkeypatch.setenv("NIGHTSCOUT_URL", "https://example.com")
now = datetime.now(timezone.utc)
payload = [
{
"created_at": now.isoformat(),
"eventType": "Correction Bolus",
"insulin": 0.5,
"type": "SMB",
},
{
"created_at": now.isoformat(),
"eventType": "Temp Basal",
"absolute": 1.2,
"duration": 30,
},
]
monkeypatch.setattr(ns.requests, "get", lambda *a, **k: FakeResponse(payload))
result = ns.fetch_treatments(hours=24)
smb_row = result[result["eventType"] == "Correction Bolus"].iloc[0]
basal_row = result[result["eventType"] == "Temp Basal"].iloc[0]
assert smb_row["type"] == "SMB"
assert basal_row["absolute"] == pytest.approx(1.2)
assert basal_row["duration"] == pytest.approx(30)
def pd_isna(value):