package LIMS::Controller::WorkList; use base 'LIMS::Base'; use Moose; with ( 'LIMS::Controller::Roles::Misc', 'LIMS::Controller::Roles::User', 'LIMS::Controller::Roles::DataMap', 'LIMS::Controller::Roles::FormData', ); __PACKAGE__->meta->make_immutable(inline_constructor => 0); use Data::Dumper; # ------------------------------------------------------------------------------ sub default : StartRunmode { my $self = shift; $self->_debug_path($self->get_current_runmode); my $active_sections = $self->model('WorkList')->get_active_sections_list; my $request_status_options = $self->request_status_options_map; # locally defined worklists: if ( my $yaml = $self->get_yaml_file('local_worklists') ) { # warn Dumper $yaml; $self->tt_params( local_worklists => $yaml ); } # print labels: if ( my $yaml = $self->get_yaml_file('print_labels') ) { $self->tt_params( print_labels => $yaml ); } $self->tt_params( active_sections => $active_sections, request_status_options => $request_status_options, ); return $self->tt_process; } # ------------------------------------------------------------------------------ sub select : Runmode { my $self = shift; $self->_debug_path($self->get_current_runmode); # don't need ValidateRM->check() as vars passed automatically on submit: my $profile = $self->validate('worklist'); my $data = $self->get_data_from_dfv($profile); # $self->debug($data); my $lab_section_id = $data->{lab_section_id} || return $self->redirect( $self->query->url . '/worklist' ); { # active investigations for this section: my $investigations = $self->model('WorkList') ->get_active_investigations_for_section($lab_section_id); $self->tt_params( active_investigations => $investigations ); } { # lab_test status_options for this section: my $section_status_options = $self->get_status_options_for_select($lab_section_id); $self->tt_params( status_options => $section_status_options ); } # get list of lab sections to require clinical trial filter if ( my $cfg = $self->get_yaml_file('worklist_cfg') ) { # warn Dumper $cfg; # check it's generating hashref or die (can't return $self->error here): die "yml doesn't return hashref" unless ref $cfg eq 'HASH'; if ( my $sections = $cfg->{clinical_trial_filter}{lab_sections} ) { # warn Dumper $sections; $self->tt_params( exclude_clinical_trial_sections => $sections ); } } # return to default() to load lab_sections & re-display: return $self->forward('default'); } # ------------------------------------------------------------------------------ # for dashboard lab-test status charts, retrieves section.id for param 'id', and # status_option.id & lab_test.id for query params & forwards to display(): sub test_status : Runmode { my $self = shift; $self->_debug_path($self->get_current_runmode); my $vars = $self->query->Vars(); my ($status_option, $section_name, $test_name) = map $vars->{$_}, qw(status section_name lab_test); # warn Dumper [$status_option, $section_name, $lab_test]; my $section = $self->model('LabSection') ->get_lab_section_by_name($section_name); # display() expects lab_section.id passing as param 'id': $self->param( id => $section->id ); # lab_section.id { # lab_test.id as query param: my %args = ( lab_section_id => $section->id, lab_test => $test_name ); my $lab_test = $self->model('LabTest')->get_section_lab_test(\%args); $self->query->param( lab_test_id => $lab_test->id ); } { # lab_test_status_option.id as query param: my $options_map = $self->lab_test_status_options_map('description'); my $option_id = $options_map->{$status_option}->{id}; # warn Dumper $option_id; $self->query->param( status_option_id => $option_id ); } return $self->forward('display'); } # ------------------------------------------------------------------------------ sub display : Runmode { my $self = shift; $self->_debug_path($self->get_current_runmode); my $errs = shift; # $self->stash( errs => $errs ); # warn Dumper $errs; my $lab_section_id = $self->param('id') || return $self->error('no lab_section_id passed to ' . $self->get_current_runmode); # don't need ValidateRM->check() as vars passed automatically on submit: my $profile = $self->validate('worklist'); my $data = $self->get_data_from_dfv($profile); # warn Dumper $data; # do NOT want status_option_id if returning from update_results() with error: delete $data->{status_option_id} # status_option_id is the one to update *to* if $self->query->param('results_entry'); # put lab_section_id into $data for model: $data->{lab_section_id} = $lab_section_id; # $self->debug($data); { # get lab_section data: my $lab_section = $self->model('LabSection')->get_lab_section($lab_section_id); $self->tt_params( lab_section => $lab_section ); # stash lab_section for request_section_notes_map() & template: $self->stash( lab_section => $lab_section ); } my $work = $self->model('WorkList')->get_outstanding_investigations($data); # check we have something to do - status_option_id restriction might have been applied unless (@$work) { my $msg; if ( my $status_option_id = $data->{status_option_id} ) { my $status_option = $self->model('LabTest')->get_status_option($status_option_id); $msg = sprintf $self->messages('worklist')->{no_tests_for_status}, uc $status_option->description; } else { # shouldn't fail if not status_option restricted, but just in case: $msg = sprintf $self->messages('worklist')->{no_outstanding_tests}, $self->stash->{lab_section}->section_name; } $self->flash ( info => $msg ); my $destination = '/worklist/select?lab_section_id=' . $lab_section_id; return $self->redirect($self->query->url . $destination); } { # convert objects to hashrefs to prevent template lookups: my @data = map { $_->as_tree(deflate => 0) } @$work; # preserve datetime $self->tt_params( outstanding_investigations => \@data ); } # get some data maps for tmpl: { my $unique_ids = $self->get_unique_request_ids($work); # arrayref of request_ids { # specimens: my $map = $self->specimen_map($unique_ids); $self->tt_params( specimen_map => $map ); } { # request_options: my $map = $self->request_options_map($unique_ids); $self->tt_params( request_options_map => $map ); } { # section notes: my $map = $self->request_section_notes_map($unique_ids); $self->tt_params( request_section_notes_map => $map ); } { # config override for non-default table cols: if ( my $yaml = $self->get_yaml_file('worklist_columns') ) { $self->tt_params( worklist_cols => $yaml ); } } { # callback for who requested test where test_type = test: if ( my $yaml = $self->get_yaml_file('requesting_user_sections') ) { $self->tt_params( requesting_user_sections => $yaml ); } my $_self = $self; weaken $_self; # or get circular refs inside the callbacks my $user = sub { $_self->model('WorkList')->get_requesting_user(@_) }; $self->tt_params( requesting_user => $user ); } } my $vars = $self->query->Vars; # warn Dumper $vars; $vars->{display_format} ||= 'defined'; # or get 'uninitialized' warning in re { # if it's a request for data entry, set tmpl flag, get lab users, rtn tt: my $is_data_entry = $vars->{results_entry} || $vars->{display_format} =~ /data entry/i; if ( $is_data_entry ) { my $user_list = $self->get_lab_staff_users; my $status_options = $self->_get_status_options_for_data_entry($lab_section_id); $self->tt_params( is_results_entry => 1, user_list => $user_list, status_options => $status_options, ); $self->js_validation_profile('worklist_update_status'); return $self->tt_process('worklist/data_entry.tt', $errs); } } # else return display format: return $self->tt_process(); } # ------------------------------------------------------------------------------ sub request_status : Runmode { my $self = shift; $self->_debug_path($self->get_current_runmode); my $status_query = $self->query->param('status_query') || return $self->forward('default'); my $duration = $self->query->param('duration') # only used for status = unreported || $self->cfg('settings')->{unreported_duration}; my %args = ( status_query => $status_query, duration => $duration, ); # warn Dumper \%args; my $data = $self->model('WorkList')->request_status_query(\%args); # return if no requests: if (! @$data ) { my $msg = $self->messages('worklist')->{no_outstanding_requests}; $self->flash( info => $msg ); return $self->redirect( $self->query->url . '/worklist' ); } $self->tt_params( requests => $data ); { # get some data maps for tmpl: my @request_ids = map { $_->id } @$data; { # specimens map: my $map = $self->specimen_map(\@request_ids); $self->tt_params( specimen_map => $map ); } { # request_options: my $map = $self->request_options_map(\@request_ids); $self->tt_params( request_options_map => $map ); } { # duration map: my $map = $self->time_duration_map($data); $self->tt_params( duration_map => $map ); } # outstanding lab-tests: my @want_lab_tests = qw( incomplete unreported unauthorised ); if ( grep $status_query eq $_, @want_lab_tests ) { my $o = $self->model('LabTest') ->get_request_lab_tests_status(\@request_ids); # warn Dumper $data; my %tests; for (@$o) { next if $_->status->description eq 'complete'; # skip my %t = ( section => $_->lab_test->lab_section->section_name, test => $_->lab_test->field_label, ); push @{ $tests{$_->request_id} }, \%t; } $self->tt_params( incomplete_lab_tests => \%tests ); } } return $self->render_view('worklist/status_query.tt'); # using firstname_format } # ------------------------------------------------------------------------------ sub update_results : Runmode { my $self = shift; $self->_debug_path($self->get_current_runmode); # need user_id & status_option_id: my $dfv = $self->check_rm('display', $self->validate('worklist_update_status') ) || return $self->dfv_error_page; my $data = $dfv->valid; # warn Dumper $data; # get list of request_lab_test.id's my @request_lab_test_ids = $self->query->param('request_lab_test_id'); if (! @request_lab_test_ids) { $self->flash( warning => $self->messages('worklist')->{no_lab_test_ids} ); my $option_id = $self->query->param('status_option_id'); # warn $option_id; my $url = $self->query->url . '/worklist/display/' . $self->param('id') # have to pass 'results_entry' flag in url: . "?results_entry=1;status_option_id=$option_id"; return $self->redirect( $url ); } =begin # too complicated to do this - using checkbox flag in tt now { # require confirmation if using delete option: my $options_map = $self->model('Result')->lab_test_status_options_map; # warn Dumper $options_map; my $option_id = $data->{status_option_id}; if ( $options_map->{$option_id}->{description} eq 'delete' ) { unless ( $self->query->param('confirm_delete') ) { $self->tt_params( confirm_required => 1 ); return $self->forward('display'); # NEED SOME PARAMS } } } return 1; =cut # add request_lab_test_ids to $data: $data->{request_lab_test_ids} = \@request_lab_test_ids; my $rtn = $self->model('Result')->update_lab_tests_from_worklist($data); $self->tt_params( updates => $rtn->{updates}, # arrayref failed => $rtn->{failures}, # scalar ie record already deleted ); { # get some maps for worklist/updates.tt: my $users_map = $self->usernames_map; $self->tt_params( users_map => $users_map ); my $status_options_map = $self->lab_test_status_options_map('id'); $self->tt_params( status_options_map => $status_options_map ); } if ( my $err = $rtn->{error} ) { # $self->debug($rtn); return $self->error($err); } elsif ($rtn->{success}) { # warn $rtn->{success}; $self->flash( info => $self->messages('worklist')->{update_success} ); return $self->tt_process('worklist/updates.tt'); } elsif ($rtn->{failures}) { # warn $rtn->{failures}; # ie all failed $self->flash( warning => $self->messages('worklist')->{update_fails} ); return $self->redirect( $self->query->param('query_params') ); # hidden fld } else { # no db error, but also no records updated (probably unlikely unless db->err): $self->flash( warning => $self->messages('worklist')->{update_failure} ); return $self->redirect( $self->query->param('query_params') ); # hidden fld } } # ------------------------------------------------------------------------------ sub _get_status_options_for_data_entry { my ($self, $lab_section_id) = @_; $self->_debug_path(); # get all status options (supply 'key'): my $all_status_options = $self->lab_test_status_options_map('description'); my $section_status_options = $self->model('LabSection')->get_section_status_options($lab_section_id); my @options = map { { description => $_->status_option->description, id => $_->status_option_id, }; } @$section_status_options; # need to add 'complete' & 'delete' to @options: push @options, ( { description => 'complete', id => $all_status_options->{complete}->{id}, }, { description => 'delete', id => $all_status_options->{delete}->{id}, }, ); # warn Dumper \@options; return \@options; =begin while ( my ($option, $data) = each %$all_status_options ) { next unless grep $option eq $_, qw(complete delete); $section_status_options->{$option} = $data->{id}; } return $section_status_options; =cut } 1;