#!/usr/bin/env perl =begin ------------------------------------------------------------------------- requests requiring confirmation of diagnosis (see .local/diagnosis_confirm.yml): 1) request is authorised 2) has no outstanding tests 3) request.status <> 'complete' 4) has a cytogenetics, molecular or FISH results summary timestamp AFTER auth date screening terms with/without sample types and clinical trials which are exempt from requiring diagnosis confirmation are defined in diagnosis_confirm.yml Also sets request status to complete if status = authorised, has no outstanding tests and NOT in incomplete_requests list ie requiring diagnosis confirmation #--------------------------------------------------------------------------- # TODO: write .t then move to Local::DB & retest =cut use Getopt::Std; getopts('t'); # testing our($opt_t); use strict; use warnings; use feature 'say'; my $JUST_TESTING = $opt_t || 0; # dumps HTML file to $Bin/incomplete.html; no emails or db update #------------------------------------------------------------------------------- my @recipients = qw( hmds.secure ); # raj sinclair douglas bagguley oconnor #------------------------------------------------------------------------------- use lib qw( /home/raj/perl5/lib/perl5 /home/raj/perl-lib ); use IO::All; use Data::Printer; use SQL::Abstract::More; use FindBin qw($Bin); # warn $Bin; use lib "$Bin/../../../lib"; use LIMS::Local::ScriptHelpers; use Local::DB; # using date auto-inflation # get tools from LIMS::Local::ScriptHelpers: my $tools = LIMS::Local::ScriptHelpers->new(); $tools->test_only($JUST_TESTING); my $config = $tools->config(); my $yaml = $tools->get_yaml_file('diagnosis_confirm'); # p $yaml; exit; my $dbix = Local::DB->dbix({dbname => 'hilis4'}); # only in use by Leeds my $sqla = SQL::Abstract::More->new; my $excluded_screens = $yaml->{exempt_all_sample_types}; # p $excluded_screens; my $excluded_trials = $yaml->{exempt_clinical_trials}; # p excluded_trials; # lab sections requiring confirmation of diagnosis: my $lab_sections = $yaml->{lab_sections}; # p $lab_sections; my $template = 'cron/incomplete_requests.tt'; my $dump_file = "$Bin/incomplete.html"; # for use if JUST_TESTING # reset dump_file: io($dump_file)->unlink if -e $dump_file; # get list of request_ids where request authorised, status incomplete and have # molecular, cytogenetic or FISH result summary: my $request_ids = _get_request_ids(); # p scalar @$request_ids; # arrayref # globals: my ( %h, # reporter => request data %all_lab_tests, # request.id => test_name & status @requires_confirmation, # request id's requiring confirmation ); REQUEST: for my $id (@$request_ids) { # p $id; next unless $id == 241124; # data for determining whether diagnosis confirmation is required: my $args = { specimen => [], # array(ref) of sample_codes lab_test => [], # AoH (keys = test_name & status) section => [], # array(ref) of lab_section names screen => undef, # str trial => undef, # str (optional) yaml => $yaml, }; # get clinical trial: $args->{trial} = _get_clinical_trial($id); # p $args; # get initial_screen: $args->{screen} = _get_initial_screen($id); # p $args; # get specimen(s) array(ref): $args->{specimen} = _get_specimen_code($id); # get lab_tests (AoH): $args->{lab_test} = _get_lab_tests($id); # get results_summary section names => result_summary timestamp (AoH): $args->{section} = _get_rs_section_datetime($id); # get report data: my $req = _get_request_report($id); # add authorisation date for comparison to result summary date: $args->{authorisation_date} = $req->{auth_date}; # next request if diagnosis confirmation NOT required: next REQUEST unless $tools->diagnosis_confirmation_required($args); my $reporter = $req->{report_by}; # p $reporter; next REQUEST; push @{ $h{$reporter} }, $req; next REQUEST if $JUST_TESTING; # don't want to update db # add to @requires_confirmation for use in _get_authorised_requests() query: push @requires_confirmation, $id; # ie diagnosis confirmation IS required } # p %h; p @requires_confirmation; my %mail = ( config => $config, content => 'html' ); # email messages: REPORTER: while ( my($reporter, $d) = each %h ) { my %tt_params = ( reporter => $reporter, data => $d ); my $msg = $tools->process_template($template, \%tt_params); ### uncomment next line to dump to file and NOT send email: # $msg >> io("$Bin/incomplete.html"); next REPORTER; die; $mail{message} = $msg; # p $msg; next REPORTER; $mail{subject} = sprintf 'HILIS records requiring confirmation of diagnosis on %s [%s]', $tools->time_now->dmy, uc $reporter; $JUST_TESTING # dump to file only if just testing ? $msg > io("/tmp/${reporter}_incomplete.html") : $tools->send_mail(\%mail, \@recipients); } set_request_status() unless $JUST_TESTING; # don't want to update db #=============================================================================== sub set_request_status { # warn 'here'; # die; # status_option.id of 'complete' requests: my $status_option_id = _complete_status_option_id(); # server username: my $server_user = $tools->get_server_user_details(); # p $server_user; # get list of requests where status = authorised and don't require diagnosis # confirmation (using @requires_confirmation array to supply list of requests # where confirmation IS required): my $authorised_requests = _get_authorised_requests(); # p $authorised_requests; DATA: # skip any requests with outstanding tests - set rest to status = complete: for my $data( @$authorised_requests ) { # p $data; my $lab_test = _get_lab_tests($data->{id}); # p $lab_test; my @status = map $_->{status}, @$lab_test; # p @status; next DATA if grep $_ ne 'complete', @status; # skip if ANY test status NOT complete # warn 'here'; { # now have authorised case with no outstanding lab-tests and not requiring a # diagnosis confirmation, so set request status to 'complete': my %h = ( status_option_id => $status_option_id, # preserve timestamp to avoid triggering unnecessary report: updated_at => $data->{updated_at}, ); # p %h; $dbix->update( 'requests', \%h, { id => $data->{id} } ); } { # log action in request_history: my %data = ( request_id => $data->{id}, user_id => $server_user->{id}, action => 'set request status to complete', ); # p %data; $dbix->insert('request_history', \%data); } } } # queries ====================================================================== sub _get_request_ids { my @cols = qw( r.id ); my @rels = ( 'requests|r' => 'ris.request_id=r.id' , 'request_initial_screen|ris' => 'ris.screen_id=s.id' , 'screens|s' => 'rrs.request_id=r.id' , 'request_result_summaries|rrs' => 'rrs.lab_section_id=ls.id' , 'lab_sections|ls' => 'rrd.request_id=r.id' , 'request_report_detail|rrd' => 'rrd.diagnosis_id=d.id' , 'diagnoses|d' => '=>rt.request_id=r.id' , 'request_trial|rt' => '=>rt.trial_id=ct.id' , 'clinical_trials|ct' => 'r.status_option_id=so.id' , 'status_options|so' ); my %where = ( -and => [ 's.description' => { -not_in => $excluded_screens }, -or => [ 'ct.trial_name' => { -not_in => $excluded_trials }, 'ct.trial_name' => undef, ], -or => [ { 'so.description' => 'authorised', 'ls.section_name' => { -in => $lab_sections }, }, { 'so.description' => 'complete', 'd.name' => { -rlike => 'awaiting final (diagnosis|review)' }, }, ], ], ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, -group_by => 'r.id', -order_by => [ 'r.year', 'r.request_number' ], ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); # exit; my $request_ids = $dbix->query($sql, @bind)->column; # p $request_ids; return $request_ids; } sub _get_authorised_requests { my @cols = qw( r.id r.updated_at ); my @rels = qw( requests|r r.status_option_id=so.id status_options|so ); my %where = ( 'so.description' => 'authorised', 'r.id' => { -not_in => \@requires_confirmation }, # global var ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); exit; my $requests = $dbix->query($sql, @bind)->hashes; # p $requests; return $requests; } sub _get_request_report { my $request_id = shift; my @cols = ( 'r.request_number', 'r.year', 'd.name|diagnosis', 'MAX(CASE WHEN rs.action = "reported" THEN rs.username END)|report_by', 'MAX(CASE WHEN rs.action = "reported" THEN rs.time END)|report_date', 'MAX(CASE WHEN rs.action = "authorised" THEN rs.username END)|auth_by', 'MAX(CASE WHEN rs.action = "authorised" THEN rs.time END)|auth_date', ); my @rels = ( 'requests|r' => 'rs.request_id=r.id', 'request_status_view|rs' => 'rr.request_id=r.id', 'request_report_view|rr' => 'rr.diagnosis_id = d.id', 'diagnoses|d' ); my %where = ( 'r.id' => $request_id ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); exit; my $ref = $dbix->query($sql, @bind)->hash; # p $ref; return $ref; } sub _get_clinical_trial { my $request_id = shift; my @cols = qw( ct.trial_name ); my @rels = qw( request_trial|rt rt.trial_id=ct.id clinical_trials|ct ); my %where = ( 'rt.request_id' => $request_id ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); exit; my $val = $dbix->query($sql, @bind)->value; # p $val; return $val; } sub _get_initial_screen { my $request_id = shift; my @cols = qw( s.description ); my @rels = qw( request_initial_screen|ris ris.screen_id=s.id screens|s ); my %where = ( 'ris.request_id' => $request_id ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); exit; my $val = $dbix->query($sql, @bind)->value; # p $val; return $val; } sub _get_specimen_code { my $request_id = shift; my @cols = qw( s.sample_code ); my @rels = qw( request_specimen|rs rs.specimen_id=s.id specimens|s ); my %where = ( 'rs.request_id' => $request_id ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); exit; my $ref = $dbix->query($sql, @bind)->column; # p $ref; return $ref; } sub _get_lab_tests { my $request_id = shift; # p $request_id; # function called twice, from REQUEST block & again from set_request_status() # say "returning $request_id" if $all_lab_tests{$request_id}; return $all_lab_tests{$request_id} if $all_lab_tests{$request_id}; my @cols = qw( lt.test_name so.description|status ); my @rels = ( 'request_lab_test_status|ts' => 'ts.status_option_id=so.id' , 'lab_test_status_options|so' => 'ts.lab_test_id=lt.id' , 'lab_tests lt' ); my %where = ( 'ts.request_id' => $request_id ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); exit; my $ref = $dbix->query($sql, @bind)->hashes; # p $ref; $all_lab_tests{$request_id} = $ref; # in case requested later return $ref; } sub _get_rs_section_datetime { my $request_id = shift; my @cols = qw( ls.section_name rrs.time ); my @rels = qw( request_result_summaries|rrs rrs.lab_section_id=ls.id lab_sections|ls ); my %where = ( 'rrs.request_id' => $request_id ); my @args = ( -columns => \@cols, -from => [ -join => @rels ], -where => \%where, ); my ($sql, @bind) = $sqla->select(@args); # p $sql; # p \@bind; # $dbix->dump_query($sql, @bind); exit; my $ref = $dbix->query($sql, @bind)->hashes; # p $ref; return $ref; } sub _complete_status_option_id { $dbix->select('status_options', 'id', { description => 'complete' })->into(my $id); # p $id; return $id; }