+$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>>.');});
+$prepared_letter = GetPreparedLetter((
+ module => 'test_date',
+ branchcode => '',
+ letter_code => 'test_date',
+ tables => $tables,
+ substitute => $substitute,
+ repeat => $repeat,
+));
+is( $prepared_letter->{content}, q|This one only contains the date: | . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test 1' );
+
+$dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp | dateonly>>.' WHERE code = 'test_date';});
+$prepared_letter = GetPreparedLetter((
+ module => 'test_date',
+ branchcode => '',
+ letter_code => 'test_date',
+ tables => $tables,
+ substitute => $substitute,
+ repeat => $repeat,
+));
+is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test 2' );
+
+$dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp|dateonly >>.' WHERE code = 'test_date';});
+$prepared_letter = GetPreparedLetter((
+ module => 'test_date',
+ branchcode => '',
+ letter_code => 'test_date',
+ tables => $tables,
+ substitute => $substitute,
+ repeat => $repeat,
+));
+is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $date, dateonly => 1 }) . q|.|, 'dateonly test 3' );
+
+t::lib::Mocks::mock_preference( 'TimeFormat', '12hr' );
+my $yesterday_night = $date->clone->add( days => -1 )->set_hour(22);
+$dbh->do(q|UPDATE biblio SET timestamp = ? WHERE biblionumber = ?|, undef, $yesterday_night, $biblionumber );
+$dbh->do(q{UPDATE letter SET content = 'And also this one:<<timestamp>>.' WHERE code = 'test_date';});
+$prepared_letter = GetPreparedLetter((
+ module => 'test_date',
+ branchcode => '',
+ letter_code => 'test_date',
+ tables => $tables,
+ substitute => $substitute,
+ repeat => $repeat,
+));
+is( $prepared_letter->{content}, q|And also this one:| . output_pref({ dt => $yesterday_night }) . q|.|, 'dateonly test 3' );
+
+$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>');});
+$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>');});
+
+# Test that _parseletter doesn't modify its parameters bug 15429
+{
+ my $values = { dateexpiry => '2015-12-13', };
+ C4::Letters::_parseletter($prepared_letter, 'borrowers', $values);
+ is( $values->{dateexpiry}, '2015-12-13', "_parseletter doesn't modify its parameters" );
+}
+
+my $bookseller = Koha::Acquisition::Bookseller->new(
+ {
+ name => "my vendor",
+ address1 => "bookseller's address",
+ phone => "0123456",
+ active => 1,
+ deliverytime => 5,
+ }
+)->store;
+my $booksellerid = $bookseller->id;
+
+Koha::Acquisition::Bookseller::Contact->new( { name => 'John Smith', phone => '0123456x1', claimacquisition => 1, orderacquisition => 1, booksellerid => $booksellerid } )->store;
+Koha::Acquisition::Bookseller::Contact->new( { name => 'Leo Tolstoy', phone => '0123456x2', claimissues => 1, booksellerid => $booksellerid } )->store;
+my $basketno = NewBasket($booksellerid, 1);
+
+my $budgetid = C4::Budgets::AddBudget({
+ budget_code => "budget_code_test_letters",
+ budget_name => "budget_name_test_letters",
+});
+
+my $bib = MARC::Record->new();
+if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
+ $bib->append_fields(
+ MARC::Field->new('200', ' ', ' ', a => 'Silence in the library'),
+ );
+} else {
+ $bib->append_fields(
+ MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
+ );
+}
+
+($biblionumber, $biblioitemnumber) = AddBiblio($bib, '');
+my $order = Koha::Acquisition::Order->new(
+ {
+ basketno => $basketno,
+ quantity => 1,
+ biblionumber => $biblionumber,
+ budget_id => $budgetid,
+ }
+)->store;
+my $ordernumber = $order->ordernumber;
+
+C4::Acquisition::CloseBasket( $basketno );
+my $err;
+warning_like {
+ $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
+ qr/^Bookseller .* without emails at/,
+ "SendAlerts prints a warning";
+is($err->{'error'}, 'no_email', "Trying to send an alert when there's no e-mail results in an error");
+
+$bookseller = Koha::Acquisition::Booksellers->find( $booksellerid );
+$bookseller->contacts->next->email('testemail@mydomain.com')->store;
+
+# Ensure that the preference 'LetterLog' is set to logging
+t::lib::Mocks::mock_preference( 'LetterLog', 'on' );
+
+# SendAlerts needs branchemail or KohaAdminEmailAddress as sender
+C4::Context->_new_userenv('DUMMY');
+C4::Context->set_userenv( 0, 0, 0, 'firstname', 'surname', $library->{branchcode}, 'My Library', 0, '', '');
+t::lib::Mocks::mock_preference( 'KohaAdminEmailAddress', 'library@domain.com' );
+
+{
+warning_is {
+ $err = SendAlerts( 'orderacquisition', $basketno , 'TESTACQORDER' ) }
+ "Fake sendmail",
+ "SendAlerts is using the mocked sendmail routine (orderacquisition)";
+is($err, 1, "Successfully sent order.");
+is($mail{'To'}, 'testemail@mydomain.com', "mailto correct in sent order");
+is($mail{'Message'}, 'my vendor|John Smith|Ordernumber ' . $ordernumber . ' (Silence in the library) (1 ordered)', 'Order notice text constructed successfully');
+
+$dbh->do(q{DELETE FROM letter WHERE code = 'TESTACQORDER';});
+warning_like {
+ $err = SendAlerts( 'orderacquisition', $basketno , 'TESTACQORDER' ) }
+ qr/No orderacquisition TESTACQORDER letter transported by email/,
+ "GetPreparedLetter warns about missing notice template";
+is($err->{'error'}, 'no_letter', "No TESTACQORDER letter was defined.");
+}
+
+{
+warning_is {
+ $err = SendAlerts( 'claimacquisition', [ $ordernumber ], 'TESTACQCLAIM' ) }
+ "Fake sendmail",
+ "SendAlerts is using the mocked sendmail routine";
+
+is($err, 1, "Successfully sent claim");
+is($mail{'To'}, 'testemail@mydomain.com', "mailto correct in sent claim");
+is($mail{'Message'}, 'my vendor|John Smith|Ordernumber ' . $ordernumber . ' (Silence in the library) (1 ordered)', 'Claim notice text constructed successfully');
+}
+
+{
+use C4::Serials;
+
+my $notes = 'notes';
+my $internalnotes = 'intnotes';
+$dbh->do(q|UPDATE subscription_numberpatterns SET numberingmethod='No. {X}' WHERE id=1|);
+my $subscriptionid = NewSubscription(
+ undef, "", undef, undef, undef, $biblionumber,
+ '2013-01-01', 1, undef, undef, undef,
+ undef, undef, undef, undef, undef, undef,
+ 1, $notes,undef, '2013-01-01', undef, 1,
+ undef, undef, 0, $internalnotes, 0,
+ undef, undef, 0, undef, '2013-12-31', 0
+);
+$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>>');});
+my ($serials_count, @serials) = GetSerials($subscriptionid);
+my $serial = $serials[0];
+
+my $borrowernumber = AddMember(
+ firstname => 'John',
+ surname => 'Smith',
+ categorycode => $patron_category,
+ branchcode => $library->{branchcode},
+ dateofbirth => $date,
+ email => 'john.smith@test.de',
+);
+my $alert_id = C4::Letters::addalert($borrowernumber, 'issue', $subscriptionid);
+
+
+my $err2;
+warning_is {
+$err2 = SendAlerts( 'issue', $serial->{serialid}, 'RLIST' ) }
+ "Fake sendmail",
+ "SendAlerts is using the mocked sendmail routine";
+is($err2, 1, "Successfully sent serial notification");
+is($mail{'To'}, 'john.smith@test.de', "mailto correct in sent serial notification");
+is($mail{'Message'}, 'Silence in the library,'.$subscriptionid.',No. 0', 'Serial notification text constructed successfully');
+}
+
+subtest 'GetPreparedLetter' => sub {
+ plan tests => 4;
+
+ Koha::Notice::Template->new(
+ {
+ module => 'test',
+ code => 'test',
+ branchcode => '',
+ message_transport_type => 'email'
+ }
+ )->store;
+ my $letter;
+ warning_like {
+ $letter = C4::Letters::GetPreparedLetter(
+ module => 'test',
+ letter_code => 'test',
+ );
+ }
+ qr{^ERROR: nothing to substitute},
+'GetPreparedLetter should warn if tables, substiture and repeat are not set';
+ is( $letter, undef,
+'No letter should be returned by GetPreparedLetter if something went wrong'
+ );
+
+ warning_like {
+ $letter = C4::Letters::GetPreparedLetter(
+ module => 'test',
+ letter_code => 'test',
+ substitute => {}
+ );
+ }
+ qr{^ERROR: nothing to substitute},
+'GetPreparedLetter should warn if tables, substiture and repeat are not set, even if the key is passed';
+ is( $letter, undef,
+'No letter should be returned by GetPreparedLetter if something went wrong'
+ );
+
+};
+
+
+
+subtest 'TranslateNotices' => sub {
+ plan tests => 4;
+
+ t::lib::Mocks::mock_preference( 'TranslateNotices', '1' );
+
+ $dbh->do(
+ q|
+ INSERT INTO letter (module, code, branchcode, name, title, content, message_transport_type, lang) VALUES
+ ('test', 'code', '', 'test', 'a test', 'just a test', 'email', 'default'),
+ ('test', 'code', '', 'test', 'una prueba', 'solo una prueba', 'email', 'es-ES');
+ | );
+ my $substitute = {};
+ my $letter = C4::Letters::GetPreparedLetter(
+ module => 'test',
+ tables => $tables,
+ letter_code => 'code',
+ message_transport_type => 'email',
+ substitute => $substitute,
+ );
+ is(
+ $letter->{title},
+ 'a test',
+ 'GetPreparedLetter should return the default one if the lang parameter is not provided'
+ );
+
+ $letter = C4::Letters::GetPreparedLetter(
+ module => 'test',
+ tables => $tables,
+ letter_code => 'code',
+ message_transport_type => 'email',
+ substitute => $substitute,
+ lang => 'es-ES',
+ );
+ is( $letter->{title}, 'una prueba',
+ 'GetPreparedLetter should return the required notice if it exists' );
+
+ $letter = C4::Letters::GetPreparedLetter(
+ module => 'test',
+ tables => $tables,
+ letter_code => 'code',
+ message_transport_type => 'email',
+ substitute => $substitute,
+ lang => 'fr-FR',
+ );
+ is(
+ $letter->{title},
+ 'a test',
+ 'GetPreparedLetter should return the default notice if the one required does not exist'
+ );
+
+ t::lib::Mocks::mock_preference( 'TranslateNotices', '' );
+
+ $letter = C4::Letters::GetPreparedLetter(
+ module => 'test',
+ tables => $tables,
+ letter_code => 'code',
+ message_transport_type => 'email',
+ substitute => $substitute,
+ lang => 'es-ES',
+ );
+ is( $letter->{title}, 'a test',
+ 'GetPreparedLetter should return the default notice if pref disabled but additional language exists' );
+
+};
+
+subtest 'SendQueuedMessages' => sub {
+
+ plan tests => 3;
+ t::lib::Mocks::mock_preference( 'SMSSendDriver', 'Email' );
+ my $patron = Koha::Patrons->find($borrowernumber);
+ $dbh->do(q|
+ INSERT INTO message_queue(borrowernumber, subject, content, message_transport_type, status, letter_code)
+ VALUES (?, 'subject', 'content', 'sms', 'pending', 'just_a_code')
+ |, undef, $borrowernumber
+ );
+ eval { C4::Letters::SendQueuedMessages(); };
+ is( $@, '', 'SendQueuedMessages should not explode if the patron does not have a sms provider set' );
+
+ my $sms_pro = $builder->build_object({ class => 'Koha::SMS::Providers', value => { domain => 'kidclamp.rocks' } });
+ ModMember( borrowernumber => $borrowernumber, smsalertnumber => '5555555555', sms_provider_id => $sms_pro->id() );
+ $message_id = C4::Letters::EnqueueLetter($my_message); #using datas set around line 95 and forward
+ C4::Letters::SendQueuedMessages();
+ my $sms_message_address = $schema->resultset('MessageQueue')->search({
+ borrowernumber => $borrowernumber,
+ status => 'sent'
+ })->next()->to_address();
+ is( $sms_message_address, '5555555555@kidclamp.rocks', 'SendQueuedMessages populates the to address correctly for SMS by email when to_address not set' );
+ $schema->resultset('MessageQueue')->search({borrowernumber => $borrowernumber,status => 'sent'})->delete(); #clear borrower queue
+ $my_message->{to_address} = 'fixme@kidclamp.iswrong';
+ $message_id = C4::Letters::EnqueueLetter($my_message);
+ C4::Letters::SendQueuedMessages();
+ $sms_message_address = $schema->resultset('MessageQueue')->search({
+ borrowernumber => $borrowernumber,
+ status => 'sent'
+ })->next()->to_address();
+ is( $sms_message_address, '5555555555@kidclamp.rocks', 'SendQueuedMessages populates the to address correctly for SMS by email when to_address is set incorrectly' );
+
+};
+
+subtest 'get_item_content' => sub {
+ plan tests => 2;
+
+ t::lib::Mocks::mock_preference('dateformat', 'metric');
+ t::lib::Mocks::mock_preference('timeformat', '24hr');
+ my @items = (
+ {date_due => '2041-01-01 12:34', title => 'a first title', barcode => 'a_first_barcode', author => 'a_first_author', itemnumber => 1 },
+ {date_due => '2042-01-02 23:45', title => 'a second title', barcode => 'a_second_barcode', author => 'a_second_author', itemnumber => 2 },
+ );
+ my @item_content_fields = qw( date_due title barcode author itemnumber );
+
+ my $items_content;
+ for my $item ( @items ) {
+ $items_content .= C4::Letters::get_item_content( { item => $item, item_content_fields => \@item_content_fields } );
+ }
+
+ my $expected_items_content = <<EOF;
+01/01/2041 12:34\ta first title\ta_first_barcode\ta_first_author\t1
+02/01/2042 23:45\ta second title\ta_second_barcode\ta_second_author\t2
+EOF
+ is( $items_content, $expected_items_content, 'get_item_content should return correct items info with time (default)' );
+
+
+ $items_content = q||;
+ for my $item ( @items ) {
+ $items_content .= C4::Letters::get_item_content( { item => $item, item_content_fields => \@item_content_fields, dateonly => 1, } );
+ }
+
+ $expected_items_content = <<EOF;
+01/01/2041\ta first title\ta_first_barcode\ta_first_author\t1
+02/01/2042\ta second title\ta_second_barcode\ta_second_author\t2
+EOF
+ is( $items_content, $expected_items_content, 'get_item_content should return correct items info without time (if dateonly => 1)' );
+};
+
+subtest 'Test limit parameter for SendQueuedMessages' => sub {
+ plan tests => 3;
+
+ my $dbh = C4::Context->dbh;
+
+ my $borrowernumber = AddMember(
+ firstname => 'Jane',
+ surname => 'Smith',
+ categorycode => $patron_category,
+ branchcode => $library->{branchcode},
+ dateofbirth => $date,
+ smsalertnumber => undef,
+ );
+
+ $dbh->do(q|DELETE FROM message_queue|);
+ $my_message = {
+ 'letter' => {
+ 'content' => 'a message',
+ 'metadata' => 'metadata',
+ 'code' => 'TEST_MESSAGE',
+ 'content_type' => 'text/plain',
+ 'title' => 'message title'
+ },
+ 'borrowernumber' => $borrowernumber,
+ 'to_address' => undef,
+ 'message_transport_type' => 'sms',
+ 'from_address' => 'from@example.com'
+ };
+ C4::Letters::EnqueueLetter($my_message);
+ C4::Letters::EnqueueLetter($my_message);
+ C4::Letters::EnqueueLetter($my_message);
+ C4::Letters::EnqueueLetter($my_message);
+ C4::Letters::EnqueueLetter($my_message);
+ my $messages_processed = C4::Letters::SendQueuedMessages( { limit => 1 } );
+ is( $messages_processed, 1,
+ 'Processed 1 message with limit of 1 and 5 unprocessed messages' );
+ $messages_processed = C4::Letters::SendQueuedMessages( { limit => 2 } );
+ is( $messages_processed, 2,
+ 'Processed 2 message with limit of 2 and 4 unprocessed messages' );
+ $messages_processed = C4::Letters::SendQueuedMessages( { limit => 3 } );
+ is( $messages_processed, 2,
+ 'Processed 2 message with limit of 3 and 2 unprocessed messages' );
+};