From 896b65b10e21485dc20f36a3e877717d5d088cfd Mon Sep 17 00:00:00 2001 From: Matthias Meusburger Date: Tue, 3 Nov 2020 14:49:31 +0000 Subject: [PATCH] Bug 26591: SIP option prevcheckout_block_checkout to block checkout of previously checked-out documents This patchs adds a new SIP option to block checkout of previously checked-out documents: prevcheckout_block_checkout See the CheckPrevCheckout system preference to enable previously checked-out verification in Koha. Test plan: 1) Apply this patch 2) Prove t/db_dependent/SIP/Message.t --- C4/SIP/ILS.pm | 4 +- C4/SIP/ILS/Transaction/Checkout.pm | 3 ++ C4/SIP/Sip/MsgType.pm | 2 +- etc/SIPconfig.xml | 1 + t/db_dependent/SIP/Message.t | 76 +++++++++++++++++++++++++++++++++++++- 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/C4/SIP/ILS.pm b/C4/SIP/ILS.pm index d2a253873b..5ea4ea0546 100644 --- a/C4/SIP/ILS.pm +++ b/C4/SIP/ILS.pm @@ -126,7 +126,7 @@ sub offline_ok { # the response. # sub checkout { - my ( $self, $patron_id, $item_id, $sc_renew, $fee_ack ) = @_; + my ( $self, $patron_id, $item_id, $sc_renew, $fee_ack, $account ) = @_; my ( $patron, $item, $circ ); $circ = C4::SIP::ILS::Transaction::Checkout->new(); @@ -153,7 +153,7 @@ sub checkout { $circ->screen_msg("Item checked out to another patron"); } else { - $circ->do_checkout(); + $circ->do_checkout($account); if ( $circ->ok ) { $debug and warn "circ is ok"; diff --git a/C4/SIP/ILS/Transaction/Checkout.pm b/C4/SIP/ILS/Transaction/Checkout.pm index aabe5e6830..2b804338f4 100644 --- a/C4/SIP/ILS/Transaction/Checkout.pm +++ b/C4/SIP/ILS/Transaction/Checkout.pm @@ -47,11 +47,13 @@ sub new { sub do_checkout { my $self = shift; + my $account = shift; siplog('LOG_DEBUG', "ILS::Transaction::Checkout performing checkout..."); my $shelf = $self->{item}->hold_attached; my $barcode = $self->{item}->id; my $patron = Koha::Patrons->find($self->{patron}->{borrowernumber}); my $overridden_duedate; # usually passed as undef to AddIssue + my $prevcheckout_block_checkout = $account->{prevcheckout_block_checkout}; $debug and warn "do_checkout borrower: . " . $patron->borrowernumber; my ($issuingimpossible, $needsconfirmation) = _can_we_issue($patron, $barcode, C4::Context->preference("AllowItemsOnHoldCheckoutSIP") @@ -95,6 +97,7 @@ sub do_checkout { } } elsif ($confirmation eq 'PREVISSUE') { $self->screen_msg("This item was previously checked out by you"); + $noerror = 0 if ($prevcheckout_block_checkout); last; } elsif ( $confirmation eq 'ADDITIONAL_MATERIALS' ) { $self->screen_msg('Item must be checked out at a circulation desk'); diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm index e5c2b9edbc..aa8cdfcf1e 100644 --- a/C4/SIP/Sip/MsgType.pm +++ b/C4/SIP/Sip/MsgType.pm @@ -533,7 +533,7 @@ sub handle_checkout { # Does the transaction date really matter for items that are # checkout out while the terminal is online? I'm guessing 'no' - $status = $ils->checkout( $patron_id, $item_id, $sc_renewal_policy, $fee_ack ); + $status = $ils->checkout( $patron_id, $item_id, $sc_renewal_policy, $fee_ack, $account ); } $item = $status->item; diff --git a/etc/SIPconfig.xml b/etc/SIPconfig.xml index 43f34ee05b..8cec48c9f6 100644 --- a/etc/SIPconfig.xml +++ b/etc/SIPconfig.xml @@ -61,6 +61,7 @@ av_field_template="[% accountline.description %] [% accountline.amountoutstanding | format('%.2f') %]" hide_fields="BD,BE,BF,PB" register_id='' + prevcheckout_block_checkout="0" holds_block_checkin="0"> diff --git a/t/db_dependent/SIP/Message.t b/t/db_dependent/SIP/Message.t index 31baf30e3a..73da5c0226 100755 --- a/t/db_dependent/SIP/Message.t +++ b/t/db_dependent/SIP/Message.t @@ -21,7 +21,7 @@ # along with Koha; if not, see . use Modern::Perl; -use Test::More tests => 9; +use Test::More tests => 10; use Test::MockObject; use Test::MockModule; use Test::Warn; @@ -30,6 +30,7 @@ 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; @@ -66,6 +67,15 @@ subtest 'Testing Patron Info Request V2' => sub { $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; @@ -486,6 +496,69 @@ sub test_request_patron_info_v2 { 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}; @@ -753,5 +826,6 @@ sub fixed_length { #length of fixed fields including response code ( PATRON_STATUS_RESP ) => 37, ( PATRON_INFO_RESP ) => 61, ( CHECKIN_RESP ) => 24, + ( CHECKOUT_RESP ) => 24, }->{$_[0]}; } -- 2.11.0