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)

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

def self.accessioning_required?
  false
end

.delegate_validatorObject


394
395
396
# File 'app/models/request.rb', line 394

def self.delegate_validator
  DelegateValidation::AlwaysValidValidator
end

.for_study(study) ⇒ Object


398
399
400
# File 'app/models/request.rb', line 398

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


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

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


569
570
571
# File 'app/models/request.rb', line 569

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


500
501
502
503
504
505
506
# File 'app/models/request.rb', line 500

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

#associated_studiesObject


485
486
487
488
489
490
491
# File 'app/models/request.rb', line 485

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


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

def billing_product_identifier; end

#cancelable?Boolean

Returns:

  • (Boolean)

592
593
594
# File 'app/models/request.rb', line 592

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

#copyObject


588
589
590
# File 'app/models/request.rb', line 588

def copy
  RequestFactory.copy_request(self)
end

#current_request_eventObject


426
427
428
429
430
431
432
# File 'app/models/request.rb', line 426

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

#customer_accepts_responsibility!Object


609
610
611
# File 'app/models/request.rb', line 609

def customer_accepts_responsibility!
  # Do nothing
end

#event_with_key_value(k, v = nil) ⇒ Object


535
536
537
# File 'app/models/request.rb', line 535

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

#eventful_studiesObject


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

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

#format_qc_informationObject


577
578
579
580
581
582
583
584
585
586
# File 'app/models/request.rb', line 577

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


508
509
510
511
512
513
514
515
# File 'app/models/request.rb', line 508

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


527
528
529
# File 'app/models/request.rb', line 527

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

#lab_events_for_batch(batch) ⇒ Object


531
532
533
# File 'app/models/request.rb', line 531

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

#manifest_processed!Object


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

def manifest_processed!; end

#next_request_type_idObject


545
546
547
548
549
550
# File 'app/models/request.rb', line 545

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


539
540
541
542
543
# File 'app/models/request.rb', line 539

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.


553
554
555
# File 'app/models/request.rb', line 553

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


557
558
559
# File 'app/models/request.rb', line 557

def next_requests_via_submission
  submission.next_requests_via_submission(self)
end

#previous_failed_requests?Boolean

Returns:

  • (Boolean)

565
566
567
# File 'app/models/request.rb', line 565

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

#priorityObject


601
602
603
# File 'app/models/request.rb', line 601

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

#product_lineObject


637
638
639
# File 'app/models/request.rb', line 637

def product_line
  _product_line&.name
end

#project=(project) ⇒ Object


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

def project=(project)
  return unless project

  self.project_id = project.id
end

#project_id=(project_id) ⇒ Object

Raises:

  • (RuntimeError)

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

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)

629
630
631
# File 'app/models/request.rb', line 629

def ready?
  true
end

#request_type_updatable?(_new_request_type) ⇒ Boolean

Returns:

  • (Boolean)

605
606
607
# File 'app/models/request.rb', line 605

def request_type_updatable?(_new_request_type)
  pending?
end

#return_pending_to_inbox!Object

Raises:

  • (StandardError)

573
574
575
# File 'app/models/request.rb', line 573

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

#run_eventsObject


410
411
412
413
414
415
416
# File 'app/models/request.rb', line 410

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

#source_labwareObject


418
419
420
# File 'app/models/request.rb', line 418

def source_labware
  asset.labware
end

#study=(study) ⇒ Object


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

def study=(study)
  return unless study

  self.study_id = study.id
end

#study_id=(study_id) ⇒ Object

Raises:

  • (RuntimeError)

473
474
475
476
477
# File 'app/models/request.rb', line 473

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

  self.initial_study_id = study_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.


621
622
623
624
625
626
627
# File 'app/models/request.rb', line 621

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


633
634
635
# File 'app/models/request.rb', line 633

def target_purpose
  nil
end

#target_tubeObject


561
562
563
# File 'app/models/request.rb', line 561

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


614
615
616
617
# File 'app/models/request.rb', line 614

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

#update_priorityObject


596
597
598
599
# File 'app/models/request.rb', line 596

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

#update_responsibilities!Object


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

def update_responsibilities!
  # Do nothing
end

#value_for(name, batch = nil) ⇒ Object


517
518
519
520
521
522
523
524
525
# File 'app/models/request.rb', line 517

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