@@ -, +, @@ - ILL request ready for pickup - ILL request unavailable - Place request with partners - Request has been modified by patron - Request has been cancelled by patron - "ILLDefaultStaffEmail" - Fallback email address for staff ILL notices - "ILLSendStaffNotices" - To specify which staff notices should be sent --- Koha/Illrequest.pm | 350 ++++++++++++++++----- Koha/Illrequest/Logger.pm | 41 ++- ill/ill-requests.pl | 36 ++- .../prog/en/modules/ill/ill-requests.tt | 39 +++ .../prog/en/modules/ill/log/patron_notice.tt | 6 + opac/opac-illrequests.pl | 2 + 6 files changed, 400 insertions(+), 74 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/ill/log/patron_notice.tt --- a/Koha/Illrequest.pm +++ a/Koha/Illrequest.pm @@ -25,6 +25,8 @@ use Encode qw( encode ); use Try::Tiny; use DateTime; +use C4::Letters; +use C4::Members; use Koha::Database; use Koha::DateUtils qw/ dt_from_string /; use Koha::Email; @@ -248,6 +250,7 @@ sub status_alias { Overloaded getter/setter for request status, also nullifies status_alias and records the fact that the status has changed +and sends a notice if appropriate =cut @@ -281,6 +284,10 @@ sub status { }); } delete $self->{previous_status}; + # If status has changed to cancellation requested, send a notice + if ($new_status eq 'CANCREQ') { + $self->send_staff_notice('ILL_REQUEST_CANCEL'); + } return $ret; } else { return $current_status; @@ -1287,38 +1294,11 @@ sub generic_confirm { my $library = Koha::Libraries->find($params->{current_branchcode}) || die "Invalid current branchcode. Are you logged in as the database user?"; if ( !$params->{stage}|| $params->{stage} eq 'init' ) { - my $draft->{subject} = "ILL Request"; - $draft->{body} = <metadata; - while (my ($title, $value) = each %{$details}) { - $draft->{body} .= " - " . $title . ": " . $value . "\n" - if $value; - } - $draft->{body} .= <$_ } - qw/ branchname branchaddress1 branchaddress2 branchaddress3 - branchzip branchcity branchstate branchcountry branchphone - branchillemail branchemail /; - my $address = ""; - foreach my $line ( @address ) { - $address .= $line . "\n" if $line; - } - - $draft->{body} .= $address; + # Get the message body from the notice definition + my $letter = $self->get_notice({ + notice_code => 'ILL_PARTNER_REQ', + transport => 'email' + }); my $partners = Koha::Patrons->search({ categorycode => $self->_config->partner_code @@ -1330,7 +1310,10 @@ EOF method => 'generic_confirm', stage => 'draft', value => { - draft => $draft, + draft => { + subject => $letter->{title}, + body => $letter->{content} + }, partners => $partners, } }; @@ -1346,57 +1329,280 @@ EOF "No target email addresses found. Either select at least one partner or check your ILL partner library records.") if ( !$to ); # Create the from, replyto and sender headers - my $from = $library->branchemail; - my $reply_to = $library->branchreplyto || $from; + my $from = $branch->branchillemail || $branch->branchemail; + my $replyto = $branch->branchreplyto || $from; Koha::Exceptions::Ill::NoLibraryEmail->throw( "Your library has no usable email address. Please set it.") if ( !$from ); - # Create the email - my $email = Koha::Email->create( - { - to => $to, - from => $from, - reply_to => $reply_to, - subject => $params->{subject}, - text_body => $params->{body}, + # So we get a notice hashref, then substitute the possibly + # modified title and body from the draft stage + my $letter = $self->get_notice({ + notice_code => 'ILL_PARTNER_REQ', + transport => 'email' + }); + $letter->{title} = $params->{subject}; + $letter->{content} = $params->{body}; + + # Send the email + my $params = { + letter => $letter, + borrowernumber => $self->borrowernumber, + message_transport_type => 'email', + to_address => $to, + from_address => $from + }; + + if ($letter) { + my $result = C4::Letters::EnqueueLetter($params); + if ( $result ) { + $self->status("GENREQ")->store; + $self->_backend_capability( + 'set_requested_partners', + { + request => $self, + to => $to + } + ); + return { + error => 0, + status => '', + message => '', + method => 'generic_confirm', + stage => 'commit', + next => 'illview', + }; } - ); + } + return { + error => 1, + status => 'email_failed', + message => 'Email queueing failed', + method => 'generic_confirm', + stage => 'draft', + }; + } else { + die "Unknown stage, should not have happened." + } +} - # Send it - try { +=head3 get_staff_to_address - $email->send_or_die({ transport => $library->smtp_server->transport }); + my $email = $request->get_staff_to_address(); - $self->status("GENREQ")->store; - $self->_backend_capability( - 'set_requested_partners', - { - request => $self, - to => $to - } - ); - return { - error => 0, - status => '', - message => '', - method => 'generic_confirm', - stage => 'commit', - next => 'illview', - }; +Get the email address to which staff notices should be sent + +=cut + +sub get_staff_to_address { + my ( $self ) = @_; + + # The various places we can get an ILL staff email address from + # (In order of preference) + # + # Dedicated branch address + my $library = Koha::Libraries->find( $self->branchcode ); + my $branch_ill_to = $library->branchillemail; + # General purpose ILL address from syspref + my $syspref = C4::Context->preference("ILLDefaultStaffEmail"); + # Branch general email address + my $branch_to = $library->branchemail; + # Last resort + my $koha_admin = C4::Context->preference('KohaAdminEmailAddress'); + + my $to; + if ($branch_ill_to) { + $to = $branch_ill_to; + } elsif ($syspref) { + $to = $syspref; + } elsif ($branch_to) { + $to = $branch_to; + } elsif ($koha_admin) { + $to = $koha_admin; + } + + # $to will not be defined if we didn't find a usable address + return $to; +} + +=head3 send_patron_notice + + my $result = $request->send_patron_notice($notice_code); + +Send a specified notice regarding this request to a patron + +=cut + +sub send_patron_notice { + my ( $self, $notice_code ) = @_; + + # We need a notice code + if (!$notice_code) { + return { + error => 'notice_no_type' + }; + } + + # Map from the notice code to the messaging preference + my %message_name = ( + ILL_PICKUP_READY => 'Ill_ready', + ILL_REQUEST_UNAVAIL => 'Ill_unavailable' + ); + + # Get the patron's messaging preferences + my $borrower_preferences = C4::Members::Messaging::GetMessagingPreferences({ + borrowernumber => $self->borrowernumber, + message_name => $message_name{$notice_code} + }); + my @transports = keys %{ $borrower_preferences->{transports} }; + + # Send the notice to the patron via the chosen transport methods + # and record the results + my @success = (); + my @fail = (); + for my $transport (@transports) { + my $letter = $self->get_notice({ + notice_code => $notice_code, + transport => $transport + }); + if ($letter) { + my $result = C4::Letters::EnqueueLetter({ + letter => $letter, + borrowernumber => $self->borrowernumber, + message_transport_type => $transport, + }); + if ($result) { + push @success, $transport; + } else { + push @fail, $transport; + } + } else { + push @fail, $transport; } - catch { - return { - error => 1, - status => 'email_failed', - message => "$_", - method => 'generic_confirm', - stage => 'draft', - }; + } + if (scalar @success > 0) { + my $logger = Koha::Illrequest::Logger->new; + $logger->log_patron_notice({ + request => $self, + notice_code => $notice_code + }); + } + return { + result => { + success => \@success, + fail => \@fail + } + }; +} + +=head3 send_staff_notice + + my $result = $request->send_staff_notice($notice_code); + +Send a specified notice regarding this request to staff + +=cut + +sub send_staff_notice { + my ( $self, $notice_code ) = @_; + + # We need a notice code + if (!$notice_code) { + return { + error => 'notice_no_type' + }; + } + + # Get the staff notices that have been assigned for sending in + # the syspref + my $staff_to_send = C4::Context->preference('ILLSendStaffNotices'); + + # If it hasn't been enabled in the syspref, we don't want to send it + if ($staff_to_send !~ /\b$notice_code\b/) { + return { + error => 'notice_not_enabled' }; + } + + my $letter = $self->get_notice({ + notice_code => $notice_code, + transport => 'email' + }); + + # Try and get an address to which to send staff notices + my $to_address = scalar $self->get_staff_to_address; + + my $params = { + letter => $letter, + borrowernumber => $self->borrowernumber, + message_transport_type => 'email', + }; + + if ($to_address) { + $params->{to_address} = $to_address; + $params->{from_address} = $to_address; } else { - die "Unknown stage, should not have happened." + return { + error => 'notice_no_create' + }; + } + + if ($letter) { + C4::Letters::EnqueueLetter($params) + or warn "can't enqueue letter $letter"; + return { + success => 'notice_queued' + }; + } else { + return { + error => 'notice_no_create' + }; + } +} + +=head3 get_notice + + my $notice = $request->get_notice($params); + +Return a compiled notice hashref for the passed notice code +and transport type + +=cut + +sub get_notice { + my ( $self, $params ) = @_; + + my $title = $self->illrequestattributes->find( + { type => 'title' } + ); + my $author = $self->illrequestattributes->find( + { type => 'author' } + ); + my $metahash = $self->metadata; + my @metaarray = (); + while (my($key, $value) = each %{$metahash}) { + push @metaarray, "- $key: $value" if $value; } + my $metastring = join("\n", @metaarray); + my $letter = C4::Letters::GetPreparedLetter( + module => 'ill', + letter_code => $params->{notice_code}, + message_transport_type => $params->{transport}, + lang => $self->patron->lang, + tables => { + illrequests => $self->illrequest_id, + borrowers => $self->borrowernumber, + biblio => $self->biblio_id, + branches => $self->branchcode, + }, + substitute => { + ill_bib_title => $title ? $title->value : 'N/A', + ill_bib_author => $author ? $author->value : 'N/A', + ill_full_metadata => $metastring + } + ); + + return $letter; } =head3 id_prefix --- a/Koha/Illrequest/Logger.pm +++ a/Koha/Illrequest/Logger.pm @@ -26,6 +26,7 @@ use C4::Context; use C4::Templates; use C4::Log qw( logaction ); use Koha::ActionLogs; +use Koha::Notice::Template; =head1 NAME @@ -62,6 +63,9 @@ sub new { $self->{loggers} = { status => sub { $self->log_status_change(@_); + }, + patron_notice => sub { + $self->log_patron_notice(@_); } }; @@ -70,7 +74,8 @@ sub new { C4::Templates::_get_template_file('ill/log/', 'intranet', $query); $self->{templates} = { - STATUS_CHANGE => $base . 'status_change.tt' + STATUS_CHANGE => $base . 'status_change.tt', + PATRON_NOTICE => $base . 'patron_notice.tt' }; bless $self, $class; @@ -103,6 +108,31 @@ sub log_maybe { } } +=head3 log_patron_notice + + Koha::IllRequest::Logger->log_patron_notice($params); + +Receive a hashref containing a request object and params to log, +and log it + +=cut + +sub log_patron_notice { + my ( $self, $params ) = @_; + + if (defined $params->{request} && defined $params->{notice_code}) { + $self->log_something({ + modulename => 'ILL', + actionname => 'PATRON_NOTICE', + objectnumber => $params->{request}->id, + infos => to_json({ + log_origin => 'core', + notice_code => $params->{notice_code} + }) + }); + } +} + =head3 log_status_change Koha::IllRequest::Logger->log_status_change($params); @@ -210,6 +240,14 @@ sub get_request_logs { { order_by => { -desc => "timestamp" } } )->unblessed; + # Populate a lookup table for all ILL notice types + my $notice_types = Koha::Notice::Templates->search({ + module => 'ill' + })->unblessed; + my $notice_hash; + foreach my $notice(@{$notice_types}) { + $notice_hash->{$notice->{code}} = $notice; + } # Populate a lookup table for status aliases my $aliases = C4::Koha::GetAuthorisedValues('ILLSTATUS'); my $alias_hash; @@ -217,6 +255,7 @@ sub get_request_logs { $alias_hash->{$alias->{authorised_value}} = $alias; } foreach my $log(@{$logs}) { + $log->{notice_types} = $notice_hash; $log->{aliases} = $alias_hash; $log->{info} = from_json($log->{info}); $log->{template} = $self->get_log_template({ --- a/ill/ill-requests.pl +++ a/ill/ill-requests.pl @@ -23,6 +23,7 @@ use CGI; use C4::Auth; use C4::Output; +use Koha::Notice::Templates; use Koha::AuthorisedValues; use Koha::Illcomment; use Koha::Illrequests; @@ -72,12 +73,28 @@ if ( $backends_available ) { # View the details of an ILL my $request = Koha::Illrequests->find($params->{illrequest_id}); + # Get the details for notices that can be sent from here + my $notices = Koha::Notice::Templates->search( + { + module => 'ill', + code => { -in => [ 'ILL_PICKUP_READY' ,'ILL_REQUEST_UNAVAIL' ] }, + }, + { + columns => [ qw/code name/ ], + distinct => 1 + } + )->unblessed; + $template->param( + notices => $notices, request => $request, csrf_token => Koha::Token->new->generate_csrf({ session_id => scalar $cgi->cookie('CGISESSID'), }), - ( $params->{error} ? ( error => $params->{error} ) : () ), + ( $params->{tran_error} ? + ( tran_error => $params->{tran_error} ) : () ), + ( $params->{tran_success} ? + ( tran_success => $params->{tran_success} ) : () ), ); } elsif ( $op eq 'create' ) { @@ -380,6 +397,23 @@ if ( $backends_available ) { ); exit; + } elsif ( $op eq "send_notice" ) { + my $illrequest_id = $params->{illrequest_id}; + my $request = Koha::Illrequests->find($illrequest_id); + my $ret = $request->send_patron_notice($params->{notice_code}); + my $append = ''; + if ($ret->{result} && scalar @{$ret->{result}->{success}} > 0) { + $append .= '&tran_success=' . join(',', @{$ret->{result}->{success}}); + } + if ($ret->{result} && scalar @{$ret->{result}->{fail}} > 0) { + $append .= '&tran_fail=' . join(',', @{$ret->{result}->{fail}}.join(',')); + } + # Redirect to view the whole request + print $cgi->redirect( + "/cgi-bin/koha/ill/ill-requests.pl?method=illview&illrequest_id=". + scalar $params->{illrequest_id} . $append + ); + exit; } else { my $request = Koha::Illrequests->find($params->{illrequest_id}); my $backend_result = $request->custom_capability($op, $params); --- a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt @@ -99,6 +99,10 @@

[% END %] + [% IF whole.success %] +

[% whole.success | html %]

+ [% END %] + [% IF query_type == 'create' %]

New ILL request

[% PROCESS $whole.template %] @@ -462,6 +466,31 @@ [% END %] [% END %] + [% IF tran_success %] + [% succ_methods = [] %] + [% IF tran_success.match('email') %] + [% succ_methods.push('email') %] + [% END %] + [% IF tran_success.match('sms') %] + [% succ_methods.push('SMS') %] + [% END %] +
+ The requested notice was queued for delivery by [% succ_methods.join(', ') | html %] +
+ [% END %] + [% IF tran_fail %] + [% fail_methods = [] %] + [% IF tran_fail.match('email') %] + [% fail_methods.push('email') %] + [% END %] + [% IF tran_fail.match('sms') %] + [% fail_methods.push('SMS') %] + [% END %] +
+ The requested notice was NOT queued for delivery by [% fail_methods.join(', ') | html %] +
+ [% END %] +

Manage ILL request