Module: Lab::OrderLocationResolver

Defined in:
app/services/lab/order_location_resolver.rb

Overview

Resolves the location that should be used for lab sync records.

LIMS workers often run as lab_daemon, whose current location can differ from the clinician/order location. Order-linked observations are the most reliable source because they carry the location where the order was created.

Constant Summary collapse

ORDER_OBSERVATION_CONCEPT_NAMES =
[
  Lab::Metadata::TEST_TYPE_CONCEPT_NAME,
  Lab::Metadata::TEST_METHOD_CONCEPT_NAME,
  Lab::Metadata::REQUESTING_CLINICIAN_CONCEPT_NAME,
  Lab::Metadata::REASON_FOR_TEST_CONCEPT_NAME,
  Lab::Metadata::TARGET_LAB_CONCEPT_NAME,
  Lab::Metadata::COMMENT_TO_FULFILLER_CONCEPT_NAME
].freeze

Class Method Summary collapse

Class Method Details

.creator_location_for_order(order) ⇒ Object



81
82
83
84
85
86
87
# File 'app/services/lab/order_location_resolver.rb', line 81

def creator_location_for_order(order)
  creator_id = record_creator_id(order)
  return nil if creator_id.blank?

  user = User.unscoped.find_by(user_id: creator_id)
  location_by_id(user&.location_id)
end

.encounter_location_for_order(order) ⇒ Object



77
78
79
# File 'app/services/lab/order_location_resolver.rb', line 77

def encounter_location_for_order(order)
  location_by_id(encounter_location_id_for_record(order))
end

.encounter_location_id_for_record(record) ⇒ Object



102
103
104
105
106
107
# File 'app/services/lab/order_location_resolver.rb', line 102

def encounter_location_id_for_record(record)
  encounter_id = record_encounter_id(record)
  return nil if encounter_id.blank?

  Encounter.unscoped.find_by(encounter_id:)&.location_id
end

.location_by_id(location_id) ⇒ Object



63
64
65
66
67
# File 'app/services/lab/order_location_resolver.rb', line 63

def location_by_id(location_id)
  return nil if location_id.blank? || location_id.to_i.zero?

  Location.unscoped.find_by(location_id:)
end

.location_for_order(order, fallback_location_id: nil, facility_name: nil) ⇒ Object



23
24
25
26
27
28
29
30
# File 'app/services/lab/order_location_resolver.rb', line 23

def location_for_order(order, fallback_location_id: nil, facility_name: nil)
  observation_location_for_order(order) ||
    location_by_id(fallback_location_id || record_location_id(order)) ||
    encounter_location_for_order(order) ||
    creator_location_for_order(order) ||
    location_from_name(facility_name) ||
    Location.current_health_center
end

.location_for_order_id(order_id, fallback_location_id: nil, facility_name: nil) ⇒ Object



36
37
38
39
40
# File 'app/services/lab/order_location_resolver.rb', line 36

def location_for_order_id(order_id, fallback_location_id: nil, facility_name: nil)
  order = Lab::LabOrder.unscoped.find_by(order_id:)

  location_for_order(order, fallback_location_id:, facility_name:)
end

.location_for_test(test) ⇒ Object



46
47
48
49
50
# File 'app/services/lab/order_location_resolver.rb', line 46

def location_for_test(test)
  location_for_order_id(record_order_id(test), fallback_location_id: record_location_id(test)) ||
    location_by_id(record_location_id(test)) ||
    location_by_id(encounter_location_id_for_record(test))
end

.location_from_name(name) ⇒ Object



56
57
58
59
60
61
# File 'app/services/lab/order_location_resolver.rb', line 56

def location_from_name(name)
  name = name.to_s.strip
  return nil if name.blank? || name.casecmp?('Unknown') || name.casecmp?('not_assigned')

  Location.unscoped.where('LOWER(name) = ?', name.downcase).first
end

.location_id_for_order(order, fallback_location_id: nil, facility_name: nil) ⇒ Object



32
33
34
# File 'app/services/lab/order_location_resolver.rb', line 32

def location_id_for_order(order, fallback_location_id: nil, facility_name: nil)
  location_for_order(order, fallback_location_id:, facility_name:)&.location_id
end

.location_id_for_order_id(order_id, fallback_location_id: nil, facility_name: nil) ⇒ Object



42
43
44
# File 'app/services/lab/order_location_resolver.rb', line 42

def location_id_for_order_id(order_id, fallback_location_id: nil, facility_name: nil)
  location_for_order_id(order_id, fallback_location_id:, facility_name:)&.location_id
end

.location_id_for_test(test) ⇒ Object



52
53
54
# File 'app/services/lab/order_location_resolver.rb', line 52

def location_id_for_test(test)
  location_for_test(test)&.location_id
end

.observation_location_for_order(order) ⇒ Object



69
70
71
72
73
74
75
# File 'app/services/lab/order_location_resolver.rb', line 69

def observation_location_for_order(order)
  order_id = record_order_id(order)
  return nil if order_id.blank?

  location_id = prioritized_order_observations(order_id).first&.location_id
  location_by_id(location_id)
end

.order_location_concept_idsObject



98
99
100
# File 'app/services/lab/order_location_resolver.rb', line 98

def order_location_concept_ids
  ConceptName.where(name: ORDER_OBSERVATION_CONCEPT_NAMES).pluck(:concept_id)
end

.prioritized_order_observations(order_id) ⇒ Object



89
90
91
92
93
94
95
96
# File 'app/services/lab/order_location_resolver.rb', line 89

def prioritized_order_observations(order_id)
  scope = Observation.unscoped.where(order_id:, voided: 0).where.not(location_id: [nil, 0])
  concept_ids = order_location_concept_ids
  return scope.order(:date_created, :obs_id) if concept_ids.blank?

  quoted_ids = concept_ids.map(&:to_i).join(',')
  scope.order(Arel.sql("CASE WHEN concept_id IN (#{quoted_ids}) THEN 0 ELSE 1 END, date_created ASC, obs_id ASC"))
end

.record_creator_id(record) ⇒ Object



130
131
132
133
134
135
# File 'app/services/lab/order_location_resolver.rb', line 130

def record_creator_id(record)
  return nil unless record
  return record.creator if record.respond_to?(:creator)

  value_from_hash(record, :creator)
end

.record_encounter_id(record) ⇒ Object



116
117
118
119
120
121
# File 'app/services/lab/order_location_resolver.rb', line 116

def record_encounter_id(record)
  return nil unless record
  return record.encounter_id if record.respond_to?(:encounter_id)

  value_from_hash(record, :encounter_id)
end

.record_location_id(record) ⇒ Object



123
124
125
126
127
128
# File 'app/services/lab/order_location_resolver.rb', line 123

def record_location_id(record)
  return nil unless record
  return record.location_id if record.respond_to?(:location_id)

  value_from_hash(record, :location_id)
end

.record_order_id(record) ⇒ Object



109
110
111
112
113
114
# File 'app/services/lab/order_location_resolver.rb', line 109

def record_order_id(record)
  return nil unless record
  return record.order_id if record.respond_to?(:order_id)

  value_from_hash(record, :order_id) || value_from_hash(record, :id)
end

.value_from_hash(record, key) ⇒ Object



137
138
139
140
141
# File 'app/services/lab/order_location_resolver.rb', line 137

def value_from_hash(record, key)
  return nil unless record.respond_to?(:[])

  record[key] || record[key.to_s]
end