Bug 17600: Standardize our EXPORT_OK
[srvgit] / Koha / Illrequest.pm
index c6280d2..2eaa5ac 100644 (file)
@@ -19,15 +19,13 @@ package Koha::Illrequest;
 
 use Modern::Perl;
 
-use Clone 'clone';
-use File::Basename qw( basename );
-use Encode qw( encode );
-use Mail::Sendmail;
-use Try::Tiny;
+use Clone qw( clone );
+use Try::Tiny qw( catch try );
 use DateTime;
 
+use C4::Letters;
 use Koha::Database;
-use Koha::Email;
+use Koha::DateUtils qw( dt_from_string );
 use Koha::Exceptions::Ill;
 use Koha::Illcomments;
 use Koha::Illrequestattributes;
@@ -39,8 +37,8 @@ use Koha::Biblios;
 use Koha::Items;
 use Koha::ItemTypes;
 use Koha::Libraries;
-use C4::Items qw( AddItem );
-use C4::Circulation qw( CanBookBeIssued AddIssue  );
+
+use C4::Circulation qw( CanBookBeIssued AddIssue );
 
 use base qw(Koha::Object);
 
@@ -135,11 +133,14 @@ sub statusalias {
     # We can't know which result is the right one if there are multiple
     # ILLSTATUS authorised values with the same authorised_value column value
     # so we just use the first
-    return Koha::AuthorisedValues->search({
-        branchcode => $self->branchcode,
-        category => 'ILLSTATUS',
-        authorised_value => $self->SUPER::status_alias
-    })->next;
+    return Koha::AuthorisedValues->search(
+        {
+            category         => 'ILLSTATUS',
+            authorised_value => $self->SUPER::status_alias
+        },
+        {},
+        $self->branchcode
+    )->next;
 }
 
 =head3 illrequestattributes
@@ -230,11 +231,15 @@ sub status_alias {
     # We can't know which result is the right one if there are multiple
     # ILLSTATUS authorised values with the same authorised_value column value
     # so we just use the first
-    my $alias = Koha::AuthorisedValues->search({
-        branchcode => $self->branchcode,
-        category => 'ILLSTATUS',
-        authorised_value => $self->SUPER::status_alias
-    })->next;
+    my $alias = Koha::AuthorisedValues->search(
+        {
+            category         => 'ILLSTATUS',
+            authorised_value => $self->SUPER::status_alias
+        },
+        {},
+        $self->branchcode
+    )->next;
+
     if ($alias) {
         return $alias->authorised_value;
     } else {
@@ -248,6 +253,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 +287,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;
@@ -495,6 +505,8 @@ sub _core_status_graph {
             ui_method_name => 'Check out',
             needs_prefs    => [ 'CirculateILL' ],
             needs_perms    => [ 'user_circulate_circulate_remaining_permissions' ],
+            # An array of functions that all must return true
+            needs_all      => [ sub { my $r = shift;  return $r->biblio; } ],
             method         => 'check_out',
             next_actions   => [ ],
             ui_method_icon => 'fa-upload',
@@ -687,7 +699,7 @@ Mark a request as completed (status = COMP).
 sub mark_completed {
     my ( $self ) = @_;
     $self->status('COMP')->store;
-    $self->completed(DateTime->now)->store;
+    $self->completed(dt_from_string())->store;
     return {
         error   => 0,
         status  => '',
@@ -1049,6 +1061,25 @@ sub requires_moderation {
     return $require_moderation->{$self->status};
 }
 
+=head3 biblio
+
+    my $biblio = $request->biblio;
+
+For a given request, return the biblio associated with it,
+or undef if none exists
+
+=cut
+
+sub biblio {
+    my ( $self ) = @_;
+
+    return if !$self->biblio_id;
+
+    return Koha::Biblios->find({
+        biblionumber => $self->biblio_id
+    });
+}
+
 =head3 check_out
 
     my $stage_summary = $request->check_out;
@@ -1072,9 +1103,8 @@ sub check_out {
         {},
         { order_by => ['branchcode'] }
     );
-    my $biblio = Koha::Biblios->find({
-        biblionumber => $self->biblio_id
-    });
+    my $biblio = $self->biblio;
+
     # Find all statistical patrons
     my $statistical_patrons = Koha::Patrons->search(
         { 'category_type' => 'x' },
@@ -1146,15 +1176,17 @@ sub check_out {
         my $itemnumber;
         if ($item_count == 0) {
             my $item_hash = {
+                biblionumber  => $self->biblio_id,
                 homebranch    => $params->{branchcode},
                 holdingbranch => $params->{branchcode},
                 location      => $params->{branchcode},
                 itype         => $params->{item_type},
                 barcode       => 'ILL-' . $self->illrequest_id
             };
-            my (undef, undef, $item_no) =
-                AddItem($item_hash, $self->biblio_id);
-            $itemnumber = $item_no;
+            try {
+                my $item = Koha::Item->new($item_hash)->store;
+                $itemnumber = $item->itemnumber;
+            };
         } else {
             $itemnumber = $items[0]->itemnumber;
         }
@@ -1265,38 +1297,11 @@ sub generic_confirm {
     my $branch = 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} = <<EOF;
-Dear Sir/Madam,
-
-    We would like to request an interlibrary loan for a title matching the
-following description:
-
-EOF
-
-        my $details = $self->metadata;
-        while (my ($title, $value) = each %{$details}) {
-            $draft->{body} .= "  - " . $title . ": " . $value . "\n"
-                if $value;
-        }
-        $draft->{body} .= <<EOF;
-
-Please let us know if you are able to supply this to us.
-
-Kind Regards
-
-EOF
-
-        my @address = map { $branch->$_ }
-            qw/ branchname branchaddress1 branchaddress2 branchaddress3
-                branchzip branchcity branchstate branchcountry branchphone
-                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
@@ -1308,7 +1313,10 @@ EOF
             method  => 'generic_confirm',
             stage   => 'draft',
             value   => {
-                draft    => $draft,
+                draft => {
+                    subject => $letter->{title},
+                    body    => $letter->{content}
+                },
                 partners => $partners,
             }
         };
@@ -1324,57 +1332,255 @@ 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 = $branch->branchemail;
-        my $replyto = $branch->branchreplyto || $from;
+        my $from = $branch->from_email_address;
+        my $replyto = $branch->inbound_ill_address;
         Koha::Exceptions::Ill::NoLibraryEmail->throw(
             "Your library has no usable email address. Please set it.")
           if ( !$from );
 
-        # Create the email
-        my $message = Koha::Email->new;
-        my %mail = $message->create_message_headers(
-            {
-                to          => $to,
-                from        => $from,
-                replyto     => $replyto,
-                subject     => Encode::encode( "utf8", $params->{subject} ),
-                message     => Encode::encode( "utf8", $params->{body} ),
-                contenttype => 'text/plain',
+        # 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};
+
+        # Queue the notice
+        my $params = {
+            letter                 => $letter,
+            borrowernumber         => $self->borrowernumber,
+            message_transport_type => 'email',
+            to_address             => $to,
+            from_address           => $from,
+            reply_address          => $replyto
+        };
+
+        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',
+                };
             }
-        );
-        # Send it
-        my $result = sendmail(%mail);
-        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',
-            };
-        } else {
-            return {
-                error   => 1,
-                status  => 'email_failed',
-                message => $Mail::Sendmail::error,
-                method  => 'generic_confirm',
-                stage   => 'draft',
-            };
         }
+        return {
+            error   => 1,
+            status  => 'email_failed',
+            message => 'Email queueing failed',
+            method  => 'generic_confirm',
+            stage   => 'draft',
+        };
     } else {
         die "Unknown stage, should not have happened."
     }
 }
 
+=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} };
+
+    # Notice should come from the library where the request was placed,
+    # not the patrons home library
+    my $branch = Koha::Libraries->find($self->branchcode);
+    my $from_address = $branch->from_email_address;
+    my $reply_address = $branch->inbound_ill_address;
+
+    # 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,
+                from_address           => $from_address,
+                reply_address          => $reply_address
+            });
+            if ($result) {
+                push @success, $transport;
+            } else {
+                push @fail, $transport;
+            }
+        } else {
+            push @fail, $transport;
+        }
+    }
+    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') // q{};
+
+    # 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 $branch = Koha::Libraries->find($self->branchcode);
+    my $to_address = $branch->inbound_ill_address;
+    my $from_address = $branch->inbound_ill_address;
+
+    my $params = {
+        letter                 => $letter,
+        borrowernumber         => $self->borrowernumber,
+        message_transport_type => 'email',
+        from_address           => $from_address
+    };
+
+    if ($to_address) {
+        $params->{to_address} = $to_address;
+    } else {
+        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},
+        branchcode             => $self->branchcode,
+        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 : '',
+            ill_bib_author     => $author ? $author->value : '',
+            ill_full_metadata  => $metastring
+        }
+    );
+
+    return $letter;
+}
+
 =head3 id_prefix
 
     my $prefix = $record->id_prefix;