From: Terran McCanna Date: Mon, 29 Aug 2022 16:24:12 +0000 (-0400) Subject: Online Renewal - First stab at adding erenew to Ecard.pm X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=84479e7cb4617dd5638fb054b966d6520a032857;p=evergreen%2Fpines.git Online Renewal - First stab at adding erenew to Ecard.pm Signed-off-by: Terran McCanna --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Ecard.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Ecard.pm index f35c448246..44f19da5f5 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Ecard.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Ecard.pm @@ -15,141 +15,93 @@ use Digest::MD5 qw(md5_hex); $Data::Dumper::Indent = 0; my $U = 'OpenILS::Application::AppUtils'; -my @api_fields = ( - {name => 'vendor_username', required => 1}, - {name => 'vendor_password', required => 1}, - {name => 'first_given_name', class => 'au', required => 1}, - {name => 'second_given_name', class => 'au'}, - {name => 'family_name', class => 'au', required => 1}, - {name => 'suffix', class => 'au'}, - {name => 'email', class => 'au', required => 1}, - {name => 'passwd', class => 'au', required => 1}, - {name => 'day_phone', class => 'au', required => 1}, - {name => 'dob', class => 'au', required => 1}, - {name => 'home_ou', class => 'au', required => 1}, - {name => 'ident_type', class => 'au', required => 1}, - {name => 'ident_value', class => 'au', required => 1}, - {name => 'ident_value2', - class => 'au', - notes => "AKA parent/guardian", - required_if => 'Patron is less than 18 years old' - }, - {name => 'pref_first_given_name', class => 'au'}, - {name => 'pref_second_given_name', class => 'au'}, - {name => 'pref_family_name', class => 'au'}, - {name => 'pref_suffix', class => 'au'}, - {name => 'physical_street1', class => 'aua', required => 1}, - {name => 'physical_street1_name'}, - {name => 'physical_street2', class => 'aua'}, - {name => 'physical_city', class => 'aua', required => 1}, - {name => 'physical_post_code', class => 'aua', required => 1}, - {name => 'physical_county', class => 'aua', required => 1}, - {name => 'physical_state', class => 'aua', required => 1}, - {name => 'physical_country', class => 'aua', required => 1}, - {name => 'mailing_street1', class => 'aua', required => 1}, - {name => 'mailing_street1_name'}, - {name => 'mailing_street2', class => 'aua'}, - {name => 'mailing_city', class => 'aua', required => 1}, - {name => 'mailing_post_code', class => 'aua', required => 1}, - {name => 'mailing_county', class => 'aua', required => 1}, - {name => 'mailing_state', class => 'aua', required => 1}, - {name => 'mailing_country', class => 'aua', required => 1}, - {name => 'voter_registration', class => 'asvr', required => 1}, - {name => 'in_house_registration', required => 1}, -); - - -# TODO: wrap the following in a check for a library setting as to whether or not -# to require emailed verification - -## Random 6-character alpha-numeric code that avoids look-alike characters -## https://ux.stackexchange.com/questions/53341/are-there-any-letters-numbers-that-should-be-avoided-in-an-id -## Also exclude vowels to avoid creating any real (potentially offensive) words. -#my @code_chars = ('C','D','F','H','J'..'N','P','R','T','V','W','X','3','4','7','9'); -#sub generate_verify_code { -# my $string = ''; -# $string .= $code_chars[rand @code_chars] for 1..6; -# return $string; -#} -# -# -## only if we're verifying the card via email -#sub load_ecard_verify { -# my $self = shift; -# my $cgi = $self->cgi; -# $self->collect_header_footer; -# -# # Loading the form. -# return Apache2::Const::OK if $cgi->request_method eq 'GET'; -# -# #$self->verify_ecard; -# return Apache2::Const::OK; -#} -# -#sub verify_ecard { -# my $self = shift; -# my $cgi = $self->cgi; -# my $ctx = $self->ctx; -# $self->log_params; -# -# my $verify_code = $ctx->{verify_code} = $cgi->param('verification_code'); -# my $barcode = $ctx->{barcode} = $cgi->param('barcode'); -# -# $ctx->{verify_failed} = 1; -# -# my $e = new_editor(); -# -# my $au = $e->search_actor_user({ -# profile => $PROVISIONAL_ECARD_GRP, -# ident_type => $ECARD_VERIFY_IDENT, -# ident_value => $verify_code -# })->[0]; -# -# if (!$au) { -# $logger->warn( -# "ECARD: No provisional ecard found with code $verify_code"); -# sleep 2; # Mitigate brute-force attacks -# return; -# } -# -# my $card = $e->search_actor_card({ -# usr => $au->id, -# barcode => $barcode -# })->[0]; -# -# if (!$card) { -# $logger->warn("ECARD: Failed to match verify code ". -# "($verify_code) with provided barcode ($barcode)"); -# sleep 2; # Mitigate brute-force attacks -# return; -# } -# -# # Verification looks good. Update the account. -# -# my $grp = new_editor()->retrieve_permission_grp_tree($FULL_ECARD_GRP); -# -# $au->profile($grp->id); -# $au->expire_date( -# DateTime->now(time_zone => 'local')->add( -# seconds => interval_to_seconds($grp->perm_interval))->iso8601() -# ); -# -# $e->xact_begin; -# -# unless ($e->update_actor_user($au)) { -# $logger->error("ECARD update failed for $barcode: " . $e->die_event); -# return; -# } -# -# $e->commit; -# $logger->info("ECARD: Update to full ecard succeeded for $barcode"); -# -# $ctx->{verify_success} = 1; -# $ctx->{verify_failed} = 0; -# -# return; -#} +# Check URL to see if this is a new registration or a renewal +# Do the subroutines have access to this variable??? +my $self = shift; +my $path = $self->apache->path_info; + +if ($path =~ m|opac/erenew/submit|) { + my $update_type = 'renew'; +} else { + my $update_type = 'register'; +} + +# Create different api_fields array if registration or renewal +if ($update_type == 'renew') { + my @api_fields = ( + {name => 'vendor_username', required => 1}, + {name => 'vendor_password', required => 1}, + {name => 'patron_id', required => 1}, #needed for matching + {name => 'email', class => 'au', required => 1}, + {name => 'day_phone', class => 'au', required => 1}, + {name => 'home_ou', class => 'au', required => 1}, + {name => 'pref_first_given_name', class => 'au'}, + {name => 'pref_second_given_name', class => 'au'}, + {name => 'pref_family_name', class => 'au'}, + {name => 'physical_street1', class => 'aua', required => 1}, + {name => 'physical_street1_name'}, + {name => 'physical_street2', class => 'aua'}, + {name => 'physical_city', class => 'aua', required => 1}, + {name => 'physical_post_code', class => 'aua', required => 1}, + {name => 'physical_county', class => 'aua', required => 1}, + {name => 'physical_state', class => 'aua', required => 1}, + {name => 'physical_country', class => 'aua', required => 1}, + {name => 'mailing_street1', class => 'aua', required => 1}, + {name => 'mailing_street1_name'}, + {name => 'mailing_street2', class => 'aua'}, + {name => 'mailing_city', class => 'aua', required => 1}, + {name => 'mailing_post_code', class => 'aua', required => 1}, + {name => 'mailing_county', class => 'aua', required => 1}, + {name => 'mailing_state', class => 'aua', required => 1}, + {name => 'mailing_country', class => 'aua', required => 1}, + {name => 'voter_registration', class => 'asvr', required => 1}, + {name => 'temp_renewal'} #new boolean value + ); +} else { + my @api_fields = ( + {name => 'vendor_username', required => 1}, + {name => 'vendor_password', required => 1}, + {name => 'first_given_name', class => 'au', required => 1}, + {name => 'second_given_name', class => 'au'}, + {name => 'family_name', class => 'au', required => 1}, + {name => 'suffix', class => 'au'}, + {name => 'email', class => 'au', required => 1}, + {name => 'passwd', class => 'au', required => 1}, + {name => 'day_phone', class => 'au', required => 1}, + {name => 'dob', class => 'au', required => 1}, + {name => 'home_ou', class => 'au', required => 1}, + {name => 'ident_type', class => 'au', required => 1}, + {name => 'ident_value', class => 'au', required => 1}, + {name => 'ident_value2', + class => 'au', + notes => "AKA parent/guardian", + required_if => 'Patron is less than 18 years old' + }, + {name => 'pref_first_given_name', class => 'au'}, + {name => 'pref_second_given_name', class => 'au'}, + {name => 'pref_family_name', class => 'au'}, + {name => 'pref_suffix', class => 'au'}, + {name => 'physical_street1', class => 'aua', required => 1}, + {name => 'physical_street1_name'}, + {name => 'physical_street2', class => 'aua'}, + {name => 'physical_city', class => 'aua', required => 1}, + {name => 'physical_post_code', class => 'aua', required => 1}, + {name => 'physical_county', class => 'aua', required => 1}, + {name => 'physical_state', class => 'aua', required => 1}, + {name => 'physical_country', class => 'aua', required => 1}, + {name => 'mailing_street1', class => 'aua', required => 1}, + {name => 'mailing_street1_name'}, + {name => 'mailing_street2', class => 'aua'}, + {name => 'mailing_city', class => 'aua', required => 1}, + {name => 'mailing_post_code', class => 'aua', required => 1}, + {name => 'mailing_county', class => 'aua', required => 1}, + {name => 'mailing_state', class => 'aua', required => 1}, + {name => 'mailing_country', class => 'aua', required => 1}, + {name => 'voter_registration', class => 'asvr', required => 1}, + {name => 'in_house_registration', required => 1}, + ); +} sub log_params { my $self = shift; @@ -162,8 +114,13 @@ sub log_params { $msg .= "|" if $msg; $msg .= "$p=".$cgi->param($p); } - - $logger->info("ECARD: Submit params: $msg"); + + # use different log msg if reg or renew + if ($update_type == 'register') { + $logger->info("ECARD: Submit params: $msg"); + } else { + $logger->info("E-RENEW: Submit params: $msg"); + } } sub handle_testmode_api { @@ -237,18 +194,27 @@ sub load_ecard_submit { return $self->handle_testmode_api if $testmode eq 'API'; return $self->handle_datamode_api($datamode) if $datamode; - return $self->compile_response unless $self->make_user; - return $self->compile_response unless $self->add_addresses; - return $self->compile_response unless $self->check_dupes; - return $self->compile_response unless $self->add_card; - return $self->compile_response unless $self->add_survey_responses; - return $self->compile_response unless $self->save_user; - return $self->compile_response unless $self->add_usr_settings; - return $self->compile_response if $ctx->{response}->{status}; - - $U->create_events_for_hook( - 'au.create.ecard', $ctx->{user}, $ctx->{user}->home_ou); - + # Accommodate reg vs renew + if ($update_type == 'register') { + return $self->compile_response unless $self->make_user; + return $self->compile_response unless $self->add_addresses; + return $self->compile_response unless $self->check_dupes; + return $self->compile_response unless $self->add_card; + return $self->compile_response unless $self->add_survey_responses; + return $self->compile_response unless $self->save_user; + return $self->compile_response unless $self->add_usr_settings; + return $self->compile_response if $ctx->{response}->{status}; + + $U->create_events_for_hook( + 'au.create.ecard', $ctx->{user}, $ctx->{user}->home_ou); + } else { + return $self->compile_response unless $self->update_user; + return $self->compile_response unless $self->update_addresses; + return $self->compile_response unless $self->add_survey_responses; + return $self->compile_response unless $self->save_user; + return $self->compile_response if $ctx->{response}->{status}; + } + $ctx->{response}->{status} = 'OK'; $ctx->{response}->{barcode} = $ctx->{user}->card->barcode; @@ -292,16 +258,23 @@ sub verify_vendor_host { return 1; } - sub compile_response { my $self = shift; my $ctx = $self->ctx; $self->apache->content_type("application/json; charset=utf-8"); $ctx->{response} = OpenSRF::Utils::JSON->perl2JSON($ctx->{response}); - $logger->info("ECARD responding with " . $ctx->{response}); + # Different log message if renew + if ($update_type == 'register') { + $logger->info("ECARD responding with " . $ctx->{response}); + } else { + $logger->info("E-RENEW responding with " . $ctx->{response}); + } return Apache2::Const::OK; } +#Do we need to change this line if usrname and passwd do not exist in +#renewal api object? +#Do we even need to do this at all? I don't see that we're calling it my %keep_case = (usrname => 1, passwd => 1, email => 1); sub upperclense { my $self = shift; @@ -366,6 +339,60 @@ sub make_user { return $ctx->{user} = $au; } +# New sub to update a user +sub update_user { + my $self = shift; + my $ctx = $self->ctx; + my $cgi = $self->cgi; + + my $au = Fieldmapper::actor::user->new; + + # Grab user id - is this how we match the right patron to update? + $au->id($cgi->param('patron_id')); + + # We need to figure out how to append this value rather than replace + $au->name_keywords('quipu_renew'); + + my $home_ou = $cgi->param('home_ou'); + + # Temp renewal is only 30 days, otherwise use perm_interval + # Is using '30 days' the right syntax here? + my $temp_renewal = $cgi->param('temp_renewal'); + + if ($temp_renewal == '1') { + $au->expire_date( + DateTime(now(time_zone => 'local')->add( + seconds => interval_to_seconds('30 days')->iso8601() + } else { + $au->profile($perm_grp); + my $grp = new_editor()->retrieve_permission_grp_tree($perm_grp); + $au->expire_date( + DateTime->now(time_zone => 'local')->add( + seconds => interval_to_seconds($grp->perm_interval))->iso8601() + ); + } + + # loop through fields submitted by quipu + for my $field_info (@api_fields) { + my $field = $field_info->{name}; + next unless $field_info->{class} eq 'au'; + + my $val = $cgi->param($field); + + if ($field_info->{required} && !$val) { + my $msg = "Value required for field: '$field'"; + $ctx->{response}->{status} = 'INVALID_PARAMS'; + push(@{$ctx->{response}->{messages}}, $msg); + $logger->error("E-RENEW $msg"); + } + + $val = undef if $field eq 'day_phone' && $val eq '--'; + $au->$field($val); + } + + return $ctx->{user} = $au; +} + # Card generation must occur after the user is saved in the DB. sub add_card { my $self = shift; @@ -518,6 +545,72 @@ sub add_addresses { return 1; } +# New subroutine to update existing addresses +# Need to figure out how to update the right ones +sub update_addresses { + my $self = shift; + my $cgi = $self->cgi; + my $ctx = $self->ctx; + my $e = $ctx->{editor}; + my $user = $ctx->{user}; # probably need to do something else here? + + # Need to see how to pass the patron id properly here + # Do we need to get the ID of the existing address? + # Or will it match because of the address_type? + my $physical_addr = Fieldmapper::actor::user_address->new; + $physical_addr->isnew(0); # is this right? + $physical_addr->usr($user->id); + $physical_addr->address_type('PHYSICAL'); + $physical_addr->within_city_limits('f'); + + my $mailing_addr = Fieldmapper::actor::user_address->new; + $mailing_addr->isnew(0); # is this right? + $mailing_addr->usr($user->id); + $mailing_addr->address_type('MAILING'); + $mailing_addr->within_city_limits('f'); + + # Use as both billing and mailing via virtual ID. + $physical_addr->id(-1); + $mailing_addr->id(-2); + $user->billing_address(-1); + $user->mailing_address(-2); + + # Confirm we have values for all of the required fields. + # Apply values to our in-progress address object. + for my $field_info (@api_fields) { + my $field = $field_info->{name}; + next unless $field =~ /physical|mailing/; + next if $field =~ /street1_/; + + my $val = $cgi->param($field); + + if ($field_info->{required} && !$val) { + my $msg = "Value required for field: '$field'"; + $ctx->{response}->{status} = 'INVALID_PARAMS'; + push(@{$ctx->{response}->{messages}}, $msg); + $logger->error("E-RENEW $msg"); + } + + if ($field =~ /physical/) { + (my $col_field = $field) =~ s/physical_//g; + $physical_addr->$col_field($val) if $val; + } else { + (my $col_field = $field) =~ s/mailing_//g; + $mailing_addr->$col_field($val) if $val; + } + + } + + # exit if there were any errors above. + return undef if $ctx->{response}->{status}; + + $user->billing_address($physical_addr); + $user->mailing_address($mailing_addr); + $user->addresses([$physical_addr, $mailing_addr]); + + return 1; +} + sub add_usr_settings { my $self = shift; my $cgi = $self->cgi; @@ -552,35 +645,6 @@ sub add_survey_responses { return 1; } -# TODO: this is KCLS-specific, but maybe we can make it something -# generic for adding stat cats to the patron - -#sub add_stat_cats { -# my $self = shift; -# my $cgi = $self->cgi; -# my $user = $self->ctx->{user}; -# -# my $ds_map = Fieldmapper::actor::stat_cat_entry_user_map->new; -# $ds_map->isnew(1); -# $ds_map->stat_cat(12); -# $ds_map->stat_cat_entry('KCLS'); -# -# my $events = $cgi->param('events_mailing'); -# my $em_map = Fieldmapper::actor::stat_cat_entry_user_map->new; -# $em_map->isnew(1); -# $em_map->stat_cat(3); -# $em_map->stat_cat_entry($events ? 'Y' : 'N'); -# -# my $foundation = $cgi->param('foundation_mailing'); -# my $fm_map = Fieldmapper::actor::stat_cat_entry_user_map->new; -# $fm_map->isnew(1); -# $fm_map->stat_cat(4); -# $fm_map->stat_cat_entry($foundation ? 'Y' : 'N'); -# -# $user->stat_cat_entries([$ds_map, $em_map, $fm_map]); -# return 1; -#} - # Returns true if no dupes found, false if dupes are found. sub check_dupes { my $self = shift; @@ -614,41 +678,6 @@ sub check_dupes { $logger->info("ECARD found potential duplicate patrons: @$ids"); -# if (my $streetname = $self->cgi->param('physical_street1_name')) { -# # We found matching patrons. Perform a secondary check on the -# # address street name only. -# -# $logger->info("ECARD secondary search on street name: $streetname"); -# -# my $addr_ids = $e->search_actor_user_address( -# { usr => $ids, -# street1 => {'~*' => "(^| )$streetname( |\$)"} -# }, {idlist => 1} -# ); -# -# if (@$addr_ids) { -# # we don't really care what patrons match at this point, -# # only whether a match is found. -# $ids = [1]; -# $logger->info("ECARD secondary address check match(es) ". -# "found on address(es) @$addr_ids"); -# -# } else { -# $ids = []; -# $logger->info( -# "ECARD secondary address check found no matches"); -# } -# -# } else { -# $ids = []; -# # unclear if this is a possibility -- err on the side of allowing -# # the registration. -# $logger->info("ECARD found possible patron match but skipping ". -# "secondary street name check -- no street name was provided"); -# } -# -# return 1 if @$ids == 0; - $ctx->{response}->{status} = 'DUPLICATE'; $ctx->{response}->{messages} = ['first_given_name', 'family_name', 'dob']; @@ -660,7 +689,7 @@ sub save_user { my $self = shift; my $ctx = $self->ctx; my $cgi = $self->cgi; - my $user = $ctx->{user}; + my $user = $ctx->{user}; #Do we need to change this for renew? my $resp = $U->simplereq( 'open-ils.actor', @@ -672,10 +701,16 @@ sub save_user { if ($U->is_event($resp)) { + if ($update_type == 'register') { my $msg = "Error creating user account: " . $resp->{textcode}; $logger->error("ECARD: $msg"); + $ctx->{response}->{status} = 'CREATE_ERR'; + } else { + my $msg = "Error updating user account: " . $resp->{textcode}; + $logger->error("E-RENEW: $msg"); + $ctx->{response}->{status} = 'UPDATE_ERR'; # Does this work? + } - $ctx->{response}->{status} = 'CREATE_ERR'; $ctx->{response}->{messages} = [{msg => $msg, pid => $$}]; return 0;