package LIMS::Controller::Search;
use base 'LIMS::Base';
use Moose;
with (
'LIMS::Controller::Roles::History',
'LIMS::Controller::Roles::DataMap',
'LIMS::Controller::Roles::RecordHandler',
'LIMS::Controller::Roles::ResultHandler',
'LIMS::Controller::Roles::SearchConstraint', # generate_search_constraints()
);
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
# can't use __PACKAGE__->authz->authz_runmodes() - crashes on non-logged-in user
#-------------------------------------------------------------------------------
sub default : StartRunmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
my $errs = shift; $self->stash(errs => $errs);
return $self->forbidden() unless $self->user_can('search');
my $trials = $self->model('ClinicalTrial')->get_trials;
$self->tt_params( trials => $trials );
return $self->tt_process($errs);
}
#-------------------------------------------------------------------------------
# recieves url for a single record, by request.id:
sub load : Runmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
return $self->forbidden() unless $self->user_can('search');
my $id = $self->param('id') || return $self->forward('default');
return $self->_get_single_record($id);
}
#-------------------------------------------------------------------------------
sub do_search : Runmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
return $self->forbidden() unless $self->user_can('search');
my $dfv = $self->check_rm('default', $self->validate('search') )
|| return $self->dfv_error_page;
my $data = $dfv->valid; # $self->debug($data);
my $search_constraints = $self->generate_search_constraints($data) # $self->debug($query);
|| return $self->forward('default'); # protect against submission of empty form
# how many records match submitted search params:
my $requests_count = $self->model('Request')
->search_requests_count($search_constraints); # $self->debug($requests_count);
# stash requests_count for possible use later (eg _get_multiple_records):
$self->stash( requests_count => $requests_count );
# zero hits, or too many to handle:
if (! $requests_count || $requests_count > 1000 ) {
$self->stash->{status_msg} = $requests_count ?
sprintf $self->messages('search')->{too_many_records}, $requests_count
: $self->messages('search')->{no_records_found};
my $html = $self->forward('default');
return $self->fill_form($html);
}
# if we only have 1 record, get request.id & pass to _get_single_record():
elsif ($requests_count == 1) {
my $request_id
= $self->model('Request')->get_request_id($search_constraints);
return $self->_get_single_record($request_id);
}
# have between 2 & 1000 records
else {
return $self->_get_multiple_records($search_constraints);
}
}
#-------------------------------------------------------------------------------
sub _get_multiple_records {
my ($self, $search_constraints) = @_; $self->_debug_path();
my $q = $self->query;
my %args_for_search = (
sort_by => join ' ', $q->param('sort_by'), uc $q->param('sort_order'),
); # $self->debug(\%args_for_search);
# retrieve requests_count from do_search():
my $requests_count = $self->stash->{requests_count};
# entries per page from form or use config default:
my $entries_per_page = $q->param('entries_per_page')
|| $self->cfg('settings')->{entries_per_page}; # warn $entries_per_page;
# if > 10, invoke pager for template and add limit & offset params to \%args:
if ( $requests_count > $entries_per_page ) {
$self->pager({ query => \%args_for_search, total => $requests_count });
} # $self->debug(\%args_for_search);
{ # get record & specimens map data structures into tt_params:
my %local_args = (
search_constraints => $search_constraints,
args_for_search => \%args_for_search,
);
# get records matching search_contraints + args_for_search:
my $records = $self->model('Request')->find_requests(\%local_args);
# get specimen_map for all requests so we have 1 db hit not 1 per request:
my @request_ids = map { $_->id } @$records;
my $specimen_map = $self->specimen_map(\@request_ids);
$self->tt_params(
records => $records,
specimen_map => $specimen_map,
);
}
# get request_histories for all requests so we have 1 db hit not 1 per request:
# my $history_map = $self->get_request_histories($records); # using 'requests.created_at' now
$self->tt_params( total_count => $requests_count );
# send template through render_view() to apply symbolise() function:
return $self->render_view('search/multiple_records.tt');
}
#-------------------------------------------------------------------------------
sub _get_single_record {
my $self = shift; $self->_debug_path();
my $request_id = shift
|| return $self->error('no id passed to '.$self->get_current_runmode);
# functions transferred to LIMS::Controller::Roles::RecordHandler
my $request_data = $self->get_single_request_data($request_id)
|| return $self->error("request_id '$request_id' does not exist");
# format lab_test data for template:
$self->format_raw_lab_test_data($request_data);
$self->process_raw_lab_test_data($request_data);
# log event:
$self->history_log_event({ request_id => $request_id, event => 'view' });
# using render_view() for access to join_hash_values:
return $self->render_view('record/default.tt', $request_data);
}
1;