Minor CQM/AMC report engine bug fix
[openemr.git] / library / classes / rulesets / ruleSet.class.php
blob586db172a85367da2a4220d154f6b8f9a038e9e9
1 <?php
2 // Copyright (C) 2011 Brady Miller <brady@sparmy.com>
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
9 require_once(dirname(__FILE__) . "/../../clinical_rules.php");
10 require_once(dirname(__FILE__) . "/../../forms.inc");
11 require_once(dirname(__FILE__) . "/../../patient.inc");
12 require_once( 'codes.php' );
14 class ruleSet
16 // Main input variables:
17 // $rule - array containing rule information
18 // $dateTarget - target date
19 // $patientData - array of pertinent patients
21 // These variables hold the results data elements, note they are all
22 // arrays that need to all contain the same number of elements.
23 // $group_label - array of titles for each group (usually only one group) TODO: get this working for when there are multiple groups
24 // $total_patients - array of total patients for each group
25 // $pass_filter - array of patients that pass filters for each group
26 // $exclude_filter - array of patients that are excluded for each group
27 // $pass_target - array of patients that pass target for each group
28 // $percentage - array of percentage of patients that pass target for each group
30 // Main processed results variable:
31 // $results - holds the result array used in reports
33 private $codes; // code lookup class
35 // Construction function
36 public function __construct( $rule, $dateTarget, $patientData ) {
37 $this->codes = new Code_Lookup();
38 $this->rule = $rule;
39 $this->dateTarget = $dateTarget;
40 $this->patientData = $patientData;
41 $this->process_rule();
42 $this->process_results();
45 // Function to return the results
46 public function return_results() {
47 return $this->results;
50 // Straightforward function to call the correct rule functions
51 private function process_rule() {
52 $rule_id=$this->rule['id'];
53 // process specific rule
54 switch ($rule_id) {
55 case "rule_htn_bp_measure_cqm":
56 // Hypertension: Blood Pressure Measurement
57 // NQF 0013
58 $this->rule_htn_bp_measure_cqm();
59 break;
60 case "rule_tob_use_assess_cqm":
61 // Tobacco Use Assessment
62 // NQF 0028a
63 $this->rule_tob_use_assess_cqm();
64 break;
65 case "rule_tob_cess_inter_cqm":
66 // Tobacco Cessation Intervention
67 // NQF 0028b
68 $this->rule_tob_cess_inter_cqm();
69 break;
70 case "rule_adult_wt_screen_fu_cqm":
71 // Adult Weight Screening and Follow-Up
72 // NQF 0421
73 // PQRI 128
74 $this->rule_adult_wt_screen_fu_cqm();
75 break;
76 case "rule_wt_assess_couns_child_cqm":
77 // Weight Assessment and Counseling for Children and Adolescents
78 // NQF 0024
79 $this->rule_wt_assess_couns_child_cqm();
80 break;
81 case "rule_influenza_ge_50_cqm":
82 // Influenza Immunization for Patients >= 50 Years Old
83 // NQF 0041
84 // PQRI 110
85 $this->rule_influenza_ge_50_cqm();
86 break;
87 case "rule_child_immun_stat_cqm":
88 // Childhood immunization Status
89 // NQF 0038
90 $this->rule_child_immun_stat_cqm();
91 break;
92 case "rule_pneumovacc_ge_65_cqm":
93 // Pneumonia Vaccination Status for Older Adults
94 // NQF 0043
95 // PQRI 111
96 $this->rule_pneumovacc_ge_65_cqm();
97 break;
98 case "rule_dm_eye_cqm":
99 // Diabetes: Eye Exam
100 // NQF 0055
101 // PQRI 117
102 $this->rule_dm_eye_cqm();
103 break;
104 case "rule_dm_foot_cqm":
105 // Diabetes: Foot Exam
106 // NQF 0056
107 // PQRI 163
108 $this->rule_dm_foot_cqm();
109 break;
110 case "rule_dm_bp_control_cqm":
111 // Diabetes: Blood Pressure Management
112 // NQF 0061
113 // PQRI 3
114 $this->rule_dm_bp_control_cqm();
115 break;
116 case "rule_dm_a1c_cqm":
117 // Diabetes: HbA1c Poor Control
118 // NQF 0059
119 // PQRI 1
120 $this->rule_dm_a1c_cqm();
121 break;
122 case "rule_dm_ldl_cqm":
123 // Diabetes: LDL Management & Control
124 // NQF 0064
125 // PQRI 2
126 $this->rule_dm_ldl_cqm();
127 break;
128 case "problem_list_amc":
129 // Maintain an up-to-date problem list of current and active diagnoses.
130 // 170.302(c)
131 $this->problem_list_amc();
132 break;
133 case "med_list_amc":
134 // Maintain active medication list.
135 // 170.302(d)
136 $this->med_list_amc();
137 break;
138 case "med_allergy_list_amc":
139 // Maintain active medication allergy list.
140 // 170.302(e)
141 $this->med_allergy_list_amc();
142 break;
143 case "record_vitals_amc":
144 // Record and chart changes in vital signs.
145 // 170.302(f)
146 $this->record_vitals_amc();
147 break;
148 case "record_smoke_amc":
149 // Record smoking status for patients 13 years old or older.
150 // 170.302(g)
151 $this->record_smoke_amc();
152 break;
153 case "lab_result_amc":
154 // Incorporate clinical lab-test results into certified EHR technology as structured data.
155 // 170.302(h)
156 $this->lab_result_amc();
157 break;
158 case "med_reconc_amc":
159 // The EP, eligible hospital or CAH who receives a patient from another setting of care or provider of care or believes an encounter is relevant should perform medication reconciliation.
160 // 170.302(j)
161 $this->med_reconc_amc();
162 break;
163 case "patient_edu_amc":
164 // Use certified EHR technology to identify patient-specific education resources and provide those resources to the patient if appropriate.
165 // 170.302(m)
166 $this->patient_edu_amc();
167 break;
168 case "cpoe_med_amc":
169 // Use CPOE for medication orders directly entered by any licensed healthcare professional who can enter orders into the medical record per state, local and professional guidelines.
170 // 170.304(a)
171 $this->cpoe_med_amc();
172 break;
173 case "e_prescribe_amc":
174 // Generate and transmit permissible prescriptions electronically.
175 // 170.304(b)
176 $this->e_prescribe_amc();
177 break;
178 case "record_dem_amc":
179 // Record demographics.
180 // 170.304(c)
181 $this->record_dem_amc();
182 break;
183 case "send_reminder_amc":
184 // Send reminders to patients per patient preference for preventive/follow up care.
185 // 170.304(d)
186 $this->send_reminder_amc();
187 break;
188 case "provide_rec_pat_amc":
189 // Provide patients with an electronic copy of their health information (including diagnostic test results, problem list, medication lists, medication allergies), upon request.
190 // 170.304(f)
191 $this->provide_rec_pat_amc();
192 break;
193 case "timely_access_amc":
194 // Provide patients with timely electronic access to their health information (including lab results, problem list, medication lists, medication allergies) within four business days of the information being available to the EP.
195 // 170.304(g)
196 $this->timely_access_amc();
197 break;
198 case "provide_sum_pat_amc":
199 // Provide clinical summaries for patients for each office visit.
200 // 170.304(h)
201 $this->provide_sum_pat_amc();
202 break;
203 case "send_sum_amc":
204 // The EP, eligible hospital or CAH who transitions their patient to another setting of care or provider of care or refers their patient to another provider of care should provide summary of care record for each transition of care or referral.
205 // 170.304(i)
206 $this->send_sum_amc();
207 break;
208 default:
209 break;
213 // Function to process the results
214 private function process_results() {
215 // if applicable, need to iterate through each group of data
216 for($i=0;$i<count($this->group_label);$i++) {
217 $newRow=array( 'is_main'=>TRUE, // TO DO: figure out way to do this when multiple groups.
218 'total_patients'=>($this->total_patients[$i]),
219 'excluded'=>($this->exclude_filter[$i]),
220 'pass_filter'=>($this->pass_filter[$i]),
221 'pass_target'=>($this->pass_target[$i]),
222 'percentage'=>($this->percentage[$i]) );
223 $newRow=array_merge($newRow,$this->rule);
224 $this->results[] = $newRow;
228 // Function to set a results element
229 // Param:
230 // $group_lab - Label of element
231 // $total_pat - Total number of patients considered
232 // $pass_filt - Number of patients that pass filter
233 // $exclude_filt - Number of patients that are excluded
234 // $pass_targ - Number of patients that pass target
235 // $perc - Calculated percentage
236 private function set_result($group_lab,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc) {
237 $this->group_label[] = $group_lab;
238 $this->total_patients[] = $total_pat;
239 $this->pass_filter[] = $pass_filt;
240 $this->exclude_filter[] = $exclude_filt;
241 $this->pass_target[] = $pass_targ;
242 $this->percentage[] = $perc;
245 // Function to see if encounters exist
246 // Parameters:
247 // $patient_id - patient id
248 // $encounter_label - encounter id from list_options
249 // $begin_date - begin of date to search (if blank, then will not limit to a begin date)
250 // $end_date - end of date to search
251 // $number - number of encounters needed
252 private function exist_encounter($patient_id,$encounter_label,$begin_date='',$end_date,$number) {
253 // use the getEncounters() function from library/forms.inc
254 $encounters = getEncounters($patient_id,$begin_date,$end_date,$encounter_label);
255 (empty($encounters)) ? $totalNumberAppt = 0 : $totalNumberAppt = count($encounters);
256 if ( $totalNumberAppt < $number ) {
257 return false;
259 else {
260 return true;
265 // Function to get patient dob
266 // Parameter:
267 // $patient_id - patient id
268 // Return: DOB (string)
269 private function get_DOB($patient_id) {
270 $dob = getPatientData($patient_id, "DATE_FORMAT(DOB,'%Y %m %d') as TS_DOB");
271 return $dob['TS_DOB'];
274 // Function to get patient id from the patient array
275 // Paramter:
276 // $array_patient - array holding patient id in the 'id' column
277 private function get_patient_id($array_patient) {
278 return $array_patient['pid'];
281 // Hypertension: Blood Pressure Measurement (NQF 0013)
283 // (note it only needs to process one group)
284 // (Measurement for 12 months from 1/1/20?? to 12/31/20??)
286 // 1) Calculate number that pass the filter
287 // -Age greater than 18 (before the beginning of the measurement period).
288 // -Diagnosis of HTN (before or during the measurement period)
289 // -At least two encounters (of a specified type and within the measurement
290 // period)
291 // 2) Deal with exclusions:
292 // -No exclusions
293 // 3) Then from patients that pass the filter (and are not excluded), calculate
294 // the number that have the target.
295 // -Measurement of a SBP and a DBP within the measurment period (needs
296 // to be on same day as specified encounter type)
297 // 4) Then calculate the percentage, which is number that meet the target
298 // divided by the number of patients that pass the filter (and are not excluded).
300 private function rule_htn_bp_measure_cqm() {
301 $rule_id=$this->rule['id'];
302 $dateTarget = $this->dateTarget;
303 $patientData = $this->patientData;
305 // Calculate measurement period
306 $tempDateArray = explode("-",$dateTarget);
307 $tempYear = $tempDateArray[0];
308 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
309 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
311 // Collect results
312 $total_pat = 0;
313 $pass_filt = 0;
314 $exclude_filt = 0;
315 $pass_targ = 0;
316 $perc = 0;
317 foreach ( $patientData as $rowPatient ) {
318 // increment total patients counter
319 $total_pat++;
321 // get patient id
322 $patient_id = $this->get_patient_id($rowPatient);
324 // filter for age greater than 18
325 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
326 if (convertDobtoAgeYearDecimal( $this->get_DOB($patient_id), $begin_measurement ) < 18) continue;
328 // filter for diagnosis of HTN
329 // utlize the exist_lists_item() function from library/clinical_rules.php
330 if (!( (exist_lists_item($patient_id,'medical_problem','CUSTOM::HTN',$end_measurement)) ||
331 (exist_lists_item($patient_id,'medical_problem','ICD9::401.0',$end_measurement)) ||
332 (exist_lists_item($patient_id,'medical_problem','ICD9::401.1',$end_measurement)) ||
333 (exist_lists_item($patient_id,'medical_problem','ICD9::401.9',$end_measurement)) ||
334 (exist_lists_item($patient_id,'medical_problem','ICD9::402.00',$end_measurement)) ||
335 (exist_lists_item($patient_id,'medical_problem','ICD9::402.01',$end_measurement)) ||
336 (exist_lists_item($patient_id,'medical_problem','ICD9::402.10',$end_measurement)) ||
337 (exist_lists_item($patient_id,'medical_problem','ICD9::402.11',$end_measurement)) ||
338 (exist_lists_item($patient_id,'medical_problem','ICD9::402.90',$end_measurement)) ||
339 (exist_lists_item($patient_id,'medical_problem','ICD9::402.91',$end_measurement)) ||
340 (exist_lists_item($patient_id,'medical_problem','ICD9::403.00',$end_measurement)) ||
341 (exist_lists_item($patient_id,'medical_problem','ICD9::403.01',$end_measurement)) ||
342 (exist_lists_item($patient_id,'medical_problem','ICD9::403.10',$end_measurement)) ||
343 (exist_lists_item($patient_id,'medical_problem','ICD9::403.11',$end_measurement)) ||
344 (exist_lists_item($patient_id,'medical_problem','ICD9::403.90',$end_measurement)) ||
345 (exist_lists_item($patient_id,'medical_problem','ICD9::403.91',$end_measurement)) ||
346 (exist_lists_item($patient_id,'medical_problem','ICD9::404.00',$end_measurement)) ||
347 (exist_lists_item($patient_id,'medical_problem','ICD9::404.01',$end_measurement)) ||
348 (exist_lists_item($patient_id,'medical_problem','ICD9::404.02',$end_measurement)) ||
349 (exist_lists_item($patient_id,'medical_problem','ICD9::404.03',$end_measurement)) ||
350 (exist_lists_item($patient_id,'medical_problem','ICD9::404.10',$end_measurement)) ||
351 (exist_lists_item($patient_id,'medical_problem','ICD9::404.11',$end_measurement)) ||
352 (exist_lists_item($patient_id,'medical_problem','ICD9::404.12',$end_measurement)) ||
353 (exist_lists_item($patient_id,'medical_problem','ICD9::404.13',$end_measurement)) ||
354 (exist_lists_item($patient_id,'medical_problem','ICD9::404.90',$end_measurement)) ||
355 (exist_lists_item($patient_id,'medical_problem','ICD9::404.91',$end_measurement)) ||
356 (exist_lists_item($patient_id,'medical_problem','ICD9::404.92',$end_measurement)) ||
357 (exist_lists_item($patient_id,'medical_problem','ICD9::404.93',$end_measurement)) )) {
358 continue;
361 // filter for 2 specified encounters
362 // make a function for this and wrap in the encounter titles
363 if (!( ($this->exist_encounter($patient_id,'enc_outpatient',$begin_measurement,$end_measurement,2)) ||
364 ($this->exist_encounter($patient_id,'enc_nurs_fac',$begin_measurement,$end_measurement,2)) )) {
366 continue;
369 // Filter has been passed
370 $pass_filt++;
372 // See if BP has been done within the measurement period (on a day of a specified encounter)
373 $query = "SELECT form_vitals.bps, form_vitals.bpd " .
374 "FROM `form_vitals` " .
375 "LEFT JOIN `form_encounter` " .
376 "ON ( DATE(form_vitals.date) = DATE(form_encounter.date)) " .
377 "LEFT JOIN `enc_category_map` " .
378 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
379 "WHERE form_vitals.pid = ?" .
380 "AND form_vitals.bps IS NOT NULL " .
381 "AND form_vitals.bpd IS NOT NULL " .
382 "AND form_vitals.date >= ? " .
383 "AND form_vitals.date <= ? " .
384 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' OR enc_category_map.rule_enc_id = 'enc_nurs_fac' )";
385 $res = sqlStatement($query, array($patient_id,$begin_measurement,$end_measurement) );
386 $number = sqlNumRows($res);
387 if ($number < 1) continue;
389 error_log("passed target",0);
391 // Target has been passed
392 $pass_targ++;
395 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
396 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
398 // Set results
399 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
402 // Tobacco Use Assessment (NQF 0028a)
403 private function rule_tob_use_assess_cqm() {
404 $rule_id=$this->rule['id'];
405 $dateTarget = $this->dateTarget;
406 $patientData =$this->patientData;
408 // Calculate measurement period
409 $tempDateArray = explode("-",$dateTarget);
410 $tempYear = $tempDateArray[0];
411 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
412 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
414 // Collect results
415 $total_pat = 0;
416 $pass_filt = 0;
417 $exclude_filt = 0;
418 $pass_targ = 0;
419 $perc = 0;
420 foreach ( $patientData as $rowPatient ) {
421 $patient_id = $this->get_patient_id($rowPatient);
422 // increment total patients counter
423 $total_pat++;
425 // filter for age greater than 18
426 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
427 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
428 if ( $age < 18) continue;
430 // filter for 2 specified encounters of some types, and 1 for others
431 // make a function for this and wrap in the encounter titles
432 if (!( ($this->exist_encounter($patient_id,'enc_off_vis',$begin_measurement,$end_measurement,2)) ||
433 ($this->exist_encounter($patient_id,'enc_hea_and_beh',$begin_measurement,$end_measurement,2)) ||
434 ($this->exist_encounter($patient_id,'enc_occ_ther',$begin_measurement,$end_measurement,2)) ||
435 ($this->exist_encounter($patient_id,'enc_psych_and_psych',$begin_measurement,$end_measurement,2)) ||
436 ($this->exist_encounter($patient_id,'enc_pre_med_ser_18_older',$begin_measurement,$end_measurement,1)) ||
437 ($this->exist_encounter($patient_id,'enc_pre_ind_counsel',$begin_measurement,$end_measurement,1)) ||
438 ($this->exist_encounter($patient_id,'enc_pre_med_group_counsel',$begin_measurement,$end_measurement,1)) ||
439 ($this->exist_encounter($patient_id,'enc_pre_med_other_serv',$begin_measurement,$end_measurement,1)) )) {
440 continue;
443 // Filter has been passed
444 $pass_filt++;
446 // See if user has been a tobacco user before or sumultaneosly to the encounter within two years (24 months)
447 $begin_24_months_before_time = strtotime( '-24 month' , strtotime ( $begin_measurement ) );
448 $begin_24_months_before = date( 'Y-m-d 00:00:00' , $begin_24_months_before_time );
449 $tobaccoHistory = getHistoryData( $patient_id, "tobacco", $begin_24_months_before, $end_measurement );
450 if ( !isset( $tobaccoHistory['tobacco'] ) ) {
451 continue;
454 // Target has been passed
455 $pass_targ++;
458 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
459 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
461 // Set results
462 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
465 // TODO
466 // Tobacco Cessation Intervention (NQF 0028b)
467 private function rule_tob_cess_inter_cqm() {
471 // Adult Weight Screening and Follow-Up (NQF 0421) (PQRI 128)
472 private function rule_adult_wt_screen_fu_cqm() {
473 $rule_id=$this->rule['id'];
474 $dateTarget = $this->dateTarget;
475 $patientData =$this->patientData;
477 // Calculate measurement period
478 $tempDateArray = explode("-",$dateTarget);
479 $tempYear = $tempDateArray[0];
480 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
481 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
483 // Collect results
484 $total_pat = 0;
485 $pass_filt = 0;
486 $exclude_filt = 0;
487 $pass_targ = 0;
488 $perc = 0;
489 foreach ( $patientData as $rowPatient ) {
490 $patient_id = $this->get_patient_id( $rowPatient );
491 // increment total patients counter
492 $total_pat++;
494 // filter for age greater than 65
495 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
496 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
497 if ( $age < 65 ) continue;
499 // filter for 1 specified encounters
500 // make a function for this and wrap in the encounter titles
501 // doesn't say anything about encounter date, so check for any encounter
502 if (!( ( $this->exist_encounter($patient_id,'enc_outpatient',$begin_measurement,$end_measurement,1)) )) {
503 continue;
506 $pass_filt++;
508 // Flow of control loop
509 $bContinue = true;
510 do {
511 // See if BMI has been recorded between >=22kg/m2 and <30kg/m2 6 months before, or simultanious to the encounter
512 $query = "SELECT form_vitals.BMI " .
513 "FROM `form_vitals` " .
514 "LEFT JOIN `form_encounter` " .
515 "ON ( form_vitals.pid = form_encounter.pid ) " .
516 "LEFT JOIN `enc_category_map` " .
517 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
518 "WHERE form_vitals.BMI IS NOT NULL " .
519 "AND form_vitals.BMI IS NOT NULL " .
520 "AND form_vitals.pid = ? AND form_vitals.BMI >= 22 AND form_vitals.BMI < 30 " .
521 "AND DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) " .
522 "AND DATE( form_vitals.date ) <= DATE( form_encounter.date ) " .
523 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
524 $res = sqlStatement( $query, array( $patient_id ) );
525 $number = sqlNumRows($res);
526 if ( $number >= 1 ) {
527 $bContinue = false;
528 break;
531 // See if BMI has been recorded >=30kg/m2 6 months before, or simultanious to the encounter
532 // TODO AND ÒCare goal: follow-up plan BMI managementÓ OR ÒCommunication provider to provider: dietary consultation orderÓ
533 $query = "SELECT form_vitals.BMI " .
534 "FROM `form_vitals` " .
535 "LEFT JOIN `form_encounter` " .
536 "ON ( form_vitals.pid = form_encounter.pid ) " .
537 "LEFT JOIN `enc_category_map` " .
538 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
539 "WHERE form_vitals.BMI IS NOT NULL " .
540 "AND form_vitals.BMI IS NOT NULL " .
541 "AND form_vitals.pid = ? AND form_vitals.BMI >= 30 " .
542 "AND ( DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) ) " .
543 "AND ( DATE( form_vitals.date ) <= DATE( form_encounter.date ) ) " .
544 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
545 $res = sqlStatement( $query, array( $patient_id ) );
546 $number = sqlNumRows($res);
547 if ( $number >= 1 ) {
548 $bContinue = false;
549 break;
552 // See if BMI has been recorded <22kg/m2 6 months before, or simultanious to the encounter
553 // TODO AND ÒCare goal: follow-up plan BMI managementÓ OR ÒCommunication provider to provider: dietary consultation orderÓ
554 $query = "SELECT form_vitals.BMI " .
555 "FROM `form_vitals` " .
556 "LEFT JOIN `form_encounter` " .
557 "ON ( form_vitals.pid = form_encounter.pid ) " .
558 "LEFT JOIN `enc_category_map` " .
559 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
560 "WHERE form_vitals.BMI IS NOT NULL " .
561 "AND form_vitals.BMI IS NOT NULL " .
562 "AND form_vitals.pid = ? AND form_vitals.BMI < 22 " .
563 "AND ( DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) ) " .
564 "AND ( DATE( form_vitals.date ) <= DATE( form_encounter.date ) ) " .
565 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
566 $res = sqlStatement( $query, array( $patient_id ) );
567 $number = sqlNumRows($res);
568 if ( $number >= 1 ) {
569 $bContinue = false;
570 break;
572 } while( false );
574 if ( $bContinue ) {
575 continue;
578 // TODO Exclusions
579 // OR:ÒPatient characteristic: Terminal illnessÓ<=6 months before or simultaneously to ÒEncounter: encounter outpatientÓ;
580 // OR:ÒPhysical exam not done: patient reasonÓ;
581 // OR:ÒPhysical exam not done: medical reasonÓ;
582 // OR:ÒPhysical rationale physical exam not done: system reasonÓ;
583 if ( $this->codes->check_for_pregnancy( $patient_id, $end_measurement ) ) {
584 $exclude_filt++;
587 $pass_targ++;
590 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
591 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
593 // Set results
594 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
596 // *** Population criteria 2 ***
597 // reset counters
598 $total_pat = 0;
599 $pass_filt = 0;
600 $exclude_filt = 0;
601 $pass_targ = 0;
602 $perc = 0;
603 foreach ( $patientData as $rowPatient ) {
604 $patient_id = $this->get_patient_id( $rowPatient );
605 // increment total patients counter
606 $total_pat++;
608 // filter for >= 18 and <= 64
609 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
610 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
611 if ( $age < 18 || $age > 65 ) continue;
613 // Denominator=
614 // AND: ÒAll patients in the initial patient populationÓ;
615 // AND: >=1 count(s) of ÒEncounter: encounter outpatientÓ;
616 if (!( ( $this->exist_encounter($patient_id,'enc_outpatient',$begin_measurement,$end_measurement,1)) )) {
617 continue;
620 $pass_filt++;
622 // Flow of control loop
623 $bContinue = true;
624 do {
625 // See if BMI has been recorded between >=18.5kg/m2 and <25kg/m2 6 months before, or simultanious to the encounter
626 $query = "SELECT form_vitals.BMI " .
627 "FROM `form_vitals` " .
628 "LEFT JOIN `form_encounter` " .
629 "ON ( form_vitals.pid = form_encounter.pid ) " .
630 "LEFT JOIN `enc_category_map` " .
631 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
632 "WHERE form_vitals.BMI IS NOT NULL " .
633 "AND form_vitals.BMI IS NOT NULL " .
634 "AND form_vitals.pid = ? AND form_vitals.BMI >= 18.5 AND form_vitals.BMI < 25 " .
635 "AND DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) " .
636 "AND DATE( form_vitals.date ) <= DATE( form_encounter.date ) " .
637 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
638 $res = sqlStatement( $query, array( $patient_id ) );
639 $number = sqlNumRows($res);
640 if ( $number >= 1 ) {
641 $bContinue = false;
642 break;
645 // See if BMI has been recorded >=25kg/m2 6 months before, or simultanious to the encounter
646 // TODO AND ÒCare goal: follow-up plan BMI managementÓ OR ÒCommunication provider to provider: dietary consultation orderÓ
647 $query = "SELECT form_vitals.BMI " .
648 "FROM `form_vitals` " .
649 "LEFT JOIN `form_encounter` " .
650 "ON ( form_vitals.pid = form_encounter.pid ) " .
651 "LEFT JOIN `enc_category_map` " .
652 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
653 "WHERE form_vitals.BMI IS NOT NULL " .
654 "AND form_vitals.BMI IS NOT NULL " .
655 "AND form_vitals.pid = ? AND form_vitals.BMI >= 25 " .
656 "AND ( DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) ) " .
657 "AND ( DATE( form_vitals.date ) <= DATE( form_encounter.date ) ) " .
658 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
659 $res = sqlStatement( $query, array( $patient_id ) );
660 $number = sqlNumRows($res);
661 if ( $number >= 1 ) {
662 $bContinue = false;
663 break;
666 } while( false );
668 if ( $bContinue ) {
669 continue;
672 // TODO Exclusions
673 // OR:ÒPatient characteristic: Terminal illnessÓ<=6 months before or simultaneously to ÒEncounter: encounter outpatientÓ;
674 // OR:ÒPhysical exam not done: patient reasonÓ;
675 // OR:ÒPhysical exam not done: medical reasonÓ;
676 // OR:ÒPhysical rationale physical exam not done: system reasonÓ;
677 if ( $this->codes->check_for_pregnancy( $patient_id, $end_measurement ) ) {
678 $exclude_filt++;
681 $pass_targ++;
684 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
685 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
687 // Set results
688 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
692 // Weight Assessment and Counseling for Children and Adolescents (NQF 0024)
693 private function rule_wt_assess_couns_child_cqm() {
694 $rule_id=$this->rule['id'];
695 $dateTarget = $this->dateTarget;
696 $patientData =$this->patientData;
698 // Calculate measurement period
699 $tempDateArray = explode("-",$dateTarget);
700 $tempYear = $tempDateArray[0];
701 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
702 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
704 // *** Patient Criteria 1 ***
705 // Collect results
706 $total_pat = 0;
707 $pass_filt = 0;
708 $exclude_filt = 0;
709 $pass_targ = array( 1 => 0, 2 => 0, 3 => 0 );
710 $perc = 0;
711 foreach ( $patientData as $rowPatient ) {
712 $patient_id = $this->get_patient_id( $rowPatient );
713 // increment total patients counter
714 $total_pat++;
716 // filter for Patient characteristic: birth dateÓ (age) >=2 and <=16 years
717 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
718 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
719 if ( $age < 2 || $age > 17 ) continue;
721 // filter for 1 specified encounters
722 // make a function for this and wrap in the encounter titles
723 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ||
724 ( $this->codes->check_for_pregnancy( $patient_id, $end_measurement ) ||
725 ( $this->exist_encounter($patient_id,'enc_pregnancy',$begin_measurement,$end_measurement,1) ) ) ) {
726 continue;
729 $pass_filt++;
731 // numerator 1: Physical exam finding: BMI percentile
732 if ( ( (exist_lists_item($patient_id,'medical_problem','CUSTOM::BMI',$end_measurement)) || // TODO where should this come from?
733 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.5',$end_measurement)) ||
734 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.51',$end_measurement)) ||
735 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.52',$end_measurement)) ||
736 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.53',$end_measurement)) ||
737 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.54',$end_measurement)) )) {
738 $pass_targ[1]++;
741 // numerator 2: Communication to patient: counseling for nutrition
742 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.3',$end_measurement ) ) { // TODO where should this come from?
743 $pass_targ[2]++;
746 // numerator 3: Communication to patient: counseling for physical activity
747 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.41',$end_measurement ) ) { // TODO where should this come from?
748 $pass_targ[3]++;
752 foreach ( $pass_targ as $pass_targ_count ) {
753 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
754 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ_count);
755 // Set results
756 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ_count,$perc);
759 // *** Patient Criteria 2 ***
760 // reset counters
761 $total_pat = 0;
762 $pass_filt = 0;
763 $exclude_filt = 0;
764 $pass_targ = array( 1 => 0, 2 => 0, 3 => 0 );
765 $perc = 0;
766 foreach ( $patientData as $rowPatient ) {
767 $patient_id = $this->get_patient_id( $rowPatient );
768 // increment total patients counter
769 $total_pat++;
771 // filter for Patient characteristic: birth dateÓ (age) >=2 and <=16 years
772 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
773 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
774 if ( $age < 2 || $age > 11 ) continue;
776 // filter for 1 specified encounters
777 // make a function for this and wrap in the encounter titles
778 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ||
779 ( $this->codes->check_for_pregnancy( $patient_id, $end_measurement ) ||
780 ( $this->exist_encounter($patient_id,'enc_pregnancy',$begin_measurement,$end_measurement,1) ) ) ) {
781 continue;
784 $pass_filt++;
786 // numerator 1: Physical exam finding: BMI percentile
787 if ( ( (exist_lists_item($patient_id,'medical_problem','CUSTOM::BMI',$end_measurement)) ||
788 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.5',$end_measurement)) ||
789 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.51',$end_measurement)) ||
790 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.52',$end_measurement)) ||
791 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.53',$end_measurement)) ||
792 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.54',$end_measurement)) )) {
793 $pass_targ[1]++;
796 // numerator 2: Communication to patient: counseling for nutrition
797 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.3',$end_measurement ) ) {
798 $pass_targ[2]++;
801 // numerator 3: Communication to patient: counseling for physical activity
802 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.41',$end_measurement ) ) {
803 $pass_targ[3]++;
807 foreach ( $pass_targ as $pass_targ_count ) {
808 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
809 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ_count);
810 // Set results
811 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ_count,$perc);
814 // *** Patient Criteria 3 ***
815 // reset counters
816 $total_pat = 0;
817 $pass_filt = 0;
818 $exclude_filt = 0;
819 $pass_targ = array( 1 => 0, 2 => 0, 3 => 0 );
820 $perc = 0;
821 foreach ( $patientData as $rowPatient ) {
822 $patient_id = $this->get_patient_id( $rowPatient );
823 // increment total patients counter
824 $total_pat++;
826 // filter for Patient characteristic: birth dateÓ (age) >=2 and <=16 years
827 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
828 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
829 if ( $age < 12 || $age > 17 ) continue;
831 // filter for 1 specified encounters
832 // make a function for this and wrap in the encounter titles
833 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ||
834 ( $this->codes->check_for_pregnancy( $patient_id, $end_measurement ) ||
835 ( $this->exist_encounter($patient_id,'enc_pregnancy',$begin_measurement,$end_measurement,1) ) ) ) {
836 continue;
839 $pass_filt++;
841 // numerator 1: Physical exam finding: BMI percentile
842 if ( ( (exist_lists_item($patient_id,'medical_problem','CUSTOM::BMI',$end_measurement)) ||
843 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.5',$end_measurement)) ||
844 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.51',$end_measurement)) ||
845 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.52',$end_measurement)) ||
846 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.53',$end_measurement)) ||
847 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.54',$end_measurement)) )) {
848 $pass_targ[1]++;
851 // numerator 2: Communication to patient: counseling for nutrition
852 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.3',$end_measurement ) ) {
853 $pass_targ[2]++;
856 // numerator 3: Communication to patient: counseling for physical activity
857 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.41',$end_measurement ) ) {
858 $pass_targ[3]++;
862 foreach ( $pass_targ as $pass_targ_count ) {
863 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
864 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ_count);
865 // Set results
866 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ_count,$perc);
871 // TODO
872 // Influenza Immunization for Patients >= 50 Years Old (NQF 0041) (PQRI 110)
873 private function rule_influenza_ge_50_cqm() {
877 // TODO
878 // Childhood immunization Status (NQF 0038)
879 private function rule_child_immun_stat_cqm() {
880 $rule_id=$this->rule['id'];
881 $dateTarget = $this->dateTarget;
882 $patientData =$this->patientData;
884 // Calculate measurement period
885 $tempDateArray = explode("-",$dateTarget);
886 $tempYear = $tempDateArray[0];
887 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
888 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
890 // Collect results
891 $total_pat = 0;
892 $pass_filt = 0;
893 $exclude_filt = 0;
894 $pass_targ = array( 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0, 10 => 0, 11 => 0, 12 => 0 );
895 $perc = 0;
896 foreach ( $patientData as $rowPatient ) {
897 $patient_id = $this->get_patient_id( $rowPatient );
898 // increment total patients counter
899 $total_pat++;
901 // filter for ÒPatient characteristic: birth dateÓ (age) >=1 year and <2 years
902 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
903 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
904 if ( $age >= 2 || $age < 1 ) continue;
906 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ) {
907 continue;
910 $pass_filt++;
912 // Numerator 1
913 $query = "SELECT immunizations.administered_date, immunizations.patient_id, immunizations.immunization_id, list_options.title, patient_data.pid, patient_data.DOB " .
914 "FROM immunizations " .
915 "LEFT JOIN list_options " .
916 "ON immunizations.immunization_id = list_options.option_id AND list_id = immunizations" .
917 "LEFT JOIN patient_data " .
918 "ON immunizations.patient_id = patient_data.pid " .
919 "WHERE immunizations.patient_id = ? " .
920 "AND ( list_options.option_id = 1 ". // Check for DTap list option ids (1-5)
921 "OR list_options.option_id = 2 ".
922 "OR list_options.option_id = 3 ".
923 "OR list_options.option_id = 4 ".
924 "OR list_options.option_id = 5 ) " .
925 "AND DATE( immunizations.administered_date ) >= DATE_ADD( patient_data.DOB, INTERVAL 42 DAY ) " .
926 "AND DATE( immunizations.administered_date ) < DATE_ADD( patient_data.DOB, INTERVAL 2 YEAR ) ";
928 $result = sqlStatement( $query, array( $patient_id ) );
929 if ( count( $result ) >= 4 &&
930 !( $this->codes->check_for_dtap_allergy( $patient_id, $end_measurement ) ) &&
931 !( exist_lists_item( $patient_id, 'medical_problem', 'ICD9::323.51', $end_measurement ) ) &&
932 !( $this->codes->check_for_progressive_neurological_disorder( $patient_id, $end_measurement ) ) ) {
933 $pass_targ[1]++;
936 // Numerator 2
937 $query = "SELECT immunizations.administered_date, immunizations.patient_id, immunizations.immunization_id, list_options.title, patient_data.pid, patient_data.DOB " .
938 "FROM immunizations " .
939 "LEFT JOIN list_options " .
940 "ON immunizations.immunization_id = list_options.option_id AND list_id = immunizations" .
941 "LEFT JOIN patient_data " .
942 "ON immunizations.patient_id = patient_data.pid " .
943 "WHERE immunizations.patient_id = ? " .
944 "AND ( list_options.option_id = 13 ". // Check for IPV list option ids (11-14)
945 "OR list_options.option_id = 11 ".
946 "OR list_options.option_id = 12 ".
947 "OR list_options.option_id = 14 ".
948 "AND DATE( immunizations.administered_date ) >= DATE_ADD( patient_data.DOB, INTERVAL 42 DAY ) " .
949 "AND DATE( immunizations.administered_date ) < DATE_ADD( patient_data.DOB, INTERVAL 2 YEAR ) ";
951 $result = sqlStatement( $query, array( $patient_id ) );
952 if ( count( $result ) >= 3 &&
953 !( $this->codes->check_for_ipv_allergy( $patient_id, $end_measurement ) ) &&
954 !( $this->codes->check_for_neomycin_allergy( $patient_id, $end_measurement ) ) &&
955 !( $this->codes->check_for_streptomycin_allergy( $patient_id, $end_measurement ) ) &&
956 !( $this->codes->check_for_polymyxin_allergy( $patient_id, $end_measurement ) ) ) {
957 $pass_targ[2]++;
961 // Numerator 3
963 // Numerator 4
964 $query = "SELECT immunizations.administered_date, immunizations.patient_id, immunizations.immunization_id, list_options.title, patient_data.pid, patient_data.DOB " .
965 "FROM immunizations " .
966 "LEFT JOIN list_options " .
967 "ON immunizations.immunization_id = list_options.option_id AND list_id = immunizations" .
968 "LEFT JOIN patient_data " .
969 "ON immunizations.patient_id = patient_data.pid " .
970 "WHERE immunizations.patient_id = ? " .
971 "AND ( list_options.option_id = 80 ". // Check for HiB list option ids
972 "OR list_options.option_id = 85 ".
973 "OR list_options.option_id = 90 ".
974 "AND DATE( immunizations.administered_date ) >= DATE_ADD( patient_data.DOB, INTERVAL 42 DAY ) " .
975 "AND DATE( immunizations.administered_date ) < DATE_ADD( patient_data.DOB, INTERVAL 2 YEAR ) ";
977 $result = sqlStatement( $query, array( $patient_id ) );
978 if ( count( $result ) >= 2 &&
979 !( $this->codes->check_for_hib_allergy( $patient_id, $end_measurement ) ) ) {
980 $pass_targ[4]++;
983 foreach ( $pass_targ as $pass_targ_count ) {
984 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
985 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ_count);
986 // Set results
987 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ_count,$perc);
991 // TODO
992 // Pneumonia Vaccination Status for Older Adults (NQF 0043) (PQRI 111)
993 private function rule_pneumovacc_ge_65_cqm() {
997 // TODO
998 // Diabetes: Eye Exam (NQF 0055) (PQRI 117)
999 private function rule_dm_eye_cqm() {
1003 // TODO
1004 // Diabetes: Foot Exam (NQF 0056) (PQRI 163)
1005 private function rule_dm_foot_cqm() {
1009 // TODO
1010 // Diabetes: Blood Pressure Management (NQF 0061) (PQRI 3)
1011 private function rule_dm_bp_control_cqm() {
1015 // Diabetes: HbA1c Poor Control (NQF 0059) (PQRI 1)
1016 private function rule_dm_a1c_cqm() {
1017 $rule_id=$this->rule['id'];
1018 $dateTarget = $this->dateTarget;
1019 $patientData =$this->patientData;
1021 // Calculate measurement period
1022 $tempDateArray = explode("-",$dateTarget);
1023 $tempYear = $tempDateArray[0];
1024 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
1025 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
1027 // Collect results
1028 $total_pat = 0;
1029 $pass_filt = 0;
1030 $exclude_filt = 0;
1031 $pass_targ = 0;
1032 $perc = 0;
1033 foreach ( $patientData as $rowPatient ) {
1034 // increment total patients counter
1035 $total_pat++;
1037 // get patient id
1038 $patient_id = $this->get_patient_id($rowPatient);
1040 // filter for age less than 18 AND greater than 75
1041 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
1042 if ( (convertDobtoAgeYearDecimal( $this->get_DOB($patient_id), $begin_measurement ) < 18) ||
1043 (convertDobtoAgeYearDecimal( $this->get_DOB($patient_id), $begin_measurement ) > 75) ) {
1044 continue;
1047 // filter for diagnosis of Diabetes
1048 // utlize the exist_lists_item() function from library/clinical_rules.php
1049 if (!( (exist_lists_item($patient_id,'medical_problem','CUSTOM::diabetes',$end_measurement)) ||
1050 (exist_lists_item($patient_id,'medical_problem','ICD9::250',$end_measurement)) ||
1051 (exist_lists_item($patient_id,'medical_problem','ICD9::250.0',$end_measurement)) ||
1052 (exist_lists_item($patient_id,'medical_problem','ICD9::250.00',$end_measurement)) ||
1053 (exist_lists_item($patient_id,'medical_problem','ICD9::250.02',$end_measurement)) ||
1054 (exist_lists_item($patient_id,'medical_problem','ICD9::250.03',$end_measurement)) ||
1055 (exist_lists_item($patient_id,'medical_problem','ICD9::250.10',$end_measurement)) ||
1056 (exist_lists_item($patient_id,'medical_problem','ICD9::250.11',$end_measurement)) ||
1057 (exist_lists_item($patient_id,'medical_problem','ICD9::250.13',$end_measurement)) ||
1058 (exist_lists_item($patient_id,'medical_problem','ICD9::250.20',$end_measurement)) ||
1059 (exist_lists_item($patient_id,'medical_problem','ICD9::250.21',$end_measurement)) ||
1060 (exist_lists_item($patient_id,'medical_problem','ICD9::250.22',$end_measurement)) ||
1061 (exist_lists_item($patient_id,'medical_problem','ICD9::250.23',$end_measurement)) ||
1062 (exist_lists_item($patient_id,'medical_problem','ICD9::250.30',$end_measurement)) ||
1063 (exist_lists_item($patient_id,'medical_problem','ICD9::250.31',$end_measurement)) ||
1064 (exist_lists_item($patient_id,'medical_problem','ICD9::250.32',$end_measurement)) ||
1065 (exist_lists_item($patient_id,'medical_problem','ICD9::250.33',$end_measurement)) ||
1066 (exist_lists_item($patient_id,'medical_problem','ICD9::250.40',$end_measurement)) ||
1067 (exist_lists_item($patient_id,'medical_problem','ICD9::250.41',$end_measurement)) ||
1068 (exist_lists_item($patient_id,'medical_problem','ICD9::250.42',$end_measurement)) ||
1069 (exist_lists_item($patient_id,'medical_problem','ICD9::250.43',$end_measurement)) ||
1070 (exist_lists_item($patient_id,'medical_problem','ICD9::250.50',$end_measurement)) ||
1071 (exist_lists_item($patient_id,'medical_problem','ICD9::250.51',$end_measurement)) ||
1072 (exist_lists_item($patient_id,'medical_problem','ICD9::250.52',$end_measurement)) ||
1073 (exist_lists_item($patient_id,'medical_problem','ICD9::250.53',$end_measurement)) ||
1074 (exist_lists_item($patient_id,'medical_problem','ICD9::250.60',$end_measurement)) ||
1075 (exist_lists_item($patient_id,'medical_problem','ICD9::250.61',$end_measurement)) ||
1076 (exist_lists_item($patient_id,'medical_problem','ICD9::250.62',$end_measurement)) ||
1077 (exist_lists_item($patient_id,'medical_problem','ICD9::250.31',$end_measurement)) ||
1078 (exist_lists_item($patient_id,'medical_problem','ICD9::250.7',$end_measurement)) ||
1079 (exist_lists_item($patient_id,'medical_problem','ICD9::250.70',$end_measurement)) ||
1080 (exist_lists_item($patient_id,'medical_problem','ICD9::250.71',$end_measurement)) ||
1081 (exist_lists_item($patient_id,'medical_problem','ICD9::250.72',$end_measurement)) ||
1082 (exist_lists_item($patient_id,'medical_problem','ICD9::250.73',$end_measurement)) ||
1083 (exist_lists_item($patient_id,'medical_problem','ICD9::250.80',$end_measurement)) ||
1084 (exist_lists_item($patient_id,'medical_problem','ICD9::250.81',$end_measurement)) ||
1085 (exist_lists_item($patient_id,'medical_problem','ICD9::250.82',$end_measurement)) ||
1086 (exist_lists_item($patient_id,'medical_problem','ICD9::250.83',$end_measurement)) ||
1087 (exist_lists_item($patient_id,'medical_problem','ICD9::250.9',$end_measurement)) ||
1088 (exist_lists_item($patient_id,'medical_problem','ICD9::250.90',$end_measurement)) ||
1089 (exist_lists_item($patient_id,'medical_problem','ICD9::250.91',$end_measurement)) ||
1090 (exist_lists_item($patient_id,'medical_problem','ICD9::250.92',$end_measurement)) ||
1091 (exist_lists_item($patient_id,'medical_problem','ICD9::250.93',$end_measurement)) ||
1092 (exist_lists_item($patient_id,'medical_problem','ICD9::357.2',$end_measurement)) ||
1093 (exist_lists_item($patient_id,'medical_problem','ICD9::362.0',$end_measurement)) ||
1094 (exist_lists_item($patient_id,'medical_problem','ICD9::362.01',$end_measurement)) ||
1095 (exist_lists_item($patient_id,'medical_problem','ICD9::362.02',$end_measurement)) ||
1096 (exist_lists_item($patient_id,'medical_problem','ICD9::362.03',$end_measurement)) ||
1097 (exist_lists_item($patient_id,'medical_problem','ICD9::362.04',$end_measurement)) ||
1098 (exist_lists_item($patient_id,'medical_problem','ICD9::362.05',$end_measurement)) ||
1099 (exist_lists_item($patient_id,'medical_problem','ICD9::362.05',$end_measurement)) ||
1100 (exist_lists_item($patient_id,'medical_problem','ICD9::366.41',$end_measurement)) ||
1101 (exist_lists_item($patient_id,'medical_problem','ICD9::648.0',$end_measurement)) ||
1102 (exist_lists_item($patient_id,'medical_problem','ICD9::648.00',$end_measurement)) ||
1103 (exist_lists_item($patient_id,'medical_problem','ICD9::648.01',$end_measurement)) ||
1104 (exist_lists_item($patient_id,'medical_problem','ICD9::648.02',$end_measurement)) ||
1105 (exist_lists_item($patient_id,'medical_problem','ICD9::648.03',$end_measurement)) ||
1106 (exist_lists_item($patient_id,'medical_problem','ICD9::648.04',$end_measurement)) )) {
1107 continue;
1110 // Filter has been passed
1111 $pass_filt++;
1113 // collect specific items that fulfill request(Hemoglobin A1C >9.0%)
1114 $proc_code = "CPT4:83036";// CPT Code for Hemoglobin A1C
1115 $sql = sqlStatement("SELECT procedure_result.result " .
1116 "FROM `procedure_type`, " .
1117 "`procedure_order`, " .
1118 "`procedure_report`, " .
1119 "`procedure_result` " .
1120 "WHERE procedure_type.procedure_type_id = procedure_order.procedure_type_id " .
1121 "AND procedure_order.procedure_order_id = procedure_report.procedure_order_id " .
1122 "AND procedure_report.procedure_report_id = procedure_result.procedure_report_id " .
1123 "AND procedure_type.standard_code = ? " .
1124 "AND procedure_result.result <= 9 " .
1125 "AND procedure_order.patient_id = ? ", array($proc_code,$patient_id) );
1126 $number = sqlNumRows($sql);
1127 if ($number < 1) continue;
1130 error_log("passed target",0);
1132 // Target has been passed
1133 $pass_targ++;
1136 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
1137 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
1139 // Set results
1140 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
1143 // TODO
1144 // Diabetes: LDL Management & Control (NQF 0064) (PQRI 2)
1145 private function rule_dm_ldl_cqm() {
1149 // TODO
1150 // Maintain an up-to-date problem list of current and active diagnoses.
1151 // 170.302(c)
1152 private function problem_list_amc() {
1156 // TODO
1157 // Maintain active medication list.
1158 // 170.302(d)
1159 private function med_list_amc() {
1163 // TODO
1164 // Maintain active medication allergy list.
1165 // 170.302(e)
1166 private function med_allergy_list_amc() {
1170 // TODO
1171 // Record and chart changes in vital signs.
1172 // 170.302(f)
1173 private function record_vitals_amc() {
1177 // TODO
1178 // Record smoking status for patients 13 years old or older.
1179 // 170.302(g)
1180 private function record_smoke_amc() {
1184 // TODO
1185 // Incorporate clinical lab-test results into certified EHR technology as structured data.
1186 // 170.302(h)
1187 private function lab_result_amc() {
1191 // TODO
1192 // The EP, eligible hospital or CAH who receives a patient from another setting of care or provider of care or believes an encounter is relevant should perform medication reconciliation.
1193 // 170.302(j)
1194 private function med_reconc_amc() {
1198 // TODO
1199 // Use certified EHR technology to identify patient-specific education resources and provide those resources to the patient if appropriate.
1200 // 170.302(m)
1201 private function patient_edu_amc() {
1205 // TODO
1206 // Use CPOE for medication orders directly entered by any licensed healthcare professional who can enter orders into the medical record per state, local and professional guidelines.
1207 // 170.304(a)
1208 private function cpoe_med_amc() {
1212 // TODO
1213 // Generate and transmit permissible prescriptions electronically.
1214 // 170.304(b)
1215 private function e_prescribe_amc() {
1219 // TODO
1220 // Record demographics.
1221 // 170.304(c)
1222 private function record_dem_amc() {
1226 // TODO
1227 // Send reminders to patients per patient preference for preventive/follow up care.
1228 // 170.304(d)
1229 private function send_reminder_amc() {
1233 // TODO
1234 // Provide patients with an electronic copy of their health information (including diagnostic test results, problem list, medication lists, medication allergies), upon request.
1235 // 170.304(f)
1236 private function provide_rec_pat_amc() {
1240 // TODO
1241 // Provide patients with timely electronic access to their health information (including lab results, problem list, medication lists, medication allergies) within four business days of the information being available to the EP.
1242 // 170.304(g)
1243 private function timely_access_amc() {
1247 // TODO
1248 // Provide clinical summaries for patients for each office visit.
1249 // 170.304(h)
1250 private function provide_sum_pat_amc() {
1254 // TODO
1255 // The EP, eligible hospital or CAH who transitions their patient to another setting of care or provider of care or refers their patient to another provider of care should provide summary of care record for each transition of care or referral.
1256 // 170.304(i)
1257 private function send_sum_amc() {