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); # warn Dumper $data->as_tree; unless ($data) { # probably incorrectly hand-typed barcode string my $msg = $self->messages('registration')->{no_request_form_id}; $self->flash( warning => $msg ); return $self->redirect( $self->query->url . '/register' ); } my $nhs_number = $data->nhs_number; 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 => $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; # if location requires external_ref (eg GeNEQ requests require NGIS id): if ( my $yaml = $self->get_yaml_file('required_external_ref') ) { # warn Dumper $yaml; my @location_names = keys %$yaml; # warn Dumper \@location_names; my $location_name = $data->location_name; # warn $location_name; if ( $nhs_number && grep $location_name =~ $_, @location_names ) { my $key = $yaml->{$location_name}; # warn $key; my %h = ( external_ref => $data->{$key}, # external ref = eg GeNEQ unique id nhs_number => $data->nhs_number, # needed to ensure correct target ); $self->session->param( required_external_ref => \%h ); } } # warn Dumper \%vars; $self->_extract_params_from_request(\%vars); # $self->debug($vars); # update request_form.imported col: $self->model('Request')->request_form_import($id); # 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->render_view('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} ) { # split $name on comma or space: my @names = split /\,\s?|\s+/, $name; # warn Dumper \@names; $param->{last_name} = shift @names; # 1st element $param->{first_name} = shift @names; # 2nd element, if any left: my $middle_name = join ' ', @names; if ( $middle_name && length $middle_name > 1 ) { # skip if only initial $param->{middle_name} = $middle_name; } # warn Dumper $param; # put last_name & first_name into query param for patient merge link: $self->query->param( last_name => $param->{last_name} ); $self->query->param( first_name => $param->{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;