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; foreach my $screen ( @$screens ) { my $type = $screen->sample_type; my $details = { id => $screen->id, term => $screen->description, }; push @{ $screens{$type} }, $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;