Skip to content

Commit

Permalink
Revert "Revert "DPL-960- Bioscan input plate state changes""
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewsparkes authored Dec 14, 2023
1 parent 7794cff commit a7031ff
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 2 deletions.
36 changes: 36 additions & 0 deletions app/models/plate_purpose/input_started.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

# Input Plate purposes are the initial stock plates passing into
# external piplines. They have special behaviour governing their state.
# This essentially makes sure that all non-empty wells on a plate have requests
# out of them. This is intended to ensure that submissions have been
# correctly built before a plate has processed.
#
# - Input plates are progressed when all sample containing wells have requests out of them
#
# This version of the input class sets the state as started rather than passed.
class PlatePurpose::InputStarted < PlatePurpose::Input
self.state_changer = StateChanger::InputStartedPlate

UNREADY_STATE = 'pending'
PREP_STATE = 'started'
READY_STATE = 'passed'

private

# The state of the plate is determined by the state of the wells
# In this version we add an extra state PREP_STATE
def calculate_state_of_plate(wells_states)
unique_states = wells_states.uniq
return UNREADY_STATE if unique_states.include?(:unready)

case unique_states.sort
when ['failed'], %w[cancelled failed]
'failed'
when ['cancelled']
'cancelled'
else
unique_states.all?('pending') ? PREP_STATE : READY_STATE
end
end
end
2 changes: 1 addition & 1 deletion app/models/receptacle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class Receptacle < Asset # rubocop:todo Metrics/ClassLength
include Uuid::Uuidable
include Commentable
include Transfer::State
include Transfer::State::ReceptacleState
include Aliquot::Remover
include StudyReport::AssetDetails
include Receptacle::DownstreamAliquotsRemoval::Mixin
Expand Down
26 changes: 26 additions & 0 deletions app/models/state_changer/input_started_plate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

module StateChanger
# This adds an additional started state to input plates, which is used
# by the input_started plate purpose.
class InputStartedPlate < InputPlate
# Target state of labware to state of associated requests.
# All other transitions will be ignored.
self.map_target_state_to_associated_request_state = { 'failed' => 'failed', 'passed' => 'started' }

private

def associated_requests
receptacles.flat_map(&:requests_as_source)
end

def _receptacles
labware.wells.includes(:requests_as_source)
end

def transfer_requests
# We don't want to update any transfer requests
[]
end
end
end
39 changes: 39 additions & 0 deletions app/models/transfer/state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,45 @@ def state_from(state_requests)
ALL_STATES.detect { |s| unique_states.include?(s) } || default_state || 'unknown'
end

# This transfer state is specific to receptacles
# Added so can specifically check the state on certain types of input plates
# and return a default state of passed to allow well failing.
module ReceptacleState
# We have to include this specifically because it does not implicitly include the
# methods from the Transfer::State module.
include Transfer::State

def default_state
# Well state was 'unknown' without this change for our input plate because input
# plates do not have any transfer requests.
# This check was added specifically for the Bioscan pipeline, where the users wish to be able to fail
# wells at this point in the pipeline, and we need wells to be in state 'passed' for well failing to
# be allowed.
return 'passed' if input_started_plate_with_aliquots?

nil
end

private

def input_started_plate_with_aliquots?
# Had to add labware and purpose checks here as many tests seem to fail otherwise, probably
# due to incomplete factory test data setup (e.g. Well with no Plate, Tube with no purpose)
# which should not happen in reality.
return false unless labware&.purpose

labware_of_input_started_type? && labware_in_valid_state? && aliquots.present?
end

def labware_of_input_started_type?
labware.purpose.type == 'PlatePurpose::InputStarted'
end

def labware_in_valid_state?
%w[started passed].include?(labware.state)
end
end

# Plate specific behaviour
module PlateState
def self.included(base) # rubocop:todo Metrics/MethodLength
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# This is the insects in ethanol plate for the start of the Lysate pipeline
# It is the original source plate that has come in from the suppliers around the UK.
LILYS-96 Stock:
type: PlatePurpose::Input
type: PlatePurpose::InputStarted
stock_plate: true
cherrypickable_target: false
# This is the lysed material plate, ready for the Library prep pipeline. These plates
Expand Down

0 comments on commit a7031ff

Please sign in to comment.