From c14c875b4c6047eedd4872a5991fc7f5e3c8bfb9 Mon Sep 17 00:00:00 2001 From: Mike Rylander Date: Fri, 29 May 2020 12:17:07 -0400 Subject: [PATCH] LP#1879983: My Account curbside TPAC app This adds code for managing curbside appointments in the public catalog My Account page. In addition to Mike Rylander, significant contributions to this patch were made and Galen Charlton. Sponsored-by: PaILS Signed-off-by: Mike Rylander Signed-off-by: Galen Charlton Signed-off-by: Michele Morgan --- .../lib/OpenILS/WWW/EGCatLoader/Account.pm | 139 ++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm index 3c78ea23a8..201d1f4d28 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm @@ -5,9 +5,11 @@ use OpenSRF::Utils::Logger qw/$logger/; use OpenILS::Utils::CStoreEditor qw/:funcs/; use OpenILS::Utils::Fieldmapper; use OpenILS::Application::AppUtils; +use OpenSRF::EX qw/:try/; use OpenILS::Event; use OpenSRF::Utils::JSON; use OpenSRF::Utils::Cache; +use OpenILS::Utils::DateTime qw/:datetime/; use Digest::MD5 qw(md5_hex); use Data::Dumper; $Data::Dumper::Indent = 0; @@ -1169,11 +1171,30 @@ sub fetch_user_holds { # put the holds back into the original server sort order my @sorted; + my %pickup_libs; for my $id (@$hold_ids) { push @sorted, grep { $_->{hold}->{hold}->id == $id } @holds; + + my $h = $sorted[-1]->{hold}->{hold}; + # if available, report the pickup lib in the list + $pickup_libs{$h->pickup_lib} = 1 if ( + $h && $h->pickup_lib == $h->current_shelf_lib && + $h->shelf_time && !$h->cancel_time && !$h->fulfillment_time + ); } - return { holds => \@sorted, ids => $hold_ids, all_ids => $all_ids }; + my $curbsides = []; + try { # if the service is not running, just let this fail silently + $curbsides = $U->simplereq( + 'open-ils.curbside', + 'open-ils.curbside.fetch_mine.atomic', + $e->authtoken + ); + } catch Error with {}; + + my @pickup_libs = sort { $U->find_org($U->get_org_tree,$a)->name cmp $U->find_org($U->get_org_tree,$b)->name } keys %pickup_libs; + + return { holds => \@sorted, ids => $hold_ids, all_ids => $all_ids, pickup_libs => \@pickup_libs, curbsides => $curbsides }; } sub handle_hold_update { @@ -1181,6 +1202,7 @@ sub handle_hold_update { my $action = shift; my $hold_ids = shift; my $e = $self->editor; + my $ctx = $self->ctx; my $url; my @hold_ids = ($hold_ids) ? @$hold_ids : $self->cgi->param('hold_id'); # for non-_all actions @@ -1252,6 +1274,93 @@ sub handle_hold_update { $url .= ";$param=" . uri_escape_utf8($_) foreach @vals; } } + } elsif ($action eq 'curbside') { # we'll only work on one curbside slot per refresh + $circ->kill_me; + + $circ = OpenSRF::AppSession->create('open-ils.curbside'); + + # see what we're doing with curbside here... + my $cs_action = $self->cgi->param("cs_action"); + my $slot_id = $self->cgi->param("cs_slot_id"); + + # we have an id, let's grab it if we can + my $slot = $e->retrieve_action_curbside($slot_id); + $slot = undef if ($slot && $slot->patron != $e->requestor->id); # nice try! + + my $org = $self->cgi->param("cs_org"); + my $date = $self->cgi->param("cs_date"); + my $time = $self->cgi->param("cs_time"); + my $notes = $self->cgi->param("cs_notes"); + + if ($slot) { + $org ||= $slot->org; + $notes ||= $slot->notes; + if ($slot->slot) { + my $dt = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($slot->slot)); + $date ||= $dt->strftime('%F'); + $time ||= $dt->strftime('%T'); + } + } + + $ctx->{cs_org} = $org; + $ctx->{cs_date} = $date; + $ctx->{cs_time} = $time; + $ctx->{cs_notes} = $notes; + $ctx->{cs_slot_id} = $slot->id if ($slot); + $ctx->{cs_slot} = $slot; + + if ($cs_action eq 'reset') { + $ctx->{cs_org} = $org = undef; + $ctx->{cs_date} = $date = undef; + $ctx->{cs_time} = $time = undef; + $ctx->{cs_notes} = $notes = undef; + $ctx->{cs_slot_id} = $slot_id = undef; + $ctx->{cs_slot} = $slot = undef; + } elsif ($cs_action eq 'save' && $org && $date && $time) { + my $mode = $slot ? 'update' : 'create'; + $slot = $circ->request( + "open-ils.curbside.${mode}_appointment", + $e->authtoken, $e->requestor->id, $date, $time, $org, $notes + )->gather(1); + + if (defined $U->event_code($slot)) { + $self->apache->log->warn( + "error attempting to $mode a curbside appointment for patron ". + $e->requestor->id . ", got event " . $slot->{textcode} + ); + $ctx->{curbside_action_event} = $slot; + $ctx->{cs_slot} = undef; + } else { + $ctx->{cs_slot} = $slot; + } + $url = $self->ctx->{proto} . '://' . $self->ctx->{hostname} . $self->ctx->{opac_root} . '/myopac/holds_curbside'; + } elsif ($cs_action eq 'cancel' && $slot) { + my $curbsides = $U->simplereq( + 'open-ils.curbside', + 'open-ils.curbside.delete_appointment', + $e->authtoken, $slot->id + ); + $url = $self->ctx->{proto} . '://' . $self->ctx->{hostname} . $self->ctx->{opac_root} . '/myopac/holds_curbside'; + } elsif ($cs_action eq 'arrive' && $slot) { + my $curbsides = $U->simplereq( + 'open-ils.curbside', + 'open-ils.curbside.mark_arrived', + $e->authtoken, $slot->id + ); + } elsif ($cs_action eq 'deliver' && $slot) { + my $curbsides = $U->simplereq( + 'open-ils.curbside', + 'open-ils.curbside.mark_delivered', + $e->authtoken, $slot->id + ); + } + + if ($date and $org and !$ctx->{cs_times}{$date}) { + $ctx->{cs_times}{$date} = $circ->request( + 'open-ils.curbside.times_for_date.atomic', + $e->authtoken, $date, $org + )->gather(1); + } } $circ->kill_me; @@ -1282,6 +1391,25 @@ sub load_myopac_holds { if($holds_object->{holds}) { $ctx->{holds} = $holds_object->{holds}; + $ctx->{curbside_appointments} = {}; + + $logger->info('curbside: found '.scalar(@{$holds_object->{curbsides}}).' appointments'); + + for my $cs (@{$holds_object->{curbsides}}) { + if ($cs->slot) { + my $dt = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($cs->slot))->strftime('%F'); + $ctx->{cs_times}{$dt} = $U->simplereq( + 'open-ils.curbside', 'open-ils.curbside.times_for_date.atomic', + $e->authtoken, $dt, $cs->org + ); + } + $ctx->{curbside_appointments}{$cs->org} = $cs; + } + + $ctx->{curbside_pickup_libs} = []; + for my $pul (@{$holds_object->{pickup_libs}}) { + push(@{$ctx->{curbside_pickup_libs}}, $pul) if $ctx->{get_org_setting}->($pul, 'circ.curbside'); + } } $ctx->{holds_ids} = $holds_object->{all_ids}; $ctx->{holds_limit} = $limit; @@ -2100,6 +2228,15 @@ sub load_myopac_hold_history { where => {id => $e->requestor->id} }); + # This is used to detect whether we want to show the curbside tab + my $extant_holds_object = $self->fetch_user_holds(); + if($extant_holds_object->{holds}) { + $ctx->{curbside_pickup_libs} = []; + for my $pul (@{$extant_holds_object->{pickup_libs}}) { + push(@{$ctx->{curbside_pickup_libs}}, $pul) if $ctx->{get_org_setting}->($pul, 'circ.curbside'); + } + } + my $holds_object = $self->fetch_user_holds([map { $_->{id} } @$hold_ids], 0, 1, 0, $limit, $offset); if($holds_object->{holds}) { $ctx->{holds} = $holds_object->{holds}; -- 2.11.0