Example #1
0
        private static string GetStatus(POCD_MT000040SubstanceAdministration medicationEntry)
        {
            return(string.Empty); //TODO:

            ////first, look for an explicit status observation
            //var statusCode = medicationEntry?.SelectSingleNode(
            //    $"entryrelationship/observation[code[@code='{LoincConstants.STATUS_OBSERVATION}']]/value")
            //    ?.GetCode();

            ////TODO: is this logic correct?
            ///*
            //    http://motorcycleguy.blogspot.com/2011/03/medication-status-in-ccd.html
            //    One of the things that people often want to know about medications is whether they are still actively be used by the patient, or whether they are historical.
            //    Some look to find this in the status element of the substanceAdministation or supply act, but that is used for a different purpose.  It is used to record
            //    the state of the act according to the state model defined in the HL7 RIM.  For example, when dealing with a request or order for medications, the state is
            //    completed when the order is filled.  When dealing with an event, such as the administration of a medication, the state is completed when the med has been
            //    given to the patient.  That means that what that statusCode element implies about the medication depends upon the type of act (specifically its mood).

            //    -----> The problem is, most sample CCDs do NOT have a status observation under Medication! - NJS

            //    https://wiki.ihe.net/index.php/1.3.6.1.4.1.19376.1.5.3.1.4.7#Medication_Fields
            //    <statusCode code='completed'/>
            //    The status of all <substanceAdministration> elements must be "completed". The act has either occurred, or the request or order has been placed.
            //*/
            //if (string.IsNullOrWhiteSpace(statusCode?.Value))
            //{
            //    //if not found, look for supply order status
            //    statusCode = medicationEntry?.SelectSingleNode("entryrelationship/supply[templateid[@root='{TemplateOidConstants.MEDICATION_SUPPLY_ORDER}']]/statuscode")?.GetCode();

            //    if (string.IsNullOrWhiteSpace(statusCode?.Value))
            //    {
            //        //if still not found, use substance administration status
            //        statusCode = medicationEntry?.SelectSingleNode("statuscode")?.GetCode();
            //    }
            //}

            //// All of our DataSubType logic keys off of descriptive status names,
            //// per the CQMSolution spec, so use DisplayName if possible.
            //var statusName = statusCode?.DisplayName;

            //if (string.IsNullOrWhiteSpace(statusName))
            //{
            //    statusName = statusCode?.Value;
            //}

            //return statusName ?? string.Empty;
        }
Example #2
0
        public static Medication GetMedicationFromMedicationEntry(this POCD_MT000040SubstanceAdministration medicationEntry, Client client,
                                                                  List <AllergyAdverseEvent> allergyAdverseEvents, CqmSolutionDateRange dischargeDateRange)
        {
            var productNode = (medicationEntry?.consumable?.manufacturedProduct?.Item as POCD_MT000040Material)?.code;
            var productCode = productNode?.GetCode();
            var dataSubType = GetDataSubType(medicationEntry, productCode, allergyAdverseEvents, dischargeDateRange, out var notPresent);

            var medication = new Medication(client, dataSubType)
            {
                Product = productCode,
                Generic = productNode?.translation?.FirstOrDefault()?.GetCode(),                 //TODO: handle multiple translation nodes?
                AdministeredDateRange = medicationEntry?.effectiveTime?.GetDateRangeFromArray(), //TODO: verify this date parsing logic
                Refills    = (medicationEntry?.entryRelationship?.FirstOrDefault(r => r.Item is POCD_MT000040Supply)?.Item as POCD_MT000040Supply)?.repeatNumber?.value,
                NotPresent = notPresent,
//TODO:                NegationRationale = notPresent ? medicationEntry.SelectSingleNode(@"entryrelationship/observation/value")?.GetCode() : null //TODO: is this correct?
            };

            return(medication);
        }
Example #3
0
        private static string GetDataSubType(POCD_MT000040SubstanceAdministration medicationEntry, Code productCode,
                                             List <AllergyAdverseEvent> allergyAdverseEvents, CqmSolutionDateRange dischargeDateRange, out bool notPresent)
        {
            notPresent = false;

            if (medicationEntry == null)
            {
                return(string.Empty);
            }

            notPresent = medicationEntry.negationInd;

            //TODO: is this correct? if so, should we compare the whole code, not just the value?
            if (!string.IsNullOrWhiteSpace(productCode?.Value))
            {
                //if patient has an allergy or adverse event for the same product, return the appropriate dataSubType
                var allergyAdverseEvent =
                    allergyAdverseEvents.FirstOrDefault(a => !a.NotPresent && a.Cause?.Value == productCode.Value);

                if (allergyAdverseEvent != null)
                {
                    return(allergyAdverseEvent.DataSubType);
                }
            }

            //TODO: Are these the correct logic and codes for Discharge/Discharge Not Done?
            if (dischargeDateRange?.DateHigh?.DateTime.HasValue == true)
            {
                return("DSC");
            }
            //
            if (dischargeDateRange?.DateLow?.DateTime.HasValue == true)
            {
                return("DSCND");
            }
            //

            var statusName = GetStatus(medicationEntry);

            switch (medicationEntry.moodCode)
            {
            case x_DocumentSubstanceMood.EVN:     //administered
                return(statusName.Equals("completed", StringComparison.InvariantCultureIgnoreCase) ? (notPresent ? "ADMND" : "ADM") : "ACT");

            //TODO: is this logic correct, and are these ^-------^
            //the right codes for Administered and Administered Not Done?
            case x_DocumentSubstanceMood.INT:     //to be administered
                return(statusName.Equals("active", StringComparison.InvariantCultureIgnoreCase) ? "ACT" : "DISP");

            //TODO: is this logic correct, and is this --^
            //the right code for Dispensed?
            //Also, shouldn't there be a subtype for "No Longer Active?"
            case x_DocumentSubstanceMood.RQO:     //ordered
                return(notPresent ? "ORDND" : "ORD");

            //TODO: Handle notPresent in all cases?

            default:
                return(string.Empty);    //TODO: default to what?
            }
        }
        public POCD_MT000040SubstanceAdministration ToPocd()
        {
            POCD_MT000040SubstanceAdministration returnVal = new POCD_MT000040SubstanceAdministration();

            returnVal.classCode = "SBADM";
            returnVal.moodCode  = x_DocumentSubstanceMood.EVN;

            returnVal.templateId = new II[]
            {
                new II {
                    root = "2.16.840.1.113883.10.20.1.24"
                },
                new II {
                    root = "1.3.6.1.4.1.19376.1.5.3.1.4.7"
                },
                new II {
                    root = "1.3.6.1.4.1.19376.1.5.3.1.4.7.1"
                }
            };

            returnVal.id = new II[] { new II {
                                          root = this.Id
                                      } };

            returnVal.statusCode = new CS {
                code = "completed"
            };

            returnVal.effectiveTime = new IVL_TS[1];

            returnVal.effectiveTime[0] = this.EffectiveTime.ToIvlTs();

            returnVal.consumable = new POCD_MT000040Consumable();

            returnVal.consumable.manufacturedProduct = new POCD_MT000040ManufacturedProduct();

            returnVal.consumable.manufacturedProduct.templateId = new II[]
            {
                new II {
                    root = "1.3.6.1.4.1.19376.1.5.3.1.4.7.2"
                },
                new II {
                    root = "2.16.840.1.113883.10.20.1.53"
                }
            };

            POCD_MT000040Material material = new POCD_MT000040Material();

            material.name = new EN()
            {
                Text = new string[] { this.Description }
            };

            if (this.ProductCode != null)
            {
                material.code = this.ProductCode.ToCE();
            }
            else
            {
                material.code = new CE()
                {
                    nullFlavor = "UNK", originalText = new ED()
                    {
                        reference = new TEL()
                        {
                            value = "N/A"
                        }
                    }
                }
            };

            returnVal.consumable.manufacturedProduct.Item = material;

            return(returnVal);
        }
    }