Bug 10900 - Follow up, since more has been added to master
[koha.git] / t / db_dependent / Letters.t
blobf53e75b4175558b560e66ea604e45d1ea1319895
1 #!/usr/bin/perl
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>.
20 use Modern::Perl;
21 use Test::More tests => 58;
22 use Test::MockModule;
23 use Test::Warn;
25 use MARC::Record;
27 my %mail;
28 my $module = new Test::MockModule('Mail::Sendmail');
29 $module->mock(
30 'sendmail',
31 sub {
32 warn "Fake sendmail";
33 %mail = @_;
37 use_ok('C4::Context');
38 use_ok('C4::Members');
39 use_ok('C4::Branch');
40 use_ok('C4::Acquisition');
41 use_ok('C4::Biblio');
42 use_ok('C4::Bookseller');
43 use_ok('C4::Letters');
44 use t::lib::Mocks;
45 use Koha::DateUtils qw( dt_from_string output_pref );
46 use Koha::Acquisition::Order;
47 use Koha::Acquisition::Bookseller;
49 my $dbh = C4::Context->dbh;
51 # Start transaction
52 $dbh->{AutoCommit} = 0;
53 $dbh->{RaiseError} = 1;
55 $dbh->do(q|DELETE FROM letter|);
56 $dbh->do(q|DELETE FROM message_queue|);
57 $dbh->do(q|DELETE FROM message_transport_types|);
59 my $date = dt_from_string;
60 my $borrowernumber = AddMember(
61 firstname => 'Jane',
62 surname => 'Smith',
63 categorycode => 'PT',
64 branchcode => 'CPL',
65 dateofbirth => $date,
68 my $marc_record = MARC::Record->new;
69 my( $biblionumber, $biblioitemnumber ) = AddBiblio( $marc_record, '' );
71 # GetMessageTransportTypes
72 my $mtts = C4::Letters::GetMessageTransportTypes();
73 is( @$mtts, 0, 'GetMessageTransportTypes returns the correct number of message types' );
75 $dbh->do(q|
76 INSERT INTO message_transport_types( message_transport_type ) VALUES ('email'), ('phone'), ('print'), ('sms')
77 |);
78 $mtts = C4::Letters::GetMessageTransportTypes();
79 is_deeply( $mtts, ['email', 'phone', 'print', 'sms'], 'GetMessageTransportTypes returns all values' );
82 # EnqueueLetter
83 is( C4::Letters::EnqueueLetter(), undef, 'EnqueueLetter without argument returns undef' );
85 my $my_message = {
86 borrowernumber => $borrowernumber,
87 message_transport_type => 'sms',
88 to_address => 'to@example.com',
89 from_address => 'from@example.com',
91 my $message_id = C4::Letters::EnqueueLetter($my_message);
92 is( $message_id, undef, 'EnqueueLetter without the letter argument returns undef' );
94 delete $my_message->{message_transport_type};
95 $my_message->{letter} = {
96 content => 'a message',
97 title => 'message title',
98 metadata => 'metadata',
99 code => 'TEST_MESSAGE',
100 content_type => 'text/plain',
102 $message_id = C4::Letters::EnqueueLetter($my_message);
103 is( $message_id, undef, 'EnqueueLetter without the message type argument argument returns undef' );
105 $my_message->{message_transport_type} = 'sms';
106 $message_id = C4::Letters::EnqueueLetter($my_message);
107 ok(defined $message_id && $message_id > 0, 'new message successfully queued');
110 # GetQueuedMessages
111 my $messages = C4::Letters::GetQueuedMessages();
112 is( @$messages, 1, 'GetQueuedMessages without argument returns all the entries' );
114 $messages = C4::Letters::GetQueuedMessages({ borrowernumber => $borrowernumber });
115 is( @$messages, 1, 'one message stored for the borrower' );
116 is( $messages->[0]->{message_id}, $message_id, 'EnqueueLetter returns the message id correctly' );
117 is( $messages->[0]->{borrowernumber}, $borrowernumber, 'EnqueueLetter stores the borrower number correctly' );
118 is( $messages->[0]->{subject}, $my_message->{letter}->{title}, 'EnqueueLetter stores the subject correctly' );
119 is( $messages->[0]->{content}, $my_message->{letter}->{content}, 'EnqueueLetter stores the content correctly' );
120 is( $messages->[0]->{message_transport_type}, $my_message->{message_transport_type}, 'EnqueueLetter stores the message type correctly' );
121 is( $messages->[0]->{status}, 'pending', 'EnqueueLetter stores the status pending correctly' );
124 # SendQueuedMessages
125 my $messages_processed = C4::Letters::SendQueuedMessages();
126 is($messages_processed, 1, 'all queued messages processed');
128 $messages = C4::Letters::GetQueuedMessages({ borrowernumber => $borrowernumber });
130 $messages->[0]->{status},
131 'failed',
132 'message marked failed if tried to send SMS message for borrower with no smsalertnumber set (bug 11208)'
135 # GetLetters
136 my $letters = C4::Letters::GetLetters();
137 is( @$letters, 0, 'GetLetters returns the correct number of letters' );
139 my $title = q|<<branches.branchname>> - <<status>>|;
140 my $content = q|Dear <<borrowers.firstname>> <<borrowers.surname>>,
141 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.
143 <<branches.branchname>>
144 <<branches.branchaddress1>>
145 URL: <<OPACBaseURL>>
147 The following item(s) is/are currently <<status>>:
149 <item> <<count>>. <<items.itemcallnumber>>, Barcode: <<items.barcode>> </item>
151 Thank-you for your prompt attention to this matter.
152 Don't forget your date of birth: <<borrowers.dateofbirth>>.
153 Look at this wonderful biblio timestamp: <<biblio.timestamp>>.
156 $dbh->do( q|INSERT INTO letter(branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES ('CPL','my module','my code','my name',1,?,?,'email')|, undef, $title, $content );
157 $letters = C4::Letters::GetLetters();
158 is( @$letters, 1, 'GetLetters returns the correct number of letters' );
159 is( $letters->[0]->{branchcode}, 'CPL', 'GetLetters gets the branch code correctly' );
160 is( $letters->[0]->{module}, 'my module', 'GetLetters gets the module correctly' );
161 is( $letters->[0]->{code}, 'my code', 'GetLetters gets the code correctly' );
162 is( $letters->[0]->{name}, 'my name', 'GetLetters gets the name correctly' );
165 # getletter
166 my $letter = C4::Letters::getletter('my module', 'my code', 'CPL', 'email');
167 is( $letter->{branchcode}, 'CPL', 'GetLetters gets the branch code correctly' );
168 is( $letter->{module}, 'my module', 'GetLetters gets the module correctly' );
169 is( $letter->{code}, 'my code', 'GetLetters gets the code correctly' );
170 is( $letter->{name}, 'my name', 'GetLetters gets the name correctly' );
171 is( $letter->{is_html}, 1, 'GetLetters gets the boolean is_html correctly' );
172 is( $letter->{title}, $title, 'GetLetters gets the title correctly' );
173 is( $letter->{content}, $content, 'GetLetters gets the content correctly' );
174 is( $letter->{message_transport_type}, 'email', 'GetLetters gets the message type correctly' );
177 # addalert
178 my $type = 'my type';
179 my $externalid = 'my external id';
180 my $alert_id = C4::Letters::addalert($borrowernumber, $type, $externalid);
181 isnt( $alert_id, undef, 'addalert does not return undef' );
183 my $alerts = C4::Letters::getalert($borrowernumber);
184 is( @$alerts, 1, 'addalert adds an alert' );
185 is( $alerts->[0]->{alertid}, $alert_id, 'addalert returns the alert id correctly' );
186 is( $alerts->[0]->{type}, $type, 'addalert stores the type correctly' );
187 is( $alerts->[0]->{externalid}, $externalid, 'addalert stores the externalid correctly' );
190 # getalert
191 $alerts = C4::Letters::getalert($borrowernumber, $type);
192 is( @$alerts, 1, 'getalert returns the correct number of alerts' );
193 $alerts = C4::Letters::getalert($borrowernumber, $type, $externalid);
194 is( @$alerts, 1, 'getalert returns the correct number of alerts' );
195 $alerts = C4::Letters::getalert($borrowernumber, 'another type');
196 is( @$alerts, 0, 'getalert returns the correct number of alerts' );
197 $alerts = C4::Letters::getalert($borrowernumber, $type, 'another external id');
198 is( @$alerts, 0, 'getalert returns the correct number of alerts' );
201 # delalert
202 eval {
203 C4::Letters::delalert();
205 isnt( $@, undef, 'delalert without argument returns an error' );
206 $alerts = C4::Letters::getalert($borrowernumber);
207 is( @$alerts, 1, 'delalert without argument does not remove an alert' );
209 C4::Letters::delalert($alert_id);
210 $alerts = C4::Letters::getalert($borrowernumber);
211 is( @$alerts, 0, 'delalert removes an alert' );
214 # GetPreparedLetter
215 t::lib::Mocks::mock_preference('OPACBaseURL', 'http://thisisatest.com');
217 my $sms_content = 'This is a SMS for an <<status>>';
218 $dbh->do( q|INSERT INTO letter(branchcode,module,code,name,is_html,title,content,message_transport_type) VALUES ('CPL','my module','my code','my name',1,'my title',?,'sms')|, undef, $sms_content );
220 my $tables = {
221 borrowers => $borrowernumber,
222 branches => 'CPL',
223 biblio => $biblionumber,
225 my $substitute = {
226 status => 'overdue',
228 my $repeat = [
230 itemcallnumber => 'my callnumber1',
231 barcode => '1234',
234 itemcallnumber => 'my callnumber2',
235 barcode => '5678',
238 my $prepared_letter = GetPreparedLetter((
239 module => 'my module',
240 branchcode => 'CPL',
241 letter_code => 'my code',
242 tables => $tables,
243 substitute => $substitute,
244 repeat => $repeat,
246 my $branch = GetBranchDetail('CPL');
247 my $my_title_letter = qq|$branch->{branchname} - $substitute->{status}|;
248 my $my_content_letter = qq|Dear Jane Smith,
249 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.
251 $branch->{branchname}
252 $branch->{branchaddress1}
253 URL: http://thisisatest.com
255 The following item(s) is/are currently $substitute->{status}:
257 <item> 1. $repeat->[0]->{itemcallnumber}, Barcode: $repeat->[0]->{barcode} </item>
258 <item> 2. $repeat->[1]->{itemcallnumber}, Barcode: $repeat->[1]->{barcode} </item>
260 Thank-you for your prompt attention to this matter.
261 Don't forget your date of birth: | . output_pref({ dt => $date, dateonly => 1 }) . q|.
262 Look at this wonderful biblio timestamp: | . output_pref({ dt => $date }) . ".\n";
263 is( $prepared_letter->{title}, $my_title_letter, 'GetPreparedLetter returns the title correctly' );
264 is( $prepared_letter->{content}, $my_content_letter, 'GetPreparedLetter returns the content correctly' );
266 $prepared_letter = GetPreparedLetter((
267 module => 'my module',
268 branchcode => 'CPL',
269 letter_code => 'my code',
270 tables => $tables,
271 substitute => $substitute,
272 repeat => $repeat,
273 message_transport_type => 'sms',
275 $my_content_letter = qq|This is a SMS for an $substitute->{status}|;
276 is( $prepared_letter->{content}, $my_content_letter, 'GetPreparedLetter returns the content correctly' );
278 $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>');});
280 my $booksellerid = C4::Bookseller::AddBookseller(
282 name => "my vendor",
283 address1 => "bookseller's address",
284 phone => "0123456",
285 active => 1,
286 deliverytime => 5,
289 { name => 'John Smith', phone => '0123456x1', claimacquisition => 1 },
290 { name => 'Leo Tolstoy', phone => '0123456x2', claimissues => 1 },
293 my $basketno = NewBasket($booksellerid, 1);
295 my $budgetid = C4::Budgets::AddBudget({
296 budget_code => "budget_code_test_letters",
297 budget_name => "budget_name_test_letters",
300 my $bib = MARC::Record->new();
301 if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
302 $bib->append_fields(
303 MARC::Field->new('200', ' ', ' ', a => 'Silence in the library'),
305 } else {
306 $bib->append_fields(
307 MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
311 ($biblionumber, $biblioitemnumber) = AddBiblio($bib, '');
312 my $order = Koha::Acquisition::Order->new(
314 basketno => $basketno,
315 quantity => 1,
316 biblionumber => $biblionumber,
317 budget_id => $budgetid,
319 )->insert;
320 my $ordernumber = $order->{ordernumber};
322 C4::Acquisition::CloseBasket( $basketno );
323 my $err;
324 warning_like {
325 $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
326 qr/^Bookseller .* without emails at/,
327 "SendAlerts prints a warning";
328 is($err->{'error'}, 'no_email', "Trying to send an alert when there's no e-mail results in an error");
330 my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
331 $bookseller->contacts->[0]->email('testemail@mydomain.com');
332 C4::Bookseller::ModBookseller($bookseller);
333 $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid });
335 warning_is {
336 $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
337 "Fake sendmail",
338 "SendAlerts is using the mocked sendmail routine";
340 is($err, 1, "Successfully sent claim");
341 is($mail{'To'}, 'testemail@mydomain.com', "mailto correct in sent claim");
342 is($mail{'Message'}, 'my vendor|John Smith|Ordernumber ' . $ordernumber . ' (Silence in the library) (1 ordered)', 'Claim notice text constructed successfully');
344 $dbh->rollback;