Bug 6906 - show 'Borrower has previously issued...
New feature: provide granular means to configure warnings about items
that have been issued to a particular borrower before, according to
their checkout history.
- Global syspref ('CheckPrevCheckout'), set to 'hardno' by default,
allows users to enable this feature library wide.
- Per patron category pref allows libraries to create overrides per
category, falling back on the global setting by default.
- Per patron pref allows switching the functionality on at the level
of patron. Fall-back to category settings by default.
* Koha/Patron (wantsCheckPrevCheckout, doCheckPrevCheckout): New
methods.
* C4/Circulation.pm (CanBookBeIssued): Introduce CheckPrevCheckout
check.
* admin/categories.pl: Pass along checkprevcheckout.
* koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt: Expose
CheckPrevCheckout per category setting.
* koha-tmpl/intranet-tmpl/prog/en/modules/preferences/patrons.pref:
Expose CheckPrevCheckout syspref.
* koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt:
Expose per patron CheckPrevCheckout preference.
* koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt: Expose
per patron CheckPrevCheckout preference.
* koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt: Add
'CHECKPREVCHECKOUT' confirmation message.
* installer/data/mysql/kohastructure.sql: Modify structure of
'categories', 'borrowers', 'oldborrowers'.
* installer/data/mysql/sysprefs.sql: Add 'CheckPrevCheckout'.
* installer/data/mysql/atomicupdate/checkPrevCheckout.sql: New file.
* t/db_dependent/Patron/CheckPrevCheckout.t: New file with unit tests.
Test plan:
- Apply patch.
- Run updatedatabase.
- Regenerate Koha Schema files.
- Run the unit tests.
- Verify 'CheckPrevCheckout' is visible in Patrons sysprefs and can be
switched to 'hardyes', 'softyes', 'softno' and 'hardno'.
+ Check out previously checked out items to a patron, checking the
message appears as expected.
- Verify no 'Check previous checkouts' setting appears on the borrower
category pages if the syspref is set to a 'hard' option.
- Verify 'Check previous checkouts' setting appears on the borrower
category pages and can be modified per borrower category.
+ Issue previously issued items to a borrower, checking the message
appears as expected (This setting should override the default
setting if that is set to a 'soft' option).
- Verify no 'Check previous checkouts' setting appears on the individual
borrower pages if the syspref is set to a 'hard' option.
- Verify 'Check previous checkouts' setting appears on individual
borrower pages and can be modified.
+ Issue previously issued items to a borrower, checking the message
appears as expected (This setting should override the category
setting and the default setting if the latter is set to a 'soft'
option).
Followed test plan, works as expected.
Signed-off-by: Marc Véron <veron@veron.ch>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
This commit is contained in:
parent
c19f342bb1
commit
6a493842cf
|
|
@ -942,6 +942,14 @@ sub CanBookBeIssued {
|
|||
}
|
||||
}
|
||||
|
||||
#
|
||||
# CHECKPREVCHECKOUT: CHECK IF ITEM HAS EVER BEEN LENT TO PATRON
|
||||
#
|
||||
my $patron = Koha::Patrons->find($borrower->{borrowernumber});
|
||||
my $wantsCheckPrevCheckout = $patron->wantsCheckPrevCheckout;
|
||||
$needsconfirmation{PREVISSUE} = 1
|
||||
if ($wantsCheckPrevCheckout and $patron->doCheckPrevCheckout($item));
|
||||
|
||||
#
|
||||
# ITEM CHECKING
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package Koha::Patron;
|
||||
|
||||
# Copyright ByWater Solutions 2014
|
||||
# Copyright PTFS Europe 2016
|
||||
#
|
||||
# This file is part of Koha.
|
||||
#
|
||||
|
|
@ -21,9 +22,13 @@ use Modern::Perl;
|
|||
|
||||
use Carp;
|
||||
|
||||
use C4::Context;
|
||||
use Koha::Database;
|
||||
use Koha::Patrons;
|
||||
use Koha::Issues;
|
||||
use Koha::OldIssues;
|
||||
use Koha::Patron::Categories;
|
||||
use Koha::Patron::Images;
|
||||
use Koha::Patrons;
|
||||
|
||||
use base qw(Koha::Object);
|
||||
|
||||
|
|
@ -95,6 +100,74 @@ sub siblings {
|
|||
);
|
||||
}
|
||||
|
||||
=head3 wantsCheckPrevCheckout
|
||||
|
||||
$wantsCheckPrevCheckout = $patron->wantsCheckPrevCheckout;
|
||||
|
||||
Return 1 if Koha needs to perform PrevIssue checking, else 0.
|
||||
|
||||
=cut
|
||||
|
||||
sub wantsCheckPrevCheckout {
|
||||
my ( $self ) = @_;
|
||||
my $syspref = C4::Context->preference("checkPrevCheckout");
|
||||
|
||||
# Simple cases
|
||||
## Hard syspref trumps all
|
||||
return 1 if ($syspref eq 'hardyes');
|
||||
return 0 if ($syspref eq 'hardno');
|
||||
## Now, patron pref trumps all
|
||||
return 1 if ($self->checkprevcheckout eq 'yes');
|
||||
return 0 if ($self->checkprevcheckout eq 'no');
|
||||
|
||||
# More complex: patron inherits -> determine category preference
|
||||
my $checkPrevCheckoutByCat = Koha::Patron::Categories
|
||||
->find($self->categorycode)->checkprevcheckout;
|
||||
return 1 if ($checkPrevCheckoutByCat eq 'yes');
|
||||
return 0 if ($checkPrevCheckoutByCat eq 'no');
|
||||
|
||||
# Finally: category preference is inherit, default to 0
|
||||
if ($syspref eq 'softyes') {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
=head3 doCheckPrevCheckout
|
||||
|
||||
$checkPrevCheckout = $patron->doCheckPrevCheckout($item);
|
||||
|
||||
Return 1 if the bib associated with $ITEM has previously been checked out to
|
||||
$PATRON, 0 otherwise.
|
||||
|
||||
=cut
|
||||
|
||||
sub doCheckPrevCheckout {
|
||||
my ( $self, $item ) = @_;
|
||||
|
||||
# Find all items for bib and extract item numbers.
|
||||
my @items = Koha::Items->search({biblionumber => $item->{biblionumber}});
|
||||
my @item_nos;
|
||||
foreach my $item (@items) {
|
||||
push @item_nos, $item->itemnumber;
|
||||
}
|
||||
|
||||
# Create (old)issues search criteria
|
||||
my $criteria = {
|
||||
borrowernumber => $self->borrowernumber,
|
||||
itemnumber => \@item_nos,
|
||||
};
|
||||
|
||||
# Check current issues table
|
||||
my $issues = Koha::Issues->search($criteria);
|
||||
return 1 if $issues->count; # 0 || N
|
||||
|
||||
# Check old issues table
|
||||
my $old_issues = Koha::OldIssues->search($criteria);
|
||||
return $old_issues->count; # 0 || N
|
||||
}
|
||||
|
||||
=head3 type
|
||||
|
||||
=cut
|
||||
|
|
@ -106,6 +179,7 @@ sub _type {
|
|||
=head1 AUTHOR
|
||||
|
||||
Kyle M Hall <kyle@bywatersolutions.com>
|
||||
Alex Sassmannshausen <alex.sassmannshausen@ptfs-europe.com>
|
||||
|
||||
=cut
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ elsif ( $op eq 'add_validate' ) {
|
|||
my $overduenoticerequired = $input->param('overduenoticerequired');
|
||||
my $category_type = $input->param('category_type');
|
||||
my $BlockExpiredPatronOpacActions = $input->param('BlockExpiredPatronOpacActions');
|
||||
my $checkPrevCheckout = $input->param('checkprevcheckout');
|
||||
my $default_privacy = $input->param('default_privacy');
|
||||
my @branches = grep { $_ ne q{} } $input->multi_param('branches');
|
||||
|
||||
|
|
@ -119,6 +120,7 @@ elsif ( $op eq 'add_validate' ) {
|
|||
$category->overduenoticerequired($overduenoticerequired);
|
||||
$category->category_type($category_type);
|
||||
$category->BlockExpiredPatronOpacActions($BlockExpiredPatronOpacActions);
|
||||
$category->checkprevcheckout($checkPrevCheckout);
|
||||
$category->default_privacy($default_privacy);
|
||||
eval {
|
||||
$category->store;
|
||||
|
|
@ -144,6 +146,7 @@ elsif ( $op eq 'add_validate' ) {
|
|||
overduenoticerequired => $overduenoticerequired,
|
||||
category_type => $category_type,
|
||||
BlockExpiredPatronOpacActions => $BlockExpiredPatronOpacActions,
|
||||
checkprevcheckout => $checkPrevCheckout,
|
||||
default_privacy => $default_privacy,
|
||||
});
|
||||
eval {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
INSERT INTO systempreferences (variable,value,options,explanation,type)
|
||||
VALUES('CheckPrevCheckout','hardno','hardyes|softyes|softno|hardno','By default, for every item checked out, should we warn if the patron has checked out that item in the past?','Choice');
|
||||
|
||||
ALTER TABLE categories
|
||||
ADD COLUMN `checkprevcheckout` varchar(7) NOT NULL default 'inherit'
|
||||
AFTER `default_privacy`;
|
||||
|
||||
ALTER TABLE borrowers
|
||||
ADD COLUMN `checkprevcheckout` varchar(7) NOT NULL default 'inherit'
|
||||
AFTER `privacy_guarantor_checkouts`;
|
||||
|
||||
ALTER TABLE deletedborrowers
|
||||
ADD COLUMN `checkprevcheckout` varchar(7) NOT NULL default 'inherit'
|
||||
AFTER `privacy_guarantor_checkouts`;
|
||||
|
|
@ -319,6 +319,7 @@ CREATE TABLE `categories` ( -- this table shows information related to Koha patr
|
|||
`category_type` varchar(1) NOT NULL default 'A', -- type of Koha patron (Adult, Child, Professional, Organizational, Statistical, Staff)
|
||||
`BlockExpiredPatronOpacActions` tinyint(1) NOT NULL default '-1', -- wheither or not a patron of this category can renew books or place holds once their card has expired. 0 means they can, 1 means they cannot, -1 means use syspref BlockExpiredPatronOpacActions
|
||||
`default_privacy` ENUM( 'default', 'never', 'forever' ) NOT NULL DEFAULT 'default', -- Default privacy setting for this patron category
|
||||
`checkprevcheckout` varchar(7) NOT NULL default 'inherit', -- produce a warning for this patron category if this item has previously been checked out to this patron if 'yes', not if 'no', defer to syspref setting if 'inherit'.
|
||||
PRIMARY KEY (`categorycode`),
|
||||
UNIQUE KEY `categorycode` (`categorycode`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
|
@ -618,6 +619,7 @@ CREATE TABLE `deletedborrowers` ( -- stores data related to the patrons/borrower
|
|||
`sms_provider_id` int(11) DEFAULT NULL, -- the provider of the mobile phone number defined in smsalertnumber
|
||||
`privacy` integer(11) DEFAULT '1' NOT NULL, -- patron/borrower's privacy settings related to their reading history KEY `borrowernumber` (`borrowernumber`),
|
||||
`privacy_guarantor_checkouts` tinyint(1) NOT NULL DEFAULT '0', -- controls if relatives can see this patron's checkouts
|
||||
`checkprevcheckout` varchar(7) NOT NULL default 'inherit', -- produce a warning for this patron if this item has previously been checked out to this patron if 'yes', not if 'no', defer to category setting if 'inherit'.
|
||||
`updated_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- time of last change could be useful for synchronization with external systems (among others)
|
||||
KEY borrowernumber (borrowernumber),
|
||||
KEY `cardnumber` (`cardnumber`),
|
||||
|
|
@ -1635,6 +1637,7 @@ CREATE TABLE `borrowers` ( -- this table includes information about your patrons
|
|||
`sms_provider_id` int(11) DEFAULT NULL, -- the provider of the mobile phone number defined in smsalertnumber
|
||||
`privacy` integer(11) DEFAULT '1' NOT NULL, -- patron/borrower's privacy settings related to their reading history
|
||||
`privacy_guarantor_checkouts` tinyint(1) NOT NULL DEFAULT '0', -- controls if relatives can see this patron's checkouts
|
||||
`checkprevcheckout` varchar(7) NOT NULL default 'inherit', -- produce a warning for this patron if this item has previously been checked out to this patron if 'yes', not if 'no', defer to category setting if 'inherit'.
|
||||
`updated_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- time of last change could be useful for synchronization with external systems (among others)
|
||||
UNIQUE KEY `cardnumber` (`cardnumber`),
|
||||
PRIMARY KEY `borrowernumber` (`borrowernumber`),
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `
|
|||
('CatalogModuleRelink','0',NULL,'If OFF the linker will never replace the authids that are set in the cataloging module.','YesNo'),
|
||||
('CataloguingLog','1',NULL,'If ON, log edit/create/delete actions on bibliographic data. WARNING: this feature is very resource consuming.','YesNo'),
|
||||
('checkdigit','none','none|katipo','If ON, enable checks on patron cardnumber: none or \"Katipo\" style checks','Choice'),
|
||||
('CheckPrevCheckout','hardno','hardyes|softyes|softno|hardno','By default, for every item checked out, should we warn if the patron has borrowed that item in the past?','Choice'),
|
||||
('CircAutocompl','1',NULL,'If ON, autocompletion is enabled for the Circulation input','YesNo'),
|
||||
('CircAutoPrintQuickSlip','qslip',NULL,'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window, Display a print slip window or Clear the screen.','Choice'),
|
||||
('CircControl','ItemHomeLibrary','PickupLibrary|PatronLibrary|ItemHomeLibrary','Specify the agency that controls the circulation and fines policy','Choice'),
|
||||
|
|
|
|||
|
|
@ -189,6 +189,28 @@
|
|||
Choose whether patrons of this category be blocked from public catalog actions such as renewing and placing holds when their cards have expired.
|
||||
</span>
|
||||
</li>
|
||||
[% IF ( Koha.Preference('CheckPrevCheckout') == 'softyes' || Koha.Preference('CheckPrevCheckout') == 'softno' ) %]
|
||||
<li><label for="checkprevcheckout">Check for previous checkouts: </label>
|
||||
<select name="checkprevcheckout" id="checkprevcheckout">
|
||||
[% IF category.checkprevcheckout == 'yes' %]
|
||||
<option value="yes" selected="selected">Yes and try to override system preferences</option>
|
||||
<option value="no">No and try to override system preferences</option>
|
||||
<option value="inherit">Inherit from system preferences</option>
|
||||
[% ELSIF category.checkprevcheckout == 'no' %]
|
||||
<option value="yes">Yes and try to override system preferences</option>
|
||||
<option value="no" selected="selected">No and try to override system preferences</option>
|
||||
<option value="inherit">Inherit from system preferences</option>
|
||||
[% ELSE %]
|
||||
<option value="yes">Yes and try to override system preferences</option>
|
||||
<option value="no">No and try to override system preferences</option>
|
||||
<option value="inherit" selected="selected">Inherit from system preferences</option>
|
||||
[% END %]
|
||||
</select>
|
||||
<span>
|
||||
Choose whether patrons of this category by default are reminded if they try to borrow an item they borrowed before.
|
||||
</span>
|
||||
</li>
|
||||
[% END %]
|
||||
<li>
|
||||
<label for="default_privacy">Default privacy: </label>
|
||||
<select id="default_privacy" name="default_privacy">
|
||||
|
|
@ -261,6 +283,22 @@
|
|||
<tr><th scope="row">Receives overdue notices: </th><td>[% IF category. overduenoticerequired %]Yes[% ELSE %]No[% END %]</td></tr>
|
||||
<tr><th scope="row">Lost items in staff client</th><td>[% IF category.hidelostitems %]Hidden by default[% ELSE %]Shown[% END %]</td></tr>
|
||||
<tr><th scope="row">Hold fee: </th><td>[% category.reservefee | $Price %]</td></tr>
|
||||
|
||||
[% IF ( Koha.Preference('CheckPrevCheckout') == 'softyes' || Koha.Preference('CheckPrevCheckout') == 'softno' ) %]
|
||||
<tr>
|
||||
<th scope="row">Check previous checkouts: </th>
|
||||
<td>
|
||||
[% SWITCH category.checkprevcheckout %]
|
||||
[% CASE 'yes' %]
|
||||
Yes
|
||||
[% CASE 'no' %]
|
||||
No
|
||||
[% CASE 'inherit' %]
|
||||
Inherit
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
<tr>
|
||||
<th scope="row">Default privacy: </th>
|
||||
<td>
|
||||
|
|
@ -317,6 +355,9 @@
|
|||
<th scope="col">Messaging</th>
|
||||
[% END %]
|
||||
<th scope="col">Branches limitations</th>
|
||||
[% IF ( Koha.Preference('CheckPrevCheckout') == 'softyes' || Koha.Preference('CheckPrevCheckout') == 'softno' ) %]
|
||||
<th scope="col">Check previous checkout?</th>
|
||||
[% END %]
|
||||
<th scope="col">Default privacy</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
|
|
@ -393,6 +434,18 @@
|
|||
No limitation
|
||||
[% END %]
|
||||
</td>
|
||||
[% IF ( Koha.Preference('CheckPrevCheckout') == 'softyes' || Koha.Preference('CheckPrevCheckout') == 'softno' ) %]
|
||||
<td>
|
||||
[% SWITCH category.checkprevcheckout %]
|
||||
[% CASE 'yes' %]
|
||||
Yes
|
||||
[% CASE 'no' %]
|
||||
No
|
||||
[% CASE 'inherit' %]
|
||||
Inherit
|
||||
[% END %]
|
||||
</td>
|
||||
[% END %]
|
||||
<td>
|
||||
[% SWITCH category.default_privacy %]
|
||||
[% CASE 'default' %]
|
||||
|
|
|
|||
|
|
@ -43,6 +43,15 @@ Patrons:
|
|||
- pref: BorrowersTitles
|
||||
class: multi
|
||||
- (separate multiple choices with |)
|
||||
-
|
||||
- pref: CheckPrevCheckout
|
||||
default: no
|
||||
choices:
|
||||
hardyes: "Do"
|
||||
softyes: "Unless overridden, do"
|
||||
softno: "Unless overridden, do not"
|
||||
hardno: "Do not"
|
||||
- " check borrower checkout history to see if the current item has been checked out before."
|
||||
-
|
||||
- pref: checkdigit
|
||||
choices:
|
||||
|
|
|
|||
|
|
@ -264,6 +264,10 @@ $(document).ready(function() {
|
|||
<li>High demand item. Loan period shortened to [% HIGHHOLDS.duration %] days (due [% HIGHHOLDS.returndate %]). Check out anyway?</li>
|
||||
[% END %]
|
||||
|
||||
[% IF PREVISSUE %]
|
||||
<li>This item has previously been checked out to this patron. Check out anyway?</li>
|
||||
[% END %]
|
||||
|
||||
[% IF BIBLIO_ALREADY_ISSUED %]
|
||||
<li>
|
||||
Patron has already checked out another item from this record.
|
||||
|
|
|
|||
|
|
@ -691,7 +691,26 @@ $(document).ready(function() {
|
|||
[% END %]
|
||||
</li>
|
||||
[% END %]
|
||||
</ol>
|
||||
[% IF ( Koha.Preference('CheckPrevCheckout') == 'softyes' || Koha.Preference('CheckPrevCheckout') == 'softno' ) %]
|
||||
<li><label for="checkprevcheckout">Check for previous checkouts: </label>
|
||||
<select name="checkprevcheckout" id="checkprevcheckout">
|
||||
[% IF ( checkprevcheckout == 'yes' ) %]
|
||||
<option value="yes" selected="selected">Yes if settings allow it</option>
|
||||
<option value="no">No if settings allow it</option>
|
||||
<option value="inherit">Inherit from settings</option>
|
||||
[% ELSIF ( checkprevcheckout == 'no' ) %]
|
||||
<option value="yes">Yes if settings allow it</option>
|
||||
<option value="no" selected="selected">No if settings allow it</option>
|
||||
<option value="inherit">Inherit from settings</option>
|
||||
[% ELSE %]
|
||||
<option value="yes">Yes if settings allow it</option>
|
||||
<option value="no">No if settings allow it</option>
|
||||
<option value="inherit" selected="selected">Inherit from settings</option>
|
||||
[% END %]
|
||||
</select>
|
||||
</li>
|
||||
[% END %]
|
||||
</ol>
|
||||
</fieldset>
|
||||
[% UNLESS nodateenrolled && noopacnote && noborrowernotes %]
|
||||
<fieldset class="rows" id="memberentry_subscription">
|
||||
|
|
|
|||
|
|
@ -410,6 +410,17 @@ function validate1(date) {
|
|||
[% ELSE %]
|
||||
<li><span class="label">Activate sync: </span>No</li>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% IF ( Koha.Preference('CheckPrevCheckout') == 'softyes' || Koha.Preference('CheckPrevCheckout') == 'softno' ) %]
|
||||
<li><span class="label">Check previous checkouts: </span>
|
||||
[% IF ( checkprevcheckout == 'yes' ) %]
|
||||
Yes
|
||||
[% ELSIF ( checkprevcheckout == 'no' ) %]
|
||||
No
|
||||
[% ELSE %]
|
||||
Inherited
|
||||
[% END %]
|
||||
</li>
|
||||
[% END %]
|
||||
</ol>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,447 @@
|
|||
#!/usr/bin/perl
|
||||
use Modern::Perl;
|
||||
|
||||
use C4::Members;
|
||||
use C4::Circulation;
|
||||
use Koha::Database;
|
||||
use Koha::Patrons;
|
||||
use Koha::Patron;
|
||||
|
||||
use Test::More tests => 59;
|
||||
|
||||
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 $staff = $builder->build({source => 'Borrower'});
|
||||
my @USERENV = (
|
||||
$staff->{borrowernumber}, 'test', 'MASTERTEST', 'firstname', 'CPL',
|
||||
'CPL', 'email@example.org'
|
||||
);
|
||||
C4::Context->_new_userenv('DUMMY_SESSION_ID');
|
||||
C4::Context->set_userenv(@USERENV);
|
||||
BAIL_OUT("No userenv") unless C4::Context->userenv;
|
||||
|
||||
|
||||
# wantsCheckPrevCheckout
|
||||
|
||||
# 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->wantsCheckPrevCheckout, $_->{result},
|
||||
"Predicate with syspref " . $syspref . ", cat " . $code
|
||||
. ", patron " . $_->{setting}
|
||||
);
|
||||
} @{$_->{patrons}};
|
||||
} @{$_->{categories}};
|
||||
} @{$mappings};
|
||||
|
||||
# doCheckPrevCheckout
|
||||
|
||||
# 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 $item_1 = $builder->build({source => 'Item'});
|
||||
my $item_2 = $builder->build({
|
||||
source => 'Item',
|
||||
value => { biblionumber => $item_1->{biblionumber} },
|
||||
});
|
||||
my $item_d = $builder->build({source => 'Item'});
|
||||
|
||||
## Testing Sub
|
||||
sub test_it {
|
||||
my ($mapping, $stage) = @_;
|
||||
map {
|
||||
my $patron = Koha::Patrons->find($_->{patron}->{borrowernumber});
|
||||
is(
|
||||
$patron->doCheckPrevCheckout($_->{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 =
|
||||
GetMember(%{{borrowernumber => $patron->{borrowernumber}}});
|
||||
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 ->wantsCheckPrevCheckout and ->doCheckPrevCheckout,
|
||||
# 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, !wantsCheckPrevCheckout, !doCheckPrevCheckout
|
||||
# [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
|
||||
# - patron, wantsCheckPrevCheckout, !doCheckPrevCheckout
|
||||
# [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
|
||||
# - patron, !wantsCheckPrevCheckout, doCheckPrevCheckout
|
||||
# [!$issuingimpossible,!$needsconfirmation->{PREVISSUE}]
|
||||
# - patron, wantsCheckPrevCheckout, doCheckPrevCheckout
|
||||
# [!$issuingimpossible,$needsconfirmation->{PREVISSUE}]
|
||||
|
||||
# Needs:
|
||||
# - $patron_from_GetMember
|
||||
# - $item objects (one not issued, another prevIssued)
|
||||
# - $checkprevcheckout pref (first hardno, then hardyes)
|
||||
|
||||
# Our Patron
|
||||
my $CBBI_patron = $builder->build({source => 'Borrower'});
|
||||
my $p_from_GetMember =
|
||||
GetMember(%{{borrowernumber => $CBBI_patron->{borrowernumber}}});
|
||||
# Our Items
|
||||
my $new_item = $builder->build({
|
||||
source => 'Item',
|
||||
value => {
|
||||
notforloan => 0,
|
||||
withdrawn => 0,
|
||||
itemlost => 0,
|
||||
},
|
||||
});
|
||||
my $prev_item = $builder->build({
|
||||
source => 'Item',
|
||||
value => {
|
||||
notforloan => 0,
|
||||
withdrawn => 0,
|
||||
itemlost => 0,
|
||||
},
|
||||
});
|
||||
# Second is Checked Out
|
||||
BAIL_OUT("CanBookBeIssued Issue failed")
|
||||
unless AddIssue($p_from_GetMember, $prev_item->{barcode});
|
||||
|
||||
# Mappings
|
||||
my $CBBI_mappings = [
|
||||
{
|
||||
syspref => 'hardno',
|
||||
item => $new_item,
|
||||
result => undef,
|
||||
msg => "patron, !wantsCheckPrevCheckout, !doCheckPrevCheckout"
|
||||
|
||||
},
|
||||
{
|
||||
syspref => 'hardyes',
|
||||
item => $new_item,
|
||||
result => undef,
|
||||
msg => "patron, wantsCheckPrevCheckout, !doCheckPrevCheckout"
|
||||
},
|
||||
{
|
||||
syspref => 'hardno',
|
||||
item => $prev_item,
|
||||
result => undef,
|
||||
msg => "patron, !wantsCheckPrevCheckout, doCheckPrevCheckout"
|
||||
},
|
||||
{
|
||||
syspref => 'hardyes',
|
||||
item => $prev_item,
|
||||
result => 1,
|
||||
msg => "patron, wantsCheckPrevCheckout, doCheckPrevCheckout"
|
||||
},
|
||||
];
|
||||
|
||||
# Tests
|
||||
map {
|
||||
t::lib::Mocks::mock_preference('checkprevcheckout', $_->{syspref});
|
||||
my ( $issuingimpossible, $needsconfirmation ) =
|
||||
C4::Circulation::CanBookBeIssued(
|
||||
$p_from_GetMember, $_->{item}->{barcode}
|
||||
);
|
||||
is($needsconfirmation->{PREVISSUE}, $_->{result}, $_->{msg});
|
||||
} @{$CBBI_mappings};
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
|
||||
1;
|
||||
Loading…
Reference in New Issue