Class: Batch
- Inherits:
-
ApplicationRecord
show all
- Extended by:
- EventfulRecord
- Includes:
- AASM, Api::BatchIo::Extensions, Api::Messages::FlowcellIo::Extensions, PipelineBehaviour, PolyMetadataBehaviour, StateMachineBehaviour, Commentable, HasPolyMetadata, SequencingQcBatch, StandardNamedScopes, UnderRepWellCommentsToBroadcast, Uuid::Uuidable
- Defined in:
- app/models/batch.rb
Overview
A Batch groups 1 or more requests together to enable processing in a
Pipeline. All requests in a batch get usually processed together, although it is
possible for requests to get removed from a batch in a handful of cases.
Defined Under Namespace
Modules: PipelineBehaviour, PolyMetadataBehaviour, RequestBehaviour, StateMachineBehaviour
Classes: RequestFailAndRemover
Constant Summary
collapse
- DEFAULT_VOLUME =
13
UnderRepWellCommentsToBroadcast::UNDER_REPRESENTED_KEY
StandardNamedScopes::SORT_FIELDS, StandardNamedScopes::SORT_ORDERS
SequencingQcBatch::VALID_QC_STATES
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#all_requests_are_ready? ⇒ Boolean
-
#assign_positions_to_requests!(request_ids_in_position_order) ⇒ Object
Sets the position of the requests in the batch to their index in the supplied array.
-
#assigned_user ⇒ Object
-
#batch_id_matches(scanned_batch_id) ⇒ Object
-
#control ⇒ Object
-
#detach_request(request, current_user = nil) ⇒ Object
Remove a request from the batch and reset it to a point where it can be put back into the pending queue.
-
#displayed_status ⇒ Object
Summarise the state encapsulated by state and production_state Essentially a 'fail' production_state over-rides the 'state' We don't use production_state directly as it it 'fail' rather than ' failed' qc_state it kept separate as its a fairly distinct concept and is summarised elsewhere in the interface.
-
#downstream_requests_needing_asset(request) {|next_requests_needing_asset| ... } ⇒ Object
-
#event_with_description(name) ⇒ Object
-
#eventful_studies ⇒ Object
-
#fail(reason, comment, ignore_requests = false) ⇒ Object
Fail was removed from State Machine (as a state) to allow the addition of qc_state column and features.
-
#fail_requests(requests_to_fail, reason, comment, fail_but_charge = false) ⇒ Object
Fail specific requests on this batch.
-
#failed? ⇒ Boolean
-
#first_output_plate ⇒ Object
-
#flowcell ⇒ Object
-
#has_control? ⇒ Boolean
-
#has_event(event_name) ⇒ Object
Tests whether this Batch has any associated LabEvents.
-
#id_dup ⇒ Object
-
#input_labware_report ⇒ Labware::ActiveRecord_Relation
Returns a list of input labware including their barcodes, purposes, and a count of the number of requests associated with the batch.
-
#input_plate_group ⇒ Object
-
#npg_set_state ⇒ Object
-
#output_labware_report ⇒ Labware::ActiveRecord_Relation
Returns a list of output labware including their barcodes, purposes, and a count of the number of requests associated with the batch.
-
#output_plate_group ⇒ Object
-
#output_plate_purpose ⇒ Object
-
#output_plate_role ⇒ Object
-
#output_plates ⇒ Object
-
#pick_information? ⇒ Boolean
-
#plate_barcode(barcode) ⇒ Object
-
#plate_group_barcodes ⇒ Object
-
#plate_ids_in_study(study) ⇒ Object
rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity.
-
#rebroadcast ⇒ Object
-
#release_pending_requests ⇒ Object
-
#remove_request_ids(request_ids, reason = nil, comment = nil) ⇒ Object
Remove the request from the batch and remove asset information.
-
#request_count ⇒ Object
-
#reset!(current_user) ⇒ Object
rubocop:todo Metrics/MethodLength.
-
#return_request_to_inbox(request, current_user = nil) ⇒ Object
-
#robot_id ⇒ Object
-
#robot_verified!(user_id) ⇒ Object
-
#set_position_based_on_asset_barcode ⇒ Object
Sets the position of the requests in the batch based on their asset barcodes.
-
#source_labware ⇒ Object
Source Labware returns the physical pieces of labware (ie. a plate for wells, but tubes for tubes).
-
#start_requests ⇒ Object
-
#subject_type ⇒ Object
-
#swap(current_user, batch_info = {}) ⇒ Object
rubocop:todo Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize.
-
#total_volume_to_cherrypick ⇒ Object
-
#tube_barcode_matches(request, scanned_barcode) ⇒ Object
-
#underrun ⇒ Object
-
#update_batch_state(reason, comment) ⇒ Object
-
#verify_amp_plate_layout(barcodes, user = nil) ⇒ Bool
Used in the Ultima sequencing pipelines to check AMP plates are in the correct position.
-
#verify_amp_plate_position(request, barcodes) ⇒ Object
-
#verify_tube_layout(barcodes, user = nil) ⇒ Bool
Used in Sequencing pipelines to check tubes are in the correct position on the flowcell.
-
#verify_tube_position(request, barcodes) ⇒ Object
has_many_events, has_many_lab_events, has_one_event_with_family
#automatic_buffer_addition?, #buffer_volume_for_empty_wells, #plate_template_for_buffer_addition
#get_poly_metadata, #set_poly_metadata
#under_rep_comments, #under_represented_well_comments
#complete_with_user!, #editable?, #finished?, included, #release_with_user!, #start_with_user!
#has_item_limit?, included, #last_completed_task
included
included, #unsaved_uuid!, #uuid
#after_comment_addition
adjacent_state_helper, included, #processing_in_manual_qc?, #qc_manual_in_progress, #qc_previous_state!, #qc_states, state_transition_helper
included
alias_association, convert_labware_to_receptacle_for, find_by_id_or_name, find_by_id_or_name!
Methods included from Squishify
extended
#broadcast_except_externally_managed, included
Instance Attribute Details
#production_state ⇒ Object
Also referenced in StateMachineBehaviour. Either nil, or fail. This is updated in Batch#fail_requests and
Batch#fail. The former is used via BatchesController#fail_items, the latter seems to be unused.
Is intended to take precedence over both other states to track failures in-spite of QC results.
#qc_state ⇒ Object
Primarily for sequencing batches. See SequencingQcBatch. Holds the sequencing QC state
#skip_request_readiness_check ⇒ Object
Flag is used by the Generate and release batch UAT action ONLY
37
38
39
|
# File 'app/models/batch.rb', line 37
def skip_request_readiness_check
@skip_request_readiness_check
end
|
Class Method Details
.barcode_without_pick_number(code) ⇒ Object
549
550
551
|
# File 'app/models/batch.rb', line 549
def self.barcode_without_pick_number(code)
code.split('-').first
end
|
553
554
555
556
557
558
559
560
|
# File 'app/models/batch.rb', line 553
def self.(code)
split_code = code.split('-')
return Integer(split_code.last) if split_code.size > 1
1
end
|
.find_by_barcode(code) ⇒ Object
Also known as:
find_from_barcode
563
564
565
566
567
568
569
570
|
# File 'app/models/batch.rb', line 563
def find_by_barcode(code)
split_code = barcode_without_pick_number(code)
human_batch_barcode = Barcode.number_to_human(split_code)
batch = Batch.find_by(barcode: human_batch_barcode)
batch ||= Batch.find_by(id: human_batch_barcode)
batch
end
|
.prefix ⇒ Object
532
533
534
|
# File 'app/models/batch.rb', line 532
def self.prefix
'BA'
end
|
.valid_barcode?(code) ⇒ Boolean
536
537
538
539
540
541
542
543
544
545
546
547
|
# File 'app/models/batch.rb', line 536
def self.valid_barcode?(code)
begin
split_code = barcode_without_pick_number(code)
Barcode.barcode_to_human!(split_code, prefix)
rescue StandardError
return false
end
return false if find_from_barcode(code).nil?
true
end
|
Instance Method Details
#all_requests_are_ready? ⇒ Boolean
123
124
125
126
127
|
# File 'app/models/batch.rb', line 123
def all_requests_are_ready?
errors.add :base, 'All requests must be ready to be added to a batch' unless requests.all?(&:ready?)
end
|
#assign_positions_to_requests!(request_ids_in_position_order) ⇒ Object
Sets the position of the requests in the batch to their index in the supplied array.
220
221
222
223
224
225
226
227
228
229
230
231
232
|
# File 'app/models/batch.rb', line 220
def assign_positions_to_requests!(request_ids_in_position_order)
request_ids_in_batch = batch_requests.map(&:request_id)
missing_requests = request_ids_in_batch.any? { |id| request_ids_in_position_order.exclude?(id) }
= request_ids_in_position_order.any? { |id| request_ids_in_batch.exclude?(id) }
raise StandardError, 'Can only sort all the requests in the batch at once' if missing_requests ||
BatchRequest.transaction do
batch_requests.each do |batch_request|
batch_request.move_to_position!(request_ids_in_position_order.index(batch_request.request_id) + 1)
end
end
end
|
#assigned_user ⇒ Object
236
237
238
|
# File 'app/models/batch.rb', line 236
def assigned_user
assignee.try(:login) || ''
end
|
#batch_id_matches(scanned_batch_id) ⇒ Object
380
381
382
|
# File 'app/models/batch.rb', line 380
def batch_id_matches(scanned_batch_id)
scanned_batch_id == id.to_s
end
|
#control ⇒ Object
204
205
206
|
# File 'app/models/batch.rb', line 204
def control
requests.detect { |request| request.try(:asset).try(:resource?) }
end
|
#detach_request(request, current_user = nil) ⇒ Object
Remove a request from the batch and reset it to a point where it can be put back into
the pending queue.
405
406
407
408
409
410
411
412
|
# File 'app/models/batch.rb', line 405
def detach_request(request, current_user = nil)
ActiveRecord::Base.transaction do
unless current_user.nil?
request.("Used to belong to Batch #{id} removed at #{Time.zone.now}", current_user)
end
pipeline.detach_request_from_batch(self, request)
end
end
|
#displayed_status ⇒ Object
Summarise the state encapsulated by state and production_state
Essentially a 'fail' production_state over-rides the 'state'
We don't use production_state directly as it it 'fail' rather than
' failed'
qc_state it kept separate as its a fairly distinct concept and is
summarised elsewhere in the interface.
605
606
607
|
# File 'app/models/batch.rb', line 605
def displayed_status
failed? ? 'failed' : state
end
|
#downstream_requests_needing_asset(request) {|next_requests_needing_asset| ... } ⇒ Object
586
587
588
589
|
# File 'app/models/batch.rb', line 586
def downstream_requests_needing_asset(request)
next_requests_needing_asset = request.next_requests.select { |r| r.asset_id.blank? }
yield(next_requests_needing_asset) if next_requests_needing_asset.present?
end
|
#event_with_description(name) ⇒ Object
192
193
194
|
# File 'app/models/batch.rb', line 192
def event_with_description(name)
lab_events.order(id: :desc).find_by(description: name)
end
|
#eventful_studies ⇒ Object
133
134
135
|
# File 'app/models/batch.rb', line 133
def eventful_studies
requests.reduce([]) { |studies, request| studies.concat(request.eventful_studies) }.uniq
end
|
#fail(reason, comment, ignore_requests = false) ⇒ Object
Fail was removed from State Machine (as a state) to allow the addition of qc_state column and features
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# File 'app/models/batch.rb', line 142
def fail(reason, , ignore_requests = false)
raise StandardError, 'Can not fail batch without failing requests' if ignore_requests
failures.create(reason: reason, comment: , notify_remote: false)
requests.each do |request|
request.failures.create(reason: reason, comment: , notify_remote: true)
EventSender.send_fail_event(request, reason, , id) unless request.asset && request.asset.resource?
end
self.production_state = 'fail'
save!
end
|
#fail_requests(requests_to_fail, reason, comment, fail_but_charge = false) ⇒ Object
Fail specific requests on this batch
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
# File 'app/models/batch.rb', line 160
def fail_requests(requests_to_fail, reason, , fail_but_charge = false) ActiveRecord::Base.transaction do
requests
.find(requests_to_fail)
.each do |request|
logger.debug "SENDING FAIL FOR REQUEST #{request.id}, BATCH #{id}, WITH REASON #{reason}"
request.customer_accepts_responsibility! if fail_but_charge
request.failures.create(reason: reason, comment: , notify_remote: true)
EventSender.send_fail_event(request, reason, , id)
end
update_batch_state(reason, )
end
end
|
#failed? ⇒ Boolean
183
184
185
|
# File 'app/models/batch.rb', line 183
def failed?
production_state == 'fail'
end
|
#first_output_plate ⇒ Object
279
280
281
|
# File 'app/models/batch.rb', line 279
def first_output_plate
Plate.output_by_batch(self).with_wells_and_requests.first
end
|
#flowcell ⇒ Object
137
138
139
|
# File 'app/models/batch.rb', line 137
def flowcell
self if sequencing?
end
|
#has_control? ⇒ Boolean
208
209
210
|
# File 'app/models/batch.rb', line 208
def has_control?
control.present?
end
|
#has_event(event_name) ⇒ Object
Tests whether this Batch has any associated LabEvents
188
189
190
|
# File 'app/models/batch.rb', line 188
def has_event(event_name)
lab_events.any? { |event| event_name.downcase == event.description.try(:downcase) }
end
|
#id_dup ⇒ Object
301
302
303
|
# File 'app/models/batch.rb', line 301
def id_dup
id
end
|
Returns a list of input labware including their barcodes,
purposes, and a count of the number of requests associated with the
batch. Output depends on Pipeline. Some pipelines return an empty relationship
249
250
251
|
# File 'app/models/batch.rb', line 249
def input_labware_report
pipeline.input_labware requests
end
|
262
263
264
|
# File 'app/models/batch.rb', line 262
def input_plate_group
source_assets.group_by(&:plate)
end
|
#npg_set_state ⇒ Object
578
579
580
581
582
583
584
|
# File 'app/models/batch.rb', line 578
def npg_set_state
if all_requests_qced?
self.state = 'released'
qc_complete
save!
end
end
|
#output_labware_report ⇒ Labware::ActiveRecord_Relation
Returns a list of output labware including their barcodes,
purposes, and a count of the number of requests associated with the
batch. Output depends on Pipeline. Some pipelines return an empty relationship
258
259
260
|
# File 'app/models/batch.rb', line 258
def output_labware_report
pipeline.output_labware requests.with_target
end
|
#output_plate_group ⇒ Object
This looks odd. Why would a request have the same asset as target asset? Why are we filtering them out here?
267
268
269
|
# File 'app/models/batch.rb', line 267
def output_plate_group
requests.select { |r| r.target_asset != r.asset }.map(&:target_asset).select(&:present?).group_by(&:plate)
end
|
#output_plate_purpose ⇒ Object
283
284
285
|
# File 'app/models/batch.rb', line 283
def output_plate_purpose
output_plates[0].plate_purpose unless output_plates[0].nil?
end
|
#output_plate_role ⇒ Object
287
288
289
|
# File 'app/models/batch.rb', line 287
def output_plate_role
requests.first.try(:role)
end
|
#output_plates ⇒ Object
271
272
273
274
275
276
277
|
# File 'app/models/batch.rb', line 271
def output_plates
return output_labware.sort_by(&:id) if output_labware.loaded?
output_labware.reorder(id: :asc)
end
|
595
596
597
|
# File 'app/models/batch.rb', line 595
def pick_information?
pipeline.pick_information?(self)
end
|
#plate_barcode(barcode) ⇒ Object
297
298
299
|
# File 'app/models/batch.rb', line 297
def plate_barcode(barcode)
barcode.presence || requests.first.target_asset.plate.human_barcode
end
|
#plate_group_barcodes ⇒ Object
291
292
293
294
295
|
# File 'app/models/batch.rb', line 291
def plate_group_barcodes
return nil unless pipeline.group_by_parent || requests.first.target_asset.is_a?(Well)
output_plate_group.presence || input_plate_group
end
|
#plate_ids_in_study(study) ⇒ Object
rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
509
510
511
|
# File 'app/models/batch.rb', line 509
def plate_ids_in_study(study)
Plate.plate_ids_from_requests(requests.for_studies(study))
end
|
#rebroadcast ⇒ Object
591
592
593
|
# File 'app/models/batch.rb', line 591
def rebroadcast
messengers.each(&:resend)
end
|
#release_pending_requests ⇒ Object
384
385
386
387
388
|
# File 'app/models/batch.rb', line 384
def release_pending_requests
requests.each { |request| detach_request(request) if request.started? }
end
|
#remove_request_ids(request_ids, reason = nil, comment = nil) ⇒ Object
Remove the request from the batch and remove asset information
391
392
393
394
395
396
397
398
399
400
401
|
# File 'app/models/batch.rb', line 391
def remove_request_ids(request_ids, reason = nil, = nil)
ActiveRecord::Base.transaction do
Request
.find(request_ids)
.each do |request|
request.failures.create(reason: reason, comment: , notify_remote: true)
detach_request(request)
end
update_batch_state(reason, )
end
end
|
#request_count ⇒ Object
574
575
576
|
# File 'app/models/batch.rb', line 574
def request_count
requests.count
end
|
#reset!(current_user) ⇒ Object
rubocop:todo Metrics/MethodLength
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
|
# File 'app/models/batch.rb', line 427
def reset!(current_user) ActiveRecord::Base.transaction do
discard!
requests.each do |request|
request.batch = nil
return_request_to_inbox(request, current_user)
end
if requests.last.submission_id.present?
Request
.where(submission_id: requests.last.submission_id, state: 'pending')
.where.not(request_type_id: pipeline.request_type_ids)
.find_each do |request|
request.asset_id = nil
request.save!
end
end
end
end
|
#return_request_to_inbox(request, current_user = nil) ⇒ Object
414
415
416
417
418
419
420
421
422
423
424
|
# File 'app/models/batch.rb', line 414
def return_request_to_inbox(request, current_user = nil)
ActiveRecord::Base.transaction do
unless current_user.nil?
request.(
"Used to belong to Batch #{id} returned to inbox unstarted at #{Time.zone.now}",
current_user
)
end
request.return_pending_to_inbox!
end
end
|
#robot_id ⇒ Object
196
197
198
|
# File 'app/models/batch.rb', line 196
def robot_id
event_with_description('Cherrypick Layout Set')&.descriptor_value('robot_id')
end
|
#robot_verified!(user_id) ⇒ Object
521
522
523
524
525
526
527
528
529
530
|
# File 'app/models/batch.rb', line 521
def robot_verified!(user_id)
return if has_event('robot verified')
pipeline.robot_verified!(self)
lab_events.create(
description: 'Robot verified',
message: 'Robot verification completed and source volumes updated.',
user_id: user_id
)
end
|
#set_position_based_on_asset_barcode ⇒ Object
Sets the position of the requests in the batch based on their asset barcodes.
This was done at Lab request to make it easier to order the tubes in the batch.
214
215
216
217
|
# File 'app/models/batch.rb', line 214
def set_position_based_on_asset_barcode
request_ids_in_position_order = requests.sort_by { |r| r.asset.human_barcode }.map(&:id)
assign_positions_to_requests!(request_ids_in_position_order)
end
|
#source_labware ⇒ Object
Source Labware returns the physical pieces of labware (ie. a plate for wells, but tubes for tubes)
306
307
308
|
# File 'app/models/batch.rb', line 306
def source_labware
input_labware
end
|
#start_requests ⇒ Object
240
241
242
|
# File 'app/models/batch.rb', line 240
def start_requests
requests.with_assets_for_starting_requests.not_failed.map(&:start!)
end
|
#subject_type ⇒ Object
129
130
131
|
# File 'app/models/batch.rb', line 129
def subject_type
sequencing? ? 'flowcell' : 'batch'
end
|
#swap(current_user, batch_info = {}) ⇒ Object
rubocop:todo Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/AbcSize
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
|
# File 'app/models/batch.rb', line 451
def swap(current_user, batch_info = {}) return false if batch_info.empty?
batch_request_left =
BatchRequest.find_by(batch_id: batch_info['batch_1']['id'], position: batch_info['batch_1']['lane']) or
errors.add('Swap: ', 'The first lane cannot be found')
batch_request_right =
BatchRequest.find_by(batch_id: batch_info['batch_2']['id'], position: batch_info['batch_2']['lane']) or
errors.add('Swap: ', 'The second lane cannot be found')
return unless batch_request_left.present? && batch_request_right.present?
ActiveRecord::Base.transaction do
batch_request_left.request.lab_events.each do |event|
event.update!(batch_id: batch_request_right.batch_id) if event.batch_id == batch_request_left.batch_id
end
batch_request_right.request.lab_events.each do |event|
event.update!(batch_id: batch_request_left.batch_id) if event.batch_id == batch_request_right.batch_id
end
original_left_batch_id, original_left_position, original_right_request_id =
batch_request_left.batch_id,
batch_request_left.position,
batch_request_right.request_id
batch_request_right.destroy
batch_request_left.update!(batch_id: batch_request_right.batch_id, position: batch_request_right.position)
batch_request_right =
BatchRequest.create!(
batch_id: original_left_batch_id,
position: original_left_position,
request_id: original_right_request_id
)
batch_request_left.batch.lab_events.create!(
description: 'Lane swap',
message:
"Lane #{batch_request_right.position} moved to #{batch_request_left.batch_id} " \
"lane #{batch_request_left.position}",
user_id: current_user.id
)
batch_request_right.batch.lab_events.create!(
description: 'Lane swap',
message:
"Lane #{batch_request_left.position} moved to #{batch_request_right.batch_id} " \
"lane #{batch_request_right.position}",
user_id: current_user.id
)
end
true
end
|
#total_volume_to_cherrypick ⇒ Object
513
514
515
516
517
518
519
|
# File 'app/models/batch.rb', line 513
def total_volume_to_cherrypick
request = requests.first
return DEFAULT_VOLUME unless request.asset.is_a?(Well)
return DEFAULT_VOLUME unless request.target_asset.is_a?(Well)
request.target_asset.get_requested_volume
end
|
#tube_barcode_matches(request, scanned_barcode) ⇒ Object
376
377
378
|
# File 'app/models/batch.rb', line 376
def tube_barcode_matches(request, scanned_barcode)
scanned_barcode == request.asset.machine_barcode || scanned_barcode == request.asset.human_barcode
end
|
#underrun ⇒ Object
200
201
202
|
# File 'app/models/batch.rb', line 200
def underrun
has_limit? ? (item_limit - batch_requests.size) : 0
end
|
#update_batch_state(reason, comment) ⇒ Object
175
176
177
178
179
180
181
|
# File 'app/models/batch.rb', line 175
def update_batch_state(reason, )
if requests.all?(&:terminated?)
failures.create(reason: reason, comment: , notify_remote: false)
self.production_state = 'fail'
save!
end
end
|
#verify_amp_plate_layout(barcodes, user = nil) ⇒ Bool
Used in the Ultima sequencing pipelines to check AMP plates are in the correct position.
Verifies that provided barcodes are in the correct locations according to the
request 'position' within the batch.
Logs an event if the layout is correct.
354
355
356
357
358
359
360
361
362
363
|
# File 'app/models/batch.rb', line 354
def verify_amp_plate_layout(barcodes, user = nil)
requests.each { |request| verify_amp_plate_position(request, barcodes) }
if errors.empty?
lab_events.create(description: 'AMP plate layout verified', user: user)
true
else
false
end
end
|
#verify_amp_plate_position(request, barcodes) ⇒ Object
365
366
367
368
369
370
371
372
373
374
|
# File 'app/models/batch.rb', line 365
def verify_amp_plate_position(request, barcodes)
divider = '-'
scanned_barcode = barcodes[request.position - 1]
scanned_batch_id, tube_barcode = scanned_barcode.split(divider)
unless batch_id_matches(scanned_batch_id) && tube_barcode_matches(request, tube_barcode)
expected_barcode = "#{id}#{divider}#{request.asset.human_barcode}"
errors.add(:base, "The barcode at position #{request.position} is incorrect: expected #{expected_barcode}.")
end
end
|
#verify_tube_layout(barcodes, user = nil) ⇒ Bool
Used in Sequencing pipelines to check tubes are in the correct position on the flowcell.
Verifies that provided barcodes are in the correct locations according to the
request 'position' within the batch.
Logs an event if the layout is correct.
322
323
324
325
326
327
328
329
330
331
|
# File 'app/models/batch.rb', line 322
def verify_tube_layout(barcodes, user = nil)
requests.each { |request| verify_tube_position(request, barcodes) }
if errors.empty?
lab_events.create(description: 'Tube layout verified', user: user)
true
else
false
end
end
|
#verify_tube_position(request, barcodes) ⇒ Object
333
334
335
336
337
338
339
340
|
# File 'app/models/batch.rb', line 333
def verify_tube_position(request, barcodes)
scanned_barcode = barcodes[request.position - 1]
unless tube_barcode_matches(request, scanned_barcode)
expected_barcode = request.asset.human_barcode
errors.add(:base, "The tube at position #{request.position} is incorrect: expected #{expected_barcode}.")
end
end
|