Koha/t/db_dependent/Patron/Borrower_PrevCheckout.t
Jonathan Druart 9e249435f9 Bug 28931: Use EXPORT_OK from Koha::DateUtils
It has been missed on bug 17600.

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Adjusted commit title.

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
2021-10-07 11:01:05 +02:00

486 lines
16 KiB
Perl
Executable file

#!/usr/bin/perl
use Modern::Perl;
use C4::Members;
use C4::Circulation qw( AddIssue AddReturn CanBookBeIssued );
use Koha::Database;
use Koha::DateUtils qw( dt_from_string );
use Koha::Patrons;
use Test::More tests => 61;
use_ok('Koha::Patron');
use t::lib::TestBuilder;
use t::lib::Mocks;
my $schema = Koha::Database->new->schema;
$schema->storage->txn_begin;
my $builder = t::lib::TestBuilder->new;
my $yesCatCode = $builder->build({
source => 'Category',
value => {
categorycode => 'yesCat',
checkprevcheckout => 'yes',
},
});
my $noCatCode = $builder->build({
source => 'Category',
value => {
categorycode => 'noCat',
checkprevcheckout => 'no',
},
});
my $inheritCatCode = $builder->build({
source => 'Category',
value => {
categorycode => 'inheritCat',
checkprevcheckout => 'inherit',
},
});
# Create context for some tests late on in the file.
my $library = $builder->build({ source => 'Branch' });
my $staff = $builder->build({source => 'Borrower'});
t::lib::Mocks::mock_userenv({ branchcode => $library->{branchcode} });
# wants_check_for_previous_checkout
# We expect the following result matrix:
#
# (1/0 indicates the return value of WantsCheckPrevCheckout; i.e. 1 says we
# should check whether the item was previously issued)
#
# | System Preference | hardyes | softyes | softno | hardno |
# |-------------------+-----------------------------------+-----------------------------------+-----------------------------------+-----------------------------------|
# | Category Setting | yes | no | inherit | yes | no | inherit | yes | no | inherit | yes | no | inherit |
# |-------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------|
# | Patron Setting | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i | y | n | i |
# |-------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
# | Expected Result | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
my $mappings = [
{
syspref => 'hardyes',
categories => [
{
setting => 'yes',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 1},
{setting => 'inherit', result => 1},
],
},
{
setting => 'no',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 1},
{setting => 'inherit', result => 1},
],
},
{
setting => 'inherit',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 1},
{setting => 'inherit', result => 1},
],
},
],
},
{
syspref => 'softyes',
categories => [
{
setting => 'yes',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 0},
{setting => 'inherit', result => 1},
],
},
{
setting => 'no',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 0},
{setting => 'inherit', result => 0},
],
},
{
setting => 'inherit',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 0},
{setting => 'inherit', result => 1},
],
},
],
},
{
syspref => 'softno',
categories => [
{
setting => 'yes',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 0},
{setting => 'inherit', result => 1},
],
},
{
setting => 'no',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 0},
{setting => 'inherit', result => 0},
],
},
{
setting => 'inherit',
patrons => [
{setting => 'yes', result => 1},
{setting => 'no', result => 0},
{setting => 'inherit', result => 0},
],
},
],
},
{
syspref => 'hardno',
categories => [
{
setting => 'yes',
patrons => [
{setting => 'yes', result => 0},
{setting => 'no', result => 0},
{setting => 'inherit', result => 0},
],
},
{
setting => 'no',
patrons => [
{setting => 'yes', result => 0},
{setting => 'no', result => 0},
{setting => 'inherit', result => 0},
],
},
{
setting => 'inherit',
patrons => [
{setting => 'yes', result => 0},
{setting => 'no', result => 0},
{setting => 'inherit', result => 0},
],
},
],
},
];
map {
my $syspref = $_->{syspref};
t::lib::Mocks::mock_preference('checkprevcheckout', $syspref);
map {
my $code = $_->{setting} . 'Cat';
map {
my $kpatron = $builder->build({
source => 'Borrower',
value => {
checkprevcheckout => $_->{setting},
categorycode => $code,
},
});
my $patron = Koha::Patrons->find($kpatron->{borrowernumber});
is(
$patron->wants_check_for_previous_checkout, $_->{result},
"Predicate with syspref " . $syspref . ", cat " . $code
. ", patron " . $_->{setting}
);
} @{$_->{patrons}};
} @{$_->{categories}};
} @{$mappings};
# do_check_for_previous_checkout
# We want to test:
# - DESCRIPTION [RETURNVALUE (0/1)]
## PreIssue (sanity checks)
# - Item, patron [0]
# - Diff item, same bib, same patron [0]
# - Diff item, diff bib, same patron [0]
# - Same item, diff patron [0]
# - Diff item, same bib, diff patron [0]
# - Diff item, diff bib, diff patron [0]
## PostIssue
# - Same item, same patron [1]
# - Diff item, same bib, same patron [1]
# - Diff item, diff bib, same patron [0]
# - Same item, diff patron [0]
# - Diff item, same bib, diff patron [0]
# - Diff item, diff bib, diff patron [0]
## PostReturn
# - Same item, same patron [1]
# - Diff item, same bib, same patron [1]
# - Diff item, diff bib, same patron [0]
# - Same item, diff patron [0]
# - Diff item, same bib, diff patron [0]
# - Diff item, diff bib, diff patron [0]
# Requirements:
# $patron, $different_patron, $items (same bib number), $different_item
my $patron = $builder->build({source => 'Borrower'});
my $patron_d = $builder->build({source => 'Borrower'});
my $biblio = $builder->build_sample_biblio;
$biblio->serial(0)->store;
my $item_1 = $builder->build_sample_item({biblionumber => $biblio->biblionumber})->unblessed;
my $item_2 = $builder->build_sample_item({biblionumber => $biblio->biblionumber})->unblessed;
my $item_d = $builder->build_sample_item->unblessed;
## Testing Sub
sub test_it {
my ($mapping, $stage) = @_;
map {
my $patron = Koha::Patrons->find($_->{patron}->{borrowernumber});
is(
$patron->do_check_for_previous_checkout($_->{item}),
$_->{result}, $stage . ": " . $_->{msg}
);
} @{$mapping};
};
## Initial Mappings
my $cpvmappings = [
{
msg => "Item, patron [0]",
item => $item_1,
patron => $patron,
result => 0,
},
{
msg => "Diff item, same bib, same patron [0]",
item => $item_2,
patron => $patron,
result => 0,
},
{
msg => "Diff item, diff bib, same patron [0]",
item => $item_d,
patron => $patron,
result => 0,
},
{
msg => "Same item, diff patron [0]",
item => $item_1,
patron => $patron_d,
result => 0,
},
{
msg => "Diff item, same bib, diff patron [0]",
item => $item_2,
patron => $patron_d,
result => 0,
},
{
msg => "Diff item, diff bib, diff patron [0]",
item => $item_d,
patron => $patron_d,
result => 0,
},
];
test_it($cpvmappings, "PreIssue");
# Issue item_1 to $patron:
my $patron_get_mem = Koha::Patrons->find( $patron->{borrowernumber} )->unblessed;
BAIL_OUT("Issue failed")
unless AddIssue($patron_get_mem, $item_1->{barcode});
# Then test:
my $cpvPmappings = [
{
msg => "Same item, same patron [1]",
item => $item_1,
patron => $patron,
result => 1,
},
{
msg => "Diff item, same bib, same patron [1]",
item => $item_2,
patron => $patron,
result => 1,
},
{
msg => "Diff item, diff bib, same patron [0]",
item => $item_d,
patron => $patron,
result => 0,
},
{
msg => "Same item, diff patron [0]",
item => $item_1,
patron => $patron_d,
result => 0,
},
{
msg => "Diff item, same bib, diff patron [0]",
item => $item_2,
patron => $patron_d,
result => 0,
},
{
msg => "Diff item, diff bib, diff patron [0]",
item => $item_d,
patron => $patron_d,
result => 0,
},
];
test_it($cpvPmappings, "PostIssue");
# Return item_1 from patron:
BAIL_OUT("Return Failed") unless AddReturn($item_1->{barcode}, $patron->{branchcode});
# Then:
test_it($cpvPmappings, "PostReturn");
# Finally test C4::Circulation::CanBookBeIssued
# We have already tested ->wants_check_for_previous_checkout and
# ->do_check_for_previous_checkout, so all that remains to be tested is
# whetherthe different combinational outcomes of the above return values in
# CanBookBeIssued result in the approriate $needsconfirmation.
# We want to test:
# - DESCRIPTION [RETURNVALUE (0/1)]
# - patron, !wants_check_for_previous_checkout, !do_check_for_previous_checkout
# [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
# - patron, wants_check_for_previous_checkout, !do_check_for_previous_checkout
# [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
# - patron, !wants_check_for_previous_checkout, do_check_for_previous_checkout
# [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
# - patron, wants_check_for_previous_checkout, do_check_for_previous_checkout
# [!$issuingimpossible,$needsconfirmation->{PREVISSUE}]
# Needs:
# - $patron
# - $item objects (one not issued, another prevIssued)
# - $checkprevcheckout pref (first hardno, then hardyes)
# Our Patron
my $patron_category = $builder->build({ source => 'Category', value => { category_type => 'P', enrolmentfee => 0 } });
my $CBBI_patron = $builder->build({source => 'Borrower', value => { categorycode => $patron_category->{categorycode} }});
$patron = Koha::Patrons->find( $CBBI_patron->{borrowernumber} );
# Our Items
my $new_item = $builder->build_sample_item->unblessed;
my $prev_item = $builder->build_sample_item->unblessed;
# Second is Checked Out
BAIL_OUT("CanBookBeIssued Issue failed")
unless AddIssue($patron->unblessed, $prev_item->{barcode});
# Mappings
my $CBBI_mappings = [
{
syspref => 'hardno',
item => $new_item,
result => undef,
msg => "patron, !wants_check_for_previous_checkout, !do_check_for_previous_checkout"
},
{
syspref => 'hardyes',
item => $new_item,
result => undef,
msg => "patron, wants_check_for_previous_checkout, !do_check_for_previous_checkout"
},
{
syspref => 'hardno',
item => $prev_item,
result => undef,
msg => "patron, !wants_check_for_previous_checkout, do_check_for_previous_checkout"
},
{
syspref => 'hardyes',
item => $prev_item,
result => 1,
msg => "patron, wants_check_for_previous_checkout, do_check_for_previous_checkout"
},
];
# Tests
map {
t::lib::Mocks::mock_preference('checkprevcheckout', $_->{syspref});
my ( $issuingimpossible, $needsconfirmation ) =
C4::Circulation::CanBookBeIssued(
$patron, $_->{item}->{barcode}
);
is($needsconfirmation->{PREVISSUE}, $_->{result}, $_->{msg});
} @{$CBBI_mappings};
$schema->storage->txn_rollback;
subtest 'Check previous checkouts for serial' => sub {
plan tests => 2;
$schema->storage->txn_begin;
my $library = $builder->build_object({ class => 'Koha::Libraries'});
my $patron = $builder->build_object({
class => 'Koha::Patrons',
value => {
branchcode => $library->branchcode
}
});
t::lib::Mocks::mock_userenv({ patron => $patron });
my $biblio = $builder->build_sample_biblio;
$biblio->serial(1)->store;
my $item1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
my $item2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
AddIssue($patron->unblessed, $item1->barcode);
is($patron->do_check_for_previous_checkout($item1->unblessed), 1, 'Check only one item if bibliographic record is serial');
is($patron->do_check_for_previous_checkout($item2->unblessed), 0, 'Check only one item if bibliographic record is serial');
$schema->storage->txn_rollback;
};
subtest 'Check previous checkouts with delay' => sub {
plan tests => 3;
$schema->storage->txn_begin;
my $library = $builder->build_object({ class => 'Koha::Libraries'});
my $biblio = $builder->build_sample_biblio;
my $patron = $builder->build({source => 'Borrower'});
my $item_object = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
my $issue = Koha::Checkout->new({ branchcode => $library->branchcode, borrowernumber => $patron->{borrowernumber}, itemnumber => $item_object->itemnumber })->store;
my $returndate = dt_from_string()->subtract( days => 3 );
my $return = AddReturn($item_object->barcode, $library->branchcode, undef, $returndate);
t::lib::Mocks::mock_preference('checkprevcheckout', 'hardyes');
t::lib::Mocks::mock_preference('checkprevcheckoutdelay', 0);
my $patron1 = Koha::Patrons->find($patron->{borrowernumber});
is(
$patron1->do_check_for_previous_checkout($item_object->unblessed),
1, "Checking CheckPrevCheckoutDelay disabled"
);
t::lib::Mocks::mock_preference('checkprevcheckoutdelay', 5);
is(
$patron1->do_check_for_previous_checkout($item_object->unblessed),
1, "Checking CheckPrevCheckoutDelay enabled within delay"
);
t::lib::Mocks::mock_preference('checkprevcheckoutdelay', 1);
is(
$patron1->do_check_for_previous_checkout($item_object->unblessed),
0, "Checking CheckPrevCheckoutDelay enabled after delay"
);
$schema->storage->txn_rollback;
}