///<summary>Get all medication documented procedures that happened in the date range that belong to the value set OIDs. These 'procedures' are actually in the ehrmeasureevent table and can only possibly be one code (restricted by value set OID), SNOMEDCT - 428191000124101 - Documentation of current medications (procedure). Ordered by PatNum, DateTEvent DESC for making CQM calc easier, most recent 'procedure' will be the first one found for the patient in list.</summary> private static Dictionary<long,List<EhrCqmMeasEvent>> GetMedDocumentedProcs(List<long> listPatNums,List<string> listValueSetOIDs,DateTime dateStart,DateTime dateEnd) { Dictionary<long,List<EhrCqmMeasEvent>> retval=new Dictionary<long,List<EhrCqmMeasEvent>>(); //if no patients, return a new empty dictionary if(listPatNums!=null && listPatNums.Count==0) { return retval; } string command="SELECT ehrmeasureevent.*,COALESCE(snomed.Description,'') AS Description " +"FROM ehrmeasureevent " +"LEFT JOIN snomed ON snomed.SnomedCode=ehrmeasureevent.CodeValueEvent AND ehrmeasureevent.CodeSystemEvent='SNOMEDCT' " +"WHERE EventType="+POut.Int((int)EhrMeasureEventType.CurrentMedsDocumented)+" " +"AND DATE(DateTEvent) BETWEEN "+POut.Date(dateStart)+" AND "+POut.Date(dateEnd)+" "; if(listPatNums!=null && listPatNums.Count>0) { command+="AND ehrmeasureevent.PatNum IN("+string.Join(",",listPatNums)+") "; } command+="ORDER BY PatNum,DateTEvent DESC"; DataTable tableEvents=Db.GetTable(command); if(tableEvents.Rows.Count==0) { return retval; } List<EhrCode> listEhrCodes=EhrCodes.GetForValueSetOIDs(listValueSetOIDs,false); Dictionary<long,EhrCode> dictEhrMeasureEventNumEhrCode=new Dictionary<long,EhrCode>(); //remove 'procs' from table of ehrmeasureevents if not in the value set OIDs in listEhrCodes for(int i=tableEvents.Rows.Count-1;i>-1;i--) { bool isValid=false; for(int j=0;j<listEhrCodes.Count;j++) {//currently this can only be one code, SNOMEDCT - 428191000124101, but we will treat it like a list in case that changes if(tableEvents.Rows[i]["CodeValueEvent"].ToString()==listEhrCodes[j].CodeValue && tableEvents.Rows[i]["CodeSystemEvent"].ToString()==listEhrCodes[j].CodeSystem) { dictEhrMeasureEventNumEhrCode.Add(PIn.Long(tableEvents.Rows[i]["EhrMeasureEventNum"].ToString()),listEhrCodes[j]); isValid=true; break; } } if(!isValid) { tableEvents.Rows.RemoveAt(i); } } for(int i=0;i<tableEvents.Rows.Count;i++) { EhrCqmMeasEvent ehrProcCur=new EhrCqmMeasEvent(); ehrProcCur.EhrCqmMeasEventNum=PIn.Long(tableEvents.Rows[i]["EhrMeasureEventNum"].ToString()); ehrProcCur.EventType=EhrMeasureEventType.CurrentMedsDocumented; ehrProcCur.PatNum=PIn.Long(tableEvents.Rows[i]["PatNum"].ToString()); ehrProcCur.CodeValue=tableEvents.Rows[i]["CodeValueEvent"].ToString(); ehrProcCur.CodeSystemName=tableEvents.Rows[i]["CodeSystemEvent"].ToString(); ehrProcCur.DateTEvent=PIn.DateT(tableEvents.Rows[i]["DateTEvent"].ToString()); string descript=tableEvents.Rows[i]["Description"].ToString();//if code is not in snomed table we will use description of EhrCode object EhrCode ehrCodeCur=dictEhrMeasureEventNumEhrCode[ehrProcCur.EhrCqmMeasEventNum]; ehrProcCur.CodeSystemOID=ehrCodeCur.CodeSystemOID; ehrProcCur.ValueSetName=ehrCodeCur.ValueSetName; ehrProcCur.ValueSetOID=ehrCodeCur.ValueSetOID; if(descript=="") { descript=ehrCodeCur.Description;//default to description of EhrCode object } ehrProcCur.Description=descript; if(retval.ContainsKey(ehrProcCur.PatNum)) { retval[ehrProcCur.PatNum].Add(ehrProcCur); } else { retval.Add(ehrProcCur.PatNum,new List<EhrCqmMeasEvent>() { ehrProcCur }); } } return retval; }
private static void GenerateMeasEventEntry(EhrCqmMeasEvent mCur) { _isWriterW=false; Start("entry","typeCode","DRIV"); if(mCur.EventType==EhrMeasureEventType.TobaccoUseAssessed) { Start("observation","classCode","OBS","moodCode","EVN"); _x.WriteComment("Tobacco Use Template"); TemplateId("2.16.840.1.113883.10.20.22.4.85"); StartAndEnd("id","root",_strOIDInternalCQMRoot,"extension",CqmItemAbbreviation.MeasEvn.ToString()+mCur.EhrCqmMeasEventNum.ToString()); StartAndEnd("code","code","ASSERTION","displayName","Assertion","codeSystem","2.16.840.1.113883.5.4","codeSystemName","ActCode"); _x.WriteElementString("text","Patient Characteristic: "+mCur.Description);//Description is of the tobacco assessment result, not the description of the assessment itself. Example: Tobacco Assessment description = History of tobacco use Narrative, but description of result is Smoker (finding). We want to display the result, Smoker. StartAndEnd("statusCode","code","completed"); Start("effectiveTime"); DateElement("low",mCur.DateTEvent); End("effectiveTime"); Start("value"); _x.WriteAttributeString("xsi","type",null,"CD"); Attribs("code",mCur.CodeValue,"displayName",mCur.Description,"codeSystem",mCur.CodeSystemOID,"codeSystemName",mCur.CodeSystemName); _x.WriteAttributeString("sdtc","valueSet",null,mCur.ValueSetOID); End("value"); End("observation"); } else if(mCur.EventType==EhrMeasureEventType.CurrentMedsDocumented) { Start("procedure","classCode","PROC","moodCode","EVN"); _x.WriteComment("Procedure Activity Procedure Template"); TemplateId("2.16.840.1.113883.10.20.22.4.14"); _x.WriteComment("Procedure Performed Template"); TemplateId("2.16.840.1.113883.10.20.24.3.64"); StartAndEnd("id","root",_strOIDInternalCQMRoot,"extension",CqmItemAbbreviation.MeasEvn.ToString()+mCur.EhrCqmMeasEventNum.ToString()); Start("code","code",mCur.CodeValue,"displayName",mCur.Description,"codeSystem",mCur.CodeSystemOID,"codeSystemName",mCur.CodeSystemName); _x.WriteAttributeString("sdtc","valueSet",null,mCur.ValueSetOID); End("code"); _x.WriteElementString("text","Procedure, Performed: "+mCur.Description); StartAndEnd("statusCode","code","completed"); Start("effectiveTime"); _x.WriteComment("Attribute: Start Datetime"); DateElement("low",mCur.DateTEvent); _x.WriteComment("Attribute: Stop Datetime"); DateElement("high",mCur.DateTEvent); End("effectiveTime"); End("procedure"); } End("entry"); _isWriterW=true; }
///<summary>Get ehrmeasureevents of type TobaccoAssessment where the event code is in the Tobacco Use Screening value set and the assessment resulted in categorizing the patient as a user or non-user and the screening was within 24 months of the measurement period end date. Ordered by PatNum, DateTEvent.</summary> private static Dictionary<long,List<EhrCqmMeasEvent>> GetTobaccoAssessmentEvents(List<long> listPatNums,DateTime dateEnd) { Dictionary<long,List<EhrCqmMeasEvent>> retval=new Dictionary<long,List<EhrCqmMeasEvent>>(); //if no patients, return a new empty dictionary if(listPatNums!=null && listPatNums.Count==0) { return retval; } string command="SELECT ehrmeasureevent.*,COALESCE(snomed.Description,'') AS Description " +"FROM ehrmeasureevent " +"LEFT JOIN snomed ON snomed.SnomedCode=ehrmeasureevent.CodeValueResult AND ehrmeasureevent.CodeSystemResult='SNOMEDCT' " +"WHERE EventType="+POut.Int((int)EhrMeasureEventType.TobaccoUseAssessed)+" " +"AND "+DbHelper.DateColumn("DateTEvent")+">="+POut.Date(dateEnd)+"-INTERVAL 24 MONTH "; if(listPatNums!=null && listPatNums.Count>0) { command+="AND ehrmeasureevent.PatNum IN("+string.Join(",",listPatNums)+") "; } command+="ORDER BY ehrmeasureevent.PatNum,ehrmeasureevent.DateTEvent DESC"; DataTable tableEvents=Db.GetTable(command); if(tableEvents.Rows.Count==0) { return retval; } Dictionary<string,string> dictEventCodesAndSystems=EhrCodes.GetCodeAndCodeSystem(new List<string>() { "2.16.840.1.113883.3.526.3.1278" },false);//Tobacco Use Screening Value Set List<string> listTobaccoStatusOIDs=new List<string>(); listTobaccoStatusOIDs.Add("2.16.840.1.113883.3.526.3.1170");//Tobacco User Grouping Value Set listTobaccoStatusOIDs.Add("2.16.840.1.113883.3.526.3.1189");//Tobacco Non-User Grouping Value Set List<EhrCode> listTobaccoStatusCodes=EhrCodes.GetForValueSetOIDs(listTobaccoStatusOIDs,false); Dictionary<long,EhrCode> dictEventNumEhrCode=new Dictionary<long,EhrCode>(); for(int i=tableEvents.Rows.Count-1;i>-1;i--) { bool isValidEvent=false; if(dictEventCodesAndSystems.ContainsKey(tableEvents.Rows[i]["CodeValueEvent"].ToString()) && dictEventCodesAndSystems[tableEvents.Rows[i]["CodeValueEvent"].ToString()]==tableEvents.Rows[i]["CodeSystemEvent"].ToString()) { isValidEvent=true; } int indexStatus=-1; for(int j=0;j<listTobaccoStatusCodes.Count;j++) { if(listTobaccoStatusCodes[j].CodeValue==tableEvents.Rows[i]["CodeValueResult"].ToString() && listTobaccoStatusCodes[j].CodeSystem==tableEvents.Rows[i]["CodeSystemResult"].ToString()) { indexStatus=j; break; } } if(isValidEvent && indexStatus>-1) { dictEventNumEhrCode.Add(PIn.Long(tableEvents.Rows[i]["EhrMeasureEventNum"].ToString()),listTobaccoStatusCodes[indexStatus]); continue; } tableEvents.Rows.RemoveAt(i); } for(int i=0;i<tableEvents.Rows.Count;i++) { EhrCqmMeasEvent tobaccoAssessCur=new EhrCqmMeasEvent(); tobaccoAssessCur.EhrCqmMeasEventNum=PIn.Long(tableEvents.Rows[i]["EhrMeasureEventNum"].ToString()); tobaccoAssessCur.EventType=EhrMeasureEventType.TobaccoUseAssessed; tobaccoAssessCur.PatNum=PIn.Long(tableEvents.Rows[i]["PatNum"].ToString()); tobaccoAssessCur.CodeValue=tableEvents.Rows[i]["CodeValueResult"].ToString(); tobaccoAssessCur.CodeSystemName=tableEvents.Rows[i]["CodeSystemResult"].ToString(); tobaccoAssessCur.DateTEvent=PIn.DateT(tableEvents.Rows[i]["DateTEvent"].ToString()); string descript=tableEvents.Rows[i]["Description"].ToString();//if code is not in snomed table we will use description of EhrCode object EhrCode ehrCodeCur=dictEventNumEhrCode[tobaccoAssessCur.EhrCqmMeasEventNum]; tobaccoAssessCur.CodeSystemOID=ehrCodeCur.CodeSystemOID; tobaccoAssessCur.ValueSetName=ehrCodeCur.ValueSetName; tobaccoAssessCur.ValueSetOID=ehrCodeCur.ValueSetOID; //all statuses for tobacco use are SNOMEDCT codes if(descript=="") { descript=ehrCodeCur.Description;//default to description of EhrCode object } tobaccoAssessCur.Description=descript; if(retval.ContainsKey(tobaccoAssessCur.PatNum)) { retval[tobaccoAssessCur.PatNum].Add(tobaccoAssessCur); } else { retval.Add(tobaccoAssessCur.PatNum,new List<EhrCqmMeasEvent>() { tobaccoAssessCur }); } } return retval; }