# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
-use Test::More tests => 7;
+use Test::More tests => 11;
+use Test::Exception;
use Test::MockObject;
use Test::MockModule;
use Test::Warn;
use t::lib::Mocks;
use t::lib::TestBuilder;
+use C4::Reserves qw( AddReserve );
+use C4::Circulation qw( AddReturn );
use Koha::Database;
use Koha::AuthUtils qw(hash_password);
use Koha::DateUtils;
use Koha::Checkouts;
use Koha::Old::Checkouts;
use Koha::Patrons;
+use Koha::Holds;
use C4::SIP::ILS;
use C4::SIP::ILS::Patron;
$schema->storage->txn_rollback;
};
+subtest 'Checkout V2' => sub {
+ my $schema = Koha::Database->new->schema;
+ $schema->storage->txn_begin;
+ plan tests => 3;
+ $C4::SIP::Sip::protocol_version = 2;
+ test_checkout_v2();
+ $schema->storage->txn_rollback;
+};
+
subtest 'Checkin V2' => sub {
my $schema = Koha::Database->new->schema;
$schema->storage->txn_begin;
- plan tests => 29;
+ plan tests => 35;
$C4::SIP::Sip::protocol_version = 2;
test_checkin_v2();
$schema->storage->txn_rollback;
my $builder = t::lib::TestBuilder->new();
- my $item = $builder->build( { source => 'Item' } );
- my $ils_item = C4::SIP::ILS::Item->new( $item->{barcode} );
+ my $item = $builder->build_sample_item;
+ my $ils_item = C4::SIP::ILS::Item->new( $item->barcode );
my $server = {};
$server->{account}->{item_field}->{code} = 'itemnumber';
$server->{account}->{item_field}->{field} = 'XY';
my $attribute_string = $ils_item->build_additional_item_fields_string( $server );
- is( $attribute_string, "XY$item->{itemnumber}|", 'Attribute field generated correctly with single param' );
+ is( $attribute_string, "XY".$item->itemnumber."|", 'Attribute field generated correctly with single param' );
$server = {};
$server->{account}->{item_field}->[0]->{code} = 'itemnumber';
$server->{account}->{item_field}->[1]->{code} = 'biblionumber';
$server->{account}->{item_field}->[1]->{field} = 'YZ';
$attribute_string = $ils_item->build_additional_item_fields_string( $server );
- is( $attribute_string, "XY$item->{itemnumber}|YZ$item->{biblionumber}|", 'Attribute field generated correctly with multiple params' );
+ is( $attribute_string, sprintf("XY%s|YZ%s|", $item->itemnumber, $item->biblionumber), 'Attribute field generated correctly with multiple params' );
$schema->storage->txn_rollback;
};
+subtest "Test cr_item_field" => sub {
+ plan tests => 2;
+
+ my $builder = t::lib::TestBuilder->new();
+ my $branchcode = $builder->build({ source => 'Branch' })->{branchcode};
+ my $branchcode2 = $builder->build({ source => 'Branch' })->{branchcode};
+ my ( $response, $findpatron );
+ my $mocks = create_mocks( \$response, \$findpatron, \$branchcode );
+
+ # create some data
+ my $patron1 = $builder->build({
+ source => 'Borrower',
+ value => {
+ password => hash_password( PATRON_PW ),
+ },
+ });
+ my $card1 = $patron1->{cardnumber};
+ my $sip_patron1 = C4::SIP::ILS::Patron->new( $card1 );
+ $findpatron = $sip_patron1;
+ my $item_object = $builder->build_sample_item({
+ damaged => 0,
+ withdrawn => 0,
+ itemlost => 0,
+ restricted => 0,
+ homebranch => $branchcode,
+ holdingbranch => $branchcode,
+ });
+
+ my $mockILS = $mocks->{ils};
+ my $server = { ils => $mockILS, account => {} };
+ $mockILS->mock( 'institution', sub { $branchcode; } );
+ $mockILS->mock( 'supports', sub { return; } );
+ $mockILS->mock( 'checkin', sub {
+ shift;
+ return C4::SIP::ILS->checkin(@_);
+ });
+ my $today = dt_from_string;
+
+ my $respcode;
+
+ # Not checked out, toggle option checked_in_ok
+ my $siprequest = CHECKIN . 'N' . 'YYYYMMDDZZZZHHMMSS' .
+ siprequestdate( $today->clone->add( days => 1) ) .
+ FID_INST_ID . $branchcode . '|'.
+ FID_ITEM_ID . $item_object->barcode . '|' .
+ FID_TERMINAL_PWD . 'ignored' . '|';
+ undef $response;
+ my $msg = C4::SIP::Sip::MsgType->new( $siprequest, 0 );
+
+ $server->{account}->{cr_item_field} = 'itemnumber';
+
+ $msg->handle_checkin( $server );
+
+ my $id = $item_object->id;
+ ok( $response =~ m/CR$id/, "Found correct CR field in response");
+
+ $siprequest = ITEM_INFORMATION . 'YYYYMMDDZZZZHHMMSS' .
+ FID_INST_ID . $branchcode . '|'.
+ FID_ITEM_ID . $item_object->barcode . '|' .
+ FID_TERMINAL_PWD . 'ignored' . '|';
+ undef $response;
+ $msg = C4::SIP::Sip::MsgType->new( $siprequest, 0 );
+
+ $mockILS->mock( 'find_item', sub {
+ return C4::SIP::ILS::Item->new( $item_object->barcode );
+ });
+
+ $server->{account}->{cr_item_field} = 'itype';
+
+ $msg->handle_item_information( $server );
+
+ my $itype = $item_object->itype;
+ ok( $response =~ m/CR$itype/, "Found correct CR field in response");
+};
+
+subtest 'Patron info summary > 5 should not crash server' => sub {
+
+ my $schema = Koha::Database->new->schema;
+ $schema->storage->txn_begin;
+
+ plan tests => 22;
+ my $builder = t::lib::TestBuilder->new();
+ my $branchcode = $builder->build({ source => 'Branch' })->{branchcode};
+ my ( $response, $findpatron );
+ my $mocks = create_mocks( \$response, \$findpatron, \$branchcode );
+ my $seen_patron = $builder->build({
+ source => 'Borrower',
+ value => {
+ lastseen => '2001-01-01',
+ password => hash_password( PATRON_PW ),
+ branchcode => $branchcode,
+ },
+ });
+ my $cardnum = $seen_patron->{cardnumber};
+ my $sip_patron = C4::SIP::ILS::Patron->new( $cardnum );
+ $findpatron = $sip_patron;
+
+ my @summaries = (
+ ' ',
+ 'Y ',
+ ' Y ',
+ ' Y ',
+ ' Y ',
+ ' Y ',
+ ' Y ',
+ ' Y ',
+ ' Y ',
+ ' Y ',
+ ' Y',
+ );
+ for my $summary ( @summaries ) {
+ my $siprequest = PATRON_INFO . 'engYYYYMMDDZZZZHHMMSS' . $summary .
+ FID_INST_ID . $branchcode . '|' .
+ FID_PATRON_ID . $cardnum . '|' .
+ FID_PATRON_PWD . PATRON_PW . '|';
+ my $msg = C4::SIP::Sip::MsgType->new( $siprequest, 0 );
+
+ my $server = { ils => $mocks->{ils} };
+ undef $response;
+ $msg->handle_patron_info( $server );
+
+ isnt( $response, undef, 'At least we got a response.' );
+ my $respcode = substr( $response, 0, 2 );
+ is( $respcode, PATRON_INFO_RESP, 'Response code fine' );
+ }
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'SC status tests' => sub {
+
+ my $schema = Koha::Database->new->schema;
+ $schema->storage->txn_begin;
+
+ plan tests => 2;
+
+ my $builder = t::lib::TestBuilder->new();
+ my $branchcode = $builder->build({ source => 'Branch' })->{branchcode};
+ my $sip_user = $builder->build_object({ class => "Koha::Patrons" });
+
+ my ( $response, $findpatron );
+ my $mocks = create_mocks( \$response, \$findpatron, \$branchcode );
+ my $mockILS = $mocks->{ils};
+ $mockILS->mock( 'checkout_ok', sub {1} );
+ $mockILS->mock( 'checkin_ok', sub {1} );
+ $mockILS->mock( 'status_update_ok', sub {1} );
+ $mockILS->mock( 'offline_ok', sub {1} );
+ $mockILS->mock( 'supports', sub {1} );
+ my $server = Test::MockObject->new();
+ $server->mock( 'get_timeout', sub {'100'});
+ $server->{ils} = $mockILS;
+ $server->{sip_username} = $sip_user->userid;
+ $server->{account} = {};
+ $server->{policy} = { renewal =>1,retries=>'000'};
+
+ my $siprequest = SC_STATUS . '0' . '030' . '2.00';
+ my $msg = C4::SIP::Sip::MsgType->new( $siprequest, 0 );
+ $msg->handle_sc_status( $server );
+
+ like( $response, qr/98YYYYYY100000[0-9 ]{19}.00AO|BXYYYYYYYYYYYYYYYY|/, 'At least we got a response.' );
+
+ $sip_user->delete;
+
+ dies_ok{ $msg->handle_sc_status( $server ) } ,"Dies if sip user cannot be found";
+
+};
+
# Here is room for some more subtests
# END of main code
check_field( $respcode, $response, FID_SCREEN_MSG, '.+', 'But we have a screen msg', 'regex' );
}
+sub test_checkout_v2 {
+ my $builder = t::lib::TestBuilder->new();
+ my $branchcode = $builder->build({ source => 'Branch' })->{branchcode};
+ my $branchcode2 = $builder->build({ source => 'Branch' })->{branchcode};
+ my ( $response, $findpatron );
+ my $mocks = create_mocks( \$response, \$findpatron, \$branchcode );
+
+ # create some data
+ my $patron1 = $builder->build({
+ source => 'Borrower',
+ value => {
+ password => hash_password( PATRON_PW ),
+ },
+ });
+ my $card1 = $patron1->{cardnumber};
+ my $sip_patron1 = C4::SIP::ILS::Patron->new( $card1 );
+ $findpatron = $sip_patron1;
+ my $item_object = $builder->build_sample_item({
+ damaged => 0,
+ withdrawn => 0,
+ itemlost => 0,
+ restricted => 0,
+ homebranch => $branchcode,
+ holdingbranch => $branchcode,
+ });
+
+ my $mockILS = $mocks->{ils};
+ my $server = { ils => $mockILS, account => {} };
+ $mockILS->mock( 'institution', sub { $branchcode; } );
+ $mockILS->mock( 'supports', sub { return; } );
+ $mockILS->mock( 'checkout', sub {
+ shift;
+ return C4::SIP::ILS->checkout(@_);
+ });
+ my $today = dt_from_string;
+ t::lib::Mocks::mock_userenv({ branchcode => $branchcode, flags => 1 });
+ t::lib::Mocks::mock_preference( 'CheckPrevCheckout', 'hardyes' );
+
+ my $issue = Koha::Checkout->new({ branchcode => $branchcode, borrowernumber => $patron1->{borrowernumber}, itemnumber => $item_object->itemnumber })->store;
+ my $return = AddReturn($item_object->barcode, $branchcode);
+
+ my $siprequest = CHECKOUT . 'YN' . siprequestdate($today) .
+ siprequestdate( $today->clone->add( days => 1) ) .
+ FID_INST_ID . $branchcode . '|'.
+ FID_PATRON_ID . $sip_patron1->id . '|' .
+ FID_ITEM_ID . $item_object->barcode . '|' .
+ FID_TERMINAL_PWD . 'ignored' . '|';
+ undef $response;
+
+ my $msg = C4::SIP::Sip::MsgType->new( $siprequest, 0 );
+ $server->{account}->{prevcheckout_block_checkout} = 1;
+ $msg->handle_checkout( $server );
+ my $respcode = substr( $response, 0, 2 );
+ check_field( $respcode, $response, FID_SCREEN_MSG, 'This item was previously checked out by you', 'Check screen msg', 'equals' );
+
+ is( Koha::Checkouts->search({ itemnumber => $item_object->id })->count, 0, "Item was not checked out (prevcheckout_block_checkout enabled)");
+
+ $server->{account}->{prevcheckout_block_checkout} = 0;
+ $msg->handle_checkout( $server );
+ $respcode = substr( $response, 0, 2 );
+ is( Koha::Checkouts->search({ itemnumber => $item_object->id })->count, 1, "Item was checked out (prevcheckout_block_checkout disabled)");
+}
+
sub test_checkin_v2 {
my $builder = t::lib::TestBuilder->new();
my $branchcode = $builder->build({ source => 'Branch' })->{branchcode};
undef $response;
$msg = C4::SIP::Sip::MsgType->new( $siprequest, 0 );
warnings_like { $msg->handle_checkin( $server ); }
- [ qr/Duplicate entry/, qr/data corrupted/ ],
+ [ qr/Duplicate entry/, qr/data issues/ ],
'DBIx error on duplicate issue_id';
is( substr($response,2,1), '0', 'OK flag is false when we encounter data corruption in old_issues' );
is( substr($response,5,1), 'Y', 'Alert flag is set' );
is( substr($response,5,1), 'N', 'Alert flag is not set' );
is( Koha::Checkouts->find( $issue->issue_id ), undef,
'Issue record is gone now' );
+
+ # Test account option no_holds_check that prevents items on hold from being checked in via SIP
+ $issue = Koha::Checkout->new({ branchcode => $branchcode, borrowernumber => $patron1->{borrowernumber}, itemnumber => $item_object->itemnumber })->store;
+ is( Koha::Checkouts->search({ itemnumber => $item_object->id })->count, 1, "Item is checked out");
+ Koha::Old::Checkouts->search({ issue_id => $issue->issue_id })->delete;
+ $server->{account}->{holds_block_checkin} = 1;
+ my $reserve_id = AddReserve({
+ branchcode => $branchcode,
+ borrowernumber => $patron1->{borrowernumber},
+ biblionumber => $item_object->biblionumber,
+ priority => 1,
+ });
+ my $hold = Koha::Holds->find( $reserve_id );
+ is( $hold->id, $reserve_id, "Hold was created successfully" );
+ undef $response;
+ $msg = C4::SIP::Sip::MsgType->new( $siprequest, 0 );
+ $msg->handle_checkin( $server );
+ is( substr($response,2,1), '0', 'OK flag is false when we check in an item on hold and we do not allow it' );
+ is( substr($response,5,1), 'Y', 'Alert flag is set' );
+ check_field( $respcode, $response, FID_SCREEN_MSG, 'Item is on hold, please return to circulation desk', 'Screen message is correct' );
+ is( Koha::Checkouts->search({ itemnumber => $item_object->id })->count, 1, "Item was not checked in");
+ $hold->delete();
+ $server->{account}->{holds_block_checkin} = 0;
+
}
sub test_hold_patron_bcode {
my ( $response, $findpatron );
my $mocks = create_mocks( \$response, \$findpatron, \$branchcode );
- my $item = $builder->build({
- source => 'Item',
- value => { damaged => 0, withdrawn => 0, itemlost => 0, restricted => 0, homebranch => $branchcode, holdingbranch => $branchcode },
- });
- my $item_object = Koha::Items->find( $item->{itemnumber} );
+ my $item = $builder->build_sample_item(
+ {
+ library => $branchcode
+ }
+ );
my $server = { ils => $mocks->{ils} };
- my $sip_item = C4::SIP::ILS::Item->new( $item->{barcode} );
+ my $sip_item = C4::SIP::ILS::Item->new( $item->barcode );
is( $sip_item->hold_patron_bcode, q{}, "SIP item with no hold returns empty string" );
( PATRON_STATUS_RESP ) => 37,
( PATRON_INFO_RESP ) => 61,
( CHECKIN_RESP ) => 24,
+ ( CHECKOUT_RESP ) => 24,
}->{$_[0]};
}