Bug 19532: Other objects used in recalls feature
- biblio->recalls - biblio->can_be_recalled - item->recall - item->can_be_recalled - item->can_set_waiting_recall - item->check_recalls - patron->recalls - Biblio.RecallsCount and relevant tests - t/db_dependent/Stats.t - t/db_dependent/Koha/Item.t - t/db_dependent/Koha/Biblio.t - t/db_dependent/Koha/Patron.t - t/db_dependent/XSLT.t - t/db_dependent/Search.t - t/db_dependent/Holds.t - t/db_dependent/Circulation/transferbook.t - t/db_dependent/Circulation.t Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> Signed-off-by: Fridolin Somers <fridolin.somers@biblibre.com>
This commit is contained in:
parent
01cc7621d5
commit
b800c2e68d
|
|
@ -299,6 +299,14 @@ The item was reserved. The value is a reference-to-hash whose keys are fields fr
|
|||
|
||||
The item was eligible to be transferred. Barring problems communicating with the database, the transfer should indeed have succeeded. The value should be ignored.
|
||||
|
||||
=item C<RecallPlacedAtHoldingBranch>
|
||||
|
||||
A recall for this item was found, and the transfer has already been completed as the item's branch matches the recall's pickup branch.
|
||||
|
||||
=item C<RecallFound>
|
||||
|
||||
A recall for this item was found, and the item needs to be transferred to the recall's pickup branch.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
|
@ -372,6 +380,19 @@ sub transferbook {
|
|||
$dotransfer = 0 unless $ignoreRs;
|
||||
}
|
||||
|
||||
# find recall
|
||||
my $recall = Koha::Recalls->find({ itemnumber => $itemnumber, status => 'T' });
|
||||
if ( defined $recall and C4::Context->preference('UseRecalls') ) {
|
||||
# do a transfer if the recall branch is different to the item holding branch
|
||||
if ( $recall->branchcode eq $fbr ) {
|
||||
$dotransfer = 0;
|
||||
$messages->{'RecallPlacedAtHoldingBranch'} = 1;
|
||||
} else {
|
||||
$dotransfer = 1;
|
||||
$messages->{'RecallFound'} = $recall;
|
||||
}
|
||||
}
|
||||
|
||||
#actually do the transfer....
|
||||
if ($dotransfer) {
|
||||
ModItemTransfer( $itemnumber, $fbr, $tbr, $trigger );
|
||||
|
|
@ -722,6 +743,10 @@ sticky due date is invalid or due date in the past
|
|||
|
||||
if the borrower borrows to much things
|
||||
|
||||
=head3 RECALLED
|
||||
|
||||
recalled by someone else
|
||||
|
||||
=cut
|
||||
|
||||
sub CanBookBeIssued {
|
||||
|
|
@ -1095,7 +1120,50 @@ sub CanBookBeIssued {
|
|||
}
|
||||
}
|
||||
|
||||
unless ( $ignore_reserves ) {
|
||||
my $recall;
|
||||
# CHECK IF ITEM HAS BEEN RECALLED BY ANOTHER PATRON
|
||||
# Only bother doing this if UseRecalls is enabled and the item is recallable
|
||||
# Don't look at recalls that are in transit
|
||||
if ( C4::Context->preference('UseRecalls') and $item_object->can_be_waiting_recall ) {
|
||||
my @recalls = $biblio->recalls;
|
||||
|
||||
foreach my $r ( @recalls ) {
|
||||
if ( $r->itemnumber and
|
||||
$r->itemnumber == $item_object->itemnumber and
|
||||
$r->borrowernumber == $patron->borrowernumber and
|
||||
$r->waiting ) {
|
||||
$messages{RECALLED} = $r->recall_id;
|
||||
$recall = $r;
|
||||
# this item is already waiting for this borrower and the recall can be fulfilled
|
||||
last;
|
||||
}
|
||||
elsif ( $r->itemnumber and
|
||||
$r->itemnumber == $item_object->itemnumber and
|
||||
$r->in_transit ) {
|
||||
# recalled item is in transit
|
||||
$issuingimpossible{RECALLED_INTRANSIT} = $r->branchcode;
|
||||
}
|
||||
elsif ( $r->item_level_recall and
|
||||
$r->itemnumber == $item_object->itemnumber and
|
||||
$r->borrowernumber != $patron->borrowernumber and
|
||||
!$r->in_transit ) {
|
||||
# this specific item has been recalled by a different patron
|
||||
$needsconfirmation{RECALLED} = $r;
|
||||
$recall = $r;
|
||||
last;
|
||||
}
|
||||
elsif ( !$r->item_level_recall and
|
||||
$r->borrowernumber != $patron->borrowernumber and
|
||||
!$r->in_transit ) {
|
||||
# a different patron has placed a biblio-level recall and this item is eligible to fill it
|
||||
$needsconfirmation{RECALLED} = $r;
|
||||
$recall = $r;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unless ( $ignore_reserves and defined $recall ) {
|
||||
# See if the item is on reserve.
|
||||
my ( $restype, $res ) = C4::Reserves::CheckReserves( $item_object->itemnumber );
|
||||
if ($restype) {
|
||||
|
|
@ -1409,6 +1477,10 @@ AddIssue does the following things :
|
|||
* RESERVE PLACED ?
|
||||
- fill reserve if reserve to this patron
|
||||
- cancel reserve or not, otherwise
|
||||
* RECALL PLACED ?
|
||||
- fill recall if recall to this patron
|
||||
- cancel recall or not
|
||||
- revert recall's waiting status or not
|
||||
* TRANSFERT PENDING ?
|
||||
- complete the transfert
|
||||
* ISSUE THE BOOK
|
||||
|
|
@ -1423,6 +1495,8 @@ sub AddIssue {
|
|||
my $onsite_checkout = $params && $params->{onsite_checkout} ? 1 : 0;
|
||||
my $switch_onsite_checkout = $params && $params->{switch_onsite_checkout};
|
||||
my $auto_renew = $params && $params->{auto_renew};
|
||||
my $cancel_recall = $params && $params->{cancel_recall};
|
||||
my $recall_id = $params && $params->{recall_id};
|
||||
my $dbh = C4::Context->dbh;
|
||||
my $barcodecheck = CheckValidBarcode($barcode);
|
||||
|
||||
|
|
@ -1496,6 +1570,8 @@ sub AddIssue {
|
|||
$item_object->discard_changes;
|
||||
}
|
||||
|
||||
Koha::Recalls->move_recall({ action => $cancel_recall, recall_id => $recall_id, itemnumber => $item_object->itemnumber, borrowernumber => $borrower->{borrowernumber} }) if C4::Context->preference('UseRecalls');
|
||||
|
||||
C4::Reserves::MoveReserve( $item_object->itemnumber, $borrower->{'borrowernumber'}, $cancelreserve );
|
||||
|
||||
# Starting process for transfer job (checking transfert and validate it if we have one)
|
||||
|
|
@ -1922,6 +1998,16 @@ Value 1 if return is successful.
|
|||
|
||||
If AutomaticItemReturn is disabled, return branch is given as value of NeedsTransfer.
|
||||
|
||||
=item C<RecallFound>
|
||||
|
||||
This item can fill a recall. The recall object is returned. If the recall pickup branch differs from
|
||||
the branch this item is being returned at, C<RecallNeedsTransfer> is also returned which contains this
|
||||
branchcode.
|
||||
|
||||
=item C<TransferredRecall>
|
||||
|
||||
This item has been transferred to this branch to fill a recall. The recall object is returned.
|
||||
|
||||
=back
|
||||
|
||||
C<$iteminformation> is a reference-to-hash, giving information about the
|
||||
|
|
@ -2198,6 +2284,17 @@ sub AddReturn {
|
|||
}
|
||||
}
|
||||
|
||||
# find recalls...
|
||||
# check if this item is recallable first, which includes checking if UseRecalls syspref is enabled
|
||||
my $recall = undef;
|
||||
$recall = $item->check_recalls if $item->can_be_waiting_recall;
|
||||
if ( defined $recall ) {
|
||||
$messages->{RecallFound} = $recall;
|
||||
if ( $recall->branchcode ne $branch ) {
|
||||
$messages->{RecallNeedsTransfer} = $branch;
|
||||
}
|
||||
}
|
||||
|
||||
# find reserves.....
|
||||
# launch the Checkreserves routine to find any holds
|
||||
my ($resfound, $resrec);
|
||||
|
|
@ -2257,13 +2354,22 @@ sub AddReturn {
|
|||
$request->status('RET') if $request;
|
||||
}
|
||||
|
||||
my $transfer_recall = Koha::Recalls->find({ itemnumber => $item->itemnumber, status => 'T' }); # all recalls that have triggered a transfer will have an allocated itemnumber
|
||||
if ( $transfer_recall and
|
||||
$transfer_recall->branchcode eq $branch and
|
||||
C4::Context->preference('UseRecalls') ) {
|
||||
$messages->{TransferredRecall} = $transfer_recall;
|
||||
}
|
||||
|
||||
# Transfer to returnbranch if Automatic transfer set or append message NeedsTransfer
|
||||
if ( $validTransfer && !C4::RotatingCollections::isItemInAnyCollection( $item->itemnumber )
|
||||
&& ( $doreturn or $messages->{'NotIssued'} )
|
||||
and !$resfound
|
||||
and ( $branch ne $returnbranch )
|
||||
and not $messages->{'WrongTransfer'}
|
||||
and not $messages->{'WasTransfered'} )
|
||||
and not $messages->{'WasTransfered'}
|
||||
and not $messages->{TransferredRecall}
|
||||
and not $messages->{RecallNeedsTransfer} )
|
||||
{
|
||||
my $BranchTransferLimitsType = C4::Context->preference("BranchTransferLimitsType") eq 'itemtype' ? 'effective_itemtype' : 'ccode';
|
||||
if (C4::Context->preference("AutomaticItemReturn" ) or
|
||||
|
|
@ -2773,6 +2879,18 @@ sub CanBookBeRenewed {
|
|||
return ( 0, $auto_renew ) if $auto_renew =~ 'auto_too_much_oweing';
|
||||
}
|
||||
|
||||
my $recall = undef;
|
||||
$recall = $item->check_recalls if $item->can_be_waiting_recall;
|
||||
if ( defined $recall ) {
|
||||
if ( $recall->item_level_recall ) {
|
||||
# item-level recall. check if this item is the recalled item, otherwise renewal will be allowed
|
||||
return ( 0, 'recalled' ) if ( $recall->itemnumber == $item->itemnumber );
|
||||
} else {
|
||||
# biblio-level recall, so only disallow renewal if the biblio-level recall has been fulfilled by a different item
|
||||
return ( 0, 'recalled' ) unless ( $recall->waiting );
|
||||
}
|
||||
}
|
||||
|
||||
my ( $resfound, $resrec, $possible_reserves ) = C4::Reserves::CheckReserves($itemnumber);
|
||||
|
||||
# If next hold is non priority, then check if any hold with priority (non_priority = 0) exists for the same biblionumber.
|
||||
|
|
|
|||
|
|
@ -375,6 +375,7 @@ sub CanBookBeReserved{
|
|||
{ status => libraryNotPickupLocation }, if given branchcode is not configured to be a pickup location
|
||||
{ status => cannotBeTransferred }, if branch transfer limit applies on given item and branchcode
|
||||
{ status => pickupNotInHoldGroup }, pickup location is not in hold group, and pickup locations are only allowed from hold groups.
|
||||
{ status => recall }, if the borrower has already placed a recall on this item
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -420,6 +421,10 @@ sub CanItemBeReserved {
|
|||
return { status =>'alreadypossession' };
|
||||
}
|
||||
|
||||
# check if a recall exists on this item from this borrower
|
||||
return { status => 'recall' }
|
||||
if Koha::Recalls->search({ borrowernumber => $borrowernumber, itemnumber => $itemnumber, old => undef })->count;
|
||||
|
||||
my $controlbranch = C4::Context->preference('ReservesControlBranch');
|
||||
|
||||
my $reserves_control_branch;
|
||||
|
|
|
|||
|
|
@ -1785,6 +1785,7 @@ sub searchResults {
|
|||
my $item_in_transit_count = 0;
|
||||
my $item_onhold_count = 0;
|
||||
my $notforloan_count = 0;
|
||||
my $item_recalled_count = 0;
|
||||
my $items_count = scalar(@fields);
|
||||
my $maxitems_pref = C4::Context->preference('maxItemsinSearchResults');
|
||||
my $maxitems = $maxitems_pref ? $maxitems_pref - 1 : 1;
|
||||
|
|
@ -1876,6 +1877,9 @@ sub searchResults {
|
|||
# is item on the reserve shelf?
|
||||
my $reservestatus = '';
|
||||
|
||||
# is item a waiting recall?
|
||||
my $recallstatus = '';
|
||||
|
||||
unless ($item->{withdrawn}
|
||||
|| $item->{itemlost}
|
||||
|| $item->{damaged}
|
||||
|
|
@ -1897,6 +1901,7 @@ sub searchResults {
|
|||
#
|
||||
($transfertwhen, $transfertfrom, $transfertto) = C4::Circulation::GetTransfers($item->{itemnumber});
|
||||
$reservestatus = C4::Reserves::GetReserveStatus( $item->{itemnumber} );
|
||||
$recallstatus = 'Waiting' if Koha::Recalls->search({ itemnumber => $item->{itemnumber}, status => 'W' })->count;
|
||||
}
|
||||
|
||||
# item is withdrawn, lost, damaged, not for loan, reserved or in transit
|
||||
|
|
@ -1905,6 +1910,7 @@ sub searchResults {
|
|||
|| $item->{damaged}
|
||||
|| $item->{notforloan}
|
||||
|| $reservestatus eq 'Waiting'
|
||||
|| $recallstatus eq 'Waiting'
|
||||
|| ($transfertwhen && $transfertwhen ne ''))
|
||||
{
|
||||
$withdrawn_count++ if $item->{withdrawn};
|
||||
|
|
@ -1912,6 +1918,7 @@ sub searchResults {
|
|||
$itemdamaged_count++ if $item->{damaged};
|
||||
$item_in_transit_count++ if $transfertwhen && $transfertwhen ne '';
|
||||
$item_onhold_count++ if $reservestatus eq 'Waiting';
|
||||
$item_recalled_count++ if $recallstatus eq 'Waiting';
|
||||
$item->{status} = ($item->{withdrawn}//q{}) . "-" . ($item->{itemlost}//q{}) . "-" . ($item->{damaged}//q{}) . "-" . ($item->{notforloan}//q{});
|
||||
|
||||
$other_count++;
|
||||
|
|
@ -1921,6 +1928,7 @@ sub searchResults {
|
|||
$other_items->{$key}->{$_} = $item->{$_};
|
||||
}
|
||||
$other_items->{$key}->{intransit} = ( $transfertwhen ne '' ) ? 1 : 0;
|
||||
$other_items->{$key}->{recalled} = ($recallstatus) ? 1 : 0;
|
||||
$other_items->{$key}->{onhold} = ($reservestatus) ? 1 : 0;
|
||||
$other_items->{$key}->{notforloan} = GetAuthorisedValueDesc('','',$item->{notforloan},'','',$notforloan_authorised_value) if $notforloan_authorised_value and $item->{notforloan};
|
||||
$other_items->{$key}->{count}++ if $item->{$hbranch};
|
||||
|
|
@ -2014,6 +2022,7 @@ sub searchResults {
|
|||
$oldbiblio->{damagedcount} = $itemdamaged_count;
|
||||
$oldbiblio->{intransitcount} = $item_in_transit_count;
|
||||
$oldbiblio->{onholdcount} = $item_onhold_count;
|
||||
$oldbiblio->{recalledcount} = $item_recalled_count;
|
||||
$oldbiblio->{orderedcount} = $ordered_count;
|
||||
$oldbiblio->{notforloancount} = $notforloan_count;
|
||||
|
||||
|
|
|
|||
|
|
@ -354,7 +354,13 @@ sub buildKohaItemsNamespace {
|
|||
my $status;
|
||||
my $substatus = '';
|
||||
|
||||
if ($item->has_pending_hold) {
|
||||
my $recalls = Koha::Recalls->search({ itemnumber => $item->itemnumber, status => 'W' });
|
||||
|
||||
if ( $recalls->count ) {
|
||||
# recalls take priority over holds
|
||||
$status = 'Waiting';
|
||||
}
|
||||
elsif ( $item->has_pending_hold ) {
|
||||
$status = 'other';
|
||||
$substatus = 'Pending hold';
|
||||
}
|
||||
|
|
|
|||
108
Koha/Biblio.pm
108
Koha/Biblio.pm
|
|
@ -1162,6 +1162,114 @@ sub get_marc_host {
|
|||
}
|
||||
}
|
||||
|
||||
=head3 recalls
|
||||
|
||||
my @recalls = $biblio->recalls;
|
||||
|
||||
Return all active recalls attached to this biblio, sorted by oldest first
|
||||
|
||||
=cut
|
||||
|
||||
sub recalls {
|
||||
my ( $self ) = @_;
|
||||
my @recalls_rs = Koha::Recalls->search({ biblionumber => $self->biblionumber, old => undef }, { order_by => { -asc => 'recalldate' } });
|
||||
return @recalls_rs;
|
||||
}
|
||||
|
||||
=head3 can_be_recalled
|
||||
|
||||
my @items_for_recall = $biblio->can_be_recalled({ patron => $patron_object });
|
||||
|
||||
Does biblio-level checks and returns the items attached to this biblio that are available for recall
|
||||
|
||||
=cut
|
||||
|
||||
sub can_be_recalled {
|
||||
my ( $self, $params ) = @_;
|
||||
|
||||
return 0 if !( C4::Context->preference('UseRecalls') );
|
||||
|
||||
my $patron = $params->{patron};
|
||||
|
||||
my $branchcode = C4::Context->userenv->{'branch'};
|
||||
if ( C4::Context->preference('CircControl') eq 'PatronLibrary' and $patron ) {
|
||||
$branchcode = $patron->branchcode;
|
||||
}
|
||||
|
||||
my @all_items = Koha::Items->search({ biblionumber => $self->biblionumber });
|
||||
|
||||
# if there are no available items at all, no recall can be placed
|
||||
return 0 if ( scalar @all_items == 0 );
|
||||
|
||||
my @itemtypes;
|
||||
my @itemnumbers;
|
||||
my @items;
|
||||
foreach my $item ( @all_items ) {
|
||||
if ( $item->can_be_recalled({ patron => $patron }) ) {
|
||||
push( @itemtypes, $item->effective_itemtype );
|
||||
push( @itemnumbers, $item->itemnumber );
|
||||
push( @items, $item );
|
||||
}
|
||||
}
|
||||
|
||||
# if there are no recallable items, no recall can be placed
|
||||
return 0 if ( scalar @items == 0 );
|
||||
|
||||
# Check the circulation rule for each relevant itemtype for this biblio
|
||||
my ( @recalls_allowed, @recalls_per_record, @on_shelf_recalls );
|
||||
foreach my $itemtype ( @itemtypes ) {
|
||||
my $rule = Koha::CirculationRules->get_effective_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron ? $patron->categorycode : undef,
|
||||
itemtype => $itemtype,
|
||||
rules => [
|
||||
'recalls_allowed',
|
||||
'recalls_per_record',
|
||||
'on_shelf_recalls',
|
||||
],
|
||||
});
|
||||
push( @recalls_allowed, $rule->{recalls_allowed} ) if $rule;
|
||||
push( @recalls_per_record, $rule->{recalls_per_record} ) if $rule;
|
||||
push( @on_shelf_recalls, $rule->{on_shelf_recalls} ) if $rule;
|
||||
}
|
||||
my $recalls_allowed = (sort {$b <=> $a} @recalls_allowed)[0]; # take highest
|
||||
my $recalls_per_record = (sort {$b <=> $a} @recalls_per_record)[0]; # take highest
|
||||
my %on_shelf_recalls_count = ();
|
||||
foreach my $count ( @on_shelf_recalls ) {
|
||||
$on_shelf_recalls_count{$count}++;
|
||||
}
|
||||
my $on_shelf_recalls = (sort {$on_shelf_recalls_count{$b} <=> $on_shelf_recalls_count{$a}} @on_shelf_recalls)[0]; # take most common
|
||||
|
||||
# check recalls allowed has been set and is not zero
|
||||
return 0 if ( !defined($recalls_allowed) || $recalls_allowed == 0 );
|
||||
|
||||
if ( $patron ) {
|
||||
# check borrower has not reached open recalls allowed limit
|
||||
return 0 if ( $patron->recalls->count >= $recalls_allowed );
|
||||
|
||||
# check borrower has not reached open recalls allowed per record limit
|
||||
return 0 if ( $patron->recalls({ biblionumber => $self->biblionumber })->count >= $recalls_per_record );
|
||||
|
||||
# check if any of the items under this biblio are already checked out by this borrower
|
||||
return 0 if ( Koha::Checkouts->search({ itemnumber => [ @itemnumbers ], borrowernumber => $patron->borrowernumber })->count > 0 );
|
||||
}
|
||||
|
||||
# check item availability
|
||||
my $checked_out_count = 0;
|
||||
foreach (@items) {
|
||||
if ( Koha::Checkouts->search({ itemnumber => $_->itemnumber })->count > 0 ){ $checked_out_count++; }
|
||||
}
|
||||
|
||||
# can't recall if on shelf recalls only allowed when all unavailable, but items are still available for checkout
|
||||
return 0 if ( $on_shelf_recalls eq 'all' && $checked_out_count < scalar @items );
|
||||
|
||||
# can't recall if no items have been checked out
|
||||
return 0 if ( $checked_out_count == 0 );
|
||||
|
||||
# can recall
|
||||
return @items;
|
||||
}
|
||||
|
||||
=head2 Internal methods
|
||||
|
||||
=head3 type
|
||||
|
|
|
|||
176
Koha/Item.pm
176
Koha/Item.pm
|
|
@ -1451,6 +1451,182 @@ sub _after_item_action_hooks {
|
|||
);
|
||||
}
|
||||
|
||||
=head3 recall
|
||||
|
||||
my $recall = $item->recall;
|
||||
|
||||
Return the relevant recall for this item
|
||||
|
||||
=cut
|
||||
|
||||
sub recall {
|
||||
my ( $self ) = @_;
|
||||
my @recalls = Koha::Recalls->search({ biblionumber => $self->biblionumber, old => undef }, { order_by => { -asc => 'recalldate' } });
|
||||
foreach my $recall (@recalls) {
|
||||
if ( $recall->item_level_recall and $recall->itemnumber == $self->itemnumber ){
|
||||
return $recall;
|
||||
}
|
||||
}
|
||||
# no item-level recall to return, so return earliest biblio-level
|
||||
# FIXME: eventually this will be based on priority
|
||||
return $recalls[0];
|
||||
}
|
||||
|
||||
=head3 can_be_recalled
|
||||
|
||||
if ( $item->can_be_recalled({ patron => $patron_object }) ) # do recall
|
||||
|
||||
Does item-level checks and returns if items can be recalled by this borrower
|
||||
|
||||
=cut
|
||||
|
||||
sub can_be_recalled {
|
||||
my ( $self, $params ) = @_;
|
||||
|
||||
return 0 if !( C4::Context->preference('UseRecalls') );
|
||||
|
||||
# check if this item is not for loan, withdrawn or lost
|
||||
return 0 if ( $self->notforloan != 0 );
|
||||
return 0 if ( $self->itemlost != 0 );
|
||||
return 0 if ( $self->withdrawn != 0 );
|
||||
|
||||
# check if this item is not checked out - if not checked out, can't be recalled
|
||||
return 0 if ( !defined( $self->checkout ) );
|
||||
|
||||
my $patron = $params->{patron};
|
||||
|
||||
my $branchcode = C4::Context->userenv->{'branch'};
|
||||
if ( $patron ) {
|
||||
$branchcode = C4::Circulation::_GetCircControlBranch( $self->unblessed, $patron->unblessed );
|
||||
}
|
||||
|
||||
# Check the circulation rule for each relevant itemtype for this item
|
||||
my $rule = Koha::CirculationRules->get_effective_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron ? $patron->categorycode : undef,
|
||||
itemtype => $self->effective_itemtype,
|
||||
rules => [
|
||||
'recalls_allowed',
|
||||
'recalls_per_record',
|
||||
'on_shelf_recalls',
|
||||
],
|
||||
});
|
||||
|
||||
# check recalls allowed has been set and is not zero
|
||||
return 0 if ( !defined($rule->{recalls_allowed}) || $rule->{recalls_allowed} == 0 );
|
||||
|
||||
if ( $patron ) {
|
||||
# check borrower has not reached open recalls allowed limit
|
||||
return 0 if ( $patron->recalls->count >= $rule->{recalls_allowed} );
|
||||
|
||||
# check borrower has not reach open recalls allowed per record limit
|
||||
return 0 if ( $patron->recalls({ biblionumber => $self->biblionumber })->count >= $rule->{recalls_per_record} );
|
||||
|
||||
# check if this patron has already recalled this item
|
||||
return 0 if ( Koha::Recalls->search({ itemnumber => $self->itemnumber, borrowernumber => $patron->borrowernumber, old => undef })->count > 0 );
|
||||
|
||||
# check if this patron has already checked out this item
|
||||
return 0 if ( Koha::Checkouts->search({ itemnumber => $self->itemnumber, borrowernumber => $patron->borrowernumber })->count > 0 );
|
||||
|
||||
# check if this patron has already reserved this item
|
||||
return 0 if ( Koha::Holds->search({ itemnumber => $self->itemnumber, borrowernumber => $patron->borrowernumber })->count > 0 );
|
||||
}
|
||||
|
||||
# check item availability
|
||||
# items are unavailable for recall if they are lost, withdrawn or notforloan
|
||||
my @items = Koha::Items->search({ biblionumber => $self->biblionumber, itemlost => 0, withdrawn => 0, notforloan => 0 });
|
||||
|
||||
# if there are no available items at all, no recall can be placed
|
||||
return 0 if ( scalar @items == 0 );
|
||||
|
||||
my $checked_out_count = 0;
|
||||
foreach (@items) {
|
||||
if ( Koha::Checkouts->search({ itemnumber => $_->itemnumber })->count > 0 ){ $checked_out_count++; }
|
||||
}
|
||||
|
||||
# can't recall if on shelf recalls only allowed when all unavailable, but items are still available for checkout
|
||||
return 0 if ( $rule->{on_shelf_recalls} eq 'all' && $checked_out_count < scalar @items );
|
||||
|
||||
# can't recall if no items have been checked out
|
||||
return 0 if ( $checked_out_count == 0 );
|
||||
|
||||
# can recall
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head3 can_be_waiting_recall
|
||||
|
||||
if ( $item->can_be_waiting_recall ) { # allocate item as waiting for recall
|
||||
|
||||
Checks item type and branch of circ rules to return whether this item can be used to fill a recall.
|
||||
At this point the item has already been recalled. We are now at the checkin and set waiting stage.
|
||||
|
||||
=cut
|
||||
|
||||
sub can_be_waiting_recall {
|
||||
my ( $self ) = @_;
|
||||
|
||||
return 0 if !( C4::Context->preference('UseRecalls') );
|
||||
|
||||
# check if this item is not for loan, withdrawn or lost
|
||||
return 0 if ( $self->notforloan != 0 );
|
||||
return 0 if ( $self->itemlost != 0 );
|
||||
return 0 if ( $self->withdrawn != 0 );
|
||||
|
||||
my $branchcode = $self->holdingbranch;
|
||||
if ( C4::Context->preference('CircControl') eq 'PickupLibrary' and C4::Context->userenv and C4::Context->userenv->{'branch'} ) {
|
||||
$branchcode = C4::Context->userenv->{'branch'};
|
||||
} else {
|
||||
$branchcode = ( C4::Context->preference('HomeOrHoldingBranch') eq 'homebranch' ) ? $self->homebranch : $self->holdingbranch;
|
||||
}
|
||||
|
||||
# Check the circulation rule for each relevant itemtype for this item
|
||||
my $rule = Koha::CirculationRules->get_effective_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => undef,
|
||||
itemtype => $self->effective_itemtype,
|
||||
rules => [
|
||||
'recalls_allowed',
|
||||
],
|
||||
});
|
||||
|
||||
# check recalls allowed has been set and is not zero
|
||||
return 0 if ( !defined($rule->{recalls_allowed}) || $rule->{recalls_allowed} == 0 );
|
||||
|
||||
# can recall
|
||||
return 1;
|
||||
}
|
||||
|
||||
=head3 check_recalls
|
||||
|
||||
my $recall = $item->check_recalls;
|
||||
|
||||
Get the most relevant recall for this item.
|
||||
|
||||
=cut
|
||||
|
||||
sub check_recalls {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @recalls = Koha::Recalls->search({ biblionumber => $self->biblionumber, itemnumber => [ $self->itemnumber, undef ], status => [ 'R','O','W','T' ] }, { order_by => { -asc => 'recalldate' } });
|
||||
|
||||
my $recall;
|
||||
# iterate through relevant recalls to find the best one.
|
||||
# if we come across a waiting recall, use this one.
|
||||
# if we have iterated through all recalls and not found a waiting recall, use the first recall in the array, which should be the oldest recall.
|
||||
foreach my $r ( @recalls ) {
|
||||
if ( $r->waiting ) {
|
||||
$recall = $r;
|
||||
last;
|
||||
}
|
||||
}
|
||||
unless ( defined $recall ) {
|
||||
$recall = $recalls[0];
|
||||
}
|
||||
|
||||
return $recall;
|
||||
}
|
||||
|
||||
=head3 _type
|
||||
|
||||
=cut
|
||||
|
|
|
|||
|
|
@ -2054,6 +2054,30 @@ sub safe_to_delete {
|
|||
return Koha::Result::Boolean->new(1);
|
||||
}
|
||||
|
||||
=head3 recalls
|
||||
|
||||
my $recalls = $patron->recalls;
|
||||
|
||||
my $recalls = $patron->recalls({ biblionumber => $biblionumber });
|
||||
|
||||
Return the patron's active recalls - total, or on a specific biblio
|
||||
|
||||
=cut
|
||||
|
||||
sub recalls {
|
||||
my ( $self, $params ) = @_;
|
||||
|
||||
my $biblionumber = $params->{biblionumber};
|
||||
|
||||
my $recalls_rs = Koha::Recalls->search({ borrowernumber => $self->borrowernumber, old => undef });
|
||||
|
||||
if ( $biblionumber ) {
|
||||
$recalls_rs = Koha::Recalls->search({ borrowernumber => $self->borrowernumber, old => undef, biblionumber => $biblionumber });
|
||||
}
|
||||
|
||||
return $recalls_rs;
|
||||
}
|
||||
|
||||
=head2 Internal methods
|
||||
|
||||
=head3 _type
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use Koha::Holds;
|
|||
use Koha::Biblios;
|
||||
use Koha::Patrons;
|
||||
use Koha::ArticleRequests;
|
||||
use Koha::Recalls;
|
||||
|
||||
sub HoldsCount {
|
||||
my ( $self, $biblionumber ) = @_;
|
||||
|
|
@ -56,4 +57,12 @@ sub CanArticleRequest {
|
|||
return $biblio ? $biblio->can_article_request( $borrower ) : 0;
|
||||
}
|
||||
|
||||
sub RecallsCount {
|
||||
my ( $self, $biblionumber ) = @_;
|
||||
|
||||
my $recalls = Koha::Recalls->search({ biblionumber => $biblionumber, old => undef });
|
||||
|
||||
return $recalls->count;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
use Modern::Perl;
|
||||
use utf8;
|
||||
|
||||
use Test::More tests => 57;
|
||||
use Test::More tests => 60;
|
||||
use Test::Exception;
|
||||
use Test::MockModule;
|
||||
use Test::Deep qw( cmp_deeply );
|
||||
|
|
@ -418,7 +418,7 @@ subtest "GetIssuingCharges tests" => sub {
|
|||
|
||||
my ( $reused_itemnumber_1, $reused_itemnumber_2 );
|
||||
subtest "CanBookBeRenewed tests" => sub {
|
||||
plan tests => 93;
|
||||
plan tests => 97;
|
||||
|
||||
C4::Context->set_preference('ItemsDeniedRenewal','');
|
||||
# Generate test biblio
|
||||
|
|
@ -1429,6 +1429,77 @@ subtest "CanBookBeRenewed tests" => sub {
|
|||
$item_3->itemcallnumber || '' ),
|
||||
"Account line description must not contain 'Lost Items ', but be title, barcode, itemcallnumber"
|
||||
);
|
||||
|
||||
# Recalls
|
||||
t::lib::Mocks::mock_preference('UseRecalls', 1);
|
||||
Koha::CirculationRules->set_rules({
|
||||
categorycode => undef,
|
||||
branchcode => undef,
|
||||
itemtype => undef,
|
||||
rules => {
|
||||
recalls_allowed => 10,
|
||||
renewalsallowed => 5,
|
||||
},
|
||||
});
|
||||
my $recall_borrower = $builder->build_object({ class => 'Koha::Patrons' });
|
||||
my $recall_biblio = $builder->build_object({ class => 'Koha::Biblios' });
|
||||
my $recall_item1 = $builder->build_object({ class => 'Koha::Items' }, { value => { biblionumber => $recall_biblio->biblionumber } });
|
||||
my $recall_item2 = $builder->build_object({ class => 'Koha::Items' }, { value => { biblionumber => $recall_biblio->biblionumber } });
|
||||
|
||||
AddIssue( $renewing_borrower, $recall_item1->barcode );
|
||||
|
||||
# item-level and this item: renewal not allowed
|
||||
my $recall = Koha::Recall->new({
|
||||
biblionumber => $recall_item1->biblionumber,
|
||||
itemnumber => $recall_item1->itemnumber,
|
||||
borrowernumber => $recall_borrower->borrowernumber,
|
||||
branchcode => $recall_borrower->branchcode,
|
||||
item_level_recall => 1,
|
||||
status => 'R',
|
||||
})->store;
|
||||
( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
|
||||
is( $error, 'recalled', 'Cannot renew item that has been recalled' );
|
||||
$recall->set_cancelled;
|
||||
|
||||
# biblio-level requested recall: renewal not allowed
|
||||
$recall = Koha::Recall->new({
|
||||
biblionumber => $recall_item1->biblionumber,
|
||||
itemnumber => undef,
|
||||
borrowernumber => $recall_borrower->borrowernumber,
|
||||
branchcode => $recall_borrower->branchcode,
|
||||
item_level_recall => 0,
|
||||
status => 'R',
|
||||
})->store;
|
||||
( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
|
||||
is( $error, 'recalled', 'Cannot renew item if biblio is recalled and has no item allocated' );
|
||||
$recall->set_cancelled;
|
||||
|
||||
# item-level and not this item: renewal allowed
|
||||
$recall = Koha::Recall->new({
|
||||
biblionumber => $recall_item2->biblionumber,
|
||||
itemnumber => $recall_item2->itemnumber,
|
||||
borrowernumber => $recall_borrower->borrowernumber,
|
||||
branchcode => $recall_borrower->branchcode,
|
||||
item_level_recall => 1,
|
||||
status => 'R',
|
||||
})->store;
|
||||
( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
|
||||
is( $renewokay, 1, 'Can renew item if item-level recall on biblio is not on this item' );
|
||||
$recall->set_cancelled;
|
||||
|
||||
# biblio-level waiting recall: renewal allowed
|
||||
$recall = Koha::Recall->new({
|
||||
biblionumber => $recall_item1->biblionumber,
|
||||
itemnumber => undef,
|
||||
borrowernumber => $recall_borrower->borrowernumber,
|
||||
branchcode => $recall_borrower->branchcode,
|
||||
item_level_recall => 0,
|
||||
status => 'R',
|
||||
})->store;
|
||||
$recall->set_waiting({ item => $recall_item1 });
|
||||
( $renewokay, $error ) = CanBookBeRenewed( $renewing_borrowernumber, $recall_item1->itemnumber );
|
||||
is( $renewokay, 1, 'Can renew item if biblio-level recall has already been allocated an item' );
|
||||
$recall->set_cancelled;
|
||||
};
|
||||
|
||||
subtest "GetUpcomingDueIssues" => sub {
|
||||
|
|
@ -1909,6 +1980,68 @@ subtest 'AddIssue & AllowReturnToBranch' => sub {
|
|||
# TODO t::lib::Mocks::mock_preference('AllowReturnToBranch', 'homeorholdingbranch');
|
||||
};
|
||||
|
||||
subtest 'AddIssue | recalls' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
t::lib::Mocks::mock_preference("UseRecalls", 1);
|
||||
t::lib::Mocks::mock_preference("item-level_itypes", 1);
|
||||
my $patron1 = $builder->build_object({ class => 'Koha::Patrons' });
|
||||
my $patron2 = $builder->build_object({ class => 'Koha::Patrons' });
|
||||
my $item = $builder->build_sample_item;
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => undef,
|
||||
itemtype => undef,
|
||||
categorycode => undef,
|
||||
rules => {
|
||||
recalls_allowed => 10,
|
||||
},
|
||||
});
|
||||
|
||||
# checking out item that they have recalled
|
||||
my $recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => $item->itemnumber,
|
||||
item_level_recall => 1,
|
||||
branchcode => $patron1->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
AddIssue( $patron1->unblessed, $item->barcode, undef, undef, undef, undef, { recall_id => $recall1->recall_id } );
|
||||
$recall1 = Koha::Recalls->find( $recall1->recall_id );
|
||||
is( $recall1->finished, 1, 'Recall was fulfilled when patron checked out item' );
|
||||
AddReturn( $item->barcode, $item->homebranch );
|
||||
|
||||
# this item is has a recall request. cancel recall
|
||||
my $recall2 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => $item->itemnumber,
|
||||
item_level_recall => 1,
|
||||
branchcode => $patron2->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
AddIssue( $patron1->unblessed, $item->barcode, undef, undef, undef, undef, { recall_id => $recall2->recall_id, cancel_recall => 'cancel' } );
|
||||
$recall2 = Koha::Recalls->find( $recall2->recall_id );
|
||||
is( $recall2->cancelled, 1, 'Recall was cancelled when patron checked out item' );
|
||||
AddReturn( $item->barcode, $item->homebranch );
|
||||
|
||||
# this item is waiting to fulfill a recall. revert recall
|
||||
my $recall3 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => $item->itemnumber,
|
||||
item_level_recall => 1,
|
||||
branchcode => $patron2->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
$recall3->set_waiting;
|
||||
AddIssue( $patron1->unblessed, $item->barcode, undef, undef, undef, undef, { recall_id => $recall3->recall_id, cancel_recall => 'revert' } );
|
||||
$recall3 = Koha::Recalls->find( $recall3->recall_id );
|
||||
is( $recall3->requested, 1, 'Recall was reverted from waiting when patron checked out item' );
|
||||
AddReturn( $item->barcode, $item->homebranch );
|
||||
};
|
||||
|
||||
|
||||
subtest 'CanBookBeIssued + Koha::Patron->is_debarred|has_overdues' => sub {
|
||||
plan tests => 8;
|
||||
|
||||
|
|
@ -3827,6 +3960,70 @@ subtest 'CanBookBeIssued | notforloan' => sub {
|
|||
# TODO test with AllowNotForLoanOverride = 1
|
||||
};
|
||||
|
||||
subtest 'CanBookBeIssued | recalls' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
t::lib::Mocks::mock_preference("UseRecalls", 1);
|
||||
t::lib::Mocks::mock_preference("item-level_itypes", 1);
|
||||
my $patron1 = $builder->build_object({ class => 'Koha::Patrons' });
|
||||
my $patron2 = $builder->build_object({ class => 'Koha::Patrons' });
|
||||
my $item = $builder->build_sample_item;
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => undef,
|
||||
itemtype => undef,
|
||||
categorycode => undef,
|
||||
rules => {
|
||||
recalls_allowed => 10,
|
||||
},
|
||||
});
|
||||
|
||||
# item-level recall
|
||||
my $recall = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => $item->itemnumber,
|
||||
item_level_recall => 1,
|
||||
branchcode => $patron1->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
|
||||
my ( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $patron2, $item->barcode, undef, undef, undef, undef );
|
||||
is( $needsconfirmation->{RECALLED}->recall_id, $recall->recall_id, "Another patron has placed an item-level recall on this item" );
|
||||
|
||||
$recall->set_cancelled;
|
||||
|
||||
# biblio-level recall
|
||||
$recall = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => undef,
|
||||
item_level_recall => 0,
|
||||
branchcode => $patron1->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
|
||||
( $issuingimpossible, $needsconfirmation ) = CanBookBeIssued( $patron2, $item->barcode, undef, undef, undef, undef );
|
||||
is( $needsconfirmation->{RECALLED}->recall_id, $recall->recall_id, "Another patron has placed a biblio-level recall and this item is eligible to fill it" );
|
||||
|
||||
$recall->set_cancelled;
|
||||
|
||||
# biblio-level recall
|
||||
$recall = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => undef,
|
||||
item_level_recall => 0,
|
||||
branchcode => $patron1->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
$recall->set_waiting({ item => $item, expirationdate => dt_from_string() });
|
||||
|
||||
my ( undef, undef, undef, $messages ) = CanBookBeIssued( $patron1, $item->barcode, undef, undef, undef, undef );
|
||||
is( $messages->{RECALLED}, $recall->recall_id, "This book can be issued by this patron and they have placed a recall" );
|
||||
|
||||
$recall->set_cancelled;
|
||||
};
|
||||
|
||||
subtest 'AddReturn should clear items.onloan for unissued items' => sub {
|
||||
plan tests => 1;
|
||||
|
||||
|
|
@ -3842,6 +4039,66 @@ subtest 'AddReturn should clear items.onloan for unissued items' => sub {
|
|||
is( $item->onloan, undef, 'AddReturn did clear items.onloan' );
|
||||
};
|
||||
|
||||
subtest 'AddReturn | recalls' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
t::lib::Mocks::mock_preference("UseRecalls", 1);
|
||||
t::lib::Mocks::mock_preference("item-level_itypes", 1);
|
||||
my $patron1 = $builder->build_object({ class => 'Koha::Patrons' });
|
||||
my $patron2 = $builder->build_object({ class => 'Koha::Patrons' });
|
||||
my $item1 = $builder->build_sample_item;
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => undef,
|
||||
itemtype => undef,
|
||||
categorycode => undef,
|
||||
rules => {
|
||||
recalls_allowed => 10,
|
||||
},
|
||||
});
|
||||
|
||||
# this item can fill a recall with pickup at this branch
|
||||
AddIssue( $patron1->unblessed, $item1->barcode );
|
||||
my $recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
biblionumber => $item1->biblionumber,
|
||||
itemnumber => $item1->itemnumber,
|
||||
item_level_recall => 1,
|
||||
branchcode => $item1->homebranch,
|
||||
status => 'R',
|
||||
})->store;
|
||||
my ( $doreturn, $messages, $iteminfo, $borrowerinfo ) = AddReturn( $item1->barcode, $item1->homebranch );
|
||||
is( $messages->{RecallFound}->recall_id, $recall1->recall_id, "Recall found" );
|
||||
$recall1->set_cancelled;
|
||||
|
||||
# this item can fill a recall but needs transfer
|
||||
AddIssue( $patron1->unblessed, $item1->barcode );
|
||||
$recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
biblionumber => $item1->biblionumber,
|
||||
itemnumber => $item1->itemnumber,
|
||||
item_level_recall => 1,
|
||||
branchcode => $patron2->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
( $doreturn, $messages, $iteminfo, $borrowerinfo ) = AddReturn( $item1->barcode, $item1->homebranch );
|
||||
is( $messages->{RecallNeedsTransfer}, $item1->homebranch, "Recall requiring transfer found" );
|
||||
$recall1->set_cancelled;
|
||||
|
||||
# this item is already in transit, do not ask to transfer
|
||||
AddIssue( $patron1->unblessed, $item1->barcode );
|
||||
$recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
biblionumber => $item1->biblionumber,
|
||||
itemnumber => $item1->itemnumber,
|
||||
item_level_recall => 1,
|
||||
branchcode => $patron2->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
$recall1->start_transfer;
|
||||
( $doreturn, $messages, $iteminfo, $borrowerinfo ) = AddReturn( $item1->barcode, $patron2->branchcode );
|
||||
is( $messages->{TransferredRecall}->recall_id, $recall1->recall_id, "In transit recall found" );
|
||||
$recall1->set_cancelled;
|
||||
};
|
||||
|
||||
subtest 'AddRenewal and AddIssuingCharge tests' => sub {
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ use Koha::DateUtils qw( dt_from_string );
|
|||
use Koha::Item::Transfers;
|
||||
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
my $schema = Koha::Database->new->schema;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
subtest 'transfer a non-existant item' => sub {
|
||||
plan tests => 2;
|
||||
|
|
@ -101,7 +104,7 @@ subtest 'field population tests' => sub {
|
|||
#FIXME:'UseBranchTransferLimits tests missing
|
||||
|
||||
subtest 'transfer already at destination' => sub {
|
||||
plan tests => 5;
|
||||
plan tests => 9;
|
||||
|
||||
my $library = $builder->build_object( { class => 'Koha::Libraries' } )->store;
|
||||
t::lib::Mocks::mock_userenv( { branchcode => $library->branchcode } );
|
||||
|
|
@ -151,6 +154,33 @@ subtest 'transfer already at destination' => sub {
|
|||
is( $dotransfer, 0, 'Transfer of reserved item doesn\'t succeed without ignore_reserves' );
|
||||
is( $messages->{ResFound}->{ResFound}, 'Reserved', "We found the reserve");
|
||||
is( $messages->{ResFound}->{itemnumber}, $item->itemnumber, "We got the reserve info");
|
||||
|
||||
# recalls
|
||||
t::lib::Mocks::mock_preference('UseRecalls', 1);
|
||||
my $recall = Koha::Recall->new({
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => $item->itemnumber,
|
||||
item_level_recall => 1,
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
branchcode => $library->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
( $recall, $dotransfer, $messages ) = $recall->start_transfer;
|
||||
is( $dotransfer, 0, 'Do not transfer recalled item, it has already arrived' );
|
||||
is( $messages->{RecallPlacedAtHoldingBranch}, 1, "We found the recall");
|
||||
|
||||
my $item2 = $builder->build_object({ class => 'Koha::Items' }); # this item will have a different holding branch to the pickup branch
|
||||
$recall = Koha::Recall->new({
|
||||
biblionumber => $item2->biblionumber,
|
||||
itemnumber => $item2->itemnumber,
|
||||
item_level_recall => 1,
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
branchcode => $library->branchcode,
|
||||
status => 'R',
|
||||
})->store;
|
||||
( $recall, $dotransfer, $messages ) = $recall->start_transfer;
|
||||
is( $dotransfer, 1, 'Transfer of recalled item succeeded' );
|
||||
is( $messages->{RecallFound}->recall_id, $recall->recall_id, "We found the recall");
|
||||
};
|
||||
|
||||
subtest 'transfer an issued item' => sub {
|
||||
|
|
@ -301,3 +331,4 @@ subtest 'transferbook test from branch' => sub {
|
|||
is( $to_branch, $library->branchcode, 'The transfer is initiated to the specified branch');
|
||||
|
||||
};
|
||||
$schema->storage->txn_rollback;
|
||||
|
|
|
|||
|
|
@ -1549,7 +1549,34 @@ subtest 'non priority holds' => sub {
|
|||
is( $err, 'on_reserve', 'Item is on hold' );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'CanItemBeReserved / recall' => sub {
|
||||
plan tests => 1;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $itemtype1 = $builder->build_object( { class => 'Koha::ItemTypes' } );
|
||||
my $library1 = $builder->build_object( { class => 'Koha::Libraries', value => {pickup_location => 1} } );
|
||||
my $patron1 = $builder->build_object( { class => 'Koha::Patrons', value => {branchcode => $library1->branchcode} } );
|
||||
my $biblio1 = $builder->build_sample_biblio({ itemtype => $itemtype1->itemtype });
|
||||
my $item1 = $builder->build_sample_item(
|
||||
{
|
||||
biblionumber => $biblio1->biblionumber,
|
||||
library => $library1->branchcode
|
||||
}
|
||||
);
|
||||
Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
biblionumber => $biblio1->biblionumber,
|
||||
branchcode => $library1->branchcode,
|
||||
itemnumber => $item1->itemnumber,
|
||||
recalldate => '2020-05-04 10:10:10',
|
||||
item_level_recall => 1,
|
||||
})->store;
|
||||
is( CanItemBeReserved( $patron1->borrowernumber, $item1->itemnumber, $library1->branchcode )->{status}, 'recall', "Can't reserve an item that they have already recalled" );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'CanItemBeReserved rule precedence tests' => sub {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
use Modern::Perl;
|
||||
|
||||
use Test::More tests => 20;
|
||||
use Test::More tests => 21; # +1
|
||||
use Test::Warn;
|
||||
|
||||
use C4::Biblio qw( AddBiblio ModBiblio ModBiblioMarc );
|
||||
|
|
@ -880,6 +880,122 @@ subtest 'get_marc_authors() tests' => sub {
|
|||
$biblio = Koha::Biblios->find( $biblio->biblionumber );
|
||||
|
||||
is( 4, @{$biblio->get_marc_authors}, 'get_marc_authors retrieves correct number of author subfields' );
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'Recalls tests' => sub {
|
||||
|
||||
plan tests => 12;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
my $item1 = $builder->build_sample_item;
|
||||
my $biblio = $item1->biblio;
|
||||
my $branchcode = $item1->holdingbranch;
|
||||
my $patron1 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $branchcode } });
|
||||
my $patron2 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $branchcode } });
|
||||
my $patron3 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $branchcode } });
|
||||
my $item2 = $builder->build_object({ class => 'Koha::Items', value => { holdingbranch => $branchcode, homebranch => $branchcode, biblionumber => $biblio->biblionumber, itype => $item1->effective_itemtype } });
|
||||
t::lib::Mocks::mock_userenv({ patron => $patron1 });
|
||||
|
||||
my $recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => $item1->itemnumber,
|
||||
expirationdate => undef,
|
||||
item_level_recall => 1
|
||||
})->store;
|
||||
my $recall2 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => undef,
|
||||
expirationdate => undef,
|
||||
item_level_recall => 0
|
||||
})->store;
|
||||
my $recall3 = Koha::Recall->new({
|
||||
borrowernumber => $patron3->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => $item1->itemnumber,
|
||||
expirationdate => undef,
|
||||
item_level_recall => 1
|
||||
})->store;
|
||||
|
||||
my $recalls_count = scalar $biblio->recalls;
|
||||
is( $recalls_count, 3, 'Correctly get number of active recalls for biblio' );
|
||||
|
||||
$recall1->set_cancelled;
|
||||
$recall2->set_expired({ interface => 'COMMANDLINE' });
|
||||
|
||||
$recalls_count = scalar $biblio->recalls;
|
||||
is( $recalls_count, 1, 'Correctly get number of active recalls for biblio' );
|
||||
|
||||
t::lib::Mocks::mock_preference('UseRecalls', 0);
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall with UseRecalls disabled" );
|
||||
|
||||
t::lib::Mocks::mock_preference("UseRecalls", 1);
|
||||
$item1->update({ notforloan => 1 });
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall with no available items" );
|
||||
|
||||
$item1->update({ notforloan => 0 });
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron1->categorycode,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 0,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'all',
|
||||
},
|
||||
});
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if recalls_allowed = 0" );
|
||||
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron1->categorycode,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 1,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'all',
|
||||
},
|
||||
});
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if patron has more existing recall(s) than recalls_allowed" );
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if patron has more existing recall(s) than recalls_per_record" );
|
||||
|
||||
$recall1->set_cancelled;
|
||||
C4::Circulation::AddIssue( $patron1->unblessed, $item2->barcode );
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if patron has already checked out an item attached to this biblio" );
|
||||
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if on_shelf_recalls = all and items are still available" );
|
||||
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron1->categorycode,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 1,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'any',
|
||||
},
|
||||
});
|
||||
C4::Circulation::AddReturn( $item2->barcode, $branchcode );
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if no items are checked out" );
|
||||
|
||||
$recall2->set_cancelled;
|
||||
C4::Circulation::AddIssue( $patron2->unblessed, $item2->barcode );
|
||||
C4::Circulation::AddIssue( $patron2->unblessed, $item1->barcode );
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 2, "Can recall two items" );
|
||||
|
||||
$item1->update({ withdrawn => 1 });
|
||||
is( $biblio->can_be_recalled({ patron => $patron1 }), 1, "Can recall one item" );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1165,7 +1165,193 @@ subtest 'columns_to_str' => sub {
|
|||
$cache->clear_from_cache("MarcSubfieldStructure-");
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'Recalls tests' => sub {
|
||||
|
||||
plan tests => 20;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $item1 = $builder->build_sample_item;
|
||||
my $biblio = $item1->biblio;
|
||||
my $branchcode = $item1->holdingbranch;
|
||||
my $patron1 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $branchcode } });
|
||||
my $patron2 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $branchcode } });
|
||||
my $patron3 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $branchcode } });
|
||||
my $item2 = $builder->build_object({ class => 'Koha::Items', value => { holdingbranch => $branchcode, homebranch => $branchcode, biblionumber => $biblio->biblionumber, itype => $item1->effective_itemtype } });
|
||||
t::lib::Mocks::mock_userenv({ patron => $patron1 });
|
||||
|
||||
my $recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => $item1->itemnumber,
|
||||
expirationdate => undef,
|
||||
item_level_recall => 1
|
||||
})->store;
|
||||
my $recall2 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => $item1->itemnumber,
|
||||
expirationdate => undef,
|
||||
item_level_recall =>1
|
||||
})->store;
|
||||
|
||||
is( $item1->recall->borrowernumber, $patron1->borrowernumber, 'Correctly returns most relevant recall' );
|
||||
|
||||
$recall2->set_cancelled;
|
||||
|
||||
t::lib::Mocks::mock_preference('UseRecalls', 0);
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall with UseRecalls disabled" );
|
||||
|
||||
t::lib::Mocks::mock_preference("UseRecalls", 1);
|
||||
|
||||
$item1->update({ notforloan => 1 });
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall that is not for loan" );
|
||||
$item1->update({ notforloan => 0, itemlost => 1 });
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall that is marked lost" );
|
||||
$item1->update({ itemlost => 0, withdrawn => 1 });
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall that is withdrawn" );
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall item if not checked out" );
|
||||
|
||||
$item1->update({ withdrawn => 0 });
|
||||
C4::Circulation::AddIssue( $patron2->unblessed, $item1->barcode );
|
||||
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron1->categorycode,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 0,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'all',
|
||||
},
|
||||
});
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if recalls_allowed = 0" );
|
||||
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron1->categorycode,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 1,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'all',
|
||||
},
|
||||
});
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if patron has more existing recall(s) than recalls_allowed" );
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if patron has more existing recall(s) than recalls_per_record" );
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if patron has already recalled this item" );
|
||||
|
||||
my $reserve_id = C4::Reserves::AddReserve({ branchcode => $branchcode, borrowernumber => $patron1->borrowernumber, biblionumber => $item1->biblionumber, itemnumber => $item1->itemnumber });
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall item if patron has already reserved it" );
|
||||
C4::Reserves::ModReserve({ rank => 'del', reserve_id => $reserve_id, branchcode => $branchcode, itemnumber => $item1->itemnumber, borrowernumber => $patron1->borrowernumber, biblionumber => $item1->biblionumber });
|
||||
|
||||
$recall1->set_cancelled;
|
||||
is( $item1->can_be_recalled({ patron => $patron2 }), 0, "Can't recall if patron has already checked out an item attached to this biblio" );
|
||||
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if on_shelf_recalls = all and items are still available" );
|
||||
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => $branchcode,
|
||||
categorycode => $patron1->categorycode,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 1,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'any',
|
||||
},
|
||||
});
|
||||
C4::Circulation::AddReturn( $item1->barcode, $branchcode );
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 0, "Can't recall if no items are checked out" );
|
||||
|
||||
C4::Circulation::AddIssue( $patron2->unblessed, $item1->barcode );
|
||||
is( $item1->can_be_recalled({ patron => $patron1 }), 1, "Can recall item" );
|
||||
|
||||
$recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => undef,
|
||||
expirationdate => undef,
|
||||
item_level_recall => 0
|
||||
})->store;
|
||||
|
||||
# Patron2 has Item1 checked out. Patron1 has placed a biblio-level recall on Biblio1, so check if Item1 can fulfill Patron1's recall.
|
||||
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => undef,
|
||||
categorycode => undef,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 0,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'any',
|
||||
},
|
||||
});
|
||||
is( $item1->can_be_waiting_recall, 0, "Recalls not allowed for this itemtype" );
|
||||
|
||||
Koha::CirculationRules->set_rules({
|
||||
branchcode => undef,
|
||||
categorycode => undef,
|
||||
itemtype => $item1->effective_itemtype,
|
||||
rules => {
|
||||
recalls_allowed => 1,
|
||||
recalls_per_record => 1,
|
||||
on_shelf_recalls => 'any',
|
||||
},
|
||||
});
|
||||
is( $item1->can_be_waiting_recall, 1, "Recalls are allowed for this itemtype" );
|
||||
|
||||
# check_recalls tests
|
||||
|
||||
$recall1 = Koha::Recall->new({
|
||||
borrowernumber => $patron2->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => $item1->itemnumber,
|
||||
expirationdate => undef,
|
||||
item_level_recall => 1
|
||||
})->store;
|
||||
$recall2 = Koha::Recall->new({
|
||||
borrowernumber => $patron1->borrowernumber,
|
||||
recalldate => Koha::DateUtils::dt_from_string,
|
||||
biblionumber => $biblio->biblionumber,
|
||||
branchcode => $branchcode,
|
||||
status => 'R',
|
||||
itemnumber => undef,
|
||||
expirationdate => undef,
|
||||
item_level_recall => 0
|
||||
})->store;
|
||||
$recall2->set_waiting({ item => $item1 });
|
||||
|
||||
# return a waiting recall
|
||||
my $check_recall = $item1->check_recalls;
|
||||
is( $check_recall->borrowernumber, $patron1->borrowernumber, "Waiting recall is highest priority and returned" );
|
||||
|
||||
$recall2->revert_waiting;
|
||||
|
||||
# return recall based on recalldate
|
||||
$check_recall = $item1->check_recalls;
|
||||
is( $check_recall->borrowernumber, $patron1->borrowernumber, "No waiting recall, so oldest recall is returned" );
|
||||
|
||||
$recall1->set_cancelled;
|
||||
|
||||
# return a biblio-level recall
|
||||
$check_recall = $item1->check_recalls;
|
||||
is( $check_recall->borrowernumber, $patron1->borrowernumber, "Only remaining recall is returned" );
|
||||
|
||||
$recall2->set_cancelled;
|
||||
};
|
||||
|
||||
subtest 'store() tests' => sub {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
use Modern::Perl;
|
||||
|
||||
use Test::More tests => 14;
|
||||
use Test::More tests => 15;
|
||||
use Test::Exception;
|
||||
use Test::Warn;
|
||||
|
||||
|
|
@ -1048,6 +1048,57 @@ subtest 'messages' => sub {
|
|||
is( $messages->count, 2, "There are two messages for this patron" );
|
||||
is( $messages->next->message, $message_1->message );
|
||||
is( $messages->next->message, $message_2->message );
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'recalls() tests' => sub {
|
||||
|
||||
plan tests => 2;
|
||||
my $biblio1 = $builder->build_object({ class => 'Koha::Biblios' });
|
||||
my $item1 = $builder->build_object({ class => 'Koha::Items' }, { value => { biblionumber => $biblio1->biblionumber } });
|
||||
my $biblio2 = $builder->build_object({ class => 'Koha::Biblios' });
|
||||
my $item2 = $builder->build_object({ class => 'Koha::Items' }, { value => { biblionumber => $biblio2->biblionumber } });
|
||||
|
||||
Koha::Recall->new({
|
||||
biblionumber => $biblio1->biblionumber,
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
itemnumber => $item1->itemnumber,
|
||||
branchcode => $patron->branchcode,
|
||||
recalldate => dt_from_string,
|
||||
status => 'R',
|
||||
item_level_recall => 1,
|
||||
})->store;
|
||||
Koha::Recall->new({
|
||||
biblionumber => $biblio2->biblionumber,
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
itemnumber => $item2->itemnumber,
|
||||
branchcode => $patron->branchcode,
|
||||
recalldate => dt_from_string,
|
||||
status => 'R',
|
||||
item_level_recall => 1,
|
||||
})->store;
|
||||
Koha::Recall->new({
|
||||
biblionumber => $biblio1->biblionumber,
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
itemnumber => undef,
|
||||
branchcode => $patron->branchcode,
|
||||
recalldate => dt_from_string,
|
||||
status => 'R',
|
||||
item_level_recall => 0,
|
||||
})->store;
|
||||
my $recall = Koha::Recall->new({
|
||||
biblionumber => $biblio1->biblionumber,
|
||||
borrowernumber => $patron->borrowernumber,
|
||||
itemnumber => undef,
|
||||
branchcode => $patron->branchcode,
|
||||
recalldate => dt_from_string,
|
||||
status => 'R',
|
||||
item_level_recall => 0,
|
||||
})->store;
|
||||
$recall->set_cancelled;
|
||||
|
||||
is( $patron->recalls->count, 3, "Correctly gets this patron's active recalls" );
|
||||
is( $patron->recalls({ biblionumber => $biblio1->biblionumber })->count, 2, "Correctly gets this patron's active recalls on a specific biblio" );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ $return_error = $@;
|
|||
isnt ($return_error,'',"UpdateStats returns undef and croaks if type is undef");
|
||||
|
||||
# returns undef and croaks if mandatory params are missing
|
||||
my @allowed_circulation_types = qw (renew issue localuse return);
|
||||
my @allowed_circulation_types = qw (renew issue localuse return onsite_checkout recall);
|
||||
my @allowed_accounts_types = qw (writeoff payment);
|
||||
my @circulation_mandatory_keys = qw (branch borrowernumber itemnumber ccode itemtype); #don't check type here
|
||||
my @accounts_mandatory_keys = qw (branch borrowernumber amount); #don't check type here
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ subtest 'transformMARCXML4XSLT tests' => sub {
|
|||
};
|
||||
|
||||
subtest 'buildKohaItemsNamespace status tests' => sub {
|
||||
plan tests => 16;
|
||||
plan tests => 17;
|
||||
|
||||
t::lib::Mocks::mock_preference('Reference_NFL_Statuses', '1|2');
|
||||
t::lib::Mocks::mock_preference( 'OPACResultsLibrary', 'holdingbranch' );
|
||||
|
|
@ -131,7 +131,8 @@ subtest 'buildKohaItemsNamespace status tests' => sub {
|
|||
}
|
||||
});
|
||||
$xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]);
|
||||
like($xml,qr{<substatus>Waiting</substatus>},"Waiting status takes precedence over In transit");
|
||||
like($xml,qr{<substatus>Waiting</substatus>},"Waiting status takes precedence over In transit (holds)");
|
||||
$hold->cancel;
|
||||
|
||||
$builder->build({ source => "TmpHoldsqueue", value => {
|
||||
itemnumber => $item->itemnumber
|
||||
|
|
@ -141,6 +142,17 @@ subtest 'buildKohaItemsNamespace status tests' => sub {
|
|||
like($xml,qr{<substatus>Pending hold</substatus>},"Pending status takes precedence over all");
|
||||
my $library_name = $holdinglibrary->branchname;
|
||||
like($xml,qr{<resultbranch>${library_name}</resultbranch>}, "Found resultbranch / holding branch" );
|
||||
|
||||
my $recall = $builder->build_object({ class => 'Koha::Recalls', value => {
|
||||
biblionumber => $item->biblionumber,
|
||||
itemnumber => $item->itemnumber,
|
||||
branchcode => $item->holdingbranch,
|
||||
status => 'R',
|
||||
}});
|
||||
$recall->set_waiting;
|
||||
$xml = C4::XSLT::buildKohaItemsNamespace( $item->biblionumber,[]);
|
||||
like($xml,qr{<status>Waiting</status>},"Waiting status takes precedence over In transit (recalls)");
|
||||
|
||||
};
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
|
|
|
|||
Loading…
Reference in New Issue