c0a8a5d7eb9496d4458ac543b7bef26e10a64dc2
[koha.git] / t / db_dependent / Letters.t
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Copyright (C) 2013 Equinox Software, Inc.
6 #
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.
11 #
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.
16 #
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>.
19
20 use Modern::Perl;
21 use Test::More tests => 75;
22 use Test::MockModule;
23 use Test::Warn;
24
25 use MARC::Record;
26
27 my %mail;
28 my $module = new Test::MockModule('Mail::Sendmail');
29 $module->mock(
30     'sendmail',
31     sub {
32         warn "Fake sendmail";
33         %mail = @_;
34     }
35 );
36
37 use_ok('C4::Context');
38 use_ok('C4::Members');
39 use_ok('C4::Acquisition');
40 use_ok('C4::Biblio');
41 use_ok('C4::Letters');
42 use t::lib::Mocks;
43 use t::lib::TestBuilder;
44 use Koha::Database;
45 use Koha::DateUtils qw( dt_from_string output_pref );
46 use Koha::Acquisition::Order;
47 use Koha::Acquisition::Booksellers;
48 use Koha::Acquisition::Bookseller::Contacts;
49 use Koha::Libraries;
50 use Koha::Notice::Templates;
51 my $schema = Koha::Database->schema;
52 $schema->storage->txn_begin();
53
54 my $builder = t::lib::TestBuilder->new;
55 my $dbh = C4::Context->dbh;
56 $dbh->{RaiseError} = 1;
57
58 $dbh->do(q|DELETE FROM letter|);
59 $dbh->do(q|DELETE FROM message_queue|);
60 $dbh->do(q|DELETE FROM message_transport_types|);
61
62 my $library = $builder->build({
63     source => 'Branch',
64 });
65 my $patron_category = $builder->build({ source => 'Category' })->{categorycode};
66 my $date = dt_from_string;
67 my $borrowernumber = AddMember(
68     firstname    => 'Jane',
69     surname      => 'Smith',
70     categorycode => $patron_category,
71     branchcode   => $library->{branchcode},
72     dateofbirth  => $date,
73     smsalertnumber => undef,
74 );
75
76 my $marc_record = MARC::Record->new;
77 my( $biblionumber, $biblioitemnumber ) = AddBiblio( $marc_record, '' );
78
79
80
81 # GetMessageTransportTypes
82 my $mtts = C4::Letters::GetMessageTransportTypes();
83 is( @$mtts, 0, 'GetMessageTransportTypes returns the correct number of message types' );
84
85 $dbh->do(q|
86     INSERT INTO message_transport_types( message_transport_type ) VALUES ('email'), ('phone'), ('print'), ('sms')
87 |);
88 $mtts = C4::Letters::GetMessageTransportTypes();
89 is_deeply( $mtts, ['email', 'phone', 'print', 'sms'], 'GetMessageTransportTypes returns all values' );
90
91
92 # EnqueueLetter
93 is( C4::Letters::EnqueueLetter(), undef, 'EnqueueLetter without argument returns undef' );
94
95 my $my_message = {
96     borrowernumber         => $borrowernumber,
97     message_transport_type => 'sms',
98     to_address             => undef,
99     from_address           => 'from@example.com',
100 };
101 my $message_id = C4::Letters::EnqueueLetter($my_message);
102 is( $message_id, undef, 'EnqueueLetter without the letter argument returns undef' );
103
104 delete $my_message->{message_transport_type};
105 $my_message->{letter} = {
106     content      => 'a message',
107     title        => 'message title',
108     metadata     => 'metadata',
109     code         => 'TEST_MESSAGE',
110     content_type => 'text/plain',
111 };
112 $message_id = C4::Letters::EnqueueLetter($my_message);
113 is( $message_id, undef, 'EnqueueLetter without the message type argument argument returns undef' );
114
115 $my_message->{message_transport_type} = 'sms';
116 $message_id = C4::Letters::EnqueueLetter($my_message);
117 ok(defined $message_id && $message_id > 0, 'new message successfully queued');
118
119
120 # GetQueuedMessages
121 my $messages = C4::Letters::GetQueuedMessages();
122 is( @$messages, 1, 'GetQueuedMessages without argument returns all the entries' );
123
124 $messages = C4::Letters::GetQueuedMessages({ borrowernumber => $borrowernumber });
125 is( @$messages, 1, 'one message stored for the borrower' );
126 is( $messages->[0]->{message_id}, $message_id, 'EnqueueLetter returns the message id correctly' );
127 is( $messages->[0]->{borrowernumber}, $borrowernumber, 'EnqueueLetter stores the borrower number correctly' );
128 is( $messages->[0]->{subject}, $my_message->{letter}->{title}, 'EnqueueLetter stores the subject correctly' );
129 is( $messages->[0]->{content}, $my_message->{letter}->{content}, 'EnqueueLetter stores the content correctly' );
130 is( $messages->[0]->{message_transport_type}, $my_message->{message_transport_type}, 'EnqueueLetter stores the message type correctly' );
131 is( $messages->[0]->{status}, 'pending', 'EnqueueLetter stores the status pending correctly' );
132
133
134 # SendQueuedMessages
135 my $messages_processed = C4::Letters::SendQueuedMessages();
136 is($messages_processed, 1, 'all queued messages processed');
137 $messages = C4::Letters::GetQueuedMessages({ borrowernumber => $borrowernumber });
138 is(
139     $messages->[0]->{status},
140     'failed',
141     'message marked failed if tried to send SMS message for borrower with no smsalertnumber set (bug 11208)'
142 );
143
144 # ResendMessage
145 my $resent = C4::Letters::ResendMessage($messages->[0]->{message_id});
146 my $message = C4::Letters::GetMessage( $messages->[0]->{message_id});
147 is( $resent, 1, 'The message should have been resent' );
148 is($message->{status},'pending', 'ResendMessage sets status to pending correctly (bug 12426)');
149 $resent = C4::Letters::ResendMessage($messages->[0]->{message_id});
150 is( $resent, 0, 'The message should not have been resent again' );
151 $resent = C4::Letters::ResendMessage();
152 is( $resent, undef, 'ResendMessage should return undef if not message_id given' );
153
154 # GetLetters
155 my $letters = C4::Letters::GetLetters();
156 is( @$letters, 0, 'GetLetters returns the correct number of letters' );
157
158 my $title = q|<<branches.branchname>> - <<status>>|;
159 my $content = q{Dear <<borrowers.firstname>> <<borrowers.surname>>,
160 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.
161
162 <<branches.branchname>>
163 <<branches.branchaddress1>>
164 URL: <<OPACBaseURL>>
165
166 The following item(s) is/are currently <<status>>:
167
168 <item> <<count>>. <<items.itemcallnumber>>, Barcode: <<items.barcode>> </item>
169
170 Thank-you for your prompt attention to this matter.
171 Don't forget your date of birth: <<borrowers.dateofbirth>>.
172 Look at this wonderful biblio timestamp: <<biblio.timestamp>>.
173 };
174
175 $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 );
176 $letters = C4::Letters::GetLetters();
177 is( @$letters, 1, 'GetLetters returns the correct number of letters' );
178 is( $letters->[0]->{branchcode}, $library->{branchcode}, 'GetLetters gets the branch code correctly' );
179 is( $letters->[0]->{module}, 'my module', 'GetLetters gets the module correctly' );
180 is( $letters->[0]->{code}, 'my code', 'GetLetters gets the code correctly' );
181 is( $letters->[0]->{name}, 'my name', 'GetLetters gets the name correctly' );
182
183
184 # getletter
185 subtest 'getletter' => sub {
186     plan tests => 16;
187     my $letter = C4::Letters::getletter('my module', 'my code', $library->{branchcode}, 'email');
188     is( $letter->{branchcode}, $library->{branchcode}, 'GetLetters gets the branch code correctly' );
189     is( $letter->{module}, 'my module', 'GetLetters gets the module correctly' );
190     is( $letter->{code}, 'my code', 'GetLetters gets the code correctly' );
191     is( $letter->{name}, 'my name', 'GetLetters gets the name correctly' );
192     is( $letter->{is_html}, 1, 'GetLetters gets the boolean is_html correctly' );
193     is( $letter->{title}, $title, 'GetLetters gets the title correctly' );
194     is( $letter->{content}, $content, 'GetLetters gets the content correctly' );
195     is( $letter->{message_transport_type}, 'email', 'GetLetters gets the message type correctly' );
196
197     my $context = Test::MockModule->new('C4::Context');
198     $context->mock( 'userenv', sub {
199         return {
200             flags  => 1,
201             branch => "anotherlib" }
202     });
203
204     t::lib::Mocks::mock_preference('IndependentBranches', 1);
205     $letter = C4::Letters::getletter('my module', 'my code', $library->{branchcode}, 'email');
206     is( $letter->{branchcode}, $library->{branchcode}, 'GetLetters gets the branch code correctly' );
207     is( $letter->{module}, 'my module', 'GetLetters gets the module correctly' );
208     is( $letter->{code}, 'my code', 'GetLetters gets the code correctly' );
209     is( $letter->{name}, 'my name', 'GetLetters gets the name correctly' );
210     is( $letter->{is_html}, 1, 'GetLetters gets the boolean is_html correctly' );
211     is( $letter->{title}, $title, 'GetLetters gets the title correctly' );
212     is( $letter->{content}, $content, 'GetLetters gets the content correctly' );
213     is( $letter->{message_transport_type}, 'email', 'GetLetters gets the message type correctly' );
214
215     $context->unmock('userenv');
216 };
217
218
219
220 # Regression test for Bug 14206
221 $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 );
222 my $letter14206_a = C4::Letters::getletter('my module', 'my code', 'FFL' );
223 is( $letter14206_a->{message_transport_type}, 'print', 'Bug 14206 - message_transport_type not passed, correct mtt detected' );
224 my $letter14206_b = C4::Letters::getletter('my module', 'my code', 'FFL', 'print');
225 is( $letter14206_b->{message_transport_type}, 'print', 'Bug 14206 - message_transport_type passed, correct mtt detected'  );
226
227 # test for overdue_notices.pl
228 my $overdue_rules = {
229     letter1         => 'my code',
230 };
231 my $i = 1;
232 my $branchcode = 'FFL';
233 my $letter14206_c = C4::Letters::getletter('my module', $overdue_rules->{"letter$i"}, $branchcode);
234 is( $letter14206_c->{message_transport_type}, 'print', 'Bug 14206 - correct mtt detected for call from overdue_notices.pl' );
235
236 # addalert
237 my $type = 'my type';
238 my $externalid = 'my external id';
239 my $alert_id = C4::Letters::addalert($borrowernumber, $type, $externalid);
240 isnt( $alert_id, undef, 'addalert does not return undef' );
241
242
243 # getalert
244 my $alerts = C4::Letters::getalert();
245 is( @$alerts, 1, 'getalert should not fail without parameter' );
246 $alerts = C4::Letters::getalert($borrowernumber);
247 is( @$alerts, 1, 'addalert adds an alert' );
248 is( $alerts->[0]->{alertid}, $alert_id, 'addalert returns the alert id correctly' );
249 is( $alerts->[0]->{type}, $type, 'addalert stores the type correctly' );
250 is( $alerts->[0]->{externalid}, $externalid, 'addalert stores the externalid correctly' );
251
252 $alerts = C4::Letters::getalert($borrowernumber, $type);
253 is( @$alerts, 1, 'getalert returns the correct number of alerts' );
254 $alerts = C4::Letters::getalert($borrowernumber, $type, $externalid);
255 is( @$alerts, 1, 'getalert returns the correct number of alerts' );
256 $alerts = C4::Letters::getalert($borrowernumber, 'another type');
257 is( @$alerts, 0, 'getalert returns the correct number of alerts' );
258 $alerts = C4::Letters::getalert($borrowernumber, $type, 'another external id');
259 is( @$alerts, 0, 'getalert returns the correct number of alerts' );
260
261
262 # delalert
263 eval {
264     C4::Letters::delalert();
265 };
266 isnt( $@, undef, 'delalert without argument returns an error' );
267 $alerts = C4::Letters::getalert($borrowernumber);
268 is( @$alerts, 1, 'delalert without argument does not remove an alert' );
269
270 C4::Letters::delalert($alert_id);
271 $alerts = C4::Letters::getalert($borrowernumber);
272 is( @$alerts, 0, 'delalert removes an alert' );
273
274
275 # GetPreparedLetter
276 t::lib::Mocks::mock_preference('OPACBaseURL', 'http://thisisatest.com');
277
278 my $sms_content = 'This is a SMS for an <<status>>';
279 $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 );
280
281 my $tables = {
282     borrowers => $borrowernumber,
283     branches => $library->{branchcode},
284     biblio => $biblionumber,
285 };
286 my $substitute = {
287     status => 'overdue',
288 };
289 my $repeat = [
290     {
291         itemcallnumber => 'my callnumber1',
292         barcode        => '1234',
293     },
294     {
295         itemcallnumber => 'my callnumber2',
296         barcode        => '5678',
297     },
298 ];
299 my $prepared_letter = GetPreparedLetter((
300     module      => 'my module',
301     branchcode  => $library->{branchcode},
302     letter_code => 'my code',
303     tables      => $tables,
304     substitute  => $substitute,
305     repeat      => $repeat,
306 ));
307 my $retrieved_library = Koha::Libraries->find($library->{branchcode});
308 my $my_title_letter = $retrieved_library->branchname . qq| - $substitute->{status}|;
309 my $biblio_timestamp = dt_from_string( GetBiblioData($biblionumber)->{timestamp} );
310 my $my_content_letter = qq|Dear Jane Smith,
311 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.
312
313 |.$retrieved_library->branchname.qq|
314 |.$retrieved_library->branchaddress1.qq|
315 URL: http://thisisatest.com
316
317 The following item(s) is/are currently $substitute->{status}:
318
319 <item> 1. $repeat->[0]->{itemcallnumber}, Barcode: $repeat->[0]->{barcode} </item>
320 <item> 2. $repeat->[1]->{itemcallnumber}, Barcode: $repeat->[1]->{barcode} </item>
321
322 Thank-you for your prompt attention to this matter.
323 Don't forget your date of birth: | . output_pref({ dt => $date, dateonly => 1 }) . q|.
324 Look at this wonderful biblio timestamp: | . output_pref({ dt => $biblio_timestamp })  . ".\n";
325
326 is( $prepared_letter->{title}, $my_title_letter, 'GetPreparedLetter returns the title correctly' );
327 is( $prepared_letter->{content}, $my_content_letter, 'GetPreparedLetter returns the content correctly' );
328
329 $prepared_letter = GetPreparedLetter((
330     module                 => 'my module',
331     branchcode             => $library->{branchcode},
332     letter_code            => 'my code',
333     tables                 => $tables,
334     substitute             => $substitute,
335     repeat                 => $repeat,
336     message_transport_type => 'sms',
337 ));
338 $my_content_letter = qq|This is a SMS for an $substitute->{status}|;
339 is( $prepared_letter->{content}, $my_content_letter, 'GetPreparedLetter returns the content correctly' );
340
341 $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>>.');});
342 $prepared_letter = GetPreparedLetter((
343     module                 => 'test_date',
344     branchcode             => '',
345     letter_code            => 'test_date',
346     tables                 => $tables,
347     substitute             => $substitute,
348     repeat                 => $repeat,
349 ));
350 is( $prepared_letter->{content}, q|This one only contains the date: | . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test 1' );
351
352 $dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp | dateonly>>.' WHERE code = 'test_date';});
353 $prepared_letter = GetPreparedLetter((
354     module                 => 'test_date',
355     branchcode             => '',
356     letter_code            => 'test_date',
357     tables                 => $tables,
358     substitute             => $substitute,
359     repeat                 => $repeat,
360 ));
361 is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test 2' );
362
363 $dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp|dateonly >>.' WHERE code = 'test_date';});
364 $prepared_letter = GetPreparedLetter((
365     module                 => 'test_date',
366     branchcode             => '',
367     letter_code            => 'test_date',
368     tables                 => $tables,
369     substitute             => $substitute,
370     repeat                 => $repeat,
371 ));
372 is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test 3' );
373
374 t::lib::Mocks::mock_preference( 'TimeFormat', '12hr' );
375 my $yesterday_night = $date->clone->add( days => -1 )->set_hour(22);
376 $dbh->do(q|UPDATE biblio SET timestamp = ? WHERE biblionumber = ?|, undef, $yesterday_night, $biblionumber );
377 $dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp>>.' WHERE code = 'test_date';});
378 $prepared_letter = GetPreparedLetter((
379     module                 => 'test_date',
380     branchcode             => '',
381     letter_code            => 'test_date',
382     tables                 => $tables,
383     substitute             => $substitute,
384     repeat                 => $repeat,
385 ));
386 is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $yesterday_night }) . q|.|, 'dateonly test 3' );
387
388 $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>');});
389 $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>');});
390
391 # Test that _parseletter doesn't modify its parameters bug 15429
392 {
393     my $values = { dateexpiry => '2015-12-13', };
394     C4::Letters::_parseletter($prepared_letter, 'borrowers', $values);
395     is( $values->{dateexpiry}, '2015-12-13', "_parseletter doesn't modify its parameters" );
396 }
397
398 my $bookseller = Koha::Acquisition::Bookseller->new(
399     {
400         name => "my vendor",
401         address1 => "bookseller's address",
402         phone => "0123456",
403         active => 1,
404         deliverytime => 5,
405     }
406 )->store;
407 my $booksellerid = $bookseller->id;
408
409 Koha::Acquisition::Bookseller::Contact->new( { name => 'John Smith',  phone => '0123456x1', claimacquisition => 1, orderacquisition => 1, booksellerid => $booksellerid } )->store;
410 Koha::Acquisition::Bookseller::Contact->new( { name => 'Leo Tolstoy', phone => '0123456x2', claimissues      => 1, booksellerid => $booksellerid } )->store;
411 my $basketno = NewBasket($booksellerid, 1);
412
413 my $budgetid = C4::Budgets::AddBudget({
414     budget_code => "budget_code_test_letters",
415     budget_name => "budget_name_test_letters",
416 });
417
418 my $bib = MARC::Record->new();
419 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
420     $bib->append_fields(
421         MARC::Field->new('200', ' ', ' ', a => 'Silence in the library'),
422     );
423 } else {
424     $bib->append_fields(
425         MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
426     );
427 }
428
429 ($biblionumber, $biblioitemnumber) = AddBiblio($bib, '');
430 my $order = Koha::Acquisition::Order->new(
431     {
432         basketno => $basketno,
433         quantity => 1,
434         biblionumber => $biblionumber,
435         budget_id => $budgetid,
436     }
437 )->insert;
438 my $ordernumber = $order->{ordernumber};
439
440 C4::Acquisition::CloseBasket( $basketno );
441 my $err;
442 warning_like {
443     $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
444     qr/^Bookseller .* without emails at/,
445     "SendAlerts prints a warning";
446 is($err->{'error'}, 'no_email', "Trying to send an alert when there's no e-mail results in an error");
447
448 $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
449 $bookseller->contacts->next->email('testemail@mydomain.com')->store;
450
451 # Ensure that the preference 'LetterLog' is set to logging
452 t::lib::Mocks::mock_preference( 'LetterLog', 'on' );
453
454 # SendAlerts needs branchemail or KohaAdminEmailAddress as sender
455 C4::Context->_new_userenv('DUMMY');
456 C4::Context->set_userenv( 0, 0, 0, 'firstname', 'surname', $library->{branchcode}, 'My Library', 0, '', '');
457 t::lib::Mocks::mock_preference( 'KohaAdminEmailAddress', 'library@domain.com' );
458
459 {
460 warning_is {
461     $err = SendAlerts( 'orderacquisition', $basketno , 'TESTACQORDER' ) }
462     "Fake sendmail",
463     "SendAlerts is using the mocked sendmail routine (orderacquisition)";
464 is($err, 1, "Successfully sent order.");
465 is($mail{'To'}, 'testemail@mydomain.com', "mailto correct in sent order");
466 is($mail{'Message'}, 'my vendor|John Smith|Ordernumber ' . $ordernumber . ' (Silence in the library) (1 ordered)', 'Order notice text constructed successfully');
467
468 $dbh->do(q{DELETE FROM letter WHERE code = 'TESTACQORDER';});
469 warning_like {
470     $err = SendAlerts( 'orderacquisition', $basketno , 'TESTACQORDER' ) }
471     qr/No orderacquisition TESTACQORDER letter transported by email/,
472     "GetPreparedLetter warns about missing notice template";
473 is($err->{'error'}, 'no_letter', "No TESTACQORDER letter was defined.");
474 }
475
476 {
477 warning_is {
478     $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
479     "Fake sendmail",
480     "SendAlerts is using the mocked sendmail routine";
481
482 is($err, 1, "Successfully sent claim");
483 is($mail{'To'}, 'testemail@mydomain.com', "mailto correct in sent claim");
484 is($mail{'Message'}, 'my vendor|John Smith|Ordernumber ' . $ordernumber . ' (Silence in the library) (1 ordered)', 'Claim notice text constructed successfully');
485 }
486
487 {
488 use C4::Serials;
489
490 my $notes = 'notes';
491 my $internalnotes = 'intnotes';
492 $dbh->do(q|UPDATE subscription_numberpatterns SET numberingmethod='No. {X}' WHERE id=1|);
493 my $subscriptionid = NewSubscription(
494      undef,      "",     undef, undef, undef, $biblionumber,
495     '2013-01-01', 1, undef, undef,  undef,
496     undef,      undef,  undef, undef, undef, undef,
497     1,          $notes,undef, '2013-01-01', undef, 1,
498     undef,       undef,  0,    $internalnotes,  0,
499     undef, undef, 0,          undef,         '2013-12-31', 0
500 );
501 $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>>');});
502 my ($serials_count, @serials) = GetSerials($subscriptionid);
503 my $serial = $serials[0];
504
505 my $borrowernumber = AddMember(
506     firstname    => 'John',
507     surname      => 'Smith',
508     categorycode => $patron_category,
509     branchcode   => $library->{branchcode},
510     dateofbirth  => $date,
511     email        => 'john.smith@test.de',
512 );
513 my $alert_id = C4::Letters::addalert($borrowernumber, 'issue', $subscriptionid);
514
515
516 my $err2;
517 warning_is {
518 $err2 = SendAlerts( 'issue', $serial->{serialid}, 'RLIST' ) }
519     "Fake sendmail",
520     "SendAlerts is using the mocked sendmail routine";
521 is($err2, 1, "Successfully sent serial notification");
522 is($mail{'To'}, 'john.smith@test.de', "mailto correct in sent serial notification");
523 is($mail{'Message'}, 'Silence in the library,'.$subscriptionid.',No. 0', 'Serial notification text constructed successfully');
524 }
525
526 subtest 'GetPreparedLetter' => sub {
527     plan tests => 4;
528
529     Koha::Notice::Template->new(
530         {
531             module                 => 'test',
532             code                   => 'test',
533             branchcode             => '',
534             message_transport_type => 'email'
535         }
536     )->store;
537     my $letter;
538     warning_like {
539         $letter = C4::Letters::GetPreparedLetter(
540             module      => 'test',
541             letter_code => 'test',
542         );
543     }
544     qr{^ERROR: nothing to substitute},
545 'GetPreparedLetter should warn if tables, substiture and repeat are not set';
546     is( $letter, undef,
547 'No letter should be returned by GetPreparedLetter if something went wrong'
548     );
549
550     warning_like {
551         $letter = C4::Letters::GetPreparedLetter(
552             module      => 'test',
553             letter_code => 'test',
554             substitute  => {}
555         );
556     }
557     qr{^ERROR: nothing to substitute},
558 'GetPreparedLetter should warn if tables, substiture and repeat are not set, even if the key is passed';
559     is( $letter, undef,
560 'No letter should be returned by GetPreparedLetter if something went wrong'
561     );
562
563 };
564
565
566
567 subtest 'TranslateNotices' => sub {
568     plan tests => 4;
569
570     t::lib::Mocks::mock_preference( 'TranslateNotices', '1' );
571
572     $dbh->do(
573         q|
574         INSERT INTO letter (module, code, branchcode, name, title, content, message_transport_type, lang) VALUES
575         ('test', 'code', '', 'test', 'a test', 'just a test', 'email', 'default'),
576         ('test', 'code', '', 'test', 'una prueba', 'solo una prueba', 'email', 'es-ES');
577     | );
578     my $substitute = {};
579     my $letter = C4::Letters::GetPreparedLetter(
580             module                 => 'test',
581             tables                 => $tables,
582             letter_code            => 'code',
583             message_transport_type => 'email',
584             substitute             => $substitute,
585     );
586     is(
587         $letter->{title},
588         'a test',
589         'GetPreparedLetter should return the default one if the lang parameter is not provided'
590     );
591
592     $letter = C4::Letters::GetPreparedLetter(
593             module                 => 'test',
594             tables                 => $tables,
595             letter_code            => 'code',
596             message_transport_type => 'email',
597             substitute             => $substitute,
598             lang                   => 'es-ES',
599     );
600     is( $letter->{title}, 'una prueba',
601         'GetPreparedLetter should return the required notice if it exists' );
602
603     $letter = C4::Letters::GetPreparedLetter(
604             module                 => 'test',
605             tables                 => $tables,
606             letter_code            => 'code',
607             message_transport_type => 'email',
608             substitute             => $substitute,
609             lang                   => 'fr-FR',
610     );
611     is(
612         $letter->{title},
613         'a test',
614         'GetPreparedLetter should return the default notice if the one required does not exist'
615     );
616
617     t::lib::Mocks::mock_preference( 'TranslateNotices', '' );
618
619     $letter = C4::Letters::GetPreparedLetter(
620             module                 => 'test',
621             tables                 => $tables,
622             letter_code            => 'code',
623             message_transport_type => 'email',
624             substitute             => $substitute,
625             lang                   => 'es-ES',
626     );
627     is( $letter->{title}, 'a test',
628         'GetPreparedLetter should return the default notice if pref disabled but additional language exists' );
629
630 };
631
632 subtest 'SendQueuedMessages' => sub {
633
634     plan tests => 2;
635     t::lib::Mocks::mock_preference( 'SMSSendDriver', 'Email' );
636     my $patron = Koha::Patrons->find($borrowernumber);
637     $dbh->do(q|
638         INSERT INTO message_queue(borrowernumber, subject, content, message_transport_type, status, letter_code)
639         VALUES (?, 'subject', 'content', 'sms', 'pending', 'just_a_code')
640         |, undef, $borrowernumber
641     );
642     eval { C4::Letters::SendQueuedMessages(); };
643     is( $@, '', 'SendQueuedMessages should not explode if the patron does not have a sms provider set' );
644
645     my $sms_pro = $builder->build_object({ class => 'Koha::SMS::Providers', value => { domain => 'kidclamp.rocks' } });
646     ModMember( borrowernumber => $borrowernumber, smsalertnumber => '5555555555', sms_provider_id => $sms_pro->id() );
647     $message_id = C4::Letters::EnqueueLetter($my_message); #using datas set around line 95 and forward
648     C4::Letters::SendQueuedMessages();
649     my $sms_message_address = $schema->resultset('MessageQueue')->search({
650         borrowernumber => $borrowernumber,
651         status => 'sent'
652     })->next()->to_address();
653     is( $sms_message_address, '5555555555@kidclamp.rocks', 'SendQueuedMessages populates the to address correctly for SMS by email' );
654
655 };