Class: BatchesController

Inherits:
ApplicationController show all
Defined in:
app/controllers/batches_controller.rb

Instance Method Summary collapse

Methods inherited from ApplicationController

#block_api_access, #clean_params_from_check, #evil_parameter_hack!, #extract_header_info, #set_cache_disabled!

Instance Method Details

#batch_parametersObject


75
76
77
# File 'app/controllers/batches_controller.rb', line 75

def batch_parameters
  @bp ||= params.require(:batch).permit(:assignee_id)
end

#completedObject


159
160
161
162
163
164
# File 'app/controllers/batches_controller.rb', line 159

def completed
  # The params fallback here reflects an older route where pipeline got passed in as :id. It should be removed
  # in the near future.
  @pipeline = Pipeline.find(params[:pipeline_id] || params[:id])
  @batches = @pipeline.batches.completed.order(id: :desc).includes(%i[user pipeline]).page(params[:page])
end

#createObject


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'app/controllers/batches_controller.rb', line 79

def create
  @pipeline = Pipeline.find(params[:id])

  # TODO: These should be different endpoints
  requests = @pipeline.extract_requests_from_input_params(params.to_unsafe_h)

  case params[:action_on_requests]
  when 'cancel_requests'
    transition_requests(requests, :cancel_before_started!, 'Requests cancelled')
  when 'hide_from_inbox'
    transition_requests(requests, :hold!, 'Requests hidden from inbox')
  else
    # This is the standard create action
    standard_create(requests)
  end
rescue ActiveRecord::RecordInvalid => e
  respond_to do |format|
    format.html do
      flash[:error] = e.record.errors.full_messages
      redirect_to(pipeline_path(@pipeline))
    end
    format.xml { render xml: @batch.errors.to_xml }
  end
end

#download_spreadsheetObject


349
350
351
352
353
354
# File 'app/controllers/batches_controller.rb', line 349

def download_spreadsheet
  csv_string = Tasks::PlateTemplateHandler.generate_spreadsheet(@batch)
  send_data csv_string, type: 'text/plain',
                        filename: "#{@batch.id}_cherrypick_layout.csv",
                        disposition: 'attachment'
end

#editObject


48
49
50
51
52
53
# File 'app/controllers/batches_controller.rb', line 48

def edit
  @rits = @batch.pipeline.request_information_types
  @requests = @batch.ordered_requests.includes(:batch_request, :asset, :target_asset, :comments)
  @users = User.all
  @controls = @batch.pipeline.controls
end

#edit_volume_and_concentrationObject


374
375
376
# File 'app/controllers/batches_controller.rb', line 374

def edit_volume_and_concentration
  @batch = Batch.find(params[:id])
end

#failObject


173
174
175
176
177
178
179
# File 'app/controllers/batches_controller.rb', line 173

def fail
  @fail_reasons = if @batch.workflow.source_is_internal?
                    FAILURE_REASONS['internal']
                  else
                    FAILURE_REASONS['external']
                  end
end

#fail_itemsObject


181
182
183
184
185
186
187
188
189
190
191
192
# File 'app/controllers/batches_controller.rb', line 181

def fail_items
  ActiveRecord::Base.transaction do
    fail_params = params.permit(:id, requested_fail: {}, requested_remove: {}, failure: [:reason, :comment, :fail_but_charge])
    fail_and_remover = Batch::RequestFailAndRemover.new(fail_params)
    if fail_and_remover.save
      flash[:notice] = fail_and_remover.notice
    else
      flash[:error] = fail_and_remover.errors.full_messages.join(';')
    end
    redirect_to action: :fail, id: params[:id]
  end
end

#failedObject


166
167
168
169
170
171
# File 'app/controllers/batches_controller.rb', line 166

def failed
  # The params fallback here reflects an older route where pipeline got passed in as :id. It should be removed
  # in the near future.
  @pipeline = Pipeline.find(params[:pipeline_id] || params[:id])
  @batches = @pipeline.batches.failed.order(id: :desc).includes(%i[user pipeline]).page(params[:page])
end

#filteredObject


336
# File 'app/controllers/batches_controller.rb', line 336

def filtered; end

#find_batch_by_barcodeObject


405
406
407
408
409
410
411
412
413
414
415
# File 'app/controllers/batches_controller.rb', line 405

def find_batch_by_barcode
  batch_id = LabEvent.find_batch_id_by_barcode(params[:id])
  if batch_id.nil?
    @batch_error = 'Batch id not found.'
    render action: 'batch_error', format: :xml
    return
  else
    @batch = Batch.find(batch_id)
    render action: 'show', format: :xml
  end
end

#find_batch_by_batch_idObject


370
371
372
# File 'app/controllers/batches_controller.rb', line 370

def find_batch_by_batch_id
  @batch = Batch.find(params[:batch_id])
end

#find_batch_by_idObject


366
367
368
# File 'app/controllers/batches_controller.rb', line 366

def find_batch_by_id
  @batch = Batch.find(params[:id])
end

#gwl_fileObject


356
357
358
359
360
361
362
363
364
# File 'app/controllers/batches_controller.rb', line 356

def gwl_file
  @plate_barcode = @batch.plate_barcode(params[:barcode])
  tecan_gwl_file_as_string = @batch.tecan_gwl_file_as_text(@plate_barcode,
                                                           @batch.total_volume_to_cherrypick,
                                                           params[:plate_type])
  send_data tecan_gwl_file_as_string, type: 'text/plain',
                                      filename: "#{@batch.id}_batch_#{@plate_barcode}.gwl",
                                      disposition: 'attachment'
end

#indexObject


18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'app/controllers/batches_controller.rb', line 18

def index
  if logged_in?
    @user = current_user
    @batches = Batch.where(assignee_id: @user).or(Batch.where(user_id: @user)).order(id: :desc).page(params[:page])
  else
    # Can end up here with XML. And it causes pain.
    @batches = Batch.order(id: :asc).page(params[:page]).limit(10)
  end
  respond_to do |format|
    format.html
    format.xml { render xml: @batches.to_xml }
    format.json { render json: @batches.to_json.gsub(/null/, '""') }
  end
end

#pacbio_sample_sheetObject


391
392
393
394
395
396
# File 'app/controllers/batches_controller.rb', line 391

def pacbio_sample_sheet
  csv_string = PacBio::SampleSheet.new.create_csv_from_batch(@batch)
  send_data csv_string, type: 'text/plain',
                        filename: "batch_#{@batch.id}_sample_sheet.csv",
                        disposition: 'attachment'
end

#pendingObject


133
134
135
136
137
138
# File 'app/controllers/batches_controller.rb', line 133

def pending
  # The params fallback here reflects an older route where pipeline got passed in as :id. It should be removed
  # in the near future.
  @pipeline = Pipeline.find(params[:pipeline_id] || params[:id])
  @batches = @pipeline.batches.pending.order(id: :desc).includes(%i[user pipeline]).page(params[:page])
end

#pipelineObject


104
105
106
107
# File 'app/controllers/batches_controller.rb', line 104

def pipeline
  # All pipline batches routes should just direct to batches#index with pipeline and state as filter parameters
  @batches = Batch.where(pipeline_id: params[:pipeline_id] || params[:id]).order(id: :desc).includes(:user, :pipeline).page(params[:page])
end

#previous_qc_stateObject


329
330
331
332
333
334
# File 'app/controllers/batches_controller.rb', line 329

def previous_qc_state
  @batch.qc_previous_state!(current_user)
  @batch.save
  flash[:notice] = "Batch #{@batch.id} reset to state #{@batch.qc_state}"
  redirect_to batch_url(@batch)
end

284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'app/controllers/batches_controller.rb', line 284

def print
  @task     = Task.find(params[:task_id]) if params[:task_id]
  @workflow = @batch.workflow
  @pipeline = @batch.pipeline
  @comments = @batch.comments

  if @pipeline.is_a?(CherrypickingPipeline)
    @plates = if params[:barcode]
                Plate.with_barcode(params[:barcode])
              else
                @batch.output_plates
              end
  end

  template = @pipeline.batch_worksheet
  render action: template, layout: false
end

275
276
277
278
279
280
281
282
# File 'app/controllers/batches_controller.rb', line 275

def print_barcodes
  if @batch.requests.empty?
    flash[:notice] = 'Your batch contains no requests.'
    redirect_to controller: 'batches', action: 'show', id: @batch.id
  else
    print_handler(LabelPrinter::Label::BatchTube)
  end
end

204
# File 'app/controllers/batches_controller.rb', line 204

def print_labels; end

267
268
269
# File 'app/controllers/batches_controller.rb', line 267

def print_multiplex_barcodes
  print_handler(LabelPrinter::Label::BatchMultiplex)
end

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'app/controllers/batches_controller.rb', line 229

def print_multiplex_labels
  request = @batch.requests.first
  if request.tag_number.nil?
    flash[:error] = 'No tags have been assigned.'
  elsif request.target_asset.present? && request.target_asset.children.present?
    # We are trying to find the MX library tube or the stock MX library
    # tube. I've added a filter so it doesn't pick up Lanes.
    children = request.target_asset.children.last.children.select { |a| a.is_a?(Tube) }
    @asset = if children.empty?
               request.target_asset.children.last
             else
               request.target_asset.children.last.children.last
             end
  else
    flash[:notice] = 'There is no multiplexed library available.'
  end
end

271
272
273
# File 'app/controllers/batches_controller.rb', line 271

def print_plate_barcodes
  print_handler(LabelPrinter::Label::BatchRedirect)
end

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'app/controllers/batches_controller.rb', line 210

def print_plate_labels
  @pipeline = @batch.pipeline
  @output_barcodes = []

  @output_labware = @batch.plate_group_barcodes || []

  @output_labware.each do |parent, _children|
    next if parent.nil?

    plate_barcode = parent.human_barcode
    @output_barcodes << plate_barcode if plate_barcode.present?
  end

  if @output_barcodes.blank?
    flash[:error] = 'Output plates do not have barcodes to print'
    redirect_to controller: 'batches', action: 'show', id: @batch.id
  end
end

206
207
208
# File 'app/controllers/batches_controller.rb', line 206

def print_stock_labels
  @batch = Batch.find(params[:id])
end

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'app/controllers/batches_controller.rb', line 247

def print_stock_multiplex_labels
  @batch = Batch.find(params[:id])
  request = @batch.requests.first
  pooled_library = request.target_asset.children.first
  stock_multiplexed_tube = nil

  if pooled_library.is_a_stock_asset?
    stock_multiplexed_tube = pooled_library
  elsif pooled_library.has_stock_asset?
    stock_multiplexed_tube = pooled_library.stock_asset
  end

  if stock_multiplexed_tube.nil?
    flash[:notice] = 'There is no stock multiplexed library available.'
    redirect_to controller: 'batches', action: 'show', id: @batch.id
  else
    @asset = stock_multiplexed_tube
  end
end

#qc_batchObject

Deals with QC failures leaving batches and items statuses intact


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'app/controllers/batches_controller.rb', line 110

def qc_batch
  @batch.qc_complete

  @batch.batch_requests.each do |br|
    next unless br && params[br.request_id.to_s]

    qc_state = params[br.request_id.to_s]['qc_state']
    target = br.request.target_asset
    if qc_state == 'fail'
      target.set_qc_state('failed')
      EventSender.send_fail_event(br.request_id, '', 'Failed manual QC', @batch.id)
    elsif qc_state == 'pass'
      target.set_qc_state('passed')
      EventSender.send_pass_event(br.request_id, '', 'Passed manual QC', @batch.id)
    end
    target.save
  end

  @batch.release_without_user!

  redirect_to controller: :pipelines, action: :show, id: @batch.qc_pipeline_id
end

#releasedObject


147
148
149
150
151
152
153
154
155
156
157
# File 'app/controllers/batches_controller.rb', line 147

def released
  # The params fallback here reflects an older route where pipeline got passed in as :id. It should be removed
  # in the near future.
  @pipeline = Pipeline.find(params[:pipeline_id] || params[:id])

  @batches = @pipeline.batches.released.order(id: :desc).includes(%i[user pipeline]).page(params[:page])
  respond_to do |format|
    format.html
    format.xml { render layout: false }
  end
end

#reset_batchObject


322
323
324
325
326
327
# File 'app/controllers/batches_controller.rb', line 322

def reset_batch
  pipeline = @batch.pipeline
  @batch.reset!(current_user)
  flash[:notice] = "Batch #{@batch.id} has been reset"
  redirect_to controller: 'pipelines', action: :show, id: pipeline.id
end

#sample_prep_worksheetObject


398
399
400
401
402
403
# File 'app/controllers/batches_controller.rb', line 398

def sample_prep_worksheet
  csv_string = PacBio::Worksheet.new.create_csv_from_batch(@batch)
  send_data csv_string, type: 'text/plain',
                        filename: "batch_#{@batch.id}_worksheet.csv",
                        disposition: 'attachment'
end

#saveObject


200
201
202
# File 'app/controllers/batches_controller.rb', line 200

def save
  redirect_to action: :show, id: @batch.id
end

#showObject


33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/controllers/batches_controller.rb', line 33

def show
  respond_to do |format|
    format.html do
      @submenu_presenter = Presenters::BatchSubmenuPresenter.new(current_user, @batch)

      @pipeline = @batch.pipeline
      @tasks    = @batch.tasks.sort_by(&:sorted)
      @rits = @pipeline.request_information_types
      @input_labware = @batch.input_labware_group
      @output_labware = @batch.output_labware_group
    end
    format.xml { render layout: false }
  end
end

#sortObject


194
195
196
197
198
# File 'app/controllers/batches_controller.rb', line 194

def sort
  @batch.assign_positions_to_requests!(params['requests_list'].map(&:to_i))
  @batch.rebroadcast
  head :ok
end

#startedObject


140
141
142
143
144
145
# File 'app/controllers/batches_controller.rb', line 140

def started
  # The params fallback here reflects an older route where pipeline got passed in as :id. It should be removed
  # in the near future.
  @pipeline = Pipeline.find(params[:pipeline_id] || params[:id])
  @batches = @pipeline.batches.started.order(id: :desc).includes(%i[user pipeline]).page(params[:page])
end

#swapObject


338
339
340
341
342
343
344
345
346
347
# File 'app/controllers/batches_controller.rb', line 338

def swap
  if @batch.swap(current_user, 'batch_1' => { 'id' => params['batch']['1'], 'lane' => params['batch']['position']['1'] },
                               'batch_2' => { 'id' => params['batch']['2'], 'lane' => params['batch']['position']['2'] })
    flash[:notice] = 'Successfully swapped lane positions'
    redirect_to batch_path(@batch)
  else
    flash[:error] = @batch.errors.full_messages.join('<br />')
    redirect_to action: :filtered, id: @batch.id
  end
end

#updateObject


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'app/controllers/batches_controller.rb', line 55

def update
  if batch_parameters[:assignee_id]
    user = User.find(batch_parameters[:assignee_id])
    assigned_message = "Assigned to #{user.name} (#{user.})."
  else
    assigned_message = ''
  end

  respond_to do |format|
    if @batch.update(batch_parameters)
      flash[:notice] = "Batch was successfully updated. #{assigned_message}"
      format.html { redirect_to batch_url(@batch) }
      format.xml  { head :ok }
    else
      format.html { render action: 'edit' }
      format.xml  { render xml: @batch.errors.to_xml }
    end
  end
end

#update_volume_and_concentrationObject


378
379
380
381
382
383
384
385
386
387
388
389
# File 'app/controllers/batches_controller.rb', line 378

def update_volume_and_concentration
  @batch = Batch.find(params[:batch_id])

  params[:assets].each do |id, values|
    asset = Asset.find(id)
    asset.volume = values[:volume]
    asset.concentration = values[:concentration]
    asset.save
  end

  redirect_to batch_path(@batch)
end

#verifyObject


302
303
304
305
306
# File 'app/controllers/batches_controller.rb', line 302

def verify
  @requests = @batch.ordered_requests
  @pipeline = @batch.pipeline
  @count = @requests.length
end

#verify_tube_layoutObject


308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'app/controllers/batches_controller.rb', line 308

def verify_tube_layout
  tube_barcodes = Array.new(@batch.requests.count) { |i| params["barcode_#{i}"] }

  results = @batch.verify_tube_layout(tube_barcodes, current_user)

  if results
    flash[:notice] = 'All of the tubes are in their correct positions.'
    redirect_to batch_path(@batch)
  elsif !results
    flash[:error] = @batch.errors.full_messages.sort
    redirect_to action: :verify, id: @batch.id
  end
end