Bug 12896: Move the bookseller-related code into Koha::Acquisition::Bookseller
[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 => 58;
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::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;
48
49 my $dbh = C4::Context->dbh;
50
51 # Start transaction
52 $dbh->{AutoCommit} = 0;
53 $dbh->{RaiseError} = 1;
54
55 $dbh->do(q|DELETE FROM letter|);
56 $dbh->do(q|DELETE FROM message_queue|);
57 $dbh->do(q|DELETE FROM message_transport_types|);
58
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,
66 );
67
68 my $marc_record = MARC::Record->new;
69 my( $biblionumber, $biblioitemnumber ) = AddBiblio( $marc_record, '' );
70
71 # GetMessageTransportTypes
72 my $mtts = C4::Letters::GetMessageTransportTypes();
73 is( @$mtts, 0, 'GetMessageTransportTypes returns the correct number of message types' );
74
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' );
80
81
82 # EnqueueLetter
83 is( C4::Letters::EnqueueLetter(), undef, 'EnqueueLetter without argument returns undef' );
84
85 my $my_message = {
86     borrowernumber         => $borrowernumber,
87     message_transport_type => 'sms',
88     to_address             => 'to@example.com',
89     from_address           => 'from@example.com',
90 };
91 my $message_id = C4::Letters::EnqueueLetter($my_message);
92 is( $message_id, undef, 'EnqueueLetter without the letter argument returns undef' );
93
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',
101 };
102 $message_id = C4::Letters::EnqueueLetter($my_message);
103 is( $message_id, undef, 'EnqueueLetter without the message type argument argument returns undef' );
104
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');
108
109
110 # GetQueuedMessages
111 my $messages = C4::Letters::GetQueuedMessages();
112 is( @$messages, 1, 'GetQueuedMessages without argument returns all the entries' );
113
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' );
122
123
124 # SendQueuedMessages
125 my $messages_processed = C4::Letters::SendQueuedMessages();
126 is($messages_processed, 1, 'all queued messages processed');
127
128 $messages = C4::Letters::GetQueuedMessages({ borrowernumber => $borrowernumber });
129 is(
130     $messages->[0]->{status},
131     'failed',
132     'message marked failed if tried to send SMS message for borrower with no smsalertnumber set (bug 11208)'
133 );
134
135 # GetLetters
136 my $letters = C4::Letters::GetLetters();
137 is( @$letters, 0, 'GetLetters returns the correct number of letters' );
138
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.
142
143 <<branches.branchname>>
144 <<branches.branchaddress1>>
145 URL: <<OPACBaseURL>>
146
147 The following item(s) is/are currently <<status>>:
148
149 <item> <<count>>. <<items.itemcallnumber>>, Barcode: <<items.barcode>> </item>
150
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>>.
154 |;
155
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' );
163
164
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' );
175
176
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' );
182
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' );
188
189
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' );
199
200
201 # delalert
202 eval {
203     C4::Letters::delalert();
204 };
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' );
208
209 C4::Letters::delalert($alert_id);
210 $alerts = C4::Letters::getalert($borrowernumber);
211 is( @$alerts, 0, 'delalert removes an alert' );
212
213
214 # GetPreparedLetter
215 t::lib::Mocks::mock_preference('OPACBaseURL', 'http://thisisatest.com');
216
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 );
219
220 my $tables = {
221     borrowers => $borrowernumber,
222     branches => 'CPL',
223     biblio => $biblionumber,
224 };
225 my $substitute = {
226     status => 'overdue',
227 };
228 my $repeat = [
229     {
230         itemcallnumber => 'my callnumber1',
231         barcode        => '1234',
232     },
233     {
234         itemcallnumber => 'my callnumber2',
235         barcode        => '5678',
236     },
237 ];
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,
245 ));
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.
250
251 $branch->{branchname}
252 $branch->{branchaddress1}
253 URL: http://thisisatest.com
254
255 The following item(s) is/are currently $substitute->{status}:
256
257 <item> 1. $repeat->[0]->{itemcallnumber}, Barcode: $repeat->[0]->{barcode} </item>
258 <item> 2. $repeat->[1]->{itemcallnumber}, Barcode: $repeat->[1]->{barcode} </item>
259
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' );
265
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',
274 ));
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' );
277
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>');});
279
280 my $booksellerid = C4::Bookseller::AddBookseller(
281     {
282         name => "my vendor",
283         address1 => "bookseller's address",
284         phone => "0123456",
285         active => 1,
286         deliverytime => 5,
287     },
288     [
289         { name => 'John Smith',  phone => '0123456x1', claimacquisition => 1 },
290         { name => 'Leo Tolstoy', phone => '0123456x2', claimissues => 1 },
291     ]
292 );
293 my $basketno = NewBasket($booksellerid, 1);
294
295 my $budgetid = C4::Budgets::AddBudget({
296     budget_code => "budget_code_test_letters",
297     budget_name => "budget_name_test_letters",
298 });
299
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'),
304     );
305 } else {
306     $bib->append_fields(
307         MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
308     );
309 }
310
311 ($biblionumber, $biblioitemnumber) = AddBiblio($bib, '');
312 my $order = Koha::Acquisition::Order->new(
313     {
314         basketno => $basketno,
315         quantity => 1,
316         biblionumber => $biblionumber,
317         budget_id => $budgetid,
318     }
319 )->insert;
320 my $ordernumber = $order->{ordernumber};
321
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");
329
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 });
334
335 warning_is {
336     $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
337     "Fake sendmail",
338     "SendAlerts is using the mocked sendmail routine";
339
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');
343
344 $dbh->rollback;