package LIMS::Model::PrintRun;
use Moose;
extends 'LIMS::Model::Base';
with 'LIMS::Model::Roles::Query';
use namespace::clean -except => 'meta';
__PACKAGE__->meta->make_immutable;
use Data::Dumper;
use LIMS::Local::Utils;
#-------------------------------------------------------------------------------
sub get_print_run_size {
my ($self, $h) = @_; # warn Dumper $h; # hashref of start & end datetimes + optional cfg
# just forward to get_print_run_request_ids and return count:
my $ids = $self->get_print_run_request_ids($h);
my $i = scalar @$ids; # warn $i;
return $i;
}
#-------------------------------------------------------------------------------
sub get_print_run_request_ids {
my ($self, $h) = @_; # warn Dumper $h; # hashref of start & end datetimes + optional cfg
my ($start_date, $end_date, $type) = @{$h}{ qw(start_date end_date type) };
my %print_run_args = (
start => $start_date,
type => $type,
end => $end_date,
);
if ( defined $h->{offset} ) { # can be zero
$print_run_args{$_} = $h->{$_} for qw(offset limit);
}
my @request_ids = do {
my ($sql, @bind) = $self->get_query_params(\%print_run_args);
# $self->lims_dbix->dump_query($sql, @bind);
$self->lims_dbix->query($sql, @bind)->flat; # warn Dumper $results;
};
# get copy-to's:
my @copy_tos = do {
my ($sql, @bind) = $self->get_cc_request_ids(\%print_run_args);
# $self->lims_dbix->dump_query($sql, @bind);
$self->lims_dbix->query($sql, @bind)->flat;
}; # warn Dumper \@copy_tos;
# combine @request_ids & @copy_tos as list of unique request ids:
my %h = map { $_ => undef } ( @request_ids, @copy_tos ); # warn Dumper \%h;
my @all_request_ids = keys %h;
# return separate request_ids & copy_tos if required, otherwise all_request_ids:
return wantarray
? ( \@request_ids, \@copy_tos )
: \@all_request_ids;
}
#-------------------------------------------------------------------------------
sub get_cc_request_ids {
my $self = shift;
my $args = shift;
my $start = $args->{start}; # DT object
my $type = $args->{type};
my $end = $args->{end}; # DT object
my @rels = (
# table|alias # FK-PK relationship
'requests|r' , 'rr.request_id = r.id' ,
'request_report_view|rr' , 'ro.request_id = r.id' ,
'request_option|ro' , 'ro.option_id = ao.id' ,
'additional_options|ao' , 'r.status_option_id = so.id' ,
'status_options|so' ,
);
# set status level required for printing reports:
my $status = $self->does_authorisation() ? 'authorised' : 'reported'; # warn $status;
my %query = (
'so.description' => { -in => [ $status, 'complete' ] },
'ao.option_name' => 'copy_to',
'DATE(rr.updated_at)' => ( $start->ymd eq $end->ymd )
? $start->ymd # or $end->ymd, both same date
: { -between => [ $start->ymd, $end->ymd ] },
);
my %h = (
cols => 'r.id',
joins => \@rels,
where => \%query,
);
if ( $type eq 'clinical-trial' ) { # include request_trial/clinical_trials:
push @rels, ( 'rt.request_id=r.id' => 'request_trial|rt' ,
'rt.trial_id=ct.id' => 'clinical_trials|ct' );
}
elsif ( $type eq 'non-trial' ) { # left join request_trial to exclude:
push @rels, ( '=>rt.request_id=r.id' => 'request_trial|rt' );
$query{'rt.request_id'} = undef;
}
my ($sql, @bind) = $self->sqla_query(\%h);
# $self->lims_dbix->dump_query($sql, @bind);
return ($sql, @bind);
}
#-------------------------------------------------------------------------------
sub get_query_params { # returns $sql & @bind params - shared with print_run.pl
my $self = shift; # warn ref $self;
my $args = shift; # trial or non-trial cases, start & end dates
my $start = $args->{start}; # DT object
my $type = $args->{type}; # trial or non-trial
my $end = $args->{end}; # DT object
my $settings = $self->lims_cfg->{settings}; # warn Dumper $settings;
my $tbl_rels = get_tbl_rels($type);
# set status level required for printing reports:
my $status = $self->does_authorisation() ? 'authorised' : 'reported'; # warn $status;
my %query = ( 'so.description' => { -in => [ $status, 'complete' ] } );
$query{'DATE(rr.updated_at)'} = ( $start->ymd eq $end->ymd )
? $start->ymd # or $end->ymd, both same date
: { -between => [ $start->ymd, $end->ymd ] }; # warn Dumper \%query;
my @sort_by;
if ( $type eq 'clinical-trial' ) { # don't exclude any locations
@sort_by = qw(ct.trial_name r.year r.request_number);
}
elsif ( $type eq 'non-trial' ) {
if ( $settings->{print_run_skip_trials} ) { # skip trial cases if configured
$query{'rt.request_id'} = undef;
}
=begin # skip_paper_reports.yml - replaced by get_email_report_details() using email_contacts table:
if ( my $cfg = $self->get_yaml_file('skip_paper_reports') ) { # p $cfg;
if ( my $org_codes = $cfg->{organisation} ) { # p $org_codes;
$query{'po.parent_code'} = { -not_in => $org_codes };
}
if ( my $hospitals = $cfg->{hospital} ) { # p $hospitals;
$query{'rs.organisation_code'} = { -not_in => $hospitals };
}
if ( my $departments = $cfg->{department} ) { # p $departments;
for (@$departments) { # eg RWA/823
my ($location, $department) = split '/'; # p $location; p $department;
# 5-digits (hospital) or 3-digits (organisation) code:
my $site_type = length $location > 3
? 'rs.organisation_code'
: 'po.parent_code';
my %h = (
$site_type => $location,
'rd.hospital_department_code' => $department,
);
push @{ $query{-not_bool} }, \%h;
}
}
}
=cut
{ # exclude any locations/departments configured for email (email_contacts table):
my $ref = $self->get_email_report_details; # warn Dumper $ref; # hashref
my %all_depts; # set in 1st 2 blocks below, used for skipping location departments
# organisations - all departments:
if ( my $org_codes = $ref->{organisation_all} ) { # aref
my $parent_ids = $all_depts{parent} = $org_codes;
$query{'rs.parent_organisation_id'} = { -not_in => $parent_ids };
}
# hospitals - all departments:
if ( my $org_codes = $ref->{hospital_all} ) { # aref
my $hospital_ids = $all_depts{hospital} = $org_codes;
$query{'rs.id'} = { -not_in => $hospital_ids };
}
# specific organisation/department combinations:
if ( my $organisation = $ref->{organisation_dept} ) { # HoA
while ( my($parent_id, $dept_ref) = each %$organisation ) {
# skip if already in organisation/all-departments list:
next if grep $parent_id == $_, @{ $all_depts{parent} };
push @{ $query{-not_bool} }, {
'rs.parent_organisation_id' => $parent_id,
'rd.hospital_department_code' => $_,
} for @$dept_ref;
}
}
# specific hospital/department combinations:
if ( my $hospital = $ref->{hospital_dept} ) {
while ( my($source_id, $dept_ref) = each %$hospital ) {
# skip if already in hospital/all-departments list:
next if grep $source_id == $_, @{ $all_depts{hospital} };
push @{ $query{-not_bool} }, {
'rs.id' => $source_id,
'rd.hospital_department_code' => $_,
} for @$dept_ref;
}
}
} # warn Dumper \%query;
@sort_by = qw(ref.name r.year r.request_number);
}
my %sqla_args = (
cols => 'r.id',
joins => $tbl_rels,
where => \%query,
order_by => \@sort_by,
);
if ( defined $args->{offset} ) { # can be zero
$sqla_args{$_} = $args->{$_} for qw(offset limit);
} # warn Dumper \%sqla_args;
my ($sql, @bind) = $self->sqla_query(\%sqla_args);
# $self->lims_dbix->dump_query($sql, @bind);
return ($sql, @bind);
}
sub get_tbl_rels {
my $type = shift; # trial or non-trial cases
my @rels = (
# table|alias # FK-PK relationship
'requests|r' , 'r.referrer_department_id = rd.id' ,
'referrer_department|rd' , 'rd.referrer_id = ref.id' ,
'referrers|ref' , 'r.patient_case_id = pc.id' ,
'patient_case|pc' , 'rr.request_id = r.id' ,
'request_report_view|rr' , 'r.status_option_id = so.id' ,
'status_options|so' , 'pc.referral_source_id = rs.id' ,
'referral_sources|rs' ,
);
if ( $type eq 'clinical-trial' ) { # include request_trial/clinical_trials:
push @rels, ( 'rt.request_id=r.id' => 'request_trial|rt' ,
'rt.trial_id=ct.id' => 'clinical_trials|ct' );
}
elsif ( $type eq 'non-trial' ) { # left join request_trial to exclude:
push @rels, ( '=>rt.request_id=r.id' => 'request_trial|rt' );
}
return \@rels;
}
sub get_email_report_details {
my $self = shift;
my @contacts = do {
my @cols = qw(
ec.display_name
ec.referral_source_id|source_id
rs.parent_organisation_id|parent_id
ec.scope
ec.department_id
ec.status
);
my @rels = (
'email_contacts|ec' => 'ec.referral_source_id=rs.id',
'referral_sources|rs'
);
my %args = (
cols => \@cols,
joins => \@rels,
where => {
'ec.is_active' => 'yes',
'ec.type' => 'report',
'ec.display_name' => { -not_rlike => 'CWT$' }, # cancer waiting times
},
); # p @args;
my ($sql, @bind) = $self->sqla_query(\%args); # warn $sql; warn Dumper \@bind;
# $self->lims_dbix->dump_query($sql, @bind);
$self->lims_dbix->query($sql, @bind)->hashes;
};
my @contact_cols = qw( scope parent_id department_id source_id status );
my %h; # HoH to provide unique location/department entries if multiple contact addresses
for my $contact (@contacts) { # warn Dumper $contact; next;
my ($scope, $parent_id, $department_id, $source_id, $want_status)
= @{$contact}{@contact_cols};
# warn Dumper [$scope, $parent_id, $department_id, $source_id, $want_status];
if ( $scope eq 'organisation' ) {
$department_id
? $h{organisation_dept}{$parent_id}{$department_id}++ # organisation/department
: $h{organisation_all}{$parent_id}++ # entire organisation
}
else { # scope = 'hospital'
$department_id
? $h{hospital_dept}{$source_id}{$department_id}++ # hospital/department
: $h{hospital_all}{$source_id}++ # entire hospital
}
} # warn Dumper \%h;
my @all_organisation_ids = keys %{ $h{organisation_all} };
my @all_hospital_ids = keys %{ $h{hospital_all} };
my $organisation_dept_ref = do { # transform $h{organisation_dept} internal hashrefs to arrayrefs:
my $o = $h{organisation_dept};
+{ map +($_ => [ keys %{$o->{$_}} ]), keys %$o }
}; # warn Dumper $organisation_dept_ref;
my $hospital_dept_ref = do { # transform $h{hospital_dept} internal hashrefs to arrayrefs:
my $o = $h{hospital_dept};
+{ map +($_ => [ keys %{$o->{$_}} ]), keys %$o }
}; # warn Dumper $hospital_dept_ref;
my %data = (
organisation_dept => $organisation_dept_ref, # HoA
organisation_all => \@all_organisation_ids, # aref
hospital_dept => $hospital_dept_ref, # HoA
hospital_all => \@all_hospital_ids, # aref
); # warn Dumper \%data;
return \%data;
# flatten organisation and hospital location_id hashrefs to array(ref) so
# $data just contains lists of arrayrefs (generates same as above %data):
my $data = LIMS::Local::Utils::convert_hashrefs_to_arrayrefs(\%h); # warn Dumper $data;
# return $data
}
1;