Created
August 22, 2014 02:24
-
-
Save jgautsch/22a01facc880e76d9143 to your computer and use it in GitHub Desktop.
classes.rb, The Classes that the NPI MapReduce script depends on
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ########################################################### | |
# Data Processing | |
# ########################################################### | |
module DataProcessing | |
class TaxonomyCache | |
def initialize | |
@@specialties = Taxonomies::Specialty.all[0..-1].group_by(&:taxonomy) | |
@@specialties.each do |k, v| | |
@@specialties[k] = v.first | |
end | |
end | |
def find(*args) | |
args.flatten! | |
result = [] | |
args.each do |tax| | |
if @@specialties.has_key?(tax) | |
result << @@specialties[tax] | |
end | |
end | |
result | |
end | |
end | |
module Stream | |
class Row | |
def initialize(row) | |
@values = CSV.parse(row).first | |
if @values.size != 329 | |
puts "ROW SIZE: #{@values.size}" | |
raise "Wrong Size Row" | |
end | |
def active? | |
# 39 --> "NPI Deactivation Date", | |
# 40 --> "NPI Reactivation Date", | |
# if it has a Deactivation date and it doesn't have a reactivation date it's inactive | |
# if the opposite of the above, it's active | |
# DeMorgan's FTW | |
value_at_index(39).blank? || !value_at_index(40).blank? | |
end | |
def entity_type | |
type_code = value_at_index(1) | |
if type_code == '1' | |
'Individual' | |
elsif type_code == '2' | |
'Organization' | |
elsif type_code == 'Entity Type Code' | |
'HeaderRow' | |
else | |
raise "Invalid Data - Entity Type Code: #{type_code}" | |
end | |
end | |
def taxonomy_codes | |
taxonomy_indexes = [47,50,51,54,55,58,59,62,63,66,67, | |
70,71,74,75,78,79,82,83,86,87,90, | |
91,94,95,98,99,102,103,106,314, | |
315,316,317,318,319,320,321,322, | |
323,324,325,326,327,328] | |
taxonomy_indexes.map {|i| value_at_index(i) }.reject!(&:blank?) | |
end | |
def individual_provider_attributes | |
attrs = { | |
npi: value_at_index(0), | |
replacement_npi: value_at_index(2), | |
ein: value_at_index(3), | |
last_name: value_at_index(5), | |
first_name: value_at_index(6), | |
middle_name: value_at_index(7), | |
name_prefix: value_at_index(8), | |
name_suffix: value_at_index(9), | |
provider_credential: value_at_index(10), | |
other_last_name: value_at_index(13), | |
other_first_name: value_at_index(14), | |
other_middle_name: value_at_index(15), | |
other_name_prefix: value_at_index(16), | |
other_name_suffix: value_at_index(17), | |
other_provider_credential: value_at_index(18), | |
other_last_name_type_code: value_at_index(19) | |
} | |
end | |
def organization_provider_attributes | |
attrs = { | |
npi: value_at_index(0), | |
replacement_npi: value_at_index(2), | |
ein: value_at_index(3), | |
name: value_at_index(4), | |
other_name: value_at_index(11), | |
other_name_type_code: value_at_index(12) | |
} | |
end | |
def mailing_address_attributes | |
attrs = { | |
first_line: value_at_index(20), | |
second_line: value_at_index(21), | |
city: value_at_index(22), | |
state: value_at_index(23), | |
postal_code: value_at_index(24), | |
country_code: value_at_index(25), | |
telephone_number: value_at_index(26), | |
fax_number: value_at_index(27) | |
} | |
end | |
def practice_address_attributes | |
attrs = { | |
first_line: value_at_index(28), | |
second_line: value_at_index(29), | |
city: value_at_index(30), | |
state: value_at_index(31), | |
postal_code: value_at_index(32), | |
country_code: value_at_index(33), | |
telephone_number: value_at_index(34), | |
fax_number: value_at_index(35) | |
} | |
end | |
def value_at_index(index) | |
value = @values[index] | |
value.blank? ? nil : value | |
end | |
end | |
end | |
class RowObjectBuilder | |
attr_accessor :object | |
def initialize(row, tax_cache) | |
@tax_cache = tax_cache | |
@row = Row.new(row) | |
end | |
def objectify | |
if @row.active? and @row.entity_type != 'HeaderRow' | |
if @row.entity_type == 'Individual' | |
@object = create_individual_provider | |
elsif @row.entity_type == 'Organization' | |
@object = create_organization_provider | |
else | |
raise 'Invalid Data' | |
end | |
associate_taxonomies if @object | |
associate_addresses if @object | |
@object.save if @object | |
puts @object.name if @object | |
end | |
end | |
private | |
def create_individual_provider | |
Providers::Individual.create(@row.individual_provider_attributes) | |
end | |
def create_organization_provider | |
Providers::Organization.create(@row.organization_provider_attributes) | |
end | |
def associate_taxonomies | |
taxonomy_codes = @row.taxonomy_codes | |
specs = @tax_cache.find(taxonomy_codes) | |
@object.specialties = specs | |
end | |
def associate_addresses | |
address1 = Locations::MailingAddress.new(@row.mailing_address_attributes) | |
address2 = Locations::PracticeAddress.new(@row.practice_address_attributes) | |
@object.addresses = [ | |
(address1.valid? ? address1 : nil), | |
(address2.valid? ? address2 : nil) | |
].compact | |
end | |
end | |
end | |
end | |
# ########################################################### | |
# Locations | |
# ########################################################### | |
module Locations | |
class BusinessAddress | |
include Mongoid::Document | |
include Geocoder::Model::Mongoid | |
after_validation :geocode | |
belongs_to :provider, class_name: 'Providers::Provider' | |
geocoded_by :address | |
validates_presence_of :first_line | |
validates_presence_of :city | |
validates_presence_of :state | |
validates_presence_of :postal_code | |
field :first_line, type: String | |
field :second_line, type: String | |
field :city, type: String | |
field :state, type: String | |
field :postal_code, type: String | |
field :country_code, type: String | |
field :telephone_number, type: String | |
field :fax_number, type: String | |
field :coordinates, type: Array | |
def address | |
if first_line && city && state && postal_code | |
if second_line.blank? | |
return "#{first_line}, #{city}, #{state}, #{postal_code.first(5)}" | |
else | |
return "#{first_line}, #{second_line}, #{city}, #{state}, #{postal_code.first(5)}" | |
end | |
end | |
end | |
end | |
class MailingAddress < BusinessAddress | |
end | |
class PracticeAddress < BusinessAddress | |
end | |
end | |
# ########################################################### | |
# Providers | |
# ########################################################### | |
module Providers | |
class Provider | |
include Mongoid::Document | |
field :npi, type: String | |
field :replacement_npi, type: String | |
field :ein, type: String | |
has_many :addresses, class_name: 'Locations::BusinessAddress', dependent: :destroy | |
has_and_belongs_to_many :specialties, class_name: 'Taxonomies::Specialty' | |
end | |
class Individual < Providers::Provider | |
field :last_name, type: String | |
field :first_name, type: String | |
field :middle_name, type: String | |
field :name_prefix, type: String | |
field :name_suffix, type: String | |
field :provider_credential, type: String | |
field :other_last_name, type: String | |
field :other_first_name, type: String | |
field :other_middle_name, type: String | |
field :other_name_prefix, type: String | |
field :other_name_suffix, type: String | |
field :other_provider_credential, type: String | |
field :other_last_name_type_code, type: String | |
def name | |
"#{name_prefix} #{first_name} #{last_name} #{name_suffix}, #{provider_credential}" | |
end | |
end | |
class Organization < Providers::Provider | |
field :name, type: String | |
field :other_name, type: String | |
field :other_name_type_code, type: String | |
# field : | |
end | |
end | |
# ########################################################### | |
# Taxonomies | |
# ########################################################### | |
module Taxonomies | |
class Catagory | |
include Mongoid::Document | |
has_many :types | |
field :name, type: String | |
end | |
class Type | |
include Mongoid::Document | |
belongs_to :catagory | |
has_many :classifications | |
field :name, type: String | |
field :description, type: String | |
end | |
class Specialty | |
include Mongoid::Document | |
has_and_belongs_to_many :providers, class_name: 'Providers::Provider' | |
field :name, type: String | |
field :taxonomy, type: String | |
field :active, type: Boolean | |
field :description, type: String | |
end | |
class Classification < Taxonomies::Specialty | |
belongs_to :type | |
has_many :specializations | |
end | |
class Specialization < Taxonomies::Specialty | |
belongs_to :classification | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment