Bug 31626: Add letter id to the message queue table
[koha-ffzg.git] / C4 / Letters.pm
index 7c63b23..4d60753 100644 (file)
@@ -29,13 +29,13 @@ use C4::Members;
 use C4::Log qw( logaction );
 use C4::SMS;
 use C4::Templates;
-use Koha::DateUtils qw( dt_from_string output_pref );
 use Koha::SMS::Providers;
 
 use Koha::Email;
 use Koha::Notice::Messages;
 use Koha::Notice::Templates;
 use Koha::DateUtils qw( dt_from_string output_pref );
+use Koha::Auth::TwoFactorAuth;
 use Koha::Patrons;
 use Koha::SMTP::Servers;
 use Koha::Subscriptions;
@@ -411,7 +411,7 @@ sub SendAlerts {
         }
 
         if ( $type eq 'orderacquisition') {
-            my $basketno = $externalid;
+            $basketno = $externalid;
             $strsth = qq{
             SELECT aqorders.*,aqbasket.*,biblio.*,biblioitems.*
             FROM aqorders
@@ -516,11 +516,12 @@ sub SendAlerts {
         return { error => $error }
             unless $success;
 
+        my $log_object = $action eq 'ACQUISITION ORDER' ? $externalid : undef;
         my $module = $action eq 'ACQUISITION ORDER' ? 'ACQUISITIONS' : 'CLAIMS';
         logaction(
             $module,
             $action,
-            undef,
+            $log_object,
             "To="
                 . join( ',', @email )
                 . " Title="
@@ -588,17 +589,19 @@ sub GetPreparedLetter {
         $letter->{'content-type'} = 'text/html; charset="UTF-8"' if $letter->{is_html};
     }
 
+    my $objects = $params{objects} || {};
     my $tables = $params{tables} || {};
     my $substitute = $params{substitute} || {};
     my $loops  = $params{loops} || {}; # loops is not supported for historical notices syntax
     my $repeat = $params{repeat};
-    %$tables || %$substitute || $repeat || %$loops
-      or carp( "ERROR: nothing to substitute - both 'tables', 'loops' and 'substitute' are empty" ),
+    %$tables || %$substitute || $repeat || %$loops || %$objects
+      or carp( "ERROR: nothing to substitute - all of 'objects', 'tables', 'loops' and 'substitute' are empty" ),
          return;
     my $want_librarian = $params{want_librarian};
 
     if (%$substitute) {
         while ( my ($token, $val) = each %$substitute ) {
+            $val //= q{};
             if ( $token eq 'items.content' ) {
                 $val =~ s|\n|<br/>|g if $letter->{is_html};
             }
@@ -668,20 +671,23 @@ sub GetPreparedLetter {
 
     $letter->{content} = _process_tt(
         {
-            content => $letter->{content},
-            tables  => $tables,
-            loops  => $loops,
+            content    => $letter->{content},
+            lang       => $lang,
+            loops      => $loops,
+            objects    => $objects,
             substitute => $substitute,
-            lang => $lang
+            tables     => $tables,
         }
     );
 
     $letter->{title} = _process_tt(
         {
-            content => $letter->{title},
-            tables  => $tables,
-            loops  => $loops,
+            content    => $letter->{title},
+            lang       => $lang,
+            loops      => $loops,
+            objects    => $objects,
             substitute => $substitute,
+            tables     => $tables,
         }
     );
 
@@ -782,6 +788,7 @@ sub _parseletter {
     # in callers ( by changing / formatting values )
     my $values = $values_in ? { %$values_in } : {};
 
+    # FIXME Dates formatting must be done in notice's templates
     if ( $table eq 'borrowers' && $values->{'dateexpiry'} ){
         $values->{'dateexpiry'} = output_pref({ dt => dt_from_string( $values->{'dateexpiry'} ), dateonly => 1 });
     }
@@ -824,8 +831,9 @@ sub _parseletter {
                     $dateonly = $1 unless $dateonly;
                 }
                 my $replacedby_date = eval {
-                    output_pref({ dt => dt_from_string( $replacedby ), dateonly => $dateonly });
+                    output_pref({ dt => scalar dt_from_string( $replacedby ), dateonly => $dateonly });
                 };
+                $replacedby_date //= q{};
 
                 if ( $letter->{ $letter_field } ) {
                     $letter->{ $letter_field } =~ s/\Q<<$table.$field$filter_string_used>>\E/$replacedby_date/g;
@@ -914,13 +922,13 @@ sub EnqueueLetter {
     my $dbh       = C4::Context->dbh();
     my $statement = << 'ENDSQL';
 INSERT INTO message_queue
-( borrowernumber, subject, content, metadata, letter_code, message_transport_type, status, time_queued, to_address, from_address, reply_address, content_type, failure_code )
-VALUES
-( ?,              ?,       ?,       ?,        ?,           ?,                      ?,      CAST(NOW() AS DATETIME),       ?,          ?,            ?,           ?,              ? )
+( letter_id, borrowernumber, subject, content, metadata, letter_code, message_transport_type, status, time_queued, to_address, from_address, reply_address, content_type, failure_code )
+VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, CAST(NOW() AS DATETIME), ?, ?, ?, ?, ? )
 ENDSQL
 
     my $sth    = $dbh->prepare($statement);
     my $result = $sth->execute(
+        $params->{letter}->{id} || undef,         # letter.id
         $params->{'borrowernumber'},              # borrowernumber
         $params->{'letter'}->{'title'},           # subject
         $params->{'letter'}->{'content'},         # content
@@ -969,7 +977,7 @@ sub SendQueuedMessages {
         'limit'          => $params->{'limit'} // 0,
         'borrowernumber' => $params->{'borrowernumber'} // q{},
         'letter_code'    => $params->{'letter_code'} // q{},
-        'type'           => $params->{'type'} // q{},
+        'message_transport_type'           => $params->{'type'} // q{},
     };
     my $unsent_messages = _get_unsent_messages( $which_unsent_messages );
     MESSAGE: foreach my $message ( @$unsent_messages ) {
@@ -1224,8 +1232,10 @@ sub _add_attachments {
   This function's parameter hash reference takes the following
   optional named parameters:
    message_transport_type: method of message sending (e.g. email, sms, etc.)
+                           Can be a single string, or an arrayref of strings
    borrowernumber        : who the message is to be sent
    letter_code           : type of message being sent (e.g. PASSWORD_RESET)
+                           Can be a single string, or an arrayref of strings
    message_id            : the message_id of the message. In that case the sub will return only 1 result
    limit                 : maximum number of messages to send
 
@@ -1247,21 +1257,25 @@ sub _get_unsent_messages {
 
     my @query_params = ('pending');
     if ( ref $params ) {
-        if ( $params->{'message_transport_type'} ) {
-            $statement .= ' AND mq.message_transport_type = ? ';
-            push @query_params, $params->{'message_transport_type'};
-        }
         if ( $params->{'borrowernumber'} ) {
             $statement .= ' AND mq.borrowernumber = ? ';
             push @query_params, $params->{'borrowernumber'};
         }
         if ( $params->{'letter_code'} ) {
-            $statement .= ' AND mq.letter_code = ? ';
-            push @query_params, $params->{'letter_code'};
+            my @letter_codes = ref $params->{'letter_code'} eq "ARRAY" ? @{$params->{'letter_code'}} : $params->{'letter_code'};
+            if ( @letter_codes ) {
+                my $q = join( ",", ("?") x @letter_codes );
+                $statement .= " AND mq.letter_code IN ( $q ) ";
+                push @query_params, @letter_codes;
+            }
         }
-        if ( $params->{'type'} ) {
-            $statement .= ' AND message_transport_type = ? ';
-            push @query_params, $params->{'type'};
+        if ( $params->{'message_transport_type'} ) {
+            my @types = ref $params->{'message_transport_type'} eq "ARRAY" ? @{$params->{'message_transport_type'}} : $params->{'message_transport_type'};
+            if ( @types ) {
+                my $q = join( ",", ("?") x @types );
+                $statement .= " AND message_transport_type IN ( $q ) ";
+                push @query_params, @types;
+            }
         }
         if ( $params->{message_id} ) {
             $statement .= ' AND message_id = ?';
@@ -1488,6 +1502,7 @@ sub _is_duplicate {
 sub _send_message_by_sms {
     my $message = shift or return;
     my $patron = Koha::Patrons->find( $message->{borrowernumber} );
+    _update_message_to_address($message->{message_id}, $patron->smsalertnumber) if $patron;
 
     unless ( $patron and $patron->smsalertnumber ) {
         _set_message_status( { message_id => $message->{'message_id'},
@@ -1567,9 +1582,10 @@ sub _set_message_status {
 sub _process_tt {
     my ( $params ) = @_;
 
-    my $content = $params->{content};
-    my $tables = $params->{tables};
-    my $loops = $params->{loops};
+    my $content    = $params->{content};
+    my $tables     = $params->{tables};
+    my $loops      = $params->{loops};
+    my $objects    = $params->{objects} || {};
     my $substitute = $params->{substitute} || {};
     my $lang = defined($params->{lang}) && $params->{lang} ne 'default' ? $params->{lang} : 'en';
     my ($theme, $availablethemes);
@@ -1596,13 +1612,16 @@ sub _process_tt {
         }
     ) or die Template->error();
 
-    my $tt_params = { %{ _get_tt_params( $tables ) }, %{ _get_tt_params( $loops, 'is_a_loop' ) }, %$substitute };
+    my $tt_params = { %{ _get_tt_params( $tables ) }, %{ _get_tt_params( $loops, 'is_a_loop' ) }, %$substitute, %$objects };
 
     $content = add_tt_filters( $content );
     $content = qq|[% USE KohaDates %][% USE Remove_MARC_punctuation %]$content|;
 
     my $output;
+    my $schema = Koha::Database->new->schema;
+    $schema->txn_begin;
     $template->process( \$content, $tt_params, \$output ) || croak "ERROR PROCESSING TEMPLATE: " . $template->error();
+    $schema->txn_rollback;
 
     return $output;
 }