aqi 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aqi.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Robert Jackson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Aqi
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'aqi'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install aqi
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/aqi.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aqi/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "aqi"
8
+ gem.version = AQI::VERSION
9
+ gem.authors = ["Robert Jackson"]
10
+ gem.email = ["robertj@promedicalinc.com"]
11
+ gem.description = %q{Generates output based on the AQI schema.}
12
+ gem.summary = %q{Generates output based on the AQI schema.}
13
+ gem.homepage = "https://github.com/promedical/aqi"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,34 @@
1
+ module AQI
2
+ class AnesthesiaCase
3
+ attr_accessor :anesthesia_record_id, :anesthesia_coverage, :anesthesia_staff_set, :monitoring_set
4
+
5
+ def self.anesthesia_coverages
6
+ ["MD-ALONE", "MD-DIRECTING", "CRNA-DIRECTED", "CRNA-ALONE",
7
+ "MD-SUPERVISING", "CRNA-DIRECTING", "MD-MD"]
8
+ end
9
+
10
+ def initialize(options)
11
+ self.anesthesia_record_id = options[:anesthesia_record_id]
12
+ self.anesthesia_coverage = validate_anesthesia_coverage(options[:anesthesia_coverage])
13
+ self.anesthesia_staff_set = options[:anesthesia_staff_set] || []
14
+ self.monitoring_set = options[:monitoring_set] || []
15
+ end
16
+
17
+ def validate_anesthesia_coverage(value)
18
+ self.class.anesthesia_coverages.include?(value) ? value : nil
19
+ end
20
+
21
+ def to_xml
22
+ builder = Builder::XmlMarkup.new
23
+ builder.AnesthesiaCase do |ac|
24
+ ac.AnesthesiaRecordID(anesthesia_record_id)
25
+ ac.AnesthesiaCoverage(anesthesia_coverage) if anesthesia_coverage
26
+ ac.AnesthesiaStaffSet do |ass|
27
+ anesthesia_staff_set.each do |as|
28
+ ass << as.to_xml
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ module AQI
2
+ class AnesthesiaDetails
3
+ attr_accessor :intake_output_set_type, :intubation_details, :anesthesia_detils_set, :medications_total_set
4
+
5
+ def initialize(options)
6
+ self.intake_output_set_type = IntakeOutputSet.new(options.delete(:intake_output_set))
7
+ self.intubation_details = IntubationDetails.new(options.delete(:intubation_details))
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,83 @@
1
+ module AQI
2
+ class AnesthesiaRecord
3
+ attr_accessor :encounter
4
+
5
+ def initialize(encounter)
6
+ self.encounter = encounter
7
+ end
8
+
9
+ def to_xml
10
+ builder = Builder::XmlMarkup.new
11
+ builder.AnesthesiaRecord do |ar|
12
+ ar << demographic.to_xml
13
+ ar << procedure.to_xml
14
+ ar << anesthesia_case.to_xml
15
+ ar << pre_op.to_xml
16
+ ar << outcome_events.to_xml
17
+ #ar << post_op
18
+ #ar << timing_milestones
19
+ #ar << outcomes_events
20
+ #ar << anesthesia_details
21
+ #ar << ic_event_set
22
+ end
23
+ end
24
+
25
+ def demographic
26
+ Demographic.new(date_of_birth: encounter.date_of_birth,
27
+ postal_code: encounter.postal_code,
28
+ state: encounter.state,
29
+ city: encounter.city,
30
+ gender: encounter.gender)
31
+ end
32
+
33
+ def outcome_events
34
+ outcomes = encounter.adverse_events.collect do |ae|
35
+ {time_date: encounter.date_of_service, name: ae}
36
+ end
37
+
38
+ OutcomeEvents.new(outcomes: outcomes)
39
+ end
40
+
41
+ def services
42
+ @services ||= encounter.services + encounter.pqrs_services
43
+ end
44
+
45
+ def start_time
46
+ services.map{|s| s.start_time}.min
47
+ end
48
+
49
+ def end_time
50
+ services.map{|s| s.end_time}.max
51
+ end
52
+
53
+ def cpt_set
54
+ services.collect{|s| CPT.new(value: s.procedure_code)}
55
+ end
56
+
57
+ def procedure
58
+ Procedure.new(procedure_id: encounter.encounter_id,
59
+ facility_id: encounter.location_id,
60
+ start_time: start_time,
61
+ end_time: end_time,
62
+ location_type: encounter.place_of_service,
63
+ location_details: encounter.location_name,
64
+ cpt_set: cpt_set)
65
+ end
66
+
67
+ def anesthesia_staffs
68
+ services.collect do |s|
69
+ AnesthesiaStaff.new(staff_id: s.provider_id, role: s.provider_type)
70
+ end
71
+ end
72
+
73
+ def anesthesia_case
74
+ AnesthesiaCase.new(anesthesia_record_id: encounter.encounter_id,
75
+ anesthesia_staff_set: anesthesia_staffs)
76
+
77
+ end
78
+
79
+ def pre_op
80
+ PreOp.new(age: encounter.patient_age, icd_set: encounter.diagnosis_codes, asa_class: encounter.asa_class)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,30 @@
1
+ module AQI
2
+ class AnesthesiaRecords
3
+ attr_accessor :encounters, :practice_id
4
+
5
+ def initialize(options = {})
6
+ self.encounters = options.delete(:encounters)
7
+ self.practice_id = options.delete(:practice_id)
8
+ end
9
+
10
+ def record_header
11
+ RecordHeader.new(practice_id).to_xml
12
+ end
13
+
14
+ def anesthesia_records
15
+ encounters.collect{|e| AnesthesiaRecord.new(e)}
16
+ end
17
+
18
+ def to_xml
19
+ builder = Builder::XmlMarkup.new
20
+ builder.instruct!
21
+ builder.AnesthesiaRecords do |ars|
22
+ ars << record_header
23
+
24
+ anesthesia_records.each do |anes_record|
25
+ ars << anes_record.to_xml
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ module AQI
2
+ class AnesthesiaStaff
3
+ attr_accessor :staff_id, :responsibility, :role, :sign_in, :sign_out, :notes
4
+
5
+ def self.responsibilities
6
+ ["Supervisory", "Monitoring", "Administrative", "In charge", "Performing the case", "Medically responsible"]
7
+ end
8
+
9
+ def self.roles
10
+ ["MD", "CRNA", "DO", "RESIDENT", "PACU Nurse", "AA"]
11
+ end
12
+
13
+ def initialize(options)
14
+ self.staff_id = options[:staff_id]
15
+ self.responsibility = validate_responsibility(options[:responsibility])
16
+ self.role = validate_role(options[:role])
17
+ self.sign_in = options[:sign_in]
18
+ self.sign_out = options[:sign_out]
19
+ self.notes = options[:notes]
20
+ end
21
+
22
+ def validate_responsibility(value)
23
+ self.class.responsibilities.include?(value) ? value : nil
24
+ end
25
+
26
+ def validate_role(value)
27
+ self.class.roles.include?(value) ? value : nil
28
+ end
29
+
30
+ def to_xml
31
+ builder = Builder::XmlMarkup.new
32
+ builder.AnesthesiaStaff do |as|
33
+ as.StaffID(staff_id)
34
+ as.StaffResponsibility(responsibility) if responsibility
35
+ as.StaffRole(role) if role
36
+ as.StaffSignIn(sign_in.strftime('%FT%T')) if sign_in
37
+ as.StaffSignOut(sign_out.strftime('%FT%T')) if sign_out
38
+ as.StaffNotes(notes) if notes
39
+ end
40
+ end
41
+ end
42
+ end
data/lib/aqi/cpt.rb ADDED
@@ -0,0 +1,26 @@
1
+ module AQI
2
+ class CPT
3
+ attr_accessor :rank, :value, :modifier
4
+
5
+ def initialize(options)
6
+ self.rank = options[:rank]
7
+ self.value = validate_value(options[:value])
8
+ self.modifier = options[:modifier]
9
+ end
10
+
11
+ def validate_value(value)
12
+ value =~ /\d\d\d\d[\w\d]/ ? value : nil
13
+ end
14
+
15
+ def to_xml
16
+ return '' unless value
17
+
18
+ builder = Builder::XmlMarkup.new
19
+ builder.CPT do |cpt|
20
+ cpt.CPTRank(rank) if rank
21
+ cpt.CPTValue(value)
22
+ cpt.CPTModifier(modifier) if modifier
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module AQI
2
+ class Demographic
3
+ attr_accessor :date_of_birth, :postal_code, :state, :city, :race, :gender
4
+
5
+ def initialize(options)
6
+ self.date_of_birth = options[:date_of_birth]
7
+ self.postal_code = options[:postal_code]
8
+ self.state = options[:state]
9
+ self.city = options[:city]
10
+ self.race = options[:race]
11
+ self.gender = options[:gender]
12
+ end
13
+
14
+ def to_xml
15
+ builder = Builder::XmlMarkup.new
16
+ builder.Demographic do |d|
17
+ d.DOB(date_of_birth.strftime('%F')) if date_of_birth
18
+ d.HomeZip(postal_code)
19
+ d.HomeState(state)
20
+ d.HomeCity(city)
21
+ d.Race(race || 'UNKNOWN')
22
+ d.Gender(gender)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ module AQI
2
+ class ICEvent
3
+ attr_accessor :event_time_date, :category, :severity, :name, :description, :value, :notes
4
+
5
+ def self.categories
6
+ ["MEDICAL DEVICE/EQUIPMENT","MEDICATION", "INFRASTRUCTURE/SYSTEM", "ASSESSMENT/DOCUMENTATION",
7
+ "RESPIRATORY/AIRWAY", "CARDIOVASCULAR", "PROCEDURE RELATED", "OTHER", "UNKNOWN" ]
8
+ end
9
+
10
+ def initialize(options)
11
+ self.event_time_date = options.delete(:event_time_date)
12
+ self.category = options.delete(:category)
13
+ self.severity = options.delete(:severity)
14
+ self.name = options.delete(:name)
15
+ self.description = options.delete(:description)
16
+ self.value = options.delete(:value)
17
+ self.notes = options.delete(:notes)
18
+ end
19
+
20
+ def validate_category(value)
21
+ self.class.categories.include?(value) ? value : "UNKNOWN"
22
+ end
23
+
24
+ def to_xml
25
+ builder = Builder::XmlMarkup.new
26
+ builder.ICEvent do |ice|
27
+ ice.ICEventTimeDate(event_time_date.strftime('%FT%T')) if event_time_date
28
+ ice.ICCategory(validate_category(category))
29
+ ice.ICSeverity(severity)
30
+ ice.ICName(name)
31
+ ice.ICDesciption(description)
32
+ ice.ICValue(value)
33
+ ice.ICNotes(notes)
34
+ end
35
+ end
36
+ end
37
+
38
+ class ICEventsPreparer
39
+ def self.prepare_ic_events(outcome_events)
40
+ ic_events = outcome_events.ic_events
41
+
42
+ ic_events.collect do |event|
43
+ self.ic_event.new(event)
44
+ end
45
+ end
46
+
47
+ def self.ic_event
48
+ ICEvent
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,13 @@
1
+ module AQI
2
+ class IntakeOutputSet
3
+ attr_accessor :output_direction, :output_name, :output_units, :input_output_total, :input_output_route
4
+
5
+ def initialize(options)
6
+ self.output_direction = options.delete(:output_direction)
7
+ self.output_name = options.delete(:output_name)
8
+ self.output_units = options.delete(:output_units)
9
+ self.input_output_total = options.delete(:input_output_total)
10
+ self.input_output_route = options.delete(:input_output_route)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module AQI
2
+ class IntubationDetail
3
+ attr_accessor :intubation_approach, :intubation_attempts, :tube_size, :tube_type, :intubation_details_properties_set
4
+
5
+ def self.approach_types
6
+ ["Endoctracheal", "Nasogastric", "Nasotracheal", "Fiberoptic", "Tracheostomy", "Speaking tracheostomy", "OTHER", "UNKNOWN"]
7
+ end
8
+
9
+ def initialize(options)
10
+ self.intubation_approach = options.delete(:intubation_approach)
11
+ self.intubation_attempts = options.delete(:intubation_attempts)
12
+ self.tube_size = options.delete(:tube_size)
13
+ self.tube_type = options.delete(:intubation_details_properties_set) # Class
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,94 @@
1
+ module AQI
2
+ class Outcome
3
+ attr_accessor :time_date, :time_frame, :severity_code, :category_code, :sub_category_code, :location_type_code, :name, :description, :value, :range_min, :range_max, :notes
4
+
5
+ def initialize(options)
6
+ self.time_date = options.delete(:time_date)
7
+ self.time_frame = options.delete(:time_frame)
8
+ self.severity_code = options.delete(:severity_code)
9
+ self.category_code = options.delete(:category_code)
10
+ self.sub_category_code = options.delete(:sub_category_code)
11
+ self.location_type_code = options.delete(:location_type_code)
12
+ self.name = options.delete(:name)
13
+ self.description = options.delete(:description)
14
+ self.value = options.delete(:value)
15
+ self.range_min = options.delete(:range_min)
16
+ self.range_max = options.delete(:range_max)
17
+ self.notes = options.delete(:notes)
18
+ end
19
+
20
+ def self.time_frames
21
+ ["PreOp", "IntraOp", "PACU", "24h", "48h", "Week", "Month"]
22
+ end
23
+
24
+ def self.severities
25
+ ["NoEffect", "PotentialHazard", "LossOfTime", "LossOfMoney", "HarmToPatient", "SevereHarmToPatient", "PermanentDisability", "Death"]
26
+ end
27
+
28
+ def self.categories
29
+ ["PatientSurvey", "Outcome", "OTHER", "UNKNOWN"]
30
+ end
31
+
32
+ def self.sub_categories
33
+ ["MEDICAL DEVICE/EQUIPMENT", "MEDICATION", "INFRASTRUCTURE/SYSTEM", "ASSESSMENT/DOCUMENTATION", "RESPIRATORY/AIRWAY", "CARDIOVASCULAR", "PROCEDURE RELATED", "OTHER", "UNKNOWN"]
34
+ end
35
+
36
+ def self.location_codes
37
+ ["In-Patient", "Post In-Patient", "Out-Patient", "Post Out-Patient", "Obstetrics", "Surgery Center", "Surgery Center Post Out-Patient", "Office", "Home", "Ambulatory Surgical Center", "Pharmacy", "Skilled Nursing Facility", "Ambulance - Land", "Emergency Room Hospital", "Urgent Care Facility", "Inpatient Psychiatric Facility", "School", "Custodial Care Facility", "Residential Substance Abuse Treatment Facility", "Military Treatment Facility", "OTHER", "UNKNOWN"]
38
+ end
39
+
40
+ def to_xml
41
+ builder = Builder::XmlMarkup.new
42
+ builder.Outcome do |o|
43
+ o.OutcomeTimeDate(time_date.strftime('%FT%T')) if time_date
44
+ o.OutcomeTimeFrame(validate_time_frames(time_frame)) if time_frame
45
+ o.OutcomeSeverity(validate_severity(severity_code)) if severity_code
46
+ o.OutcomeCategory(validate_category(category_code)) if category_code
47
+ o.OutcomeSubcategory(validate_sub_category(sub_category_code)) if sub_category_code
48
+ o.OutcomeLocation(validate_location_code(location_type_code)) if location_type_code
49
+ o.OutcomeName(name) if name
50
+ o.OutcomeDesciption(description) if description
51
+ o.OutcomeValue(value) if value
52
+ o.OutcomeRangeMin(range_min) if range_min
53
+ o.OutcomeRangeMax(range_max) if range_max
54
+ o.OutcomeNotes(notes) if notes
55
+ end
56
+ end
57
+
58
+ protected
59
+
60
+ def validate_category(value)
61
+ self.class.categories.include?(value) ? value : "UNKNOWN"
62
+ end
63
+
64
+ def validate_time_frames(value)
65
+ self.class.time_frames.include?(value) ? value : ""
66
+ end
67
+
68
+ def validate_severity(value)
69
+ self.class.severities.include?(value) ? value : "NoEffect"
70
+ end
71
+
72
+ def validate_sub_category(value)
73
+ self.class.sub_categories.include?(value) ? value : "UNKNOWN"
74
+ end
75
+
76
+ def validate_location_code(value)
77
+ self.class.location_codes.include?(value) ? value : "UNKNOWN"
78
+ end
79
+ end
80
+
81
+ class OutcomesPreparer
82
+ def self.prepare_outcomes(outcome_events)
83
+ outcomes = outcome_events.outcomes
84
+
85
+ outcomes.collect do |o|
86
+ self.outcome.new(o)
87
+ end
88
+ end
89
+
90
+ def self.outcome
91
+ Outcome
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,41 @@
1
+ module AQI
2
+ class OutcomeEvents
3
+ attr_accessor :ic_events, :outcomes, :event_preparer, :outcomes_preparer
4
+ def initialize(options)
5
+ @event_preparer = options.delete(:event_preparer) || AQI::ICEventsPreparer
6
+ @ic_events = options.delete(:ic_events) || []
7
+ @outcomes_preparer = options.delete(:outcomes_preparer) || AQI::OutcomesPreparer
8
+ @outcomes = options.delete(:outcomes) || []
9
+ prepare
10
+ end
11
+
12
+ def prepare
13
+ prepare_ic_events
14
+ prepare_outcomes
15
+ end
16
+
17
+ def prepare_ic_events
18
+ self.ic_events = event_preparer.prepare_ic_events(self)
19
+ end
20
+
21
+ def prepare_outcomes
22
+ self.outcomes = outcomes_preparer.prepare_outcomes(self)
23
+ end
24
+
25
+ def to_xml
26
+ builder = Builder::XmlMarkup.new
27
+ builder.OutcomesEvents do |oe|
28
+ oe.ICEventSet do |ic_set|
29
+ self.ic_events.each do |event|
30
+ ic_set.ICEvent << event.to_xml
31
+ end
32
+ end
33
+ oe.OutcomeSet do |outcome_set|
34
+ self.outcomes.each do |outcome|
35
+ outcome_set.Outcome << outcome.to_xml
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/aqi/pre_op.rb ADDED
@@ -0,0 +1,109 @@
1
+ class PreOp
2
+
3
+ ICD = Struct.new(:rank, :value) do
4
+ def to_xml
5
+ builder = Builder::XmlMarkup.new
6
+ builder.ICD do |icd|
7
+ icd.ICDRank(rank)
8
+ icd.ICDValue(value)
9
+ end
10
+ end
11
+ end
12
+
13
+ PreRisk = Struct.new(:category, :name, :notes) do
14
+ def to_xml
15
+ builder = Builder::XmlMarkup.new
16
+ builder.PreRisk do |prs|
17
+ prs.PreOPRiskCategory(category)
18
+ prs.PreOPRiskName(name)
19
+ prs.PreOPRiskNotes(notes)
20
+ end
21
+ end
22
+ end
23
+
24
+ attr_accessor :age, :weight_pounds, :height_inches, :asa_class, :pre_anesthesia_status, :icd_set, :pre_risk_set
25
+
26
+ def initialize(options)
27
+ self.age = validate_age(options.delete(:age))
28
+ self.weight_pounds = options.delete(:weight_pounds)
29
+ self.height_inches = options.delete(:height_inches)
30
+ self.asa_class = validate_asa_class(options.delete(:asa_class))
31
+ self.pre_anesthesia_status = validate_pre_anesthesia_status(options.delete(:pre_anesthesia_status))
32
+
33
+ self.icd_set = setup_icd_set(options.delete(:icd_set))
34
+ self.pre_risk_set = setup_pre_risk_set(options.delete(:pre_risk_set))
35
+ end
36
+
37
+ def self.asa_classes
38
+ ["I", "II", "III", "IV", "V", "VI", "IE", "IIE", "IIIE", "IVE", "VE", "VIE"]
39
+ end
40
+
41
+ def self.pre_anesthesia_statuses
42
+ ["Awake", "Awake", "Asleep", "Confused", "Unresponsive", "Apprehensive", "Uncooperative", "OTHER", "UNKNOWN"]
43
+ end
44
+
45
+ def height_in_cm
46
+ self.height_inches.to_f / 0.3937
47
+ end
48
+
49
+ def weight_in_kg
50
+ self.weight_pounds.to_f / 0.45359
51
+ end
52
+
53
+ def to_xml
54
+ builder = Builder::XmlMarkup.new
55
+ builder.PreOp do |pre|
56
+ pre.Age(age) if age
57
+ pre.Weight(weight_pounds) if weight_pounds
58
+ pre.WeightInKg(weight_in_kg) if weight_pounds
59
+ pre.Height(height_inches) if height_inches
60
+ pre.HeightInCm(height_in_cm) if height_inches
61
+ pre.ASAClass(asa_class) if asa_class
62
+ pre.PreAnesthStatus(pre_anesthesia_status) if pre_anesthesia_status
63
+
64
+ pre.ICDSet do |set|
65
+ icd_set.each do |icd|
66
+ set << icd.to_xml
67
+ end
68
+ end
69
+
70
+ pre.PreRiskSet do |set|
71
+ pre_risk_set.each do |prs|
72
+ set << prs.to_xml
73
+ end
74
+ end
75
+
76
+ # pre.PreLabSet
77
+ end
78
+ end
79
+
80
+ protected
81
+
82
+ def setup_pre_risk_set(set)
83
+ return [] if set.nil?
84
+
85
+ set.collect do |args|
86
+ PreRisk.new(*args)
87
+ end
88
+ end
89
+
90
+ def setup_icd_set(set)
91
+ return [] if set.nil?
92
+
93
+ set.collect.with_index do |icd, index|
94
+ ICD.new(index + 1, icd)
95
+ end
96
+ end
97
+
98
+ def validate_age(value)
99
+ value.to_i > 0 ? value.to_i : nil
100
+ end
101
+
102
+ def validate_asa_class(value)
103
+ self.class.asa_classes.include?(value) ? value : nil # no default
104
+ end
105
+
106
+ def validate_pre_anesthesia_status(value)
107
+ self.class.pre_anesthesia_statuses.include?(value) ? value : nil
108
+ end
109
+ end
@@ -0,0 +1,70 @@
1
+ module AQI
2
+ class Procedure
3
+ attr_accessor :procedure_id, :facility_id, :location, :location_type, :location_details,
4
+ :start_time, :end_time, :admission_status, :status, :transfer_status,
5
+ :admission_date, :notes, :cpt_set
6
+
7
+ def self.admission_statuses
8
+ %w{Emergency Inpatient Outpatient Urgent OTHER UNKNOWN}
9
+ end
10
+
11
+ def self.statuses
12
+ %w{Emergent Urgent Elective OTHER UNKNOWN}
13
+ end
14
+
15
+ def self.transfer_statuses
16
+ ["Floor bed", "Observation unit", "Telemetry/step-down unit", "Home with services", "Died",
17
+ "Operating Room", "Intensive Care Unit", "Home without services", "Left against medical advice",
18
+ "Transferred to another hospital", "OTHER", "UNKNOWN"]
19
+ end
20
+
21
+ def initialize(options)
22
+ self.procedure_id = options[:procedure_id]
23
+ self.facility_id = options[:facility_id]
24
+ self.start_time = options[:start_time]
25
+ self.end_time = options[:end_time]
26
+ self.admission_status = validate_admission_status(options[:admission_status])
27
+ self.status = validate_status(options[:status])
28
+ self.transfer_status = validate_transfer_status(options[:transfer_status])
29
+ self.admission_date = options[:admission_date]
30
+ self.notes = options[:notes]
31
+ self.cpt_set = options[:cpt_set] || []
32
+
33
+ self.location = options[:location] || ProcedureLocation.new(type: options[:location_type],
34
+ details: options[:location_details])
35
+ end
36
+
37
+ def validate_admission_status(value)
38
+ self.class.admission_statuses.include?(value) ? value : 'UNKNOWN'
39
+ end
40
+
41
+ def validate_status(value)
42
+ self.class.statuses.include?(value) ? value : 'UNKNOWN'
43
+ end
44
+
45
+ def validate_transfer_status(value)
46
+ self.class.transfer_statuses.include?(value) ? value : 'UNKNOWN'
47
+ end
48
+
49
+ def to_xml
50
+ builder = Builder::XmlMarkup.new
51
+ builder.Procedure do |p|
52
+ p.ProcedureID(procedure_id)
53
+ p.FacilityID(facility_id)
54
+ p << location.to_xml
55
+ p.ProcStartTime(start_time.strftime('%FT%T')) if start_time
56
+ p.ProcEndTime(end_time.strftime('%FT%T')) if end_time
57
+ p.AdmissionStatus(admission_status)
58
+ p.ProcStatus(status)
59
+ p.TransferStatus(transfer_status)
60
+ p.AdmissionDate(admission_date.strftime('%FT%T')) if admission_date
61
+ p.ProcedureNotes(notes) if notes
62
+ p.CPTSet do |c|
63
+ cpt_set.each do |cpt|
64
+ c << cpt.to_xml
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,34 @@
1
+ module AQI
2
+ class ProcedureLocation
3
+ attr_accessor :type, :details
4
+
5
+ def self.types
6
+ ["In-Patient", "Post In-Patient", "Out-Patient", "Post Out-Patient", "Obstetrics", "Surgery Center",
7
+ "Surgery Center Post Out-Patient", "Office", "Home", "Ambulatory Surgical Center", "Pharmacy",
8
+ "Skilled Nursing Facility", "Ambulance - Land", "Emergency Room Hospital", "Urgent Care Facility",
9
+ "Inpatient Psychiatric Facility", "School", "Custodial Care Facility",
10
+ "Residential Substance Abuse Treatment Facility", "Military Treatment Facility", "OTHER", "UNKNOWN"]
11
+ end
12
+
13
+ def initialize(options)
14
+ self.type = validate_type_code(options[:type])
15
+ self.details = options[:details]
16
+ end
17
+
18
+ def validate_type_code(code)
19
+ if self.class.types.include?(code)
20
+ code
21
+ else
22
+ 'UNKNOWN'
23
+ end
24
+ end
25
+
26
+ def to_xml
27
+ builder = Builder::XmlMarkup.new
28
+ builder.ProcedureLocation do |pl|
29
+ pl.LocationType(type)
30
+ pl.LocationDetails(details)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module AQI
2
+ class RecordHeader
3
+ attr_accessor :practice_id
4
+
5
+ def initialize(practice_id)
6
+ self.practice_id = practice_id
7
+ end
8
+
9
+ def to_xml
10
+ builder = Builder::XmlMarkup.new
11
+ builder.RecordHeader do |rh|
12
+ rh.PracticeID(practice_id)
13
+ rh.CreatedBy('ProMedical')
14
+ rh.CreateDate(Time.now.strftime('%FT%T'))
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module AQI
2
+ VERSION = "0.0.3" unless defined?(AQI::VERSION)
3
+ end
data/lib/aqi.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'builder'
2
+ require 'date'
3
+ require 'pry'
4
+
5
+ require_relative "aqi/version"
6
+ require_relative "aqi/record_header"
7
+ require_relative "aqi/anesthesia_records"
8
+ require_relative "aqi/anesthesia_record"
9
+ require_relative "aqi/demographic"
10
+ require_relative "aqi/procedure_location"
11
+ require_relative "aqi/procedure"
12
+ require_relative "aqi/anesthesia_case"
13
+ require_relative "aqi/anesthesia_staff"
14
+ require_relative "aqi/ic_event"
15
+ require_relative "aqi/cpt"
16
+ require_relative "aqi/anesthesia_detail"
17
+ require_relative "aqi/intubation_detail"
18
+ require_relative "aqi/intake_output_set"
19
+ require_relative "aqi/pre_op"
20
+ require_relative "aqi/outcome_events"
21
+ require_relative "aqi/outcome"
22
+
23
+ module AQI; end
24
+
25
+ if __FILE__ == $0
26
+ class NullEncounter
27
+ Service = Struct.new(:start_time, :end_time, :performing_provider)
28
+
29
+ def date_of_birth; Time.now; end
30
+ def postal_code; "34476"; end
31
+ def state; "FL"; end
32
+ def city; "Ocala"; end
33
+ def gender; "M"; end
34
+ def encounter_id; 1; end
35
+ def location; "1003"; end
36
+ def location_name; "LROR"; end
37
+ def place_of_service; "LROR"; end
38
+ def services
39
+ [Service.new(Time.now, Time.now, "Dr. Perry Platypus")]
40
+ end
41
+ end
42
+
43
+ puts AQI::RecordHeader.new("100000").to_xml
44
+ puts AQI::AnesthesiaRecord.new(NullEncounter.new).to_xml
45
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aqi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Robert Jackson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-04 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Generates output based on the AQI schema.
15
+ email:
16
+ - robertj@promedicalinc.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - aqi.gemspec
27
+ - lib/aqi.rb
28
+ - lib/aqi/anesthesia_case.rb
29
+ - lib/aqi/anesthesia_detail.rb
30
+ - lib/aqi/anesthesia_record.rb
31
+ - lib/aqi/anesthesia_records.rb
32
+ - lib/aqi/anesthesia_staff.rb
33
+ - lib/aqi/cpt.rb
34
+ - lib/aqi/demographic.rb
35
+ - lib/aqi/ic_event.rb
36
+ - lib/aqi/intake_output_set.rb
37
+ - lib/aqi/intubation_detail.rb
38
+ - lib/aqi/outcome.rb
39
+ - lib/aqi/outcome_events.rb
40
+ - lib/aqi/pre_op.rb
41
+ - lib/aqi/procedure.rb
42
+ - lib/aqi/procedure_location.rb
43
+ - lib/aqi/record_header.rb
44
+ - lib/aqi/version.rb
45
+ homepage: https://github.com/promedical/aqi
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ none: false
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ none: false
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Generates output based on the AQI schema.
69
+ test_files: []
70
+ has_rdoc: