Feature #344
openCanteen: Patient charges Task 1 -- fix DietChargeAccrualJobs hospital-scoping bug
0%
Description
DietChargeAccrualService.PostAsync reads hospitalId from CurrentHospitalId (IHospitalContext, HttpContext-based), but DietChargeAccrualJob has no HttpContext -- every accrual the job writes gets HospitalId 0, and every Billing call inside PostAsync runs with hospitalId 0 too, so GetChargeByCodeAsync almost certainly finds nothing and PostAsync throws DietChargeNotConfigured, silently caught per-order, every cycle, forever. Found while tracing the Patient charges read path on 2026-10-12.
Fix: extract the jobs per-hospital loop body into IDietChargeAccrualService.AccrueActiveOrdersAsync(DateOnly serviceDate, ct), which reads CurrentHospitalId like every other method on the service (works correctly once the caller sets it). DietChargeAccrualJob pushes a synthetic HttpContext.Items["CurrentHospitalId"] per hospital before calling it, per iteration -- the exact pattern nuvita-ipd/BedDayChargeJob.cs already uses for the identical problem. One method then serves both the nightly job and the portals manual post-pending button (#next task) -- no duplicate loop.
Test fix: DietChargeAccrualJobTests.cs currently registers a fixed IHospitalContext stub (TestDoubles.HospitalContext), which is exactly what masks this bug -- rewrite its harness to use the real HospitalContext + IHttpContextAccessor (mirrors nuvita-ipd BedDayChargeJobTests), so the regression test actually fails before the fix and passes after.