CQM module: More interim work on the cqm rules.
[openemr.git] / library / classes / rulesets / ruleSet.class.php
blobed95e2d95556cc1b36539b6f2b2fd612fc4dbb73
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 const CODE_TYPE_ICD9 ='ICD9';
17 const CODE_TYPE_ICD9 ='ICD9';
18 // Main input variables:
19 // $rule - array containing rule information
20 // $dateTarget - target date
21 // $patientData - array of pertinent patients
23 // These variables hold the results data elements, note they are all
24 // arrays that need to all contain the same number of elements.
25 // $group_label - array of titles for each group (usually only one group) TODO: get this working for when there are multiple groups
26 // $total_patients - array of total patients for each group
27 // $pass_filter - array of patients that pass filters for each group
28 // $exclude_filter - array of patients that are excluded for each group
29 // $pass_target - array of patients that pass target for each group
30 // $percentage - array of percentage of patients that pass target for each group
32 // Main processed results variable:
33 // $results - holds the result array used in reports
36 // Construction function
37 public function __construct( $rule, $dateTarget, $patientData ) {
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: Hemoglobin A1C >9.0%
118 // NQF 0059
119 $this->rule_dm_a1c_cqm();
120 break;
121 case "problem_list_amc":
122 // Maintain an up-to-date problem list of current and active diagnoses.
123 // 170.302(c)
124 $this->problem_list_amc();
125 break;
126 case "med_list_amc":
127 // Maintain active medication list.
128 // 170.302(d)
129 $this->med_list_amc();
130 break;
131 case "med_allergy_list_amc":
132 // Maintain active medication allergy list.
133 // 170.302(e)
134 $this->med_allergy_list_amc();
135 break;
136 case "record_vitals_amc":
137 // Record and chart changes in vital signs.
138 // 170.302(f)
139 $this->record_vitals_amc();
140 break;
141 case "record_smoke_amc":
142 // Record smoking status for patients 13 years old or older.
143 // 170.302(g)
144 $this->record_smoke_amc();
145 break;
146 case "lab_result_amc":
147 // Incorporate clinical lab-test results into certified EHR technology as structured data.
148 // 170.302(h)
149 $this->lab_result_amc();
150 break;
151 case "med_reconc_amc":
152 // 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.
153 // 170.302(j)
154 $this->med_reconc_amc();
155 break;
156 case "patient_edu_amc":
157 // Use certified EHR technology to identify patient-specific education resources and provide those resources to the patient if appropriate.
158 // 170.302(m)
159 $this->patient_edu_amc();
160 break;
161 case "cpoe_med_amc":
162 // 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.
163 // 170.304(a)
164 $this->cpoe_med_amc();
165 break;
166 case "e_prescribe_amc":
167 // Generate and transmit permissible prescriptions electronically.
168 // 170.304(b)
169 $this->e_prescribe_amc();
170 break;
171 case "record_dem_amc":
172 // Record demographics.
173 // 170.304(c)
174 $this->record_dem_amc();
175 break;
176 case "send_reminder_amc":
177 // Send reminders to patients per patient preference for preventive/follow up care.
178 // 170.304(d)
179 $this->send_reminder_amc();
180 break;
181 case "provide_rec_pat_amc":
182 // Provide patients with an electronic copy of their health information (including diagnostic test results, problem list, medication lists, medication allergies), upon request.
183 // 170.304(f)
184 $this->provide_rec_pat_amc();
185 break;
186 case "timely_access_amc":
187 // 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.
188 // 170.304(g)
189 $this->timely_access_amc();
190 break;
191 case "provide_sum_pat_amc":
192 // Provide clinical summaries for patients for each office visit.
193 // 170.304(h)
194 $this->provide_sum_pat_amc();
195 break;
196 case "send_sum_amc":
197 // 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.
198 // 170.304(i)
199 $this->send_sum_amc();
200 break;
201 default:
202 break;
206 // Function to process the results
207 private function process_results() {
208 // if applicable, need to iterate through each group of data
209 for($i=0;$i<count($this->group_label);$i++) {
210 $newRow=array( 'is_main'=>TRUE, // TO DO: figure out way to do this when multiple groups.
211 'total_patients'=>($this->total_patients[$i]),
212 'excluded'=>($this->exclude_filter[$i]),
213 'pass_filter'=>($this->pass_filter[$i]),
214 'pass_target'=>($this->pass_target[$i]),
215 'percentage'=>($this->percentage[$i]) );
216 $newRow=array_merge($newRow,$this->rule);
217 $this->results[] = $newRow;
221 // Function to set a results element
222 // Param:
223 // $group_lab - Label of element
224 // $total_pat - Total number of patients considered
225 // $pass_filt - Number of patients that pass filter
226 // $exclude_filt - Number of patients that are excluded
227 // $pass_targ - Number of patients that pass target
228 // $perc - Calculated percentage
229 private function set_result($group_lab,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc) {
230 $this->group_label[] = $group_lab;
231 $this->total_patients[] = $total_pat;
232 $this->pass_filter[] = $pass_filt;
233 $this->exclude_filter[] = $exclude_filt;
234 $this->pass_target[] = $pass_targ;
235 $this->percentage[] = $perc;
238 // Function to see if encounters exist
239 // Parameters:
240 // $patient_id - patient id
241 // $encounter_label - encounter id from list_options
242 // $begin_date - begin of date to search (if blank, then will not limit to a begin date)
243 // $end_date - end of date to search
244 // $number - number of encounters needed
245 private function exist_encounter($patient_id,$encounter_label,$begin_date='',$end_date,$number) {
246 // use the getEncounters() function from library/forms.inc
247 $encounters = getEncounters($patient_id,$begin_date,$end_date,$encounter_label);
248 (empty($encounters)) ? $totalNumberAppt = 0 : $totalNumberAppt = count($encounters);
249 if ( $totalNumberAppt < $number ) {
250 return false;
252 else {
253 return true;
257 private function check_for_pregnancy( $patient_id, $end_measurement ) {
258 global $pregnancy_codes;
260 foreach( $pregnancy_codes as $pregnancy_code ) {
261 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::'.$pregnancy_code,$end_measurement ) ) {
262 return true;
265 return false;
268 private function check_for_obgyn( $patient_id, $end_measurement ) {
269 global $obgyn_codes;
271 foreach( $obgyn_codes as $obgyn_code ) {
272 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::'.$obgyn_code,$end_measurement ) ) {
273 return true;
276 return false;
279 private function check_for_allergy( $patient_id, $end_measurement ) {
283 // Function to get patient dob
284 // Parameter:
285 // $patient_id - patient id
286 // Return: DOB (string)
287 private function get_DOB($patient_id) {
288 $dob = getPatientData($patient_id, "DATE_FORMAT(DOB,'%Y %m %d') as TS_DOB");
289 return $dob['TS_DOB'];
292 // Function to get patient id from the patient array
293 // Paramter:
294 // $array_patient - array holding patient id in the 'id' column
295 private function get_patient_id($array_patient) {
296 return $array_patient['pid'];
299 // Hypertension: Blood Pressure Measurement (NQF 0013)
301 // (note it only needs to process one group)
302 // (Measurement for 12 months from 1/1/20?? to 12/31/20??)
304 // 1) Calculate number that pass the filter
305 // -Age greater than 18 (before the beginning of the measurement period).
306 // -Diagnosis of HTN (before or during the measurement period)
307 // -At least two encounters (of a specified type and within the measurement
308 // period)
309 // 2) Deal with exclusions:
310 // -No exclusions
311 // 3) Then from patients that pass the filter (and are not excluded), calculate
312 // the number that have the target.
313 // -Measurement of a SBP and a DBP within the measurment period (needs
314 // to be on same day as specified encounter type)
315 // 4) Then calculate the percentage, which is number that meet the target
316 // divided by the number of patients that pass the filter (and are not excluded).
318 private function rule_htn_bp_measure_cqm() {
319 $rule_id=$this->rule['id'];
320 $dateTarget = $this->dateTarget;
321 $patientData = $this->patientData;
323 // Calculate measurement period
324 $tempDateArray = explode("-",$dateTarget);
325 $tempYear = $tempDateArray[0];
326 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
327 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
329 // Collect results
330 $total_pat = 0;
331 $pass_filt = 0;
332 $exclude_filt = 0;
333 $pass_targ = 0;
334 $perc = 0;
335 foreach ( $patientData as $rowPatient ) {
336 // increment total patients counter
337 $total_pat++;
339 // get patient id
340 $patient_id = $this->get_patient_id($rowPatient);
342 // filter for age greater than 18
343 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
344 if (convertDobtoAgeYearDecimal( $this->get_DOB($patient_id), $begin_measurement ) < 18) continue;
346 // filter for diagnosis of HTN
347 // utlize the exist_lists_item() function from library/clinical_rules.php
348 if (!( (exist_lists_item($patient_id,'medical_problem','CUSTOM::HTN',$end_measurement)) ||
349 (exist_lists_item($patient_id,'medical_problem','ICD9::401.0',$end_measurement)) ||
350 (exist_lists_item($patient_id,'medical_problem','ICD9::401.1',$end_measurement)) ||
351 (exist_lists_item($patient_id,'medical_problem','ICD9::401.9',$end_measurement)) ||
352 (exist_lists_item($patient_id,'medical_problem','ICD9::402.00',$end_measurement)) ||
353 (exist_lists_item($patient_id,'medical_problem','ICD9::402.01',$end_measurement)) ||
354 (exist_lists_item($patient_id,'medical_problem','ICD9::402.10',$end_measurement)) ||
355 (exist_lists_item($patient_id,'medical_problem','ICD9::402.11',$end_measurement)) ||
356 (exist_lists_item($patient_id,'medical_problem','ICD9::402.90',$end_measurement)) ||
357 (exist_lists_item($patient_id,'medical_problem','ICD9::402.91',$end_measurement)) ||
358 (exist_lists_item($patient_id,'medical_problem','ICD9::403.00',$end_measurement)) ||
359 (exist_lists_item($patient_id,'medical_problem','ICD9::403.01',$end_measurement)) ||
360 (exist_lists_item($patient_id,'medical_problem','ICD9::403.10',$end_measurement)) ||
361 (exist_lists_item($patient_id,'medical_problem','ICD9::403.11',$end_measurement)) ||
362 (exist_lists_item($patient_id,'medical_problem','ICD9::403.90',$end_measurement)) ||
363 (exist_lists_item($patient_id,'medical_problem','ICD9::403.91',$end_measurement)) ||
364 (exist_lists_item($patient_id,'medical_problem','ICD9::404.00',$end_measurement)) ||
365 (exist_lists_item($patient_id,'medical_problem','ICD9::404.01',$end_measurement)) ||
366 (exist_lists_item($patient_id,'medical_problem','ICD9::404.02',$end_measurement)) ||
367 (exist_lists_item($patient_id,'medical_problem','ICD9::404.03',$end_measurement)) ||
368 (exist_lists_item($patient_id,'medical_problem','ICD9::404.10',$end_measurement)) ||
369 (exist_lists_item($patient_id,'medical_problem','ICD9::404.11',$end_measurement)) ||
370 (exist_lists_item($patient_id,'medical_problem','ICD9::404.12',$end_measurement)) ||
371 (exist_lists_item($patient_id,'medical_problem','ICD9::404.13',$end_measurement)) ||
372 (exist_lists_item($patient_id,'medical_problem','ICD9::404.90',$end_measurement)) ||
373 (exist_lists_item($patient_id,'medical_problem','ICD9::404.91',$end_measurement)) ||
374 (exist_lists_item($patient_id,'medical_problem','ICD9::404.92',$end_measurement)) ||
375 (exist_lists_item($patient_id,'medical_problem','ICD9::404.93',$end_measurement)) )) {
376 continue;
379 // filter for 2 specified encounters
380 // make a function for this and wrap in the encounter titles
381 if (!( ($this->exist_encounter($patient_id,'enc_outpatient',$begin_measurement,$end_measurement,2)) ||
382 ($this->exist_encounter($patient_id,'enc_nurs_fac',$begin_measurement,$end_measurement,2)) )) {
384 continue;
387 // Filter has been passed
388 $pass_filt++;
390 // See if BP has been done within the measurement period (on a day of a specified encounter)
391 $query = "SELECT form_vitals.bps, form_vitals.bpd " .
392 "FROM `form_vitals` " .
393 "LEFT JOIN `form_encounter` " .
394 "ON ( DATE(form_vitals.date) = DATE(form_encounter.date)) " .
395 "LEFT JOIN `enc_category_map` " .
396 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
397 "WHERE form_vitals.pid = ?" .
398 "AND form_vitals.bps IS NOT NULL " .
399 "AND form_vitals.bpd IS NOT NULL " .
400 "AND form_vitals.date >= ? " .
401 "AND form_vitals.date <= ? " .
402 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' OR enc_category_map.rule_enc_id = 'enc_nurs_fac' )";
403 $res = sqlStatement($query, array($patient_id,$begin_measurement,$end_measurement) );
404 $number = sqlNumRows($res);
405 if ($number < 1) continue;
407 error_log("passed target",0);
409 // Target has been passed
410 $pass_targ++;
413 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
414 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
416 // Set results
417 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
420 // Tobacco Use Assessment (NQF 0028a)
421 private function rule_tob_use_assess_cqm() {
422 $rule_id=$this->rule['id'];
423 $dateTarget = $this->dateTarget;
424 $patientData =$this->patientData;
426 // Calculate measurement period
427 $tempDateArray = explode("-",$dateTarget);
428 $tempYear = $tempDateArray[0];
429 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
430 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
432 // Collect results
433 $total_pat = 0;
434 $pass_filt = 0;
435 $exclude_filt = 0;
436 $pass_targ = 0;
437 $perc = 0;
438 foreach ( $patientData as $rowPatient ) {
439 $patient_id = $this->get_patient_id($rowPatient);
440 // increment total patients counter
441 $total_pat++;
443 // filter for age greater than 18
444 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
445 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
446 if ( $age < 18) continue;
448 // filter for 2 specified encounters of some types, and 1 for others
449 // make a function for this and wrap in the encounter titles
450 if (!( ($this->exist_encounter($patient_id,'enc_off_vis',$begin_measurement,$end_measurement,2)) ||
451 ($this->exist_encounter($patient_id,'enc_hea_and_beh',$begin_measurement,$end_measurement,2)) ||
452 ($this->exist_encounter($patient_id,'enc_occ_ther',$begin_measurement,$end_measurement,2)) ||
453 ($this->exist_encounter($patient_id,'enc_psych_and_psych',$begin_measurement,$end_measurement,2)) ||
454 ($this->exist_encounter($patient_id,'enc_pre_med_ser_18_older',$begin_measurement,$end_measurement,1)) ||
455 ($this->exist_encounter($patient_id,'enc_pre_ind_counsel',$begin_measurement,$end_measurement,1)) ||
456 ($this->exist_encounter($patient_id,'enc_pre_med_group_counsel',$begin_measurement,$end_measurement,1)) ||
457 ($this->exist_encounter($patient_id,'enc_pre_med_other_serv',$begin_measurement,$end_measurement,1)) )) {
458 continue;
461 // Filter has been passed
462 $pass_filt++;
464 // See if user has been a tobacco user before or sumultaneosly to the encounter within two years (24 months)
465 $begin_24_months_before_time = strtotime( '-24 month' , strtotime ( $begin_measurement ) );
466 $begin_24_months_before = date( 'Y-m-d 00:00:00' , $begin_24_months_before_time );
467 $tobaccoHistory = getHistoryData( $patient_id, "tobacco", $begin_24_months_before, $end_measurement );
468 if ( !isset( $tobaccoHistory['tobacco'] ) ) {
469 continue;
472 // Target has been passed
473 $pass_targ++;
476 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
477 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
479 // Set results
480 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
483 // TODO
484 // Tobacco Cessation Intervention (NQF 0028b)
485 private function rule_tob_cess_inter_cqm() {
489 // Adult Weight Screening and Follow-Up (NQF 0421) (PQRI 128)
490 private function rule_adult_wt_screen_fu_cqm() {
491 $rule_id=$this->rule['id'];
492 $dateTarget = $this->dateTarget;
493 $patientData =$this->patientData;
495 // Calculate measurement period
496 $tempDateArray = explode("-",$dateTarget);
497 $tempYear = $tempDateArray[0];
498 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
499 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
501 // Collect results
502 $total_pat = 0;
503 $pass_filt = 0;
504 $exclude_filt = 0;
505 $pass_targ = 0;
506 $perc = 0;
507 foreach ( $patientData as $rowPatient ) {
508 $patient_id = $this->get_patient_id( $rowPatient );
509 // increment total patients counter
510 $total_pat++;
512 // filter for age greater than 65
513 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
514 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
515 if ( $age < 65 ) continue;
517 // filter for 1 specified encounters
518 // make a function for this and wrap in the encounter titles
519 // doesn't say anything about encounter date, so check for any encounter
520 if (!( ( $this->exist_encounter($patient_id,'enc_outpatient',$begin_measurement,$end_measurement,1)) )) {
521 continue;
524 $pass_filt++;
526 // Flow of control loop
527 $bContinue = true;
528 do {
529 // See if BMI has been recorded between >=22kg/m2 and <30kg/m2 6 months before, or simultanious to the encounter
530 $query = "SELECT form_vitals.BMI " .
531 "FROM `form_vitals` " .
532 "LEFT JOIN `form_encounter` " .
533 "ON ( form_vitals.pid = form_encounter.pid ) " .
534 "LEFT JOIN `enc_category_map` " .
535 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
536 "WHERE form_vitals.BMI IS NOT NULL " .
537 "AND form_vitals.BMI IS NOT NULL " .
538 "AND form_vitals.pid = ? AND form_vitals.BMI >= 22 AND form_vitals.BMI < 30 " .
539 "AND DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) " .
540 "AND DATE( form_vitals.date ) <= DATE( form_encounter.date ) " .
541 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
542 $res = sqlStatement( $query, array( $patient_id ) );
543 $number = sqlNumRows($res);
544 if ( $number >= 1 ) {
545 $bContinue = false;
546 break;
549 // See if BMI has been recorded >=30kg/m2 6 months before, or simultanious to the encounter
550 // TODO AND ÒCare goal: follow-up plan BMI managementÓ OR ÒCommunication provider to provider: dietary consultation orderÓ
551 $query = "SELECT form_vitals.BMI " .
552 "FROM `form_vitals` " .
553 "LEFT JOIN `form_encounter` " .
554 "ON ( form_vitals.pid = form_encounter.pid ) " .
555 "LEFT JOIN `enc_category_map` " .
556 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
557 "WHERE form_vitals.BMI IS NOT NULL " .
558 "AND form_vitals.BMI IS NOT NULL " .
559 "AND form_vitals.pid = ? AND form_vitals.BMI >= 30 " .
560 "ANS ( DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) ) " .
561 "AND ( DATE( form_vitals.date ) <= DATE( form_encounter.date ) ) " .
562 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
563 $res = sqlStatement( $query, array( $patient_id ) );
564 $number = sqlNumRows($res);
565 if ( $number >= 1 ) {
566 $bContinue = false;
567 break;
570 // See if BMI has been recorded <22kg/m2 6 months before, or simultanious to the encounter
571 // TODO AND ÒCare goal: follow-up plan BMI managementÓ OR ÒCommunication provider to provider: dietary consultation orderÓ
572 $query = "SELECT form_vitals.BMI " .
573 "FROM `form_vitals` " .
574 "LEFT JOIN `form_encounter` " .
575 "ON ( form_vitals.pid = form_encounter.pid ) " .
576 "LEFT JOIN `enc_category_map` " .
577 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
578 "WHERE form_vitals.BMI IS NOT NULL " .
579 "AND form_vitals.BMI IS NOT NULL " .
580 "AND form_vitals.pid = ? AND form_vitals.BMI < 22 " .
581 "ANS ( DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) ) " .
582 "AND ( DATE( form_vitals.date ) <= DATE( form_encounter.date ) ) " .
583 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
584 $res = sqlStatement( $query, array( $patient_id ) );
585 $number = sqlNumRows($res);
586 if ( $number >= 1 ) {
587 $bContinue = false;
588 break;
590 } while( false );
592 if ( $bContinue ) {
593 continue;
596 // TODO Exclusions
597 // OR:ÒPatient characteristic: Terminal illnessÓ<=6 months before or simultaneously to ÒEncounter: encounter outpatientÓ;
598 // OR:ÒPhysical exam not done: patient reasonÓ;
599 // OR:ÒPhysical exam not done: medical reasonÓ;
600 // OR:ÒPhysical rationale physical exam not done: system reasonÓ;
601 if ( $this->check_for_pregnancy( $patient_id, $end_measurement ) ) {
602 $exclude_filt++;
605 $pass_targ++;
608 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
609 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
611 // Set results
612 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
614 // *** Population criteria 2 ***
615 // reset counters
616 $total_pat = 0;
617 $pass_filt = 0;
618 $exclude_filt = 0;
619 $pass_targ = 0;
620 $perc = 0;
621 foreach ( $patientData as $rowPatient ) {
622 $patient_id = $this->get_patient_id( $rowPatient );
623 // increment total patients counter
624 $total_pat++;
626 // filter for >= 18 and <= 64
627 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
628 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
629 if ( $age < 18 || $age > 65 ) continue;
631 // Denominator=
632 // AND: ÒAll patients in the initial patient populationÓ;
633 // AND: >=1 count(s) of ÒEncounter: encounter outpatientÓ;
634 if (!( ( $this->exist_encounter($patient_id,'enc_outpatient',$begin_measurement,$end_measurement,1)) )) {
635 continue;
638 $pass_filt++;
640 // Flow of control loop
641 $bContinue = true;
642 do {
643 // See if BMI has been recorded between >=18.5kg/m2 and <25kg/m2 6 months before, or simultanious to the encounter
644 $query = "SELECT form_vitals.BMI " .
645 "FROM `form_vitals` " .
646 "LEFT JOIN `form_encounter` " .
647 "ON ( form_vitals.pid = form_encounter.pid ) " .
648 "LEFT JOIN `enc_category_map` " .
649 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
650 "WHERE form_vitals.BMI IS NOT NULL " .
651 "AND form_vitals.BMI IS NOT NULL " .
652 "AND form_vitals.pid = ? AND form_vitals.BMI >= 18.5 AND form_vitals.BMI < 25 " .
653 "AND DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) " .
654 "AND DATE( form_vitals.date ) <= DATE( form_encounter.date ) " .
655 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
656 $res = sqlStatement( $query, array( $patient_id ) );
657 $number = sqlNumRows($res);
658 if ( $number >= 1 ) {
659 $bContinue = false;
660 break;
663 // See if BMI has been recorded >=25kg/m2 6 months before, or simultanious to the encounter
664 // TODO AND ÒCare goal: follow-up plan BMI managementÓ OR ÒCommunication provider to provider: dietary consultation orderÓ
665 $query = "SELECT form_vitals.BMI " .
666 "FROM `form_vitals` " .
667 "LEFT JOIN `form_encounter` " .
668 "ON ( form_vitals.pid = form_encounter.pid ) " .
669 "LEFT JOIN `enc_category_map` " .
670 "ON (enc_category_map.main_cat_id = form_encounter.pc_catid) " .
671 "WHERE form_vitals.BMI IS NOT NULL " .
672 "AND form_vitals.BMI IS NOT NULL " .
673 "AND form_vitals.pid = ? AND form_vitals.BMI >= 25 " .
674 "ANS ( DATE( form_vitals.date ) >= DATE_ADD( form_encounter.date, INTERVAL -6 MONTH ) ) " .
675 "AND ( DATE( form_vitals.date ) <= DATE( form_encounter.date ) ) " .
676 "AND ( enc_category_map.rule_enc_id = 'enc_outpatient' )";
677 $res = sqlStatement( $query, array( $patient_id ) );
678 $number = sqlNumRows($res);
679 if ( $number >= 1 ) {
680 $bContinue = false;
681 break;
684 } while( false );
686 if ( $bContinue ) {
687 continue;
690 // TODO Exclusions
691 // OR:ÒPatient characteristic: Terminal illnessÓ<=6 months before or simultaneously to ÒEncounter: encounter outpatientÓ;
692 // OR:ÒPhysical exam not done: patient reasonÓ;
693 // OR:ÒPhysical exam not done: medical reasonÓ;
694 // OR:ÒPhysical rationale physical exam not done: system reasonÓ;
695 if ( $this->check_for_pregnancy( $patient_id, $end_measurement ) ) {
696 $exclude_filt++;
699 $pass_targ++;
702 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
703 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
705 // Set results
706 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
710 // Weight Assessment and Counseling for Children and Adolescents (NQF 0024)
711 private function rule_wt_assess_couns_child_cqm() {
712 $rule_id=$this->rule['id'];
713 $dateTarget = $this->dateTarget;
714 $patientData =$this->patientData;
716 // Calculate measurement period
717 $tempDateArray = explode("-",$dateTarget);
718 $tempYear = $tempDateArray[0];
719 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
720 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
722 // *** Patient Criteria 1 ***
723 // Collect results
724 $total_pat = 0;
725 $pass_filt = 0;
726 $exclude_filt = 0;
727 $pass_targ = array( 1, 2, 3 );
728 $perc = 0;
729 foreach ( $patientData as $rowPatient ) {
730 $patient_id = $this->get_patient_id( $rowPatient );
731 // increment total patients counter
732 $total_pat++;
734 // filter for Patient characteristic: birth dateÓ (age) >=2 and <=16 years
735 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
736 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
737 if ( $age < 2 || $age > 17 ) continue;
739 // filter for 1 specified encounters
740 // make a function for this and wrap in the encounter titles
741 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ||
742 ( $this->check_for_pregnancy( $patient_id, $end_measurement ) ||
743 ( $this->exist_encounter($patient_id,'enc_pregnancy',$begin_measurement,$end_measurement,1) ) ) ) {
744 continue;
747 $pass_filt++;
749 // numerator 1: Physical exam finding: BMI percentile
750 if ( ( (exist_lists_item($patient_id,'medical_problem','CUSTOM::BMI',$end_measurement)) || // TODO where should this come from?
751 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.5',$end_measurement)) ||
752 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.51',$end_measurement)) ||
753 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.52',$end_measurement)) ||
754 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.53',$end_measurement)) ||
755 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.54',$end_measurement)) )) {
756 $pass_targ[1]++;
759 // numerator 2: Communication to patient: counseling for nutrition
760 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.3',$end_measurement ) ) { // TODO where should this come from?
761 $pass_targ[2]++;
764 // numerator 3: Communication to patient: counseling for physical activity
765 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.41',$end_measurement ) ) { // TODO where should this come from?
766 $pass_targ[3]++;
770 foreach ( $pass_targ as $pass_targ_count ) {
771 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
772 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ_count);
773 // Set results
774 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ_count,$perc);
777 // *** Patient Criteria 2 ***
778 // reset counters
779 $total_pat = 0;
780 $pass_filt = 0;
781 $exclude_filt = 0;
782 $pass_targ = array( 1, 2, 3 );
783 $perc = 0;
784 foreach ( $patientData as $rowPatient ) {
785 $patient_id = $this->get_patient_id( $rowPatient );
786 // increment total patients counter
787 $total_pat++;
789 // filter for Patient characteristic: birth dateÓ (age) >=2 and <=16 years
790 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
791 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
792 if ( $age < 2 || $age > 11 ) continue;
794 // filter for 1 specified encounters
795 // make a function for this and wrap in the encounter titles
796 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ||
797 ( $this->check_for_pregnancy( $patient_id, $end_measurement ) ||
798 ( $this->exist_encounter($patient_id,'enc_pregnancy',$begin_measurement,$end_measurement,1) ) ) ) {
799 continue;
802 $pass_filt++;
804 // numerator 1: Physical exam finding: BMI percentile
805 if ( ( (exist_lists_item($patient_id,'medical_problem','CUSTOM::BMI',$end_measurement)) ||
806 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.5',$end_measurement)) ||
807 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.51',$end_measurement)) ||
808 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.52',$end_measurement)) ||
809 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.53',$end_measurement)) ||
810 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.54',$end_measurement)) )) {
811 $pass_targ[1]++;
814 // numerator 2: Communication to patient: counseling for nutrition
815 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.3',$end_measurement ) ) {
816 $pass_targ[2]++;
819 // numerator 3: Communication to patient: counseling for physical activity
820 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.41',$end_measurement ) ) {
821 $pass_targ[3]++;
825 foreach ( $pass_targ as $pass_targ_count ) {
826 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
827 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ_count);
828 // Set results
829 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ_count,$perc);
832 // *** Patient Criteria 3 ***
833 // reset counters
834 $total_pat = 0;
835 $pass_filt = 0;
836 $exclude_filt = 0;
837 $pass_targ = array( 1, 2, 3 );
838 $perc = 0;
839 foreach ( $patientData as $rowPatient ) {
840 $patient_id = $this->get_patient_id( $rowPatient );
841 // increment total patients counter
842 $total_pat++;
844 // filter for Patient characteristic: birth dateÓ (age) >=2 and <=16 years
845 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
846 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
847 if ( $age < 12 || $age > 17 ) continue;
849 // filter for 1 specified encounters
850 // make a function for this and wrap in the encounter titles
851 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ||
852 ( $this->check_for_pregnancy( $patient_id, $end_measurement ) ||
853 ( $this->exist_encounter($patient_id,'enc_pregnancy',$begin_measurement,$end_measurement,1) ) ) ) {
854 continue;
857 $pass_filt++;
859 // numerator 1: Physical exam finding: BMI percentile
860 if ( ( (exist_lists_item($patient_id,'medical_problem','CUSTOM::BMI',$end_measurement)) ||
861 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.5',$end_measurement)) ||
862 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.51',$end_measurement)) ||
863 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.52',$end_measurement)) ||
864 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.53',$end_measurement)) ||
865 (exist_lists_item($patient_id,'medical_problem','ICD9::V85.54',$end_measurement)) )) {
866 $pass_targ[1]++;
869 // numerator 2: Communication to patient: counseling for nutrition
870 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.3',$end_measurement ) ) {
871 $pass_targ[2]++;
874 // numerator 3: Communication to patient: counseling for physical activity
875 if ( exist_lists_item( $patient_id,'medical_problem','ICD9::V65.41',$end_measurement ) ) {
876 $pass_targ[3]++;
880 foreach ( $pass_targ as $pass_targ_count ) {
881 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
882 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ_count);
883 // Set results
884 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ_count,$perc);
889 // TODO
890 // Influenza Immunization for Patients >= 50 Years Old (NQF 0041) (PQRI 110)
891 private function rule_influenza_ge_50_cqm() {
895 // TODO
896 // Childhood immunization Status (NQF 0038)
897 private function rule_child_immun_stat_cqm() {
898 $rule_id=$this->rule['id'];
899 $dateTarget = $this->dateTarget;
900 $patientData =$this->patientData;
902 // Calculate measurement period
903 $tempDateArray = explode("-",$dateTarget);
904 $tempYear = $tempDateArray[0];
905 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
906 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
908 // Collect results
909 $total_pat = 0;
910 $pass_filt = 0;
911 $exclude_filt = 0;
912 $pass_targ = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 );
913 $perc = 0;
914 foreach ( $patientData as $rowPatient ) {
915 $patient_id = $this->get_patient_id( $rowPatient );
916 // increment total patients counter
917 $total_pat++;
919 // filter for ÒPatient characteristic: birth dateÓ (age) >=1 year and <2 years
920 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
921 $age = convertDobtoAgeYearDecimal( $this->get_DOB( $patient_id ), $begin_measurement );
922 if ( $age >= 2 || $age < 1 ) continue;
924 if ( ( !( $this->exist_encounter($patient_id,'enc_out_pcp_obgyn',$begin_measurement,$end_measurement,1) ) ) ) {
925 continue;
928 $pass_filt++;
930 // Numerator 1
931 $query = "SELECT immunizations.administered_date, immunizations.patient_id, immunizations.immunization_id, list_options.title, patient_data.pid, patient_data.DOB " .
932 "FROM immunizations " .
933 "LEFT JOIN list_options " .
934 "ON immunizations.immunization_id = list_options.option_id AND list_id = immunizations" .
935 "LEFT JOIN patient_data " .
936 "ON immunizations.patient_id = patient_data.pid " .
937 "WHERE immunizations.patient_id = ? " .
938 "AND ( list_options.option_id = 1 ". // Check for DTap list option ids (1-5)
939 "OR list_options.option_id = 2 ".
940 "OR list_options.option_id = 3 ".
941 "OR list_options.option_id = 4 ".
942 "OR list_options.option_id = 5 ) " .
943 "AND DATE( immunizations.administered_date ) >= DATE_ADD( patient_data.DOB, INTERVAL 42 DAY ) " .
944 "AND DATE( immunizations.administered_date ) < DATE_ADD( patient_data.DOB, INTERVAL 2 YEAR ) ";
946 $result = sqlStatement( $query, array( $patient_id ) );
947 if ( count( $result ) >= 4 ) {
948 $pass_targ[1]++;
951 // Numerator 2
952 $query = "SELECT immunizations.administered_date, immunizations.patient_id, immunizations.immunization_id, list_options.title, patient_data.pid, patient_data.DOB " .
953 "FROM immunizations " .
954 "LEFT JOIN list_options " .
955 "ON immunizations.immunization_id = list_options.option_id AND list_id = immunizations" .
956 "LEFT JOIN patient_data " .
957 "ON immunizations.patient_id = patient_data.pid " .
958 "WHERE immunizations.patient_id = ? " .
959 "AND ( list_options.option_id = 1 ". // Check for DTap list option ids (1-5)
960 "OR list_options.option_id = 2 ".
961 "OR list_options.option_id = 3 ".
962 "OR list_options.option_id = 4 ".
963 "OR list_options.option_id = 5 ) " .
964 "AND DATE( immunizations.administered_date ) >= DATE_ADD( patient_data.DOB, INTERVAL 42 DAY ) " .
965 "AND DATE( immunizations.administered_date ) < DATE_ADD( patient_data.DOB, INTERVAL 2 YEAR ) ";
967 $result = sqlStatement( $query, array( $patient_id ) );
968 if ( count( $result ) >= 4 &&
969 !(exist_lists_item( $patient_id,'allergy','RxNorm::204525',$end_measurement )) ) {
970 $pass_targ[1]++;
977 // TODO
978 // Pneumonia Vaccination Status for Older Adults (NQF 0043) (PQRI 111)
979 private function rule_pneumovacc_ge_65_cqm() {
983 // TODO
984 // Diabetes: Eye Exam (NQF 0055) (PQRI 117)
985 private function rule_dm_eye_cqm() {
989 // TODO
990 // Diabetes: Foot Exam (NQF 0056) (PQRI 163)
991 private function rule_dm_foot_cqm() {
995 // TODO
996 // Diabetes: Blood Pressure Management (NQF 0061) (PQRI 3)
997 private function rule_dm_bp_control_cqm() {
1001 // Diabetes Control: Hemoglobin A1C >9.0% (NQF 0059) (PQRI 1)
1002 private function rule_dm_a1c_cqm() {
1003 $rule_id=$this->rule['id'];
1004 $dateTarget = $this->dateTarget;
1005 $patientData =$this->patientData;
1007 // Calculate measurement period
1008 $tempDateArray = explode("-",$dateTarget);
1009 $tempYear = $tempDateArray[0];
1010 $begin_measurement = $tempDateArray[0] . "-01-01 00:00:00";
1011 $end_measurement = $tempDateArray[0] . "-12-31 23:59:59";
1013 // Collect results
1014 $total_pat = 0;
1015 $pass_filt = 0;
1016 $exclude_filt = 0;
1017 $pass_targ = 0;
1018 $perc = 0;
1019 foreach ( $patientData as $rowPatient ) {
1020 // increment total patients counter
1021 $total_pat++;
1023 // get patient id
1024 $patient_id = $this->get_patient_id($rowPatient);
1026 // filter for age less than 18 AND greater than 75
1027 // utilize the convertDobtoAgeYearDecimal() function from library/clinical_rules.php
1028 if ( (convertDobtoAgeYearDecimal( $this->get_DOB($patient_id), $begin_measurement ) < 18) ||
1029 (convertDobtoAgeYearDecimal( $this->get_DOB($patient_id), $begin_measurement ) > 75) ) {
1030 continue;
1033 // filter for diagnosis of Diabetes
1034 // utlize the exist_lists_item() function from library/clinical_rules.php
1035 if (!( (exist_lists_item($patient_id,'medical_problem','CUSTOM::diabetes',$end_measurement)) ||
1036 (exist_lists_item($patient_id,'medical_problem','ICD9::250',$end_measurement)) ||
1037 (exist_lists_item($patient_id,'medical_problem','ICD9::250.0',$end_measurement)) ||
1038 (exist_lists_item($patient_id,'medical_problem','ICD9::250.00',$end_measurement)) ||
1039 (exist_lists_item($patient_id,'medical_problem','ICD9::250.02',$end_measurement)) ||
1040 (exist_lists_item($patient_id,'medical_problem','ICD9::250.03',$end_measurement)) ||
1041 (exist_lists_item($patient_id,'medical_problem','ICD9::250.10',$end_measurement)) ||
1042 (exist_lists_item($patient_id,'medical_problem','ICD9::250.11',$end_measurement)) ||
1043 (exist_lists_item($patient_id,'medical_problem','ICD9::250.13',$end_measurement)) ||
1044 (exist_lists_item($patient_id,'medical_problem','ICD9::250.20',$end_measurement)) ||
1045 (exist_lists_item($patient_id,'medical_problem','ICD9::250.21',$end_measurement)) ||
1046 (exist_lists_item($patient_id,'medical_problem','ICD9::250.22',$end_measurement)) ||
1047 (exist_lists_item($patient_id,'medical_problem','ICD9::250.23',$end_measurement)) ||
1048 (exist_lists_item($patient_id,'medical_problem','ICD9::250.30',$end_measurement)) ||
1049 (exist_lists_item($patient_id,'medical_problem','ICD9::250.31',$end_measurement)) ||
1050 (exist_lists_item($patient_id,'medical_problem','ICD9::250.32',$end_measurement)) ||
1051 (exist_lists_item($patient_id,'medical_problem','ICD9::250.33',$end_measurement)) ||
1052 (exist_lists_item($patient_id,'medical_problem','ICD9::250.40',$end_measurement)) ||
1053 (exist_lists_item($patient_id,'medical_problem','ICD9::250.41',$end_measurement)) ||
1054 (exist_lists_item($patient_id,'medical_problem','ICD9::250.42',$end_measurement)) ||
1055 (exist_lists_item($patient_id,'medical_problem','ICD9::250.43',$end_measurement)) ||
1056 (exist_lists_item($patient_id,'medical_problem','ICD9::250.50',$end_measurement)) ||
1057 (exist_lists_item($patient_id,'medical_problem','ICD9::250.51',$end_measurement)) ||
1058 (exist_lists_item($patient_id,'medical_problem','ICD9::250.52',$end_measurement)) ||
1059 (exist_lists_item($patient_id,'medical_problem','ICD9::250.53',$end_measurement)) ||
1060 (exist_lists_item($patient_id,'medical_problem','ICD9::250.60',$end_measurement)) ||
1061 (exist_lists_item($patient_id,'medical_problem','ICD9::250.61',$end_measurement)) ||
1062 (exist_lists_item($patient_id,'medical_problem','ICD9::250.62',$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.7',$end_measurement)) ||
1065 (exist_lists_item($patient_id,'medical_problem','ICD9::250.70',$end_measurement)) ||
1066 (exist_lists_item($patient_id,'medical_problem','ICD9::250.71',$end_measurement)) ||
1067 (exist_lists_item($patient_id,'medical_problem','ICD9::250.72',$end_measurement)) ||
1068 (exist_lists_item($patient_id,'medical_problem','ICD9::250.73',$end_measurement)) ||
1069 (exist_lists_item($patient_id,'medical_problem','ICD9::250.80',$end_measurement)) ||
1070 (exist_lists_item($patient_id,'medical_problem','ICD9::250.81',$end_measurement)) ||
1071 (exist_lists_item($patient_id,'medical_problem','ICD9::250.82',$end_measurement)) ||
1072 (exist_lists_item($patient_id,'medical_problem','ICD9::250.83',$end_measurement)) ||
1073 (exist_lists_item($patient_id,'medical_problem','ICD9::250.9',$end_measurement)) ||
1074 (exist_lists_item($patient_id,'medical_problem','ICD9::250.90',$end_measurement)) ||
1075 (exist_lists_item($patient_id,'medical_problem','ICD9::250.91',$end_measurement)) ||
1076 (exist_lists_item($patient_id,'medical_problem','ICD9::250.92',$end_measurement)) ||
1077 (exist_lists_item($patient_id,'medical_problem','ICD9::250.93',$end_measurement)) ||
1078 (exist_lists_item($patient_id,'medical_problem','ICD9::357.2',$end_measurement)) ||
1079 (exist_lists_item($patient_id,'medical_problem','ICD9::362.0',$end_measurement)) ||
1080 (exist_lists_item($patient_id,'medical_problem','ICD9::362.01',$end_measurement)) ||
1081 (exist_lists_item($patient_id,'medical_problem','ICD9::362.02',$end_measurement)) ||
1082 (exist_lists_item($patient_id,'medical_problem','ICD9::362.03',$end_measurement)) ||
1083 (exist_lists_item($patient_id,'medical_problem','ICD9::362.04',$end_measurement)) ||
1084 (exist_lists_item($patient_id,'medical_problem','ICD9::362.05',$end_measurement)) ||
1085 (exist_lists_item($patient_id,'medical_problem','ICD9::362.05',$end_measurement)) ||
1086 (exist_lists_item($patient_id,'medical_problem','ICD9::366.41',$end_measurement)) ||
1087 (exist_lists_item($patient_id,'medical_problem','ICD9::648.0',$end_measurement)) ||
1088 (exist_lists_item($patient_id,'medical_problem','ICD9::648.00',$end_measurement)) ||
1089 (exist_lists_item($patient_id,'medical_problem','ICD9::648.01',$end_measurement)) ||
1090 (exist_lists_item($patient_id,'medical_problem','ICD9::648.02',$end_measurement)) ||
1091 (exist_lists_item($patient_id,'medical_problem','ICD9::648.03',$end_measurement)) ||
1092 (exist_lists_item($patient_id,'medical_problem','ICD9::648.04',$end_measurement)) )) {
1093 continue;
1096 // Filter has been passed
1097 $pass_filt++;
1099 // collect specific items that fulfill request(Hemoglobin A1C >9.0%)
1100 $proc_code = "CPT4:83036";// CPT Code for Hemoglobin A1C
1101 $sql = sqlStatement("SELECT procedure_result.result " .
1102 "FROM `procedure_type`, " .
1103 "`procedure_order`, " .
1104 "`procedure_report`, " .
1105 "`procedure_result` " .
1106 "WHERE procedure_type.procedure_type_id = procedure_order.procedure_type_id " .
1107 "AND procedure_order.procedure_order_id = procedure_report.procedure_order_id " .
1108 "AND procedure_report.procedure_report_id = procedure_result.procedure_report_id " .
1109 "AND procedure_type.standard_code = ? " .
1110 "AND procedure_result.result <= 9 " .
1111 "AND procedure_order.patient_id = ? ", array($proc_code,$patient_id) );
1112 $number = sqlNumRows($sql);
1113 if ($number < 1) continue;
1116 error_log("passed target",0);
1118 // Target has been passed
1119 $pass_targ++;
1122 // Calculate Percentage (use calculate_percentage() function from library/clinical_rules.php
1123 $perc = calculate_percentage($pass_filt,$exclude_filt,$pass_targ);
1125 // Set results
1126 $this->set_result($rule_id,$total_pat,$pass_filt,$exclude_filt,$pass_targ,$perc);
1130 // TODO
1131 // Maintain an up-to-date problem list of current and active diagnoses.
1132 // 170.302(c)
1133 private function problem_list_amc() {
1137 // TODO
1138 // Maintain active medication list.
1139 // 170.302(d)
1140 private function med_list_amc() {
1144 // TODO
1145 // Maintain active medication allergy list.
1146 // 170.302(e)
1147 private function med_allergy_list_amc() {
1151 // TODO
1152 // Record and chart changes in vital signs.
1153 // 170.302(f)
1154 private function record_vitals_amc() {
1158 // TODO
1159 // Record smoking status for patients 13 years old or older.
1160 // 170.302(g)
1161 private function record_smoke_amc() {
1165 // TODO
1166 // Incorporate clinical lab-test results into certified EHR technology as structured data.
1167 // 170.302(h)
1168 private function lab_result_amc() {
1172 // TODO
1173 // 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.
1174 // 170.302(j)
1175 private function med_reconc_amc() {
1179 // TODO
1180 // Use certified EHR technology to identify patient-specific education resources and provide those resources to the patient if appropriate.
1181 // 170.302(m)
1182 private function patient_edu_amc() {
1186 // TODO
1187 // 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.
1188 // 170.304(a)
1189 private function cpoe_med_amc() {
1193 // TODO
1194 // Generate and transmit permissible prescriptions electronically.
1195 // 170.304(b)
1196 private function e_prescribe_amc() {
1200 // TODO
1201 // Record demographics.
1202 // 170.304(c)
1203 private function record_dem_amc() {
1207 // TODO
1208 // Send reminders to patients per patient preference for preventive/follow up care.
1209 // 170.304(d)
1210 private function send_reminder_amc() {
1214 // TODO
1215 // Provide patients with an electronic copy of their health information (including diagnostic test results, problem list, medication lists, medication allergies), upon request.
1216 // 170.304(f)
1217 private function provide_rec_pat_amc() {
1221 // TODO
1222 // 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.
1223 // 170.304(g)
1224 private function timely_access_amc() {
1228 // TODO
1229 // Provide clinical summaries for patients for each office visit.
1230 // 170.304(h)
1231 private function provide_sum_pat_amc() {
1235 // TODO
1236 // 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.
1237 // 170.304(i)
1238 private function send_sum_amc() {