package LIMS::Controller::Register;
use Moose;
BEGIN { extends 'LIMS::Base'; }
with (
'LIMS::Controller::Roles::Misc',
);
__PACKAGE__->meta->make_immutable(inline_constructor => 0);
use LIMS::Local::Utils;
use Data::Dumper;
#-------------------------------------------------------------------------------
sub default : StartRunmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
my $errs = shift; # $self->stash( errs => $errs ); # for debugging in tmpl
return $self->forbidden() unless $self->user_can('register');
# TODO: js_validation doesn't work with 'require_some'
$self->js_validation_profile('patient_search_data');
return $self->tt_process($errs);
}
#-------------------------------------------------------------------------------
sub online_request_form : Runmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
return $self->forbidden() unless $self->user_can('register');
my $id = $self->query->param('id') || return $self->forward('default');
my $data = $self->model('Request')->get_request_form($id);
my $name = sprintf '%s, %s', $data->last_name, $data->first_name;
# put nhs_number & name into query params in format expected by patient_search():
my %vars = (
patient_no => $data->nhs_number,
name => $name,
); # warn Dumper \%vars;
$self->query->param( $_ => $vars{$_} ) for keys %vars;
# get output from patient_search() but don't return view yet:
my $template = $self->forward('patient_search'); # uses patient_no & name
# add rest of vars from online request form & redo _extract_params_from_request()
# in case patient not found in patient_search() - populates tt form with params:
$vars{$_} = $data->{$_} for qw(location_name location_id gender);
$vars{$_} = $data->dob->$_ for qw(year month day);
$vars{unit_number} = $data->patient_number;
$self->_extract_params_from_request(\%vars); # $self->debug($vars);
# now return template processed in patient_search():
return $template;
}
#-------------------------------------------------------------------------------
sub patient_search : Runmode {
my $self = shift; $self->_debug_path($self->get_current_runmode);
return $self->forbidden() unless $self->user_can('register');
my $dfv = $self->check_rm('default', $self->validate('patient_search_data') )
|| return $self->dfv_error_page;
# need form params in scalar (hashref) context:
my $form_params = $dfv->valid; # $self->debug('form_params:'); # $self->debug($form_params);
# parse valid form params (extract last_name, first_name, dob, nhs_number, unit_number):
my $vars = $self->_extract_params_from_request($form_params); # $self->debug($vars);
# get search params as arrayref for query, or redisplay search page:
my $search_param = $self->_generate_search_constraints($vars)
|| return $self->forward('default'); # $self->debug($search_param);
# format search terms as a string for display in template:
my $search_terms = $self->_convert_search_terms_for_display($vars);
my %args_for_search = ( query => $search_param ); # $self->debug(\%args_for_search);
my $patient_matches_count
= $self->model('Patient')->patient_matches_count(\%args_for_search);
# $self->debug([$patient_matches_count]);
if (! $patient_matches_count ) {
my $msg = sprintf $self->messages('registration')->{no_records_found},
$search_terms;
$self->flash( info => $msg );
return $self->redirect( $self->query->url . '/patient' );
}
# override cfg.settings.entries_per_page for this search:
$self->cfg('settings')->{entries_per_page} = 50;
if ( $patient_matches_count > $self->cfg('settings')->{entries_per_page} ) {
# invoke pager for template and add limit & offset params to \%args_for_search:
$self->pager({ query => \%args_for_search, total => $patient_matches_count });
} # $self->debug(\%args_for_search);
# do search for previous patients:
my $patient_cases
= $self->model('PatientCase')->registration_search(\%args_for_search);
my $results = $self->extract_patients_and_locations($patient_cases);
$self->tt_params(
total_count => $patient_matches_count,
search_term => $search_terms,
results => $results,
);
return $self->tt_process('register/select_patient.tt');
}
#-------------------------------------------------------------------------------
sub _convert_search_terms_for_display {
my $self = shift; $self->get_current_runmode;
my $vars = shift || return;
# convert DT object back to EU date string for template:
if ( my $dob = $vars->{dob} ) {
$vars->{dob} = $dob->dmy; # dd-mm-yyyy format
}
my $search_terms = join ' & ',
map { sprintf '%s=%s', $_, $vars->{$_} }
grep { $vars->{$_} } qw(name dob patient_no);
return $search_terms;
}
#-------------------------------------------------------------------------------
sub _extract_params_from_request {
my $self = shift; $self->_debug_path();
my $param = shift; # $self->debug($param);
if ( my $name = $param->{name} ) {
my ($last_name, $first_name) = split /\,\s?/, $name;
$param->{last_name} = $last_name;
$param->{first_name} = $first_name || undef;
# put last_name & first_name into query param for patient merge link:
$self->query->param( last_name => $last_name );
$self->query->param( first_name => $first_name );
}
if ( my $patient_no = $param->{patient_no} ) { # DEBUG 'patient_no:' .$patient_no;
LIMS::Local::Utils::check_nhsno( $patient_no ) # if $patient_no passes nhs_no validation:
? $param->{nhs_number} = $patient_no
: $param->{unit_number} = $patient_no;
}
if ( grep $param->{$_}, qw(day month year) ) {
# create dob as DT object:
my $dob = DateTime->new( map { $_ => $param->{$_} } qw(day month year) ); # $self->debug($dob);
$param->{dob} = $dob;
} # warn Dumper $param;
# save extracted search params in session for retrieval if redirected to /patient (if no records found):
$self->session->param( patient_search_params => $param );
return $param;
}
#-------------------------------------------------------------------------------
sub _generate_search_constraints {
my $self = shift; $self->_debug_path();
my $param = shift; # $self->debug($param);
my %search;
my @form_fields = qw(patient_id last_name first_name dob unit_number nhs_number); # DEBUG $form_fields;
my @search_keys = grep $param->{$_}, @form_fields; # $self->debug(\@search_keys);
@search{@search_keys} = map {
/_name/ ?
{ like => $param->{$_} . '%' } : # create 'like' query
$param->{$_}; # create regular query
} @search_keys; # $self->debug(\%search);
if (%search) {
return [ %search ]; # query needs arrayref
}
else {
$self->stash->{error_msg}
= $self->messages('registration')->{empty_submission};
return 0;
}
}
=begin
sub _group_cases_by_patient {
my $self = shift;
my $iterator = shift;
my %patients;
CASE:
while (my $case = $iterator->next) {
my $id = $case->patient->id; # $self->debug($id);
# add referral_source object:
push @{ $patients{$id}{referral_source} }, $case;
# only need details once per patient:
next CASE if $patients{$id}{details};
my %details = (
last_name => $case->patient->last_name,
first_name => $case->patient->first_name,
middle_name => $case->patient->middle_name,
nhs_number => $case->patient->nhs_number,
gender => $case->patient->gender,
dob => $case->patient->dob,
id => $case->patient->id,
);
$patients{$id}{details} = \%details;
}
my @patients;
sub by_name {
$patients{$a}{details}{last_name} cmp $patients{$b}{details}{last_name}
||
$patients{$a}{details}{first_name} cmp $patients{$b}{details}{first_name}
||
$patients{$a}{details}{middle_name} cmp $patients{$b}{details}{middle_name};
}
foreach ( sort by_name keys %patients ) { # $self->debug($patients{$_}{referral_source});
push @patients, {
details => $patients{$_}{details},
referral_source => $patients{$_}{referral_source},
};
}
return \@patients;
}
=cut
1;