Class: TransferRequest

Inherits:
ApplicationRecord show all
Extended by:
Request::Statemachine::ClassMethods
Includes:
AASM, AASM::Extensions, Uuid::Uuidable
Defined in:
app/models/transfer_request.rb

Overview

Note:

The setting of submission_id and outer_request is quite complicated, and depends

Every request “moving” an asset from somewhere to somewhere else without really transforming it (chemically) as, cherrypicking, pooling, spreading on the floor etc

on the exact route by which the transfer request has been created. The preferred route is by setting outer_request explicitly. However much of the historic code handles it via submission_id, either set explicitly, (eg Transfer::BetweenPlates#calculate_location_submissions) or extracted from the pool_id attribute on well, which itself is populated as part of an sql query. (See #with_pool_id on the well association in Plate)

Constant Summary collapse

ACTIVE_STATES =

States which are still considered to be processable (ie. not failed or cancelled)

%w[pending started passed qc_complete].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from AASM::Extensions

#transition_to

Methods included from Uuid::Uuidable

included, #unsaved_uuid!, #uuid

Methods inherited from ApplicationRecord

alias_association, convert_labware_to_receptacle_for, find_by_id_or_name, find_by_id_or_name!

Methods included from Squishify

extended

Instance Attribute Details

#aliquot_attributes=(value) ⇒ Object

Sets the attribute aliquot_attributes

Parameters:

  • value

    the value to set the attribute aliquot_attributes to.



27
28
29
# File 'app/models/transfer_request.rb', line 27

def aliquot_attributes=(value)
  @aliquot_attributes = value
end

#keep_this_aliquot_when_deduplicatingObject

merge_equivalent_aliquots determines if we attempt to filter out equivalent aliquots before performing transfers. list_of_aliquot_attributes_to_consider_a_duplicate is optional, and is used to determine which aliquots are equivalent for custom use cases. keep_this_aliquot_when_deduplicating is optional, and is used to determine which aliquot to keep from the duplicates in custom cases.



24
25
26
# File 'app/models/transfer_request.rb', line 24

def keep_this_aliquot_when_deduplicating
  @keep_this_aliquot_when_deduplicating
end

#list_of_aliquot_attributes_to_consider_a_duplicateObject

merge_equivalent_aliquots determines if we attempt to filter out equivalent aliquots before performing transfers. list_of_aliquot_attributes_to_consider_a_duplicate is optional, and is used to determine which aliquots are equivalent for custom use cases. keep_this_aliquot_when_deduplicating is optional, and is used to determine which aliquot to keep from the duplicates in custom cases.



24
25
26
# File 'app/models/transfer_request.rb', line 24

def list_of_aliquot_attributes_to_consider_a_duplicate
  @list_of_aliquot_attributes_to_consider_a_duplicate
end

#merge_equivalent_aliquotsObject

merge_equivalent_aliquots determines if we attempt to filter out equivalent aliquots before performing transfers. list_of_aliquot_attributes_to_consider_a_duplicate is optional, and is used to determine which aliquots are equivalent for custom use cases. keep_this_aliquot_when_deduplicating is optional, and is used to determine which aliquot to keep from the duplicates in custom cases.



24
25
26
# File 'app/models/transfer_request.rb', line 24

def merge_equivalent_aliquots
  @merge_equivalent_aliquots
end

Instance Method Details

#outer_requestObject



163
164
165
# File 'app/models/transfer_request.rb', line 163

def outer_request
  asset.outer_request(submission_id)
end

#outer_request=(request) ⇒ Object

Note:

This is particularly important when transferring out of the initial

Set the outer request associated with this transfer request the outer request is the Request which is currently being processed, such as a LibraryCreationRequest. Setting this ensures that the transferred Aliquots are associated with the correct request, and that submission_id on transfer request is recorded correctly. Receptacle when there may be multiple active Receptacle#requests_as_source

Parameters:

  • request (Request)

    The request which is being processed



152
153
154
155
# File 'app/models/transfer_request.rb', line 152

def outer_request=(request)
  @outer_request = request
  self.submission_id = request.submission_id
end

#outer_request_candidates_lengthObject



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'app/models/transfer_request.rb', line 178

def outer_request_candidates_length
  # Its a simple scenario, we avoid doing anything fancy and just give the thumbs up
  return true if one_or_fewer_outer_requests?

  # @todo The code below assumes that if we've got multiple outer requests then
  #       we must be at the multiplexing stage further down the pipeline. While
  #       this seems to be true in practice, it could result in some strange behaviour
  #       if triggered in other circumstances. One example was when the PacBio Library
  #       prep pipeline had multiple requests in the same submission out of each well.
  #       In this case the source aliquots didn't have a submission id set, so we couldn't
  #       find a next request to select.
  #
  #       The code currently:
  #       - For each aliquot in the receptacle detects an 'outer request' that is the next request in
  #         the submission after the request associated with the aliquot.
  #       - Ensures that this works for all aliquots in the receptacle
  #       - Creates an error for any that don't have a next request
  #
  #       In the example above, this was failing because the aliquot wasn't associated with a request,
  #       so it made no sense to find a 'next request in the submission'. It should still have failed,
  #       as the outer_request is ambiguous, but its kind of failing by accident.
  #
  #      = Fixing this
  #
  #      Firstly, I *think* this code is currently doing the right things, for the wrong reasons. So I
  #      believe it falls under general maintenance, rather than a bug fix. But all that could change.
  #
  #      This should probably be addressed as part of #3100 (https://github.com/sanger/sequencescape/issues/3100)
  #      The main aim here should probably to aim for explicitness and simplicity, rather than making
  #      this code more complicated to handle further cases.
  #
  # If we're a bit more complicated attempt to match up requests
  # This operation is a bit expensive, but needs to handle scenarios where:
  # 1) We've already done some pooling, and have multiple requests in and out
  # 2) We've got multiple aliquots from a single request, such as in Chromium
  # Failing silently at this point could result in aliquots being assigned to the wrong study
  # or the correct request information being missing downstream. (Which is then tricky to diagnose and repair)
  asset
    .aliquots
    .reduce(true) do |valid, aliquot|
      compatible = next_request_index[aliquot.id].present?
      unless compatible
        errors.add(:outer_request, "not found for aliquot #{aliquot.id} with previous request #{aliquot.request}")
      end
      valid && compatible
    end
end

#outer_request_id=(request_id) ⇒ Object

Sets the #outer_request from just a request_id

Parameters:



159
160
161
# File 'app/models/transfer_request.rb', line 159

def outer_request_id=(request_id)
  self.outer_request = Request.find(request_id)
end

#sibling_requestsObject

A sibling request is a customer request out of the same asset and in the same submission



168
169
170
171
172
173
174
175
176
# File 'app/models/transfer_request.rb', line 168

def sibling_requests # rubocop:todo Metrics/AbcSize
  if associated_requests.loaded?
    associated_requests.select { |r| r.submission_id == submission_id }
  elsif asset.requests.loaded?
    asset.requests.select { |r| r.submission_id == submission_id }
  else
    associated_requests.where(submission: submission_id)
  end
end

#source_and_target_assets_are_differentObject

validation method



136
137
138
139
140
141
142
# File 'app/models/transfer_request.rb', line 136

def source_and_target_assets_are_different
  return true unless asset_id.present? && asset_id == target_asset_id

  errors.add(:asset, 'cannot be the same as the target')
  errors.add(:target_asset, 'cannot be the same as the source')
  false
end