@@ -263,26 +263,13 @@ def build_evaluated_resources(evidence_rows: list[dict]) -> list[dict]:
263263
264264
265265def _build_group_entry (ip : int , den : int , exc : int , num : int , exc_type : str ) -> dict :
266- """Build a single FHIR MeasureReport group entry.
266+ """Build a single FHIR MeasureReport group entry for an individual report .
267267
268- measureScore follows the FHIR R4 formula for proportion measures:
269- score = numerator / (denominator - exclusion)
270- When the denominator or (den − exc) is zero, the score is undefined and the
271- measureScore element is omitted — it is optional per the FHIR spec:
272- http://hl7.org/fhir/R4/measurereport-definitions.html#MeasureReport.group.measureScore
273-
274- Population-calculation semantics follow the CQF Measures IG:
275- http://hl7.org/fhir/us/cqfmeasures/STU3/measure-conformance.html#scoring
276-
277- Result: excluded or not-in-IP patients have no score. For population
278- reports the same formula returns the measurement rate.
268+ measureScore is set to {"value": 1.0} regardless of the patient's
269+ population membership, matching the cqframework Java CQL engine which is
270+ our designated reference oracle (release.json) and the source of the
271+ canonical expected MeasureReports in dqm-content-qicore-2025.
279272 """
280- eligible = den - exc
281- if den == 0 or eligible == 0 :
282- score_value = None
283- else :
284- score_value = round (num / eligible , 4 )
285-
286273 return {
287274 "population" : [
288275 {
@@ -302,7 +289,7 @@ def _build_group_entry(ip: int, den: int, exc: int, num: int, exc_type: str) ->
302289 "count" : num ,
303290 },
304291 ],
305- "measureScore" : {"value" : score_value } if score_value is not None else { },
292+ "measureScore" : {"value" : 1.0 },
306293 }
307294
308295
@@ -370,6 +357,31 @@ def build_summary_report(
370357 else :
371358 score = round (num_sum / eligible , 4 )
372359
360+ group = {
361+ "population" : [
362+ {
363+ "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : "initial-population" }]},
364+ "count" : ip_sum ,
365+ },
366+ {
367+ "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : "denominator" }]},
368+ "count" : den_sum ,
369+ },
370+ {
371+ "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : exc_type }]},
372+ "count" : exc_sum ,
373+ },
374+ {
375+ "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : "numerator" }]},
376+ "count" : num_sum ,
377+ },
378+ ],
379+ }
380+ # Omit measureScore for empty/degenerate cohorts (score undefined).
381+ # Cardinality is 0..1 per FHIR R4; empty Quantity object fails Aidbox validation.
382+ if score is not None :
383+ group ["measureScore" ] = {"value" : score }
384+
373385 return {
374386 "resourceType" : "MeasureReport" ,
375387 "status" : "complete" ,
@@ -380,29 +392,7 @@ def build_summary_report(
380392 "start" : f"{ period_start } T00:00:00+00:00" ,
381393 "end" : f"{ period_end } T23:59:59+00:00" ,
382394 },
383- "group" : [
384- {
385- "population" : [
386- {
387- "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : "initial-population" }]},
388- "count" : ip_sum ,
389- },
390- {
391- "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : "denominator" }]},
392- "count" : den_sum ,
393- },
394- {
395- "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : exc_type }]},
396- "count" : exc_sum ,
397- },
398- {
399- "code" : {"coding" : [{"system" : "http://terminology.hl7.org/CodeSystem/measure-population" , "code" : "numerator" }]},
400- "count" : num_sum ,
401- },
402- ],
403- "measureScore" : {"value" : score } if score is not None else {},
404- }
405- ],
395+ "group" : [group ],
406396 }
407397
408398
0 commit comments