3 # This file is part of Koha.
5 # Copyright (C) 2013 Equinox Software, Inc.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
21 use Test
::More tests
=> 73;
27 my ( $email_object, $sendmail_params );
29 my $email_sender_module = Test
::MockModule
->new('Email::Stuffer');
30 $email_sender_module->mock(
33 ( $email_object, $sendmail_params ) = @_;
34 warn "Fake send_or_die";
38 use_ok
('C4::Context');
39 use_ok
('C4::Members');
40 use_ok
('C4::Acquisition');
42 use_ok
('C4::Letters');
44 use t
::lib
::TestBuilder
;
46 use Koha
::DateUtils
qw( dt_from_string output_pref );
47 use Koha
::Acquisition
::Booksellers
;
48 use Koha
::Acquisition
::Bookseller
::Contacts
;
49 use Koha
::Acquisition
::Orders
;
51 use Koha
::Notice
::Templates
;
53 use Koha
::Subscriptions
;
54 my $schema = Koha
::Database
->schema;
55 $schema->storage->txn_begin();
57 my $builder = t
::lib
::TestBuilder
->new;
58 my $dbh = C4
::Context
->dbh;
60 $dbh->do(q
|DELETE FROM letter
|);
61 $dbh->do(q
|DELETE FROM message_queue
|);
62 $dbh->do(q
|DELETE FROM message_transport_types
|);
64 my $library = $builder->build({
67 branchemail
=> 'branchemail@address.com',
68 branchreplyto
=> 'branchreplyto@address.com',
69 branchreturnpath
=> 'branchreturnpath@address.com',
72 my $patron_category = $builder->build({ source
=> 'Category' })->{categorycode
};
73 my $date = dt_from_string
;
74 my $borrowernumber = Koha
::Patron
->new({
77 categorycode
=> $patron_category,
78 branchcode
=> $library->{branchcode
},
80 smsalertnumber
=> undef,
81 })->store->borrowernumber;
83 my $marc_record = MARC
::Record
->new;
84 my( $biblionumber, $biblioitemnumber ) = AddBiblio
( $marc_record, '' );
88 # GetMessageTransportTypes
89 my $mtts = C4
::Letters
::GetMessageTransportTypes
();
90 is
( @
$mtts, 0, 'GetMessageTransportTypes returns the correct number of message types' );
93 INSERT INTO message_transport_types
( message_transport_type
) VALUES
('email'), ('phone'), ('print'), ('sms')
95 $mtts = C4
::Letters
::GetMessageTransportTypes
();
96 is_deeply
( $mtts, ['email', 'phone', 'print', 'sms'], 'GetMessageTransportTypes returns all values' );
100 is
( C4
::Letters
::EnqueueLetter
(), undef, 'EnqueueLetter without argument returns undef' );
103 borrowernumber
=> $borrowernumber,
104 message_transport_type
=> 'sms',
106 from_address
=> 'from@example.com',
108 my $message_id = C4
::Letters
::EnqueueLetter
($my_message);
109 is
( $message_id, undef, 'EnqueueLetter without the letter argument returns undef' );
111 delete $my_message->{message_transport_type
};
112 $my_message->{letter
} = {
113 content
=> 'a message',
114 title
=> 'message title',
115 metadata
=> 'metadata',
116 code
=> 'TEST_MESSAGE',
117 content_type
=> 'text/plain',
120 $message_id = C4
::Letters
::EnqueueLetter
($my_message);
121 is
( $message_id, undef, 'EnqueueLetter without the message type argument argument returns undef' );
123 $my_message->{message_transport_type
} = 'sms';
124 $message_id = C4
::Letters
::EnqueueLetter
($my_message);
125 ok
(defined $message_id && $message_id > 0, 'new message successfully queued');
129 my $messages = C4
::Letters
::GetQueuedMessages
();
130 is
( @
$messages, 1, 'GetQueuedMessages without argument returns all the entries' );
132 $messages = C4
::Letters
::GetQueuedMessages
({ borrowernumber
=> $borrowernumber });
133 is
( @
$messages, 1, 'one message stored for the borrower' );
134 is
( $messages->[0]->{message_id
}, $message_id, 'EnqueueLetter returns the message id correctly' );
135 is
( $messages->[0]->{borrowernumber
}, $borrowernumber, 'EnqueueLetter stores the borrower number correctly' );
136 is
( $messages->[0]->{subject
}, $my_message->{letter
}->{title
}, 'EnqueueLetter stores the subject correctly' );
137 is
( $messages->[0]->{content
}, $my_message->{letter
}->{content
}, 'EnqueueLetter stores the content correctly' );
138 is
( $messages->[0]->{message_transport_type
}, $my_message->{message_transport_type
}, 'EnqueueLetter stores the message type correctly' );
139 is
( $messages->[0]->{status
}, 'pending', 'EnqueueLetter stores the status pending correctly' );
140 isnt
( $messages->[0]->{time_queued
}, undef, 'Time queued inserted by default in message_queue table' );
141 is
( $messages->[0]->{updated_on
}, $messages->[0]->{time_queued
}, 'Time status changed equals time queued when created in message_queue table' );
143 # Setting time_queued to something else than now
144 my $yesterday = dt_from_string
->subtract( days
=> 1 );
145 Koha
::Notice
::Messages
->find($messages->[0]->{message_id
})->time_queued($yesterday)->store;
148 my $messages_processed = C4
::Letters
::SendQueuedMessages
( { type
=> 'email' });
149 is
($messages_processed, 0, 'No queued messages processed if type limit passed with unused type');
150 $messages_processed = C4
::Letters
::SendQueuedMessages
( { type
=> 'sms' });
151 is
($messages_processed, 1, 'All queued messages processed, found correct number of messages with type limit');
152 $messages = C4
::Letters
::GetQueuedMessages
({ borrowernumber
=> $borrowernumber });
154 $messages->[0]->{status
},
156 'message marked failed if tried to send SMS message for borrower with no smsalertnumber set (bug 11208)'
158 isnt
($messages->[0]->{updated_on
}, $messages->[0]->{time_queued
}, 'Time status changed differs from time queued when status changes' );
159 is
(dt_from_string
($messages->[0]->{time_queued
}), $yesterday, 'Time queued remaines inmutable' );
162 my $resent = C4
::Letters
::ResendMessage
($messages->[0]->{message_id
});
163 my $message = C4
::Letters
::GetMessage
( $messages->[0]->{message_id
});
164 is
( $resent, 1, 'The message should have been resent' );
165 is
($message->{status
},'pending', 'ResendMessage sets status to pending correctly (bug 12426)');
166 $resent = C4
::Letters
::ResendMessage
($messages->[0]->{message_id
});
167 is
( $resent, 0, 'The message should not have been resent again' );
168 $resent = C4
::Letters
::ResendMessage
();
169 is
( $resent, undef, 'ResendMessage should return undef if not message_id given' );
172 my $letters = C4
::Letters
::GetLetters
();
173 is
( @
$letters, 0, 'GetLetters returns the correct number of letters' );
175 my $title = q
|<<branches.branchname>> - <<status>>|;
176 my $content = q{Dear <<borrowers.firstname>> <<borrowers.surname>>,
177 According to our current records, you have items that are overdue.Your library does not charge late fines, but please return or renew them at the branch below as soon as possible.
179 <<branches.branchname
>>
180 <<branches.branchaddress1>>
183 The following item(s) is/are currently <<status>>:
185 <item> <<count>>. <<items.itemcallnumber>>, Barcode: <<items.barcode>> </item>
187 Thank-you for your prompt attention to this matter.
188 Don't forget your date of birth: <<borrowers.dateofbirth>>.
189 Look at this wonderful biblio timestamp: <<biblio.timestamp>>.
192 $dbh->do( q|INSERT INTO letter(branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES (?,'my module','my code','my name',1,?,?,'email')|, undef, $library->{branchcode}, $title, $content );
193 $letters = C4::Letters::GetLetters();
194 is( @$letters, 1, 'GetLetters returns the correct number of letters' );
195 is( $letters->[0]->{module}, 'my module', 'GetLetters gets the module correctly' );
196 is( $letters->[0]->{code}, 'my code', 'GetLetters gets the code correctly' );
197 is( $letters->[0]->{name}, 'my name', 'GetLetters gets the name correctly' );
201 subtest 'getletter' => sub {
203 t::lib::Mocks::mock_preference('IndependentBranches', 0);
204 my $letter = C4::Letters::getletter('my module', 'my code', $library->{branchcode}, 'email');
205 is( $letter->{branchcode}, $library->{branchcode}, 'GetLetters gets the branch code correctly' );
206 is( $letter->{module}, 'my module', 'GetLetters gets the module correctly' );
207 is( $letter->{code}, 'my code', 'GetLetters gets the code correctly' );
208 is( $letter->{name}, 'my name', 'GetLetters gets the name correctly' );
209 is( $letter->{is_html}, 1, 'GetLetters gets the boolean is_html correctly' );
210 is( $letter->{title}, $title, 'GetLetters gets the title correctly' );
211 is( $letter->{content}, $content, 'GetLetters gets the content correctly' );
212 is( $letter->{message_transport_type}, 'email', 'GetLetters gets the message type correctly' );
214 t::lib::Mocks::mock_userenv({ branchcode => "anotherlib", flags => 1 });
216 t::lib::Mocks::mock_preference('IndependentBranches', 1);
217 $letter = C4::Letters::getletter('my module', 'my code', $library->{branchcode}, 'email');
218 is( $letter->{branchcode}, $library->{branchcode}, 'GetLetters gets the branch code correctly' );
219 is( $letter->{module}, 'my module', 'GetLetters gets the module correctly' );
220 is( $letter->{code}, 'my code', 'GetLetters gets the code correctly' );
221 is( $letter->{name}, 'my name', 'GetLetters gets the name correctly' );
222 is( $letter->{is_html}, 1, 'GetLetters gets the boolean is_html correctly' );
223 is( $letter->{title}, $title, 'GetLetters gets the title correctly' );
224 is( $letter->{content}, $content, 'GetLetters gets the content correctly' );
225 is( $letter->{message_transport_type}, 'email', 'GetLetters gets the message type correctly' );
230 # Regression test for Bug 14206
231 $dbh->do( q|INSERT INTO letter(branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES ('FFL','my module','my code','my name',1,?,?,'print')|, undef, $title, $content );
232 my $letter14206_a = C4::Letters::getletter('my module', 'my code', 'FFL' );
233 is( $letter14206_a->{message_transport_type}, 'print', 'Bug 14206 - message_transport_type not passed, correct mtt detected' );
234 my $letter14206_b = C4::Letters::getletter('my module', 'my code', 'FFL', 'print');
235 is( $letter14206_b->{message_transport_type}, 'print', 'Bug 14206 - message_transport_type passed, correct mtt detected' );
237 # test for overdue_notices.pl
238 my $overdue_rules = {
239 letter1 => 'my code',
242 my $branchcode = 'FFL';
243 my $letter14206_c = C4::Letters::getletter('my module', $overdue_rules->{"letter$i"}, $branchcode);
244 is( $letter14206_c->{message_transport_type}, 'print', 'Bug 14206 - correct mtt detected for call from overdue_notices.pl' );
247 t::lib::Mocks::mock_preference('OPACBaseURL', 'http://thisisatest.com');
248 t::lib::Mocks::mock_preference( 'SendAllEmailsTo', '' );
250 my $sms_content = 'This is a SMS for an <<status>>';
251 $dbh->do( q|INSERT INTO letter(branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES (?,'my module','my code','my name',1,'my title',?,'sms')|, undef, $library->{branchcode}, $sms_content );
254 borrowers => $borrowernumber,
255 branches => $library->{branchcode},
256 biblio => $biblionumber,
263 itemcallnumber
=> 'my callnumber1',
267 itemcallnumber
=> 'my callnumber2',
271 my $prepared_letter = GetPreparedLetter
((
272 module
=> 'my module',
273 branchcode
=> $library->{branchcode
},
274 letter_code
=> 'my code',
276 substitute
=> $substitute,
279 my $retrieved_library = Koha
::Libraries
->find($library->{branchcode
});
280 my $my_title_letter = $retrieved_library->branchname . qq| - $substitute->{status
}|;
281 my $biblio_timestamp = dt_from_string
( GetBiblioData
($biblionumber)->{timestamp
} );
282 my $my_content_letter = qq|Dear Jane Smith
,
283 According to
our current records
, you have items that are overdue
.Your library does
not charge late fines
, but please
return or renew them at the branch below as soon as possible
.
285 |.$retrieved_library->branchname.qq|
286 |.$retrieved_library->branchaddress1.qq|
287 URL
: http
://thisisatest
.com
289 The following item
(s
) is
/are currently
$substitute->{status
}:
291 <item
> 1. $repeat->[0]->{itemcallnumber
}, Barcode
: $repeat->[0]->{barcode
} </item
>
292 <item
> 2. $repeat->[1]->{itemcallnumber
}, Barcode
: $repeat->[1]->{barcode
} </item
>
294 Thank
-you
for your prompt attention to this matter
.
295 Don
't forget your date of birth: | . output_pref({ dt => $date, dateonly => 1 }) . q|.
296 Look at this wonderful biblio timestamp: | . output_pref({ dt => $biblio_timestamp }) . ".\n";
298 is( $prepared_letter->{title}, $my_title_letter, 'GetPreparedLetter returns the title correctly
' );
299 is( $prepared_letter->{content}, $my_content_letter, 'GetPreparedLetter returns the content correctly
' );
301 $prepared_letter = GetPreparedLetter((
302 module => 'my module
',
303 branchcode => $library->{branchcode},
304 letter_code => 'my code
',
306 substitute => $substitute,
308 message_transport_type => 'sms
',
310 $my_content_letter = qq|This is a SMS for an $substitute->{status}|;
311 is( $prepared_letter->{content}, $my_content_letter, 'GetPreparedLetter returns the content correctly
' );
313 $dbh->do(q{INSERT INTO letter (module, code, name, title, content) VALUES ('test_date
','TEST_DATE
','Test dates
','A title with a timestamp
: <<biblio.timestamp>>','This one only contains the date: <<biblio.timestamp
| dateonly
>>.');});
314 $prepared_letter = GetPreparedLetter((
315 module => 'test_date
',
317 letter_code => 'test_date
',
319 substitute => $substitute,
322 is( $prepared_letter->{content}, q|This one only contains the date: | . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test
1' );
324 $dbh->do(q{UPDATE letter SET content = 'And also this one
:<<timestamp | dateonly>>.' WHERE code = 'test_date';});
325 $prepared_letter = GetPreparedLetter((
326 module => 'test_date',
328 letter_code => 'test_date',
330 substitute => $substitute,
333 is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test 2' );
335 $dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp|dateonly
>>.' WHERE code = 'test_date
';});
336 $prepared_letter = GetPreparedLetter((
337 module => 'test_date
',
339 letter_code => 'test_date
',
341 substitute => $substitute,
344 is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test
3' );
346 t::lib::Mocks::mock_preference( 'TimeFormat
', '12hr
' );
347 my $yesterday_night = $date->clone->add( days => -1 )->set_hour(22);
348 $dbh->do(q|UPDATE biblio SET timestamp = ? WHERE biblionumber
= ?
|, undef, $yesterday_night, $biblionumber );
349 $dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp>>.' WHERE code = 'test_date';});
350 $prepared_letter = GetPreparedLetter
((
351 module
=> 'test_date',
353 letter_code
=> 'test_date',
355 substitute
=> $substitute,
358 is
( $prepared_letter->{content
}, q
|And also this one
:| . output_pref
({ dt
=> $yesterday_night }) . q
|.|, 'dateonly test 3' );
360 $dbh->do(q{INSERT INTO letter (module, code, name, title, content) VALUES ('claimacquisition','TESTACQCLAIM','Acquisition Claim','Item Not Received','<<aqbooksellers.name>>|<<aqcontacts.name>>|<order>Ordernumber <<aqorders.ordernumber>> (<<biblio.title>>) (<<aqorders.quantity>> ordered)</order>');});
361 $dbh->do(q{INSERT INTO letter (module, code, name, title, content) VALUES ('orderacquisition','TESTACQORDER','Acquisition Order','Order','<<aqbooksellers.name>>|<<aqcontacts.name>>|<order>Ordernumber <<aqorders.ordernumber>> (<<biblio.title>>) (<<aqorders.quantity>> ordered)</order>');});
363 # Test that _parseletter doesn't modify its parameters bug 15429
365 my $values = { dateexpiry
=> '2015-12-13', };
366 C4
::Letters
::_parseletter
($prepared_letter, 'borrowers', $values);
367 is
( $values->{dateexpiry
}, '2015-12-13', "_parseletter doesn't modify its parameters" );
370 # Correctly format dateexpiry
372 my $values = { dateexpiry
=> '2015-12-13', };
374 t
::lib
::Mocks
::mock_preference
('dateformat', 'metric');
375 t
::lib
::Mocks
::mock_preference
('timeformat', '24hr');
376 my $letter = C4
::Letters
::_parseletter
({ content
=> "expiry on <<borrowers.dateexpiry>>"}, 'borrowers', $values);
377 is( $letter->{content}, 'expiry on
13/12/2015' );
379 t::lib::Mocks::mock_preference('dateformat
', 'metric
');
380 t::lib::Mocks::mock_preference('timeformat
', '12hr
');
381 $letter = C4::Letters::_parseletter({ content => "expiry on <<borrowers.dateexpiry>>"}, 'borrowers
', $values);
382 is( $letter->{content}, 'expiry on
13/12/2015' );
385 my $bookseller = Koha::Acquisition::Bookseller->new(
388 address1 => "bookseller's address
",
394 my $booksellerid = $bookseller->id;
396 Koha::Acquisition::Bookseller::Contact->new( { name => 'John Smith', phone => '0123456x1', claimacquisition => 1, orderacquisition => 1, booksellerid => $booksellerid } )->store;
397 Koha::Acquisition::Bookseller::Contact->new( { name => 'Leo Tolstoy', phone => '0123456x2', claimissues => 1, booksellerid => $booksellerid } )->store;
398 my $basketno = NewBasket($booksellerid, 1);
400 my $budgetid = C4::Budgets::AddBudget({
401 budget_code => "budget_code_test_letters
",
402 budget_name => "budget_name_test_letters
",
405 my $bib = MARC::Record->new();
406 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
408 MARC::Field->new('200', ' ', ' ', a => 'Silence in the library'),
412 MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
416 my $logged_in_user = $builder->build_object(
418 class => 'Koha::Patrons',
420 branchcode => $library->{branchcode},
421 email => 'some@email.com'
426 t::lib::Mocks::mock_userenv({ patron => $logged_in_user });
428 ($biblionumber, $biblioitemnumber) = AddBiblio($bib, '');
429 my $order = Koha::Acquisition::Order->new(
431 basketno => $basketno,
433 biblionumber => $biblionumber,
434 budget_id => $budgetid,
437 my $ordernumber = $order->ordernumber;
439 C4::Acquisition::CloseBasket( $basketno );
442 $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
443 qr/^Bookseller .* without emails at/,
444 "SendAlerts prints a warning
";
445 is($err->{'error'}, 'no_email', "Trying to
send an alert
when there
's no e-mail results in an error");
447 $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
448 $bookseller->contacts->next->email('testemail
@mydomain.com
')->store;
450 # Ensure that the preference 'LetterLog
' is set to logging
451 t::lib::Mocks::mock_preference( 'LetterLog
', 'on
' );
453 # SendAlerts needs branchemail or KohaAdminEmailAddress as sender
454 t::lib::Mocks::mock_preference( 'KohaAdminEmailAddress
', 'library
@domain.com
' );
458 $err = SendAlerts( 'orderacquisition
', $basketno , 'TESTACQORDER
' ) }
459 qr|Fake send_or_die|,
460 "SendAlerts is using the mocked sendmail routine (orderacquisition)";
461 is($err, 1, "Successfully sent order.");
462 is($email_object->email->header('To
'), 'testemail
@mydomain.com
', "mailto correct in sent order");
463 is($email_object->email->body, 'my vendor
|John Smith
|Ordernumber
' . $ordernumber . ' (Silence
in the library
) (1 ordered
)', 'Order notice text constructed successfully
');
465 $dbh->do(q{DELETE FROM letter WHERE code = 'TESTACQORDER
';});
467 $err = SendAlerts( 'orderacquisition
', $basketno , 'TESTACQORDER
' ) }
468 qr/No orderacquisition TESTACQORDER letter transported by email/,
469 "GetPreparedLetter warns about missing notice template";
470 is($err->{'error
'}, 'no_letter
', "No TESTACQORDER letter was defined.");
475 $err = SendAlerts( 'claimacquisition
', [ $ordernumber ], 'TESTACQCLAIM
' ) }
476 qr|Fake send_or_die|,
477 "SendAlerts is using the mocked sendmail routine";
479 is($err, 1, "Successfully sent claim");
480 is($email_object->email->header('To
'), 'testemail
@mydomain.com
', "mailto correct in sent claim");
481 is($email_object->email->body, 'my vendor
|John Smith
|Ordernumber
' . $ordernumber . ' (Silence
in the library
) (1 ordered
)', 'Claim notice text constructed successfully
');
488 my $internalnotes = 'intnotes
';
489 $dbh->do(q|UPDATE subscription_numberpatterns SET numberingmethod='No
. {X
}' WHERE id=1|);
490 my $subscriptionid = NewSubscription(
491 undef, "", undef, undef, undef, $biblionumber,
492 '2013-01-01', 1, undef, undef, undef,
493 undef, undef, undef, undef, undef, undef,
494 1, $notes,undef, '2013-01-01', undef, 1,
495 undef, undef, 0, $internalnotes, 0,
496 undef, undef, 0, undef, '2013-12-31', 0
498 $dbh->do(q{INSERT INTO letter (module, code, name, title, content) VALUES ('serial
','RLIST
','Serial issue notification
','Serial issue notification
','<<biblio.title>>,<<subscription.subscriptionid>>,<<serial.serialseq>>');});
499 my ($serials_count, @serials) = GetSerials($subscriptionid);
500 my $serial = $serials[0];
502 my $patron = Koha::Patron->new({
505 categorycode => $patron_category,
506 branchcode => $library->{branchcode},
507 dateofbirth => $date,
508 email => 'john.smith@test.de',
510 my $borrowernumber = $patron->borrowernumber;
511 my $subscription = Koha::Subscriptions->find( $subscriptionid );
512 $subscription->add_subscriber( $patron );
514 t::lib::Mocks::mock_userenv({ branch => $library->{branchcode} });
517 $err2 = SendAlerts( 'issue', $serial->{serialid}, 'RLIST' ) }
518 qr|Fake send_or_die|,
519 "SendAlerts is using the mocked sendmail routine";
521 is($err2, 1, "Successfully sent serial notification
");
522 is($email_object->email->header('To'), 'john.smith@test.de', "mailto correct
in sent serial notification
");
523 is($email_object->email->body, 'Silence in the library,'.$subscriptionid.',No. 0', 'Serial notification text constructed successfully');
525 t::lib::Mocks::mock_preference( 'SendAllEmailsTo', 'robert.tables@mail.com' );
529 $err3 = SendAlerts( 'issue', $serial->{serialid}, 'RLIST' ) }
530 qr|Fake send_or_die|,
531 "SendAlerts is using the mocked sendmail routine
";
532 is($email_object->email->header('To'), 'robert.tables@mail.com', "mailto address overwritten by SendAllMailsTo preference
");
534 t::lib::Mocks::mock_preference( 'SendAllEmailsTo', '' );
536 subtest 'SendAlerts - claimissue' => sub {
541 $dbh->do(q{INSERT INTO letter (module, code, name, title, content) VALUES ('claimissues','TESTSERIALCLAIM','Serial claim test','Serial claim test','<<serial.serialid>>|<<subscription.startdate>>|<<biblio.title>>|<<biblioitems.issn>>');});
543 my $bookseller = Koha
::Acquisition
::Bookseller
->new(
546 address1
=> "bookseller's address",
552 my $booksellerid = $bookseller->id;
554 Koha
::Acquisition
::Bookseller
::Contact
->new( { name
=> 'Leo Tolstoy', phone
=> '0123456x2', claimissues
=> 1, booksellerid
=> $booksellerid } )->store;
556 my $bib = MARC
::Record
->new();
557 if (C4
::Context
->preference('marcflavour') eq 'UNIMARC') {
559 MARC
::Field
->new('011', ' ', ' ', a
=> 'xxxx-yyyy'),
560 MARC
::Field
->new('200', ' ', ' ', a
=> 'Silence in the library'),
564 MARC
::Field
->new('022', ' ', ' ', a
=> 'xxxx-yyyy'),
565 MARC
::Field
->new('245', ' ', ' ', a
=> 'Silence in the library'),
568 my ($biblionumber) = AddBiblio
($bib, '');
570 $dbh->do(q
|UPDATE subscription_numberpatterns SET numberingmethod
='No. {X}' WHERE id
=1|);
571 my $subscriptionid = NewSubscription
(
572 undef, "", $booksellerid, undef, undef, $biblionumber,
573 '2013-01-01', 1, undef, undef, undef,
574 undef, undef, undef, undef, undef, undef,
575 1, 'public',undef, '2013-01-01', undef, 1,
576 undef, undef, 0, 'internal', 0,
577 undef, undef, 0, undef, '2013-12-31', 0
580 my ($serials_count, @serials) = GetSerials
($subscriptionid);
581 my @serialids = ($serials[0]->{serialid
});
585 $err = SendAlerts
( 'claimissues', \
@serialids, 'TESTSERIALCLAIM' ) }
586 qr/^Bookseller .* without emails at/,
587 "Warn on vendor without email address";
589 $bookseller = Koha
::Acquisition
::Booksellers
->find( $booksellerid );
590 $bookseller->contacts->next->email('testemail@mydomain.com')->store;
592 # Ensure that the preference 'LetterLog' is set to logging
593 t
::lib
::Mocks
::mock_preference
( 'LetterLog', 'on' );
595 # SendAlerts needs branchemail or KohaAdminEmailAddress as sender
596 t
::lib
::Mocks
::mock_userenv
({ branchcode
=> $library->{branchcode
} });
598 t
::lib
::Mocks
::mock_preference
( 'KohaAdminEmailAddress', 'library@domain.com' );
602 $err = SendAlerts
( 'claimissues', \
@serialids , 'TESTSERIALCLAIM' ) }
603 qr
|Fake send_or_die
|,
604 "SendAlerts is using the mocked sendmail routine (claimissues)";
605 is
( $err, 1, "Successfully sent claim" );
606 is
( $email_object->email->header('To'),
607 'testemail@mydomain.com', "mailto correct in sent claim" );
609 $email_object->email->body,
610 "$serialids[0]|2013-01-01|Silence in the library|xxxx-yyyy",
611 'Serial claim letter for 1 issue constructed successfully'
616 my $publisheddate = output_pref
({ dt
=> dt_from_string
, dateformat
=> 'iso', dateonly
=> 1 });
617 my $serialexpected = ( C4
::Serials
::findSerialsByStatus
( 1, $subscriptionid ) )[0];
618 ModSerialStatus
( $serials[0]->{serialid
}, "No. 1", $publisheddate, $publisheddate, $publisheddate, '3', 'a note' );
619 ($serials_count, @serials) = GetSerials
($subscriptionid);
620 push @serialids, ($serials[1]->{serialid
});
622 warning_like
{ $err = SendAlerts
( 'claimissues', \
@serialids, 'TESTSERIALCLAIM' ); }
623 qr
|Fake send_or_die
|,
624 "SendAlerts is using the mocked sendmail routine (claimissues)";
627 $email_object->email->body,
628 "$serialids[0]|2013-01-01|Silence in the library|xxxx-yyyy"
629 . $email_object->email->crlf
630 . "$serialids[1]|2013-01-01|Silence in the library|xxxx-yyyy",
631 "Serial claim letter for 2 issues constructed successfully"
634 $dbh->do(q{DELETE FROM letter WHERE code = 'TESTSERIALCLAIM';});
636 $err = SendAlerts
( 'orderacquisition', $basketno , 'TESTSERIALCLAIM' ) }
637 qr/No orderacquisition TESTSERIALCLAIM letter transported by email/,
638 "GetPreparedLetter warns about missing notice template";
639 is
($err->{'error'}, 'no_letter', "No TESTSERIALCLAIM letter was defined");
644 subtest
'GetPreparedLetter' => sub {
647 Koha
::Notice
::Template
->new(
652 message_transport_type
=> 'email'
657 $letter = C4
::Letters
::GetPreparedLetter
(
659 letter_code
=> 'test',
662 qr{^ERROR: nothing to substitute},
663 'GetPreparedLetter should warn if tables, substiture and repeat are not set';
665 'No letter should be returned by GetPreparedLetter if something went wrong'
669 $letter = C4
::Letters
::GetPreparedLetter
(
671 letter_code
=> 'test',
675 qr{^ERROR: nothing to substitute},
676 'GetPreparedLetter should warn if tables, substiture and repeat are not set, even if the key is passed';
678 'No letter should be returned by GetPreparedLetter if something went wrong'
685 subtest
'TranslateNotices' => sub {
688 t
::lib
::Mocks
::mock_preference
( 'TranslateNotices', '1' );
692 INSERT INTO letter
(module
, code
, branchcode
, name
, title
, content
, message_transport_type
, lang
) VALUES
693 ('test', 'code', '', 'test', 'a test', 'just a test', 'email', 'default'),
694 ('test', 'code', '', 'test', 'una prueba', 'solo una prueba', 'email', 'es-ES');
697 my $letter = C4
::Letters
::GetPreparedLetter
(
700 letter_code
=> 'code',
701 message_transport_type
=> 'email',
702 substitute
=> $substitute,
707 'GetPreparedLetter should return the default one if the lang parameter is not provided'
710 $letter = C4
::Letters
::GetPreparedLetter
(
713 letter_code
=> 'code',
714 message_transport_type
=> 'email',
715 substitute
=> $substitute,
718 is
( $letter->{title
}, 'una prueba',
719 'GetPreparedLetter should return the required notice if it exists' );
721 $letter = C4
::Letters
::GetPreparedLetter
(
724 letter_code
=> 'code',
725 message_transport_type
=> 'email',
726 substitute
=> $substitute,
732 'GetPreparedLetter should return the default notice if the one required does not exist'
735 t
::lib
::Mocks
::mock_preference
( 'TranslateNotices', '' );
737 $letter = C4
::Letters
::GetPreparedLetter
(
740 letter_code
=> 'code',
741 message_transport_type
=> 'email',
742 substitute
=> $substitute,
745 is
( $letter->{title
}, 'a test',
746 'GetPreparedLetter should return the default notice if pref disabled but additional language exists' );
750 subtest
'SendQueuedMessages' => sub {
754 t
::lib
::Mocks
::mock_preference
( 'SMSSendDriver', 'Email' );
755 t
::lib
::Mocks
::mock_preference
('EmailSMSSendDriverFromAddress', '');
757 my $patron = Koha
::Patrons
->find($borrowernumber);
759 INSERT INTO message_queue
(borrowernumber
, subject
, content
, message_transport_type
, status
, letter_code
)
760 VALUES
(?
, 'subject', 'content', 'sms', 'pending', 'just_a_code')
761 |, undef, $borrowernumber
763 eval { C4
::Letters
::SendQueuedMessages
(); };
764 is
( $@
, '', 'SendQueuedMessages should not explode if the patron does not have a sms provider set' );
766 my $sms_pro = $builder->build_object({ class => 'Koha::SMS::Providers', value
=> { domain
=> 'kidclamp.rocks' } });
767 $patron->set( { smsalertnumber
=> '5555555555', sms_provider_id
=> $sms_pro->id() } )->store;
768 $message_id = C4
::Letters
::EnqueueLetter
($my_message); #using datas set around line 95 and forward
770 warning_like
{ C4
::Letters
::SendQueuedMessages
(); }
771 qr
|Fake send_or_die
|,
772 "SendAlerts is using the mocked sendmail routine (claimissues)";
774 my $message = $schema->resultset('MessageQueue')->search({
775 borrowernumber
=> $borrowernumber,
779 is
( $message->to_address(), '5555555555@kidclamp.rocks', 'SendQueuedMessages populates the to address correctly for SMS by email when to_address not set' );
781 $message->from_address(),
783 'SendQueuedMessages uses message queue item \"from address\" for SMS by email when EmailSMSSendDriverFromAddress system preference is not set'
786 $schema->resultset('MessageQueue')->search({borrowernumber
=> $borrowernumber, status
=> 'sent'})->delete(); #clear borrower queue
788 t
::lib
::Mocks
::mock_preference
('EmailSMSSendDriverFromAddress', 'override@example.com');
790 $message_id = C4
::Letters
::EnqueueLetter
($my_message);
791 warning_like
{ C4
::Letters
::SendQueuedMessages
(); }
792 qr
|Fake send_or_die
|,
793 "SendAlerts is using the mocked sendmail routine (claimissues)";
795 $message = $schema->resultset('MessageQueue')->search({
796 borrowernumber
=> $borrowernumber,
801 $message->from_address(),
802 'override@example.com',
803 'SendQueuedMessages uses EmailSMSSendDriverFromAddress value for SMS by email when EmailSMSSendDriverFromAddress is set'
806 $schema->resultset('MessageQueue')->search({borrowernumber
=> $borrowernumber,status
=> 'sent'})->delete(); #clear borrower queue
807 $my_message->{to_address
} = 'fixme@kidclamp.iswrong';
808 $message_id = C4
::Letters
::EnqueueLetter
($my_message);
810 my $number_attempted = C4
::Letters
::SendQueuedMessages
({
811 borrowernumber
=> -1, # -1 still triggers the borrowernumber condition
812 letter_code
=> 'PASSWORD_RESET',
814 is
( $number_attempted, 0, 'There were no password reset messages for SendQueuedMessages to attempt.' );
816 warning_like
{ C4
::Letters
::SendQueuedMessages
(); }
817 qr
|Fake send_or_die
|,
818 "SendAlerts is using the mocked sendmail routine (claimissues)";
820 my $sms_message_address = $schema->resultset('MessageQueue')->search({
821 borrowernumber
=> $borrowernumber,
823 })->next()->to_address();
824 is
( $sms_message_address, '5555555555@kidclamp.rocks', 'SendQueuedMessages populates the to address correctly for SMS by email when to_address is set incorrectly' );
828 subtest
'get_item_content' => sub {
831 t
::lib
::Mocks
::mock_preference
('dateformat', 'metric');
832 t
::lib
::Mocks
::mock_preference
('timeformat', '24hr');
834 {date_due
=> '2041-01-01 12:34', title
=> 'a first title', barcode
=> 'a_first_barcode', author
=> 'a_first_author', itemnumber
=> 1 },
835 {date_due
=> '2042-01-02 23:45', title
=> 'a second title', barcode
=> 'a_second_barcode', author
=> 'a_second_author', itemnumber
=> 2 },
837 my @item_content_fields = qw( date_due title barcode author itemnumber );
840 for my $item ( @items ) {
841 $items_content .= C4
::Letters
::get_item_content
( { item
=> $item, item_content_fields
=> \
@item_content_fields } );
844 my $expected_items_content = <<EOF;
845 01/01/2041 12:34\ta first title\ta_first_barcode\ta_first_author\t1
846 02/01/2042 23:45\ta second title\ta_second_barcode\ta_second_author\t2
848 is
( $items_content, $expected_items_content, 'get_item_content should return correct items info with time (default)' );
851 $items_content = q
||;
852 for my $item ( @items ) {
853 $items_content .= C4
::Letters
::get_item_content
( { item
=> $item, item_content_fields
=> \
@item_content_fields, dateonly
=> 1, } );
856 $expected_items_content = <<EOF;
857 01/01/2041\ta first title\ta_first_barcode\ta_first_author\t1
858 02/01/2042\ta second title\ta_second_barcode\ta_second_author\t2
860 is
( $items_content, $expected_items_content, 'get_item_content should return correct items info without time (if dateonly => 1)' );
863 subtest
'Test limit parameter for SendQueuedMessages' => sub {
866 my $dbh = C4
::Context
->dbh;
868 my $borrowernumber = Koha
::Patron
->new({
871 categorycode
=> $patron_category,
872 branchcode
=> $library->{branchcode
},
873 dateofbirth
=> $date,
874 smsalertnumber
=> undef,
875 })->store->borrowernumber;
877 $dbh->do(q
|DELETE FROM message_queue
|);
880 'content' => 'a message',
881 'metadata' => 'metadata',
882 'code' => 'TEST_MESSAGE',
883 'content_type' => 'text/plain',
884 'title' => 'message title'
886 'borrowernumber' => $borrowernumber,
887 'to_address' => undef,
888 'message_transport_type' => 'sms',
889 'from_address' => 'from@example.com'
891 C4
::Letters
::EnqueueLetter
($my_message);
892 C4
::Letters
::EnqueueLetter
($my_message);
893 C4
::Letters
::EnqueueLetter
($my_message);
894 C4
::Letters
::EnqueueLetter
($my_message);
895 C4
::Letters
::EnqueueLetter
($my_message);
896 my $messages_processed = C4
::Letters
::SendQueuedMessages
( { limit
=> 1 } );
897 is
( $messages_processed, 1,
898 'Processed 1 message with limit of 1 and 5 unprocessed messages' );
899 $messages_processed = C4
::Letters
::SendQueuedMessages
( { limit
=> 2 } );
900 is
( $messages_processed, 2,
901 'Processed 2 message with limit of 2 and 4 unprocessed messages' );
902 $messages_processed = C4
::Letters
::SendQueuedMessages
( { limit
=> 3 } );
903 is
( $messages_processed, 2,
904 'Processed 2 message with limit of 3 and 2 unprocessed messages' );