From e1295732794e77b9634aa81c5e21cfd59fd6f67a Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Tue, 11 May 2021 07:51:45 -0400 Subject: [PATCH] Bug 26370: Add ability to disable demagnetizing items via SIP2 for arbitrary patron categories Some libraries have certain patron categories that can only do in house checkouts via SIP self check machines. In these cases, the items should not be demagnetized since the items cannot leave the library. Test Plan: 1) Apply this patch 2) prove t/db_dependent/SIP/Message.t --- C4/SIP/Sip/MsgType.pm | 27 ++++++- t/db_dependent/SIP/Message.t | 151 ++++++++++++++++++++++++++++++++++- 2 files changed, 175 insertions(+), 3 deletions(-) diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm index 1e38f29a68..5d674be45d 100644 --- a/C4/SIP/Sip/MsgType.pm +++ b/C4/SIP/Sip/MsgType.pm @@ -552,7 +552,7 @@ sub handle_checkout { } # We never return the obsolete 'U' value for 'desensitize' - $resp .= sipbool( $status->desensitize ); + $resp .= sipbool( desensitize( { status => $status, patron => $patron, server => $server } ) ); $resp .= timestamp; # Now for the variable fields @@ -1458,7 +1458,7 @@ sub handle_renew { } else { $resp .= 'U'; } - $resp .= sipbool( $status->desensitize ); + $resp .= sipbool( desensitize( { status => $status, patron => $patron, server => $server } ) ); $resp .= timestamp; $resp .= add_field( FID_PATRON_ID, $patron->id, $server ); $resp .= add_field( FID_ITEM_ID, $item->id, $server ); @@ -1701,6 +1701,29 @@ sub api_auth { return $status; } +sub desensitize { + my ($params) = @_; + + my $status = $params->{status}; + my $desensitize = $status->desensitize(); + + # If desenstize is already false, no need to do anything + return unless $desensitize; + + my $patron = $params->{patron}; + my $server = $params->{server}; + + my $patron_categories = $server->{account}->{never_demagnitize}; + + # If no patron categories are set for never desensitize, no need to do anything + return $desensitize unless $patron_categories; + + my $patron_category = $patron->ptype(); + my @patron_categories = split( /,/, $patron_categories ); + + return !grep( /^$patron_category$/, @patron_categories ); +} + 1; __END__ diff --git a/t/db_dependent/SIP/Message.t b/t/db_dependent/SIP/Message.t index e032b7964e..e10b1bffc0 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 => 10; +use Test::More tests => 12; use Test::MockObject; use Test::MockModule; use Test::Warn; @@ -76,6 +76,24 @@ subtest 'Checkout V2' => sub { $schema->storage->txn_rollback; }; +subtest 'Test checkout desensitize' => sub { + my $schema = Koha::Database->new->schema; + $schema->storage->txn_begin; + plan tests => 3; + $C4::SIP::Sip::protocol_version = 2; + test_checkout_desensitize(); + $schema->storage->txn_rollback; +}; + +subtest 'Test renew desensitize' => sub { + my $schema = Koha::Database->new->schema; + $schema->storage->txn_begin; + plan tests => 3; + $C4::SIP::Sip::protocol_version = 2; + test_renew_desensitize(); + $schema->storage->txn_rollback; +}; + subtest 'Checkin V2' => sub { my $schema = Koha::Database->new->schema; $schema->storage->txn_begin; @@ -793,6 +811,137 @@ sub test_hold_patron_bcode { is( $resp, q{}, "maybe_add returns empty string for SIP item with no hold returns empty string" ); } +sub test_checkout_desensitize { + my $builder = t::lib::TestBuilder->new(); + my $branchcode = $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 ); + my $patron_category = $sip_patron1->ptype(); + $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 $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}->{never_demagnitize} = "A,$patron_category,Z"; + $msg->handle_checkout( $server ); + my $respcode = substr( $response, 5, 1 ); + is( $respcode, 'N', "Desensitize flag was not set for patron category in never_demagnitize" ); + + undef $response; + $server->{account}->{never_demagnitize} = "A,B,C"; + $msg->handle_checkout( $server ); + $respcode = substr( $response, 5, 1 ); + is( $respcode, 'Y', "Desensitize flag was set for patron category not in never_demagnitize" ); + + undef $response; + $server->{account}->{never_demagnitize} = ""; + $msg->handle_checkout( $server ); + $respcode = substr( $response, 5, 1 ); + is( $respcode, 'Y', "Desensitize flag was set for empty never_demagnitize" ); +} + +sub test_renew_desensitize { + my $builder = t::lib::TestBuilder->new(); + my $branchcode = $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 ); + my $patron_category = $sip_patron1->ptype(); + $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 }); + + my $issue = Koha::Checkout->new({ branchcode => $branchcode, borrowernumber => $patron1->{borrowernumber}, itemnumber => $item_object->itemnumber })->store; + + my $siprequest = RENEW . '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}->{never_demagnitize} = "A,$patron_category,Z"; + $msg->handle_checkout( $server ); + my $respcode = substr( $response, 5, 1 ); + is( $respcode, 'N', "Desensitize flag was not set for patron category in never_demagnitize" ); + + undef $response; + $server->{account}->{never_demagnitize} = "A,B,C"; + $msg->handle_checkout( $server ); + $respcode = substr( $response, 5, 1 ); + is( $respcode, 'Y', "Desensitize flag was set for patron category not in never_demagnitize" ); + + undef $response; + $server->{account}->{never_demagnitize} = ""; + $msg->handle_checkout( $server ); + $respcode = substr( $response, 5, 1 ); + is( $respcode, 'Y', "Desensitize flag was set for empty never_demagnitize" ); +} + # Helper routines sub create_mocks { -- 2.24.3 (Apple Git-128)