Module: Lab::OrdersService
- Defined in:
- app/services/lab/orders_service.rb
Overview
Manage lab orders.
Lab orders are just ordinary openmrs orders with extra metadata that separates them from other orders. Lab orders have an order type of ‘Lab’ with the order’s test type as the order’s concept. The order’s start date is the day the order is made. Additional information pertaining to the order is stored as observations that point to the order. The specimen types, requesting clinician, target lab, and reason for test are saved as observations to the order. Refer to method #order_test for more information.
Class Method Summary collapse
- .check_tracking_number(tracking_number) ⇒ Object
-
.order_test(order_params) ⇒ Object
Create a lab order.
- .update_order(order_id, params) ⇒ Object
- .update_order_result(order_params) ⇒ Object
- .update_order_status(order_params) ⇒ Object
- .void_order(order_id, reason) ⇒ Object
Class Method Details
.check_tracking_number(tracking_number) ⇒ Object
111 112 113 |
# File 'app/services/lab/orders_service.rb', line 111 def check_tracking_number(tracking_number) accession_number_exists?(tracking_number) || nlims_accession_number_exists?(tracking_number) end |
.order_test(order_params) ⇒ Object
Create a lab order.
Parameters schema:
{
encounter_id: {
type: :integer,
required: :false,
description: 'Attach order to this if program_id and patient_id are not provided'
},
program_id: { type: :integer, required: false },
patient_id: { type: :integer, required: false }
specimen: { type: :object, properties: { concept_id: :integer }, required: %i[concept_id] },
test_type_ids: {
type: :array,
items: {
type: :object,
properties: { concept_id: :integer },
required: %i[concept_id]
}
},
start_date: { type: :datetime }
accession_number: { type: :string }
target_lab: { type: :string },
reason_for_test_id: { type: :integer },
requesting_clinician: { type: :string }
}
encounter_id: is an ID of the encounter the lab order is to be created under test_type_id: is a concept_id of the name of test being ordered specimen_type_id: is a list of IDs for the specimens to be tested (can be ommited) target_lab: is the name of the lab where test will be carried out reason_for_test_id: is a concept_id for a (standard) reason of why the test is being carried out requesting_clinician: Name of the clinician requesting the test (defaults to current user)
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'app/services/lab/orders_service.rb', line 52 def order_test(order_params) Order.transaction do encounter = find_encounter(order_params) if order_params[:accession_number].present? && check_tracking_number(order_params[:accession_number]) raise 'Accession number already exists' end order = create_order(encounter, order_params) Lab::TestsService.create_tests(order, order_params[:date], order_params[:tests]) Lab::LabOrderSerializer.serialize_order( order, requesting_clinician: add_requesting_clinician(order, order_params), reason_for_test: add_reason_for_test(order, order_params), target_lab: add_target_lab(order, order_params) ) end end |
.update_order(order_id, params) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'app/services/lab/orders_service.rb', line 71 def update_order(order_id, params) specimen_id = params.dig(:specimen, :concept_id) raise ::InvalidParameterError, 'Specimen concept_id is required' unless specimen_id order = Lab::LabOrder.find(order_id) if order.concept_id != unknown_concept_id && !params[:force_update]&.casecmp?('true') raise ::UnprocessableEntityError, "Can't change order specimen once set" end if specimen_id.to_i != order.concept_id Rails.logger.debug("Updating order ##{order.order_id}") order.update!(concept_id: specimen_id, discontinued: true, discontinued_by: User.current.user_id, discontinued_date: params[:date]&.to_date || Time.now, discontinued_reason_non_coded: 'Sample drawn/updated') end reason_for_test = params[:reason_for_test] || params[:reason_for_test_id] if reason_for_test Rails.logger.debug("Updating reason for test on order ##{order.order_id}") update_reason_for_test(order, Concept.find(reason_for_test)&.id) end Lab::LabOrderSerializer.serialize_order(order) end |
.update_order_result(order_params) ⇒ Object
134 135 136 137 138 139 |
# File 'app/services/lab/orders_service.rb', line 134 def update_order_result(order_params) order = find_order(order_params['tracking_number']) order_dto = Lab::Lims::OrderSerializer.serialize_order(order) patch_order_dto_with_lims_results!(order_dto, order_params['results']) Lab::Lims::PullWorker.new(nil).process_order(order_dto) end |
.update_order_status(order_params) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'app/services/lab/orders_service.rb', line 115 def update_order_status(order_params) # find the order order = find_order(order_params['tracking_number']) concept = ConceptName.find_by_name Lab::Metadata::LAB_ORDER_STATUS_CONCEPT_NAME ActiveRecord::Base.transaction do void_order_status(order, concept) Observation.create!( person_id: order.patient_id, encounter_id: order.encounter_id, concept_id: concept.concept_id, order_id: order.id, obs_datetime: order_params['status_time'] || Time.now, value_text: order_params['status'], creator: User.current.id ) end create_rejection_notification(order_params) if order_params['status'] == 'test-rejected' end |
.void_order(order_id, reason) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 |
# File 'app/services/lab/orders_service.rb', line 99 def void_order(order_id, reason) order = Lab::LabOrder.includes(%i[requesting_clinician reason_for_test target_lab], tests: [:result]) .find(order_id) order.requesting_clinician&.void(reason) order.reason_for_test&.void(reason) order.target_lab&.void(reason) order.tests.each { |test| test.void(reason) } order.void(reason) end |