RSS Git Download  Clone
Raw Blame History
#!/usr/bin/perl

=begin -------------------------------------------------------------------------
generates NYCRIS data feed for new and revised diagnoses during previous 1 month
creates pipe-delimited rows, one row per request
=cut ---------------------------------------------------------------------------

use strict;
use warnings;

my $JUST_TESTING = 1; # skips ftp, puts data files in /tmp, emails just raj

BEGIN {
    use FindBin qw($Bin); # warn $Bin; exit;
    use lib "$Bin/../../../lib";
}

use IO::All;
use Config::Auto;
use Data::Dumper;
use DateTime::Format::MySQL;
use LIMS::Local::ScriptHelpers;
use Text::Wrap qw($columns fill); $columns = 68;

#################################
my $delimiter = '|';            #
my $duration  = 2; # months ago #
#################################

my $cfg_file = "$Bin/../lib/settings.cfg";
my $settings = Config::Auto::parse($cfg_file); # warn Dumper $settings;
    
# get tools from LIMS::Local::ScriptHelpers:
my $tools = LIMS::Local::ScriptHelpers->new();

my $sql_lib = $tools->sql_lib();
my $config  = $tools->config(); 
my $dbix    = $tools->dbix();
my $today   = $tools->time_now();

my $data_filename = sprintf 'hmds_%s', $today->ymd('_');

my @data = ();

# go:
{
    # get request ID's for horizontal & vertical tables:
    my $request_ids = get_request_ids(); # warn Dumper $request_ids;
    
    # get data maps of vertical tables - much faster than tying into main query:
    my $data_map = get_data_map($request_ids); # warn Dumper $data_map;

    # get request result 1-to-1 data:
    my $query = $sql_lib->retr('nycris_data');
    my $result = $dbix->query($query, @$request_ids);
    
    while ( my $vars = $result->hash ) { # warn Dumper $vars; next;
        my $row = parse_data($vars, $data_map); # combine horizontal & vertical tbls
		push @data, $row; # warn $row;
    } # warn Dumper \@data;
}

{ # create file & FTP:
    my $file_path = '/tmp/' . $data_filename;

    my $contents = join "\n", @data; 
    $contents > io($file_path); # warn $contents;

    # ftp file:
    unless ($JUST_TESTING) {
        my %args = (
            local_filename  => $file_path,
            remote_filename => $data_filename,
        );
        ftp_file(\%args);
    }
}

# archive results file:
unless ($JUST_TESTING) {}

# combine horizontal & vertical tables:
sub parse_data {
    my ($vars, $data_map) = @_;
    
    { # add data-map fields:
        my $request_id = $vars->{request_id};
        
        # specimen code(s):
        $vars->{specimen_code}
            = $data_map->{specimen}->{$request_id}->{specimen_code};
        # result summaries:
        map $vars->{$_} = $data_map->{result_summary}->{$request_id}->{$_},
            qw(immunocytochemistry flow_cytometry fish cytogenetics molecular);
        # reporter:
        map $vars->{$_} = $data_map->{reporter_data}->{$request_id}->{$_},
            qw(reporter_name reporter_code);
    }
    
    # tidy up (trim content & substitute new-line markers):
    map { $vars->{$_} = tidy($vars->{$_}) }
        grep $vars->{$_},
            qw(comment immunocytochemistry flow_cytometry fish cytogenetics
                gross_description molecular);
    
    $vars->{gender} ||= 'U';
    
    my @fields = qw(
        request_id
        labno
        request_date
		last_name
        first_name
        middle_name
		unit_number
		dob
		nhs_number
		gender
		referrer
		referrer_code
        location
		organisation_code
		specimen_code
        clinical_details
        gross_description
        specimen_quality
        comment
        diagnosis
        icdo3
        flow_cytometry
        immunohistochemistry
        molecular
        cytogenetics
        fish
        reporter_name
        reporter_code
		authorisation_date
	);
    
    no warnings 'uninitialized'; # lots in $vars
    my $row = join $delimiter, map $vars->{$_}, @fields;
    # row needs to start with request ID - in case unescaped new-line marker present
    die unless $row =~ /\A\d{6,}/;
    return $row;
}

sub get_request_ids {
    my @request_ids = ();
    { # new diagnoses:
        my $sql = $sql_lib->retr('nycris_new_diagnosis_request_ids');
        my $request_ids = $dbix->query($sql, $duration, $duration)->flat;
        push @request_ids, @$request_ids; # warn Dumper $request_ids;
    }    
    { # get revised diagnoses:
        my $sql = $sql_lib->retr('nycris_revised_diagnosis_request_ids');
        my $request_ids = $dbix->query($sql, $duration, $duration)->flat;
        push @request_ids, @$request_ids; # warn Dumper $request_ids;
    }
    # combine & eliminate duplicates
    my %request_ids = map { $_ => 1 } @request_ids; # warn Dumper \%request_ids;
    
    return [ keys %request_ids ];    
}

sub ftp_file { return 0;
    my $args = shift;
    
    my $cfg = $settings->{nycris_server};
    
    my %params = (
        local_filename  => $args->{local_filename},
        remote_filename => $args->{remote_filename},
        server_addr     => $cfg->{remote_address},
        username        => $cfg->{username},
        password        => $cfg->{password},
    );

    # ftp file (returns str on failure, undef on success):
    my $rtn = $tools->ftp_file(\%params);

    if ($rtn) {
        $tools->mail_admin({ script => $0, msg => $rtn });
        warn "$0 - $rtn\n"; # dump to logs but don't die!!
    }
    else {
        io($args->{local_filename})->unlink;
    }
}

sub user_codes {
    my $username = shift;
    
    my $national_codes = {
        swirsky  => 'C2202309',   
        burton   => 'C4370806',
        tooze    => 'C3664265',    
        cargo    => 'C6050871',
        jack     => 'C2547174',   
        owen     => 'C3271078',
        
        richards => 'CS01892',   
        rawstron => 'CS01874',
        oconnor  => 'CS01696',
        evans    => 'CS09254',         
	};
    
    return $national_codes->{$username}
    || 'H9999998'; # OTHER HEALTH CARE PROFESSIONAL
}

sub get_data_map {
    my $request_ids = shift;
    
    my $map = {};
    
    { # request_specimens:
        my $sql = q!select `request_id`,
            group_concat(`description` separator '/') as 'description',
            group_concat(`sample_code`) as 'code' from `request_specimen` rs
            join `specimens` s on rs.`specimen_id` = s.`id`
            where rs.`request_id` in (??) group by `request_id`!;
        my $result = $dbix->query($sql, @$request_ids);
        
        while ( my $vars = $result->hash ) { # warn Dumper $vars;
            my $request_id = $vars->{request_id};
            
            my %data = (
                specimen_code => $vars->{code},
                description   => $vars->{description},
            );
            $map->{specimen}->{$request_id} = \%data;
        }  # warn Dumper $map->{specimen};
    }
    { # reporter data:
        my $sql = q!select rh.request_id, u.username, u.first_name, u.last_name
            from request_history rh join users u on ( rh.user_id = u.id and
            action = 'reported' ) where request_id in (??)!;
            
        my $result = $dbix->query($sql, @$request_ids);

        while ( my $vars = $result->hash ) { # warn Dumper $vars;
            my $request_id = $vars->{request_id};
            
            my $reporter = join ' ',
                    ucfirst $vars->{first_name},
                    ucfirst $vars->{last_name};

            my $reporter_code = user_codes($vars->{username});
            
            my %data = (
                reporter_name => $reporter,
                reporter_code => $reporter_code,
            );
            $map->{reporter_data}->{$request_id} = \%data;
        } # warn Dumper $map->{reporter_data};
    }
    { # result_summaries:
        my $sql = q!select rs.`request_id`, rs.`results_summary`, ls.`section_name`
            from `request_result_summaries` rs join `lab_sections` ls on
            rs.`lab_section_id` = ls.`id` where rs.`request_id` in (??)!;
        my $result = $dbix->query($sql, @$request_ids);
        
        while ( my $vars = $result->hash ) { # warn Dumper $vars;
            my $request_id  = $vars->{request_id};
            my $section     = $vars->{section_name};
            my $result      = $vars->{results_summary};              
           
            $section =~ s/ /_/g;
            $map->{result_summary}->{$request_id}->{lc $section} = $result;
        } # warn Dumper $map->{result_summary}; 
    }
    
    return $map;
}

sub tidy {
    my $str = shift;
    
    # trim:
    $str =~ s/\A\s+//; # leading
    $str =~ s/\s+\Z//; # trailing
    
    $str =~ s/(\r\n)/[NEW_LINE]/g; # substitute new-line marker

    return $str;
}

=begin
# format text: indent, replace blanks with N/A, max 68 chars / line:
sub format_text {
	my $str = shift || ''; # needs to exist or uninitialized warnings below
	
    # put '07|' after of new-line markers:
    my $formatted_newline = $settings->{new_line};

	$str =~ s/^(\s+|\t)//; # remove leading spaces or tabs	
	$str =~ s/\|//g; # remove pipes if used!!

	$str ||= 'N/A'; # only applies to @formatted_fields, others already grepped

	my $wrapped_text = fill($settings->{indent}, $settings->{indent}, $str); # Text::Wrap function

	# new 07| in front of newly-wrapped lines:
	$wrapped_text =~ s/\n/$formatted_newline/g; # print $wrapped_text;

	return $wrapped_text; 
}

sub specimen_summary {
	local $_ = shift; # specimen string
	
	my @title; 
	
	push @title, 'peripheral blood' 	if /PB|CMP/; # CMP excluded
	push @title, 'chimerism' 			if /CHI/; # currently excluding chimerism screen
	push @title, 'bone marrow aspirate' if /BMA$|BMA\,/; # BMA[^T] doesn't work
	push @title, 'bone marrow biopsy' 	if /BMAT|T[B|S][L|P]/;
	push @title, 'tissue biopsy' 		if /[DGLRX][BL|F|SL|U|A]/;
	push @title, 'effusion' 			if /EF/;
	push @title, 'CSF' 					if /CF/;
	push @title, 'slide' 				if /HS/;
	push @title, 'serum' 				if /SE/;
	push @title, 'urine' 				if /URI/;

#	my $title = @title > 1 ? join (' & ' => join (', ' => @title[ 0 .. @title - 2 ]), $title[-1]) : $title[0]; 
	my $title = join '/', @title; # print Dumper ($title, length $title) if length $title > 40;
	$title ||= $_; # so var not empty if specimen doesn't match in regex's
	
	return ( length $title < 41 )
        ? $title
        : 'multiple blood/marrow/tissue specimens';
}


=cut