Bugzilla – Attachment 134487 Details for
Bug 30484
Interlibrary loans should have the ability to send notices based on request supplier updates
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 30484: Implement support for ILL request updates
Bug-30484-Implement-support-for-ILL-request-update.patch (text/plain), 15.55 KB, created by
Andrew Isherwood
on 2022-05-03 08:46:52 UTC
(
hide
)
Description:
Bug 30484: Implement support for ILL request updates
Filename:
MIME Type:
Creator:
Andrew Isherwood
Created:
2022-05-03 08:46:52 UTC
Size:
15.55 KB
patch
obsolete
>From 07b8492a465a3b9b073c08e4e3dfbf99055e7b57 Mon Sep 17 00:00:00 2001 >From: Andrew Isherwood <andrew.isherwood@ptfs-europe.com> >Date: Fri, 8 Apr 2022 16:09:30 +0100 >Subject: [PATCH] Bug 30484: Implement support for ILL request updates > >This commit adds support for the concept of ILL request update notices. > >- Adds a new Koha::Illrequest::SupplierUpdate class that is used to >encapsulate an update to a request, this update may come from a >supplier via a backend or from core ILL via, perhaps, a user action >- Adds a new Koha::Illrequest::SupplierUpdateProcessor base class that >can be subclassed in order to create a processor that can be passed an >update and act accordingly. >- Updates to Illrequest.pm to support the above classes and allow core >Koha to offer update processors >- A shell script to initiate a periodic process to check for updates >meeting given criteria and run the appropriate processors >--- > Koha/Illrequest.pm | 101 +++++++++++++- > Koha/Illrequest/SupplierUpdate.pm | 111 +++++++++++++++ > Koha/Illrequest/SupplierUpdateProcessor.pm | 85 ++++++++++++ > misc/process_ill_updates.pl | 153 +++++++++++++++++++++ > 4 files changed, 444 insertions(+), 6 deletions(-) > create mode 100644 Koha/Illrequest/SupplierUpdate.pm > create mode 100644 Koha/Illrequest/SupplierUpdateProcessor.pm > create mode 100755 misc/process_ill_updates.pl > >diff --git a/Koha/Illrequest.pm b/Koha/Illrequest.pm >index 511b3f5ffe..2d23be74cf 100644 >--- a/Koha/Illrequest.pm >+++ b/Koha/Illrequest.pm >@@ -116,6 +116,33 @@ available for request. > > =head2 Class methods > >+=head3 init_processors >+ >+ $request->init_processors() >+ >+Initialises an empty processors arrayref >+ >+=cut >+ >+sub init_processors { >+ my ( $self ) = @_; >+ >+ $self->{processors} = []; >+} >+ >+=head3 push_processor >+ >+ $request->push_processors(sub { ...something... }); >+ >+Pushes a passed processor function into our processors arrayref >+ >+=cut >+ >+sub push_processor { >+ my ( $self, $processor ) = @_; >+ push @{$self->{processors}}, $processor; >+} >+ > =head3 statusalias > > my $statusalias = $request->statusalias; >@@ -371,6 +398,7 @@ sub _backend_capability { > try { > $capability = $self->_backend->capabilities($name); > } catch { >+ warn $_; > return 0; > }; > # Try to invoke it >@@ -896,6 +924,28 @@ sub backend_create { > return $self->expandTemplate($result); > } > >+=head3 backend_get_update >+ >+ my $update = backend_get_update($request); >+ >+ Given a request, returns an update in a prescribed >+ format that can then be passed to update parsers >+ >+=cut >+ >+sub backend_get_update { >+ my ( $self, $delay ) = @_; >+ >+ my $response = $self->_backend_capability( >+ 'get_supplier_update', >+ { >+ request => $self, >+ delay => $delay >+ } >+ ); >+ return $response; >+} >+ > =head3 expandTemplate > > my $params = $abstract->expandTemplate($params); >@@ -1419,7 +1469,7 @@ Send a specified notice regarding this request to a patron > =cut > > sub send_patron_notice { >- my ( $self, $notice_code ) = @_; >+ my ( $self, $notice_code, $additional_text ) = @_; > > # We need a notice code > if (!$notice_code) { >@@ -1430,8 +1480,9 @@ sub send_patron_notice { > > # Map from the notice code to the messaging preference > my %message_name = ( >- ILL_PICKUP_READY => 'Ill_ready', >- ILL_REQUEST_UNAVAIL => 'Ill_unavailable' >+ ILL_PICKUP_READY => 'Ill_ready', >+ ILL_REQUEST_UNAVAIL => 'Ill_unavailable', >+ ILL_REQUEST_UPDATE => 'Ill_update' > ); > > # Get the patron's messaging preferences >@@ -1453,8 +1504,9 @@ sub send_patron_notice { > my @fail = (); > for my $transport (@transports) { > my $letter = $self->get_notice({ >- notice_code => $notice_code, >- transport => $transport >+ notice_code => $notice_code, >+ transport => $transport, >+ additional_text => $additional_text > }); > if ($letter) { > my $result = C4::Letters::EnqueueLetter({ >@@ -1595,13 +1647,50 @@ sub get_notice { > substitute => { > ill_bib_title => $title ? $title->value : '', > ill_bib_author => $author ? $author->value : '', >- ill_full_metadata => $metastring >+ ill_full_metadata => $metastring, >+ additional_text => $params->{additional_text} > } > ); > > return $letter; > } > >+ >+=head3 attach_processors >+ >+Receive a Koha::Illrequest::SupplierUpdate and attach >+any processors we have for it >+ >+=cut >+ >+sub attach_processors { >+ my ( $self, $update ) = @_; >+ >+ foreach my $processor(@{$self->{processors}}) { >+ if ( >+ $processor->{target_source_type} eq $update->{source_type} && >+ $processor->{target_source_name} eq $update->{source_name} >+ ) { >+ $update->attach_processor($processor); >+ } >+ } >+} >+ >+=head3 append_to_note >+ >+ append_to_note("Some text"); >+ >+Append some text to the staff note >+ >+=cut >+ >+sub append_to_note { >+ my ($self, $text) = @_; >+ my $current = $self->notesstaff; >+ $text = ($current && length $current > 0) ? "$current\n\n$text" : $text; >+ $self->notesstaff($text)->store; >+} >+ > =head3 id_prefix > > my $prefix = $record->id_prefix; >diff --git a/Koha/Illrequest/SupplierUpdate.pm b/Koha/Illrequest/SupplierUpdate.pm >new file mode 100644 >index 0000000000..93624311a7 >--- /dev/null >+++ b/Koha/Illrequest/SupplierUpdate.pm >@@ -0,0 +1,111 @@ >+package Koha::Illrequest::SupplierUpdate; >+ >+# Copyright 2022 PTFS Europe Ltd >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+=head1 NAME >+ >+Koha::Illrequest::SupplierUpdate - Represents a single request update from a supplier >+ >+=head1 SYNOPSIS >+ >+Object-oriented class that provides an object allowing us to interact with >+an update from a supplier >+ >+=head1 DESCRIPTION >+ >+Object-oriented class that provides an object allowing us to interact with >+an update from a supplier >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=head3 new >+ >+ my $update = Koha::Illrequest::SupplierUpdate->new( >+ $source_type, >+ $source_name, >+ $update >+ ); >+ >+Create a new Koha::Illrequest::SupplierUpdate object. >+ >+=cut >+ >+sub new { >+ my ( $class, $source_type, $source_name, $update, $request ) = @_; >+ my $self = {}; >+ >+ $self->{source_type} = $source_type; >+ $self->{source_name} = $source_name; >+ $self->{update} = $update; >+ $self->{request} = $request; >+ $self->{processors} = []; >+ >+ bless $self, $class; >+ >+ return $self; >+} >+ >+=head3 attach_processor >+ >+ Koha::Illrequest::SupplierUpdate->attach_processor($processor); >+ >+Pushes a processor function onto the 'processors' arrayref >+ >+=cut >+ >+sub attach_processor { >+ my ( $self, $processor ) = @_; >+ push(@{$self->{processors}}, $processor); >+} >+ >+=head3 run_processors >+ >+ Koha::Illrequest::SupplierUpdate->run_processors(); >+ >+Iterates all processors on this object and runs each >+ >+=cut >+ >+sub run_processors { >+ my ( $self ) = @_; >+ my $results = []; >+ foreach my $processor(@{$self->{processors}}) { >+ my $processor_result = { >+ name => $processor->{name}, >+ result => { >+ success => [], >+ error => [] >+ } >+ }; >+ $processor->run($self, $processor_result->{result}); >+ push @{$results}, $processor_result; >+ } >+ return $results; >+} >+ >+=head1 AUTHOR >+ >+Andrew Isherwood <andrew.isherwood@ptfs-europe.com> >+ >+=cut >+ >+1; >diff --git a/Koha/Illrequest/SupplierUpdateProcessor.pm b/Koha/Illrequest/SupplierUpdateProcessor.pm >new file mode 100644 >index 0000000000..3136127c83 >--- /dev/null >+++ b/Koha/Illrequest/SupplierUpdateProcessor.pm >@@ -0,0 +1,85 @@ >+package Koha::Illrequest::SupplierUpdateProcessor; >+ >+# Copyright 2022 PTFS Europe Ltd >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+=head1 NAME >+ >+Koha::Illrequest::SupplierUpdateProcessor - Represents a SupplerUpdate processor >+ >+=head1 SYNOPSIS >+ >+Object-oriented class that provides an object allowing us to perform processing on >+a SupplierUpdate >+ >+=head1 DESCRIPTION >+ >+Object-oriented base class that provides an object allowing us to perform processing on >+a SupplierUpdate >+** This class should not be directly instantiated, it should only be sub-classed ** >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=head3 new >+ >+ my $processor = Koha::Illrequest::SupplierUpdateProcessor->new( >+ $target_source_type, >+ $target_source_name >+ ); >+ >+Create a new Koha::Illrequest::SupplierUpdateProcessor object. >+ >+=cut >+ >+sub new { >+ my ( $class, $target_source_type, $target_source_name, $processor_name ) = @_; >+ my $self = {}; >+ >+ $self->{target_source_type} = $target_source_type; >+ $self->{target_source_name} = $target_source_name; >+ $self->{name} = $processor_name; >+ >+ bless $self, $class; >+ >+ return $self; >+} >+ >+=head3 run >+ >+ Koha::Illrequest::SupplierUpdateProcessor->run(); >+ >+Runs the processor >+ >+=cut >+ >+sub run { >+ my ( $self ) = @_; >+ my ( $package, $filename ) = caller; >+ warn __PACKAGE__ . " run should only be invoked by a subclass\n"; >+} >+ >+=head1 AUTHOR >+ >+Andrew Isherwood <andrew.isherwood@ptfs-europe.com> >+ >+=cut >+ >+1; >diff --git a/misc/process_ill_updates.pl b/misc/process_ill_updates.pl >new file mode 100755 >index 0000000000..4854db7f66 >--- /dev/null >+++ b/misc/process_ill_updates.pl >@@ -0,0 +1,153 @@ >+#!/usr/bin/perl >+ >+# This file is part of Koha. >+# >+# Copyright (C) 2022 PTFS Europe >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+use Getopt::Long qw( GetOptions ); >+use POSIX; >+ >+use Koha::Script; >+use Koha::Illrequests; >+ >+# Command line option values >+my $get_help = 0; >+my $delay = 0; >+my $statuses = ""; >+my $backend = ""; >+ >+my $options = GetOptions( >+ 'h|help' => \$get_help, >+ 'statuses=s' => \$statuses, >+ 'backend=s' => \$backend, >+ 'api-delay:i' => \$delay >+); >+ >+if ($get_help) { >+ get_help(); >+ exit 1; >+} >+ >+if (!$backend) { >+ print "No backend specified\n"; >+ exit 0; >+} >+ >+# First check we can proceed >+my $cfg = Koha::Illrequest::Config->new; >+my $backends = $cfg->available_backends; >+my $has_branch = $cfg->has_branch; >+my $backends_available = ( scalar @{$backends} > 0 ); >+if (!$has_branch || $backends_available == 0) { >+ print "Unable to proceed:\n"; >+ print "Branch configured: $has_branch\n"; >+ print "Backends available: $backends_available\n"; >+ exit 0; >+} >+ >+# Get all requests with a REQ status >+my @statuses_arr = split(/:/, $statuses); >+if (scalar @statuses_arr == 0) { >+ print "No statuses supplied\n"; >+ exit 0; >+} >+ >+my $where = { >+ status => { -in => \@statuses_arr }, >+ backend => $backend >+}; >+ >+my $requests = Koha::Illrequests->search($where); >+ >+# The progress log >+my $output = []; >+ >+while (my $request = $requests->next) { >+ my $update = $request->backend_get_update($delay); >+ # The log for this request >+ my $update_log = { >+ request_id => $request->illrequest_id, >+ processed_by => $request->_backend->name, >+ processors_run => [] >+ }; >+ if ($update) { >+ # Currently we make an assumption, this may need revisiting >+ # if we need to extend the functionality: >+ # >+ # Only the backend that originated the update will want to >+ # process it >+ # >+ # Since each backend's update format is different, it may >+ # be necessary for a backend to subclass Koha::Illrequest::SupplierUpdate >+ # so it can provide methods (corresponding to a generic interface) that >+ # return pertinent info to core ILL when it is processing updates >+ # >+ # Attach any request processors >+ $request->attach_processors($update); >+ # Attach any processors from this request's backend >+ $request->_backend->attach_processors($update); >+ my $processor_results = $update->run_processors($delay); >+ # Update our progress log >+ $update_log->{processors_run} = $processor_results; >+ } >+ push @{$output}, $update_log; >+} >+ >+print_summary($output); >+ >+sub print_summary { >+ my ( $log ) = @_; >+ >+ my $timestamp = POSIX::strftime("%d/%m/%Y %H:%M:%S\n", localtime); >+ print "Run details:\n"; >+ foreach my $entry(@{$log}) { >+ my @processors_run = @{$entry->{processors_run}}; >+ print "Request ID: " . $entry->{request_id} . "\n"; >+ print " Processing by: " . $entry->{processed_by} . "\n"; >+ print " Number of processors run: " . scalar @processors_run . "\n"; >+ if (scalar @processors_run > 0) { >+ print " Processor details:\n"; >+ foreach my $processor(@processors_run) { >+ print " Processor name: " . $processor->{name} . "\n"; >+ print " Success messages: " . join(", ", @{$processor->{result}->{success}}) . "\n"; >+ print " Error messages: " . join(", ", @{$processor->{result}->{error}}) . "\n"; >+ } >+ } >+ } >+ print "Job completed at $timestamp\n====================================\n\n" >+} >+ >+sub get_help { >+ print <<"HELP"; >+$0: Fetch and process outstanding ILL updates >+ >+This script will fetch all requests that have the specified >+statuses and run any applicable processor scripts on them. >+For example, the RapidILL backend provides a processor script >+that emails users when their requested electronic resource >+request has been fulfilled >+ >+Parameters: >+ --statuses <statuses> [required] specify the statuses a request must have in order to be processed, >+ statuses should be separated by a : e.g. REQ:COMP:NEW >+ >+ --delay <seconds> if a processing script needs to make an API call, how long a pause >+ should be inserted between each API call >+ >+ --help or -h get help >+HELP >+} >-- >2.20.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 30484
:
133394
|
133395
|
133396
|
133399
|
133400
|
133401
|
134486
|
134487
|
134488
|
134569
|
134570
|
134571
|
134572
|
134573
|
134574
|
134626
|
134627
|
134628
|
138859
|
138860
|
138861
|
138862