package LIMS::Controller::Admin::Screen::Test;
use strict;
use base 'LIMS::Controller::Admin';
use Moose;
with 'LIMS::Controller::Roles::DataMap';
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
__PACKAGE__->authz->authz_runmodes( ':all' => 'do_admin' );
#-------------------------------------------------------------------------------
sub list : StartRunmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
# get screens table data in list mode:
my $screens = $self->stash->{screens_data} # stashed for _check_required_data()
= $self->model('Screen')->get_all_screens({ sort_by => 'description' }); # DEBUG $screens;
# need to have at least 1 of each lab test, screening term & lab section defined:
$self->_check_required_data
|| return $self->forward('missing_data'); # returns true if OK
# a re-direct from update() passes id as param:
if ( my $id = $self->param('id') ) {
$self->query->param(id => $id); # for next section and default.tt
}
# if we have a screening term selected:
if ( my $screen_id = $self->query->param('id') ) { # warn 'screen_id:'.$screen_id;
my $lab_tests = $self->_lab_tests($screen_id); # hash of arrayrefs
$self->tt_params( lab_tests => $lab_tests );
# get assigned section details for this screen_id:
my $sections_details_map
= $self->_assigned_test_details($screen_id); # $self->debug($sections_details_map);
$self->tt_params( section_details_map => $sections_details_map );
my $lab_sections_map = $self->lab_sections_map;
$self->tt_params( lab_sections_map => $lab_sections_map );
}
# hash of screening terms: keys = tissue_type, vals = hashref of id & initial_screen_term
{
my %screens;
SCREEN: foreach my $screen ( @$screens ) {
next SCREEN unless $screen->category->is_active eq 'yes'
&& $screen->active eq 'yes' ; # skip inactive categories & terms
my $category = $screen->category->name;
my $details = {
id => $screen->id,
term => $screen->description,
};
push @{ $screens{$category} }, $details;
}
$self->tt_params( screening_list => \%screens );
}
$self->csrf_insert_token;
return $self->tt_process('admin/screen/test/default.tt');
}
#-------------------------------------------------------------------------------
sub update : Runmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
my $screen_id = $self->param('id')
|| return $self->error('no id passed to '.$self->get_current_runmode);
unless ( $self->csrf_check_token ) {
return $self->tt_process('site/csrf_error.tt');
}
my @test_ids = $self->query->param('test_id'); # DEBUG @test_ids;
unless (@test_ids) {
$self->flash( warning => $self->messages('screen')->{empty_screen_list} );
}
# collect any lab-section details separately:
my $details = $self->_get_lab_section_details();
my %args = (
screen_id => $screen_id,
test_ids => \@test_ids,
details => $details,
);
# update lab_test entries for this screen_id:
my $rtn = $self->model('Screen')->update_lab_tests(\%args); # DEBUG $rtn;
return $rtn ?
$self->error($rtn) :
$self->redirect( $self->query->url . '/admin/screen_test/list/'.$screen_id );
}
#-------------------------------------------------------------------------------
# if any lab section details submitted, create hash of lab_section_id => value:
sub _get_lab_section_details {
my $self = shift; # $self->debug($self->param);
my $params = $self->query->Vars; # can't use $dfv->valid for dynamic params
my %map;
while ( my($param, $value) = each %$params ) {
# look for param lab_section_id_(\d):
my ($lab_section_id) = $param =~ /lab_section_id_(\d+)/; # don't do '|| next' here
next unless $lab_section_id;
$map{$lab_section_id} = $value;
} # $self->debug(\%map);
return \%map;
}
#-------------------------------------------------------------------------------
# return hash: keys = section_name, vals = ref to array of { lab_test_id, lab_test_name, lab_test_field_name, active }
sub _lab_tests {
my $self = shift; $self->_debug_path('_lab_tests');
my $screen_id = shift || die 'No screen_id value passed to _lab_tests()';
my %lab_tests;
# get details of all tests in lab_tests table:
my $data = $self->model('LabTest')->get_all_active_lab_tests; # returns iterator
# get assigned lab_tests for this screen_id:
my $assigned_lab_tests_ids = $self->_assigned_lab_tests($screen_id); # arrayref of lab_test_ids
while ( my $test = $data->next ) { # DEBUG $test->lab_section->section_name;
my $section_name = $test->lab_section->section_name;
my $data = $test->as_tree;
# if the test_id matches an assigned test_id, set field to 'selected' for template:
if ( grep { $test->id == $_ } @$assigned_lab_tests_ids ) {
$data->{selected} = 1;
}
push @{ $lab_tests{ $section_name } }, $data;
} # $self->debug(\%lab_tests);
return \%lab_tests;
}
#-------------------------------------------------------------------------------
sub _assigned_lab_tests {
my $self = shift; $self->_debug_path('_assigned_lab_tests');
my $screen_id = shift || die 'No screen_id value passed to _assigned_lab_tests()';
my $assigned_tests = $self->model('Screen')->get_assigned_tests($screen_id);
my @assigned_lab_tests_ids = map { $_->lab_test_id } @$assigned_tests; # DEBUG \@assigned_lab_tests_ids;
return \@assigned_lab_tests_ids;
}
#-------------------------------------------------------------------------------
sub _assigned_test_details {
my $self = shift; $self->_debug_path('_assigned_test_details');
my $screen_id = shift || die 'No screen_id value passed to _assigned_test_details()';
my $test_details = $self->model('Screen')->get_assigned_test_details($screen_id);
my %test_details = map {
$_->lab_section_id => $_->test_details;
} @$test_details; # DEBUG \%test_details;
return \%test_details;
}
#-------------------------------------------------------------------------------
sub _check_required_data {
my $self = shift; $self->_debug_path('_check_required_data');
# first check we have at least 1 lab section defined:
unless ($self->have_lab_sections) {
$self->stash( error_msg => $self->messages('admin')->{no_sections} );
return 0;
}
# check we have at least one lab test defined:
unless ($self->have_lab_tests) {
$self->stash( error_msg => $self->messages('admin')->{no_tests} );
return 0;
}
# require at least 1 screening term to allocate lab tests to:
my $screens = $self->stash->{screens_data};
unless (@$screens) {
$self->stash( error_msg => $self->messages('admin')->{no_screens} );
return 0;
}
# OK, passed all tests:
return 1;
}
1;