Class: Request

Inherits:
ApplicationRecord show all
Extended by:
EventfulRecord, Metadata, Statistics
Includes:
AASM, Aliquot::DeprecatedBehaviours::Request, Api::RequestIO::Extensions, Batch::RequestBehaviour, Commentable, ModelExtensions::Request, CustomerResponsibility, Statemachine, StandardNamedScopes, Uuid::Uuidable
Defined in:
app/models/request.rb,
app/models/request/traction.rb,
app/models/request/traction/grid_ion.rb

Overview

A Request represents work which needs to be done, either to fulfil a customers needs CustomerRequest or for internal reasons SystemRequest. The progress of a request is tracked through its state machine.

Direct Known Subclasses

CustomerRequest, SystemRequest

Defined Under Namespace

Modules: AccessioningRequired, CustomerResponsibility, GroupingHelpers, HasNoTargetAsset, LibraryManufacture, Statemachine, Statistics, Traction Classes: AutoMultiplexing, ChangeDecision, LibraryCreation, Multiplexing

Constant Summary

Constants included from Metadata

Metadata::SECTION_FIELDS

Constants included from Statemachine

Statemachine::ACTIVE, Statemachine::COMPLETED_STATE, Statemachine::INACTIVE, Statemachine::OPENED_STATE, Statemachine::SORT_ORDER

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Metadata

has_metadata, required_tags

Methods included from EventfulRecord

has_many_events, has_many_lab_events, has_one_event_with_family

Methods included from Statistics

asset_statistics, progress_statistics, sample_statistics_new

Methods included from CustomerResponsibility

included

Methods included from Batch::RequestBehaviour

#create_batch_request!, included, #recycle_from_batch!, #return_for_inbox!, #with_batch_id

Methods included from Statemachine

#cancellable?, #change_decision!, #closed?, #failed_downstream!, #failed_upstream!, #finished?, included, #on_blocked, #on_cancelled, #on_failed, #on_hold, #on_passed, #on_started, #open?, #terminated?, #transfer_aliquots, #transition_to

Methods included from StandardNamedScopes

included

Methods included from Commentable

#after_comment_addition

Methods included from Uuid::Uuidable

included, #unsaved_uuid!, #uuid

Methods included from Api::RequestIO::Extensions

included, #json_root

Methods included from Aliquot::DeprecatedBehaviours::Request

#sample_name, #tag, #tag_number

Methods inherited from ApplicationRecord

convert_labware_to_receptacle_for, find_by_id_or_name, find_by_id_or_name!

Methods included from Warren::BroadcastMessages

#broadcast, included, #queue_associated_for_broadcast, #queue_for_broadcast, #warren

Class Method Details

.accessioning_required?Boolean

Returns:

  • (Boolean)

296
297
298
# File 'app/models/request.rb', line 296

def self.accessioning_required?
  false
end

.delegate_validatorObject


284
285
286
# File 'app/models/request.rb', line 284

def self.delegate_validator
  DelegateValidation::AlwaysValidValidator
end

.for_study(study) ⇒ Object


288
289
290
# File 'app/models/request.rb', line 288

def self.for_study(study)
  Request.for_study_id(study.id)
end

.number_expected_for_submission_id_and_request_type_id(submission_id, request_type_id) ⇒ Object


292
293
294
# File 'app/models/request.rb', line 292

def self.number_expected_for_submission_id_and_request_type_id(submission_id, request_type_id)
  Request.where(submission_id: submission_id, request_type_id: request_type_id)
end

Instance Method Details

#add_comment(comment, user, title = nil) ⇒ Object


444
445
446
# File 'app/models/request.rb', line 444

def add_comment(comment, user, title = nil)
  comments.create(description: comment, user: user, title: title)
end

#aliquot_attributesHash

Passed into cloned aliquots at the beginning of a pipeline to set appropriate options

Returns:

  • (Hash)

    A hash of aliquot attributes


375
376
377
378
379
380
381
# File 'app/models/request.rb', line 375

def aliquot_attributes
  {
    study_id: initial_study_id,
    project_id: initial_project_id,
    request_id: id
  }
end

#associated_studiesObject


360
361
362
363
364
365
366
# File 'app/models/request.rb', line 360

def associated_studies
  return [initial_study] if initial_study.present?
  return asset.studies.uniq if asset.present?
  return submission.studies if submission.present?

  []
end

#billing_product_identifierObject


518
# File 'app/models/request.rb', line 518

def billing_product_identifier; end

#cancelable?Boolean

Returns:

  • (Boolean)

467
468
469
# File 'app/models/request.rb', line 467

def cancelable?
  batch_request.nil? && (pending? || blocked?)
end

#copyObject


463
464
465
# File 'app/models/request.rb', line 463

def copy
  RequestFactory.copy_request(self)
end

#current_request_eventObject


316
317
318
319
320
321
322
# File 'app/models/request.rb', line 316

def current_request_event
  if request_events.loaded?
    request_events.detect(&:current?)
  else
    request_events.current.last
  end
end

#customer_accepts_responsibility!Object


484
485
486
# File 'app/models/request.rb', line 484

def customer_accepts_responsibility!
  # Do nothing
end

#event_with_key_value(k, v = nil) ⇒ Object


410
411
412
# File 'app/models/request.rb', line 410

def event_with_key_value(k, v = nil)
  v.nil? ? false : lab_events.with_descriptor(k, v).first
end

#eventful_studiesObject


312
313
314
# File 'app/models/request.rb', line 312

def eventful_studies
  initial_study.present? ? [initial_study] : asset_studies
end

#format_qc_informationObject


452
453
454
455
456
457
458
459
460
461
# File 'app/models/request.rb', line 452

def format_qc_information
  return [] if lab_events.empty?

  events.map do |event|
    next if event.family.nil? or not %w[pass fail].include?(event.family.downcase)

    message = event.message || '(No message was specified)'
    { 'event_id' => event.id, 'status' => event.family.downcase, 'message' => message, 'created_at' => event.created_at }
  end.compact
end

#get_value(request_information_type) ⇒ Object


383
384
385
386
387
388
389
390
# File 'app/models/request.rb', line 383

def get_value(request_information_type)
  return '' unless .respond_to?(request_information_type.key.to_sym)

  value = .send(request_information_type.key.to_sym)
  return value.to_s if value.blank? or request_information_type.data_type != 'Date'

  value.to_date.strftime('%d %B %Y')
end

#has_passed(batch, task) ⇒ Object


402
403
404
# File 'app/models/request.rb', line 402

def has_passed(batch, task)
  lab_events_for_batch(batch).any? { |event| event.description == task.name }
end

#lab_events_for_batch(batch) ⇒ Object


406
407
408
# File 'app/models/request.rb', line 406

def lab_events_for_batch(batch)
  lab_events.where(batch_id: batch.id)
end

#manifest_processed!Object


516
# File 'app/models/request.rb', line 516

def manifest_processed!; end

#next_request_type_idObject


420
421
422
423
424
425
# File 'app/models/request.rb', line 420

def next_request_type_id
  # May be nil, so can't use lazy assignment
  return @next_request_type_id if instance_variable_defined?('@next_request_type_id')

  @next_request_type_id = calculate_next_request_type_id
end

#next_requestsObject


414
415
416
417
418
# File 'app/models/request.rb', line 414

def next_requests
  return [] if submission.nil? || next_request_type_id.nil?

  next_requests_via_asset || next_requests_via_submission
end

#next_requests_via_assetObject

CAUTION!: This may not behaves as expected. I'll be deprecating this soon.


428
429
430
# File 'app/models/request.rb', line 428

def next_requests_via_asset
  target_asset.requests.where(submission_id: submission_id, request_type_id: next_request_type_id) if target_asset.present?
end

#next_requests_via_submissionObject


432
433
434
# File 'app/models/request.rb', line 432

def next_requests_via_submission
  submission.next_requests_via_submission(self)
end

#previous_failed_requests?Boolean

Returns:

  • (Boolean)

440
441
442
# File 'app/models/request.rb', line 440

def previous_failed_requests?
  asset.requests.any?(&:failed?)
end

#priorityObject


476
477
478
# File 'app/models/request.rb', line 476

def priority
  submission.try(:priority) || 0
end

#product_lineObject


512
513
514
# File 'app/models/request.rb', line 512

def product_line
  _product_line&.name
end

#project=(project) ⇒ Object


342
343
344
345
346
# File 'app/models/request.rb', line 342

def project=(project)
  return unless project

  self.project_id = project.id
end

#project_id=(project_id) ⇒ Object

Raises:

  • (RuntimeError)

324
325
326
327
328
# File 'app/models/request.rb', line 324

def project_id=(project_id)
  raise RuntimeError, 'Initial project already set' if initial_project_id

  self.initial_project_id = project_id
end

#ready?Boolean

Returns:

  • (Boolean)

504
505
506
# File 'app/models/request.rb', line 504

def ready?
  true
end

#request_type_updatable?(_new_request_type) ⇒ Boolean

Returns:

  • (Boolean)

480
481
482
# File 'app/models/request.rb', line 480

def request_type_updatable?(_new_request_type)
  pending?
end

#return_pending_to_inbox!Object

Raises:

  • (StandardError)

448
449
450
# File 'app/models/request.rb', line 448

def return_pending_to_inbox!
  raise StandardError, "Can only return pending requests, request is #{state}" unless pending?
end

#run_eventsObject


300
301
302
303
304
305
306
# File 'app/models/request.rb', line 300

def run_events
  if events.loaded?
    events.select { |e| e.message.starts_with?('Run') }
  else
    where('message LIKE "Run%"')
  end
end

#source_labwareObject


308
309
310
# File 'app/models/request.rb', line 308

def source_labware
  asset.labware
end

#study=(study) ⇒ Object


354
355
356
357
358
# File 'app/models/request.rb', line 354

def study=(study)
  return unless study

  self.study_id = study.id
end

#study_id=(study_id) ⇒ Object

Raises:

  • (RuntimeError)

348
349
350
351
352
# File 'app/models/request.rb', line 348

def study_id=(study_id)
  raise RuntimeError, 'Initial study already set' if initial_study_id

  self.initial_study_id = study_id
end

#submission_plate_countObject


330
331
332
333
334
335
336
# File 'app/models/request.rb', line 330

def submission_plate_count
  submission.requests
            .where(request_type_id: request_type_id)
            .joins(:source_labware)
            .distinct
            .count('labware.id')
end

#submitted_atObject

The date at which the submission was made. In most cases this will be similar to the request's created_at timestamp. We go via submission to ensure that copied requests bear the original timestamp.


496
497
498
499
500
501
502
# File 'app/models/request.rb', line 496

def 
  # Hopefully we shouldn't get any requests that don't have a submission. But validation is turned off, so
  # we should assume it it possible.
  return '' if submission.nil?

  submission.created_at.strftime('%Y-%m-%d')
end

#target_purposeObject


508
509
510
# File 'app/models/request.rb', line 508

def target_purpose
  nil
end

#target_tubeObject


436
437
438
# File 'app/models/request.rb', line 436

def target_tube
  target_asset if target_asset.is_a?(Tube)
end

#update_pool_information(pool_information) ⇒ Object

Adds any pool information to the structure so that it can be reported to client applications


489
490
491
492
# File 'app/models/request.rb', line 489

def update_pool_information(pool_information)
  pool_information[:request_type] = request_type.key
  pool_information[:for_multiplexing] = request_type.for_multiplexing?
end

#update_priorityObject


471
472
473
474
# File 'app/models/request.rb', line 471

def update_priority
  priority = (self.priority + 1) % 4
  submission.update!(priority: priority)
end

#update_responsibilities!Object


338
339
340
# File 'app/models/request.rb', line 338

def update_responsibilities!
  # Do nothing
end

#value_for(name, batch = nil) ⇒ Object


392
393
394
395
396
397
398
399
400
# File 'app/models/request.rb', line 392

def value_for(name, batch = nil)
  rit = RequestInformationType.find_by(name: name)
  rit_value = get_value(rit) if rit.present?
  return rit_value if rit_value.present?

  list = (batch.present? ? lab_events_for_batch(batch) : lab_events)
  list.each { |event| desc = event.descriptor_value_for(name) and return desc }
  ''
end