aqi 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: