Permalink
Browse files

moved provider to health data standards

  • Loading branch information...
ssayer committed Feb 15, 2012
1 parent 793b7a0 commit bc27940b1c9946f3cf70004ad9a54eed80c17483
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ClinicalDocument
- xmlns="urn:hl7-org:v3" xmlns:sdct="urn:hl7-org:sdct"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-<documentationOf>
- <serviceEvent classCode="PCPR">
- <effectiveTime>
- <low value="19650120"/>
- <high value="20070209"/>
- </effectiveTime>
- <performer typeCode="PRF">
- <templateId root="2.16.840.1.113883.3.88.11.83.4" assigningAuthorityName="HITSP C83"/>
- <templateId root="1.3.6.1.4.1.19376.1.5.3.1.2.3" assigningAuthorityName="IHE PCC"/>
- <functionCode code="PP" displayName="Primary Care Provider" codeSystem="2.16.840.1.113883.12.443" codeSystemName="Provider Role">
- <originalText>Primary Care Provider</originalText>
- </functionCode>
- <time>
- <low value="20020716"/>
- <high value="20070915"/>
- </time>
- <assignedEntity>
-
- <id root="2.16.840.1.113883.4.6" extension="808401234567893"/>
- <code code="200000000X" displayName="Allopathic and Osteopathic Physicians" codeSystemName="Provider Codes" codeSystem="2.16.840.1.113883.6.101"/>
- <addr/>
- <telecom value="tel:+1-301-975-3251" use="HP"/>
- <assignedPerson>
- <name>
- <prefix>Dr.</prefix>
- <given>Stanley</given>
- <family>Strangelove</family>
- </name>
- <sdtc:birthTime nullFlavor="ASKU"/>
- </assignedPerson>
- <representedOrganization>
- <id root="2.16.840.1.113883.3.72.5"/>
- <name>Kubrick Permanente</name>
- <telecom/>
- <addr/>
- </representedOrganization>
- <sdtc:patient>
- <sdtc:id/>
- </sdtc:patient>
- </assignedEntity>
- </performer>
- <performer typeCode="PRF">
- <templateId root="2.16.840.1.113883.3.88.11.83.4" assigningAuthorityName="HITSP C83"/>
- <templateId root="1.3.6.1.4.1.19376.1.5.3.1.2.3" assigningAuthorityName="IHE PCC"/>
- <functionCode code="CP" displayName="Consulting Provider" codeSystem="2.16.840.1.113883.12.443" codeSystemName="Provider Role"/>
- <originalText>Consulting Provider</originalText>
- <time>
- <low value=""/>
- <high value=""/>
- </time>
- <assignedEntity>
- <id extension="1234567893" root="2.16.840.1.113883.3.72.5.2"/>
- <code code="230000000X" displayName="Speech, Language and Hearing Providers" codeSystem="2.16.840.1.113883.6.101" codeSystemName="ProviderCodes"/>
- <assignedPerson>
- <name>
- <prefix>Dr.</prefix>
- <given>Teddy</given>
- <family>Seuss</family>
- </name>
- </assignedPerson>
- <representedOrganization>
- <id root="2.16.840.1.113883.3.72.5"/>
- <name>Redfish Labs</name>
- <telecom/>
- <addr/>
- </representedOrganization>
- <sdtc:patient>
- <sdtc:id root="78A150ED-B890-49dc-B716-5EC0027B3983" extension="MedicalRecordNumber"/>
- </sdtc:patient>
- </assignedEntity>
- </performer>
- </serviceEvent>
-</documentationOf>
-<!-- --></ClinicalDocument>
@@ -1,97 +0,0 @@
-require "date"
-require "date/delta"
-
-module QME
- module Importer
- class ProviderImporter
- include Singleton
-
- # Extract Healthcare Providers from C32
- #
- # @param [Nokogiri::XML::Document] doc It is expected that the root node of this document
- # will have the "cda" namespace registered to "urn:hl7-org:v3"
- # @return [Array] an array of providers found in the document
- def extract_providers(doc, use_encounters=false)
-
-
- xpath_base = use_encounters ? "//cda:encounter/cda:performer" : "//cda:documentationOf/cda:serviceEvent/cda:performer"
-
- performers = doc.xpath(xpath_base)
-
- providers = performers.map do |performer|
- provider = {}
- entity = performer.xpath(performer, "./cda:assignedEntity")
- name = entity.xpath("./cda:assignedPerson/cda:name")
- provider[:title] = extract_data(name, "./cda:prefix")
- provider[:given_name] = extract_data(name, "./cda:given[1]")
- provider[:family_name] = extract_data(name, "./cda:family")
- provider[:phone] = extract_data(entity, "./cda:telecom/@value") { |text| text.gsub("tel:", "") }
- provider[:organization] = extract_data(entity, "./cda:representedOrganization/cda:name")
- provider[:specialty] = extract_data(entity, "./cda:code/@code")
- time = performer.xpath(performer, "./cda:time")
- provider[:start] = extract_date(time, "./cda:low/@value")
- provider[:end] = extract_date(time, "./cda:high/@value")
- # NIST sample C32s use different OID for NPI vs C83, support both
- npi = extract_data(entity, "./cda:id[@root='2.16.840.1.113883.4.6' or @root='2.16.840.1.113883.3.72.5.2']/@extension")
- if ProviderImporter::valid_npi?(npi)
- provider[:npi] = npi
- else
- puts "Warning: Invalid NPI (#{npi})"
- end
- provider
- end
- end
-
- private
-
- def extract_date(subject,query)
- date = extract_data(subject,query)
- date ? Date.parse(date).to_time.to_i : nil
- end
-
- # Returns nil if result is an empty string, block allows text munging of result if there is one
- def extract_data(subject, query)
- result = subject.xpath(query).text
- if result == ""
- nil
- elsif block_given?
- yield(result)
- else
- result
- end
- end
-
- # validate the NPI, should be 10 or 15 digits total with the final digit being a
- # checksum using the Luhn algorithm with additional special handling as described in
- # https://www.cms.gov/NationalProvIdentStand/Downloads/NPIcheckdigit.pdf
- def self.valid_npi?(npi)
- return false if npi.length != 10 and npi.length != 15
- return false if npi.gsub(/\d/, '').length > 0 # npi must be all digits
- return false if npi.length == 15 and (npi =~ /^80840/)==nil # 15 digit npi must start with 80840
-
- # checksum is always calculated as if 80840 prefix is present
- if npi.length==10
- npi = '80840'+npi
- end
-
- return luhn_checksum(npi[0,14])==npi[14]
- end
-
- def self.luhn_checksum(num)
- double = {'0' => 0, '1' => 2, '2' => 4, '3' => 6, '4' => 8, '5' => 1, '6' => 3, '7' => 5, '8' => 7, '9' => 9}
- sum = 0
- num.reverse!
- num.split("").each_with_index do |char, i|
- if (i%2)==0
- sum+=double[char]
- else
- sum+=char.to_i
- end
- end
- sum = (9*sum)%10
-
- return sum.to_s
- end
- end
- end
-end
@@ -22,7 +22,6 @@
require_relative 'qme/importer/property_matcher'
require_relative 'qme/importer/generic_importer'
-require_relative 'qme/importer/provider_importer'
require_relative 'qme/importer/measure_properties_generator'
require 'json'
@@ -1,78 +0,0 @@
-describe QME::Importer::ProviderImporter do
- before do
- @doc = Nokogiri::XML(File.new("fixtures/c32_fragments/provider.xml"))
- @doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
- @nist_doc = Nokogiri::XML(File.new("fixtures/c32_fragments/NISTExampleC32.xml"))
- @nist_doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
- @importer = QME::Importer::ProviderImporter.instance
- end
-
- it 'should validate npi values' do
- QME::Importer::ProviderImporter::luhn_checksum('7992739871').should == '3'
- QME::Importer::ProviderImporter::valid_npi?('1234567893').should == true
- QME::Importer::ProviderImporter::valid_npi?('808401234567893').should == true
- QME::Importer::ProviderImporter::valid_npi?('1').should == false
- QME::Importer::ProviderImporter::valid_npi?('1010101010').should == false
- QME::Importer::ProviderImporter::valid_npi?('abcdefghij').should == false
- end
-
- it "should extract providers from document" do
- providers = @importer.extract_providers(@doc)
-
- providers.size.should == 2
-
- provider = providers.first
- provider[:title].should == "Dr."
- provider[:given_name].should == "Stanley"
- provider[:family_name].should == "Strangelove"
- provider[:phone].should == "+1-301-975-3251"
- provider[:npi].should == '808401234567893'
- provider[:organization].should == "Kubrick Permanente"
- provider[:specialty].should == "200000000X"
-
- provider2 = providers.last
- provider2[:title].should == "Dr."
- provider2[:given_name].should == "Teddy"
- provider2[:family_name].should == "Seuss"
- provider2[:phone].should == nil
- provider2[:npi].should == '1234567893'
- provider2[:organization].should == "Redfish Labs"
- provider2[:specialty].should == "230000000X"
- end
-
- it "should extract providers from NIST sample" do
- providers = @importer.extract_providers(@nist_doc)
-
- providers.size.should == 2
-
- provider = providers.first
- provider[:title].should == "Dr."
- provider[:given_name].should == "Pseudo"
- provider[:family_name].should == "Physician-1"
- provider[:npi].should == '808401234567893'
- provider[:organization].should == "NIST HL7 Test Laboratory"
- provider[:specialty].should == "200000000X"
-
- provider2 = providers.last
- provider2[:title].should == "Dr."
- provider2[:given_name].should == "Pseudo"
- provider2[:family_name].should == "Physician-3"
- provider2[:npi].should == nil
- provider2[:organization].should == "NIST HL7 Test Laboratory"
- provider2[:specialty].should == "200000000X"
- end
-
- it "should extract providers from encounters" do
- providers = @importer.extract_providers(@nist_doc, true)
- providers.size.should == 1
-
- provider = providers.first
- provider[:given_name].should == "John"
- provider[:family_name].should == "Johnson"
- provider[:phone].should == nil
- provider[:npi].should == "808401234567893"
- provider[:organization].should == "Family Doctors"
- provider[:start].should_not == nil
- end
-
-end

0 comments on commit bc27940

Please sign in to comment.