X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=opac%2Fopac-reserve.pl;h=d0da2c5de6b16087358680d58d1e26c92ed59798;hb=afccbfcce7192c6e1fcd73f137135cb5289c3d3d;hp=98fa43ff1f63975dda6e96023e951dad16d44915;hpb=9e7c94bf96b9029187dfdd957457b13c9dbed718;p=koha.git diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl index 98fa43ff1f..d0da2c5de6 100755 --- a/opac/opac-reserve.pl +++ b/opac/opac-reserve.pl @@ -1,5 +1,8 @@ #!/usr/bin/perl +# Copyright Katipo Communications 2002 +# Copyright Koha Development team 2012 +# # This file is part of Koha. # # Koha is free software; you can redistribute it and/or modify it under the @@ -11,25 +14,28 @@ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU General Public License for more details. # -# You should have received a copy of the GNU General Public License along with -# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, -# Suite 330, Boston, MA 02111-1307 USA +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. use strict; -require Exporter; +use warnings; use CGI; -use C4::Biblio; -use C4::Items; use C4::Auth; # checkauth, getborrowernumber. use C4::Koha; use C4::Circulation; use C4::Reserves; +use C4::Biblio; +use C4::Items; use C4::Output; use C4::Dates qw/format_date/; use C4::Context; use C4::Members; use C4::Branch; # GetBranches -use Data::Dumper; +use C4::Overdues; +use C4::Debug; +use Koha::DateUtils; +# use Data::Dumper; my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves"); @@ -45,386 +51,524 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( } ); +my ($show_holds_count, $show_priority); +for ( C4::Context->preference("OPACShowHoldQueueDetails") ) { + m/holds/o and $show_holds_count = 1; + m/priority/ and $show_priority = 1; +} + +sub get_out { + output_html_with_http_headers(shift,shift,shift); # $query, $cookie, $template->output; + exit; +} + # get borrower information .... -my ( $borr, $flags ) = GetMemberDetails( $borrowernumber ); +my ( $borr ) = GetMemberDetails( $borrowernumber ); +# Pass through any reserve charge +if ($borr->{reservefee} > 0){ + $template->param( RESERVE_CHARGE => sprintf("%.2f",$borr->{reservefee})); +} # get branches and itemtypes my $branches = GetBranches(); -my $itemtypes = GetItemTypes(); - -# get biblionumber..... -my $biblionumber = $query->param('biblionumber'); +my $itemTypes = GetItemTypes(); + +# There are two ways of calling this script, with a single biblio num +# or multiple biblio nums. +my $biblionumbers = $query->param('biblionumbers'); +my $reserveMode = $query->param('reserve_mode'); +if ($reserveMode && ($reserveMode eq 'single')) { + my $bib = $query->param('single_bib'); + $biblionumbers = "$bib/"; +} +if (! $biblionumbers) { + $biblionumbers = $query->param('biblionumber'); +} -my $bibdata = GetBiblioData($biblionumber); -$template->param($bibdata); -$template->param( biblionumber => $biblionumber ); +if ((! $biblionumbers) && (! $query->param('place_reserve'))) { + $template->param(message=>1, no_biblionumber=>1); + &get_out($query, $cookie, $template->output); +} -# get the rank number.... -my ( $rank, $reserves ) = GetReservesFromBiblionumber( $biblionumber); -$template->param( reservecount => $rank ); +# Pass the numbers to the page so they can be fed back +# when the hold is confirmed. TODO: Not necessary? +$template->param( biblionumbers => $biblionumbers ); -foreach my $res (@$reserves) { - if ( $res->{'found'} eq 'W' ) { - $rank--; - } +# Each biblio number is suffixed with '/', e.g. "1/2/3/" +my @biblionumbers = split /\//, $biblionumbers; +if (($#biblionumbers < 0) && (! $query->param('place_reserve'))) { + # TODO: New message? + $template->param(message=>1, no_biblionumber=>1); + &get_out($query, $cookie, $template->output); } -$rank++; -$template->param( rank => $rank ); - # pass the pickup branch along.... -my $branch = $query->param('branch'); +my $branch = $query->param('branch') || $borr->{'branchcode'} || C4::Context->userenv->{branch} || '' ; +($branches->{$branch}) or $branch = ""; # Confirm branch is real $template->param( branch => $branch ); -# make sure it's a real branch -if ( !$branches->{$branch} ) { - $branch = ''; -} -$template->param( branchname => $branches->{$branch}->{'branchname'} ); - # make branch selection options... -my @branches; -my @select_branch; -my %select_branches; - -my @CGIbranchlooparray; - -foreach my $branch ( keys %$branches ) { - if ($branch) { - my %line; - $line{branch} = $branches->{$branch}->{'branchname'}; - $line{value} = $branch; - if ($line{value} eq C4::Context->userenv->{'branch'}) { - $line{selected} = 1; - } - push @CGIbranchlooparray, \%line; - } -} -@CGIbranchlooparray = - sort { $a->{branch} cmp $b->{branch} } @CGIbranchlooparray; -my $CGIbranchloop = \@CGIbranchlooparray; -$template->param( CGIbranch => $CGIbranchloop ); - -#### THIS IS A BIT OF A HACK BECAUSE THE BIBLIOITEMS DATA IS A LITTLE MESSED UP! -# get the itemtype data.... -my @items = GetItemsInfo($biblionumber); -####################################################### -# old version, add so that old templates still work -my %types_old; -foreach my $itm (@items) { - my $ity = $itm->{'itemtype'}; - unless ( $types_old{$ity} ) { - $types_old{$ity}->{'itemtype'} = $ity; - $types_old{$ity}->{'branchinfo'}->{ $itm->{'branchcode'} } = 1; - $types_old{$ity}->{'description'} = $itm->{'description'}; +my $branchloop = GetBranchesLoop($branch); + +# Is the person allowed to choose their branch +my $OPACChooseBranch = (C4::Context->preference("OPACAllowUserToChooseBranch")) ? 1 : 0; + +$template->param( choose_branch => $OPACChooseBranch); + +# +# +# Build hashes of the requested biblio(item)s and items. +# +# + +my %biblioDataHash; # Hash of biblionumber to biblio/biblioitems record. +my %itemInfoHash; # Hash of itemnumber to item info. +foreach my $biblioNumber (@biblionumbers) { + + my $biblioData = GetBiblioData($biblioNumber); + $biblioDataHash{$biblioNumber} = $biblioData; + + my @itemInfos = GetItemsInfo($biblioNumber); + + my $marcrecord= GetMarcBiblio($biblioNumber); + + # flag indicating existence of at least one item linked via a host record + my $hostitemsflag; + # adding items linked via host biblios + my @hostitemInfos = GetHostItemsInfo($marcrecord); + if (@hostitemInfos){ + $hostitemsflag =1; + push (@itemInfos,@hostitemInfos); } - else { - $types_old{$ity}->{'branchinfo'}->{ $itm->{'branchcode'} }++; + + $biblioData->{itemInfos} = \@itemInfos; + foreach my $itemInfo (@itemInfos) { + $itemInfoHash{$itemInfo->{itemnumber}} = $itemInfo; } -} -foreach my $type ( values %types_old ) { - my $copies = ""; - foreach my $bc ( keys %{ $type->{'branchinfo'} } ) { - $copies .= - $branches->{$bc}->{'branchname'} . "(" - . $type->{'branchinfo'}->{$bc} . ")"; + # Compute the priority rank. + my ( $rank, $reserves ) = + GetReservesFromBiblionumber( $biblioNumber, 1 ); + $biblioData->{reservecount} = 1; # new reserve + foreach my $res (@{$reserves}) { + my $found = $res->{found}; + if ( $found && $found eq 'W' ) { + $rank--; + } + else { + $biblioData->{reservecount}++; + } } - $type->{'copies'} = $copies; + $biblioData->{rank} = $rank + 1; } -my @types_old = values %types_old; +# +# +# If this is the second time through this script, it +# means we are carrying out the hold request, possibly +# with a specific item for each biblionumber. +# +# +if ( $query->param('place_reserve') ) { + my $notes = $query->param('notes'); + my $reserve_cnt = 0; + if ($MAXIMUM_NUMBER_OF_RESERVES) { + $reserve_cnt = GetReservesFromBorrowernumber( $borrowernumber ); + } -# end old version -################################ + # List is composed of alternating biblio/item/branch + my $selectedItems = $query->param('selecteditems'); -my @temp; -foreach my $itm (@items) { - push @temp, $itm if $itm->{'itemtype'}; -} -@items = @temp; -my $itemcount = @items; -$template->param( itemcount => $itemcount ); - -my %types; -my %itemtypes; -my @duedates; -#die @items; -foreach my $itm (@items) { - push @duedates, { date_due => format_date( $itm->{'date_due'} ) } - if defined $itm->{'date_due'}; - $itm->{ $itm->{'publictype'} } = 1; - my $fee = GetReserveFee( undef, $borrowernumber, $itm->{'biblionumber'}, - 'a', ( $itm->{'biblioitemnumber'} ) ); - $fee = sprintf "%.02f", $fee; - $itm->{'reservefee'} = $fee; - my $pty = $itm->{'publictype'}; - $itemtypes{ $itm->{'itemtype'} } = $itm; - unless ( $types{$pty} ) { - $types{$pty}->{'count'} = 1; - $types{$pty}->{ $itm->{'itemtype'} } = 1; - push @{ $types{$pty}->{'items'} }, $itm; - } - else { - unless ( $types{$pty}->{ $itm->{'itemtype'} } ) { - $types{$pty}->{'count'}++; - $types{$pty}->{ $itm->{'itemtype'} } = 1; - push @{ $types{$pty}->{'items'} }, $itm; + if ($query->param('reserve_mode') eq 'single') { + # This indicates non-JavaScript mode, so there was + # only a single biblio number selected. + my $bib = $query->param('single_bib'); + my $item = $query->param("checkitem_$bib"); + if ($item eq 'any') { + $item = ''; } + my $branch = $query->param('branch'); + $selectedItems = "$bib/$item/$branch/"; } -} -$template->param( ITEMS => \@duedates ); + $selectedItems =~ s!/$!!; + my @selectedItems = split /\//, $selectedItems, -1; -my $width = keys %types; -my @publictypes = sort { $b->{'count'} <=> $a->{'count'} } values %types; -my $typecount; -foreach my $pt (@publictypes) { - $typecount += $pt->{'count'}; -} -$template->param( onlyone => 1 ) if $typecount == 1; - -my @typerows; -for ( my $rownum = 0 ; $rownum < $publictypes[0]->{'count'} ; $rownum++ ) { - my @row; - foreach my $pty (@publictypes) { - my @items = @{ $pty->{'items'} }; - push @row, $items[$rownum] if defined $items[$rownum]; + # Make sure there is a biblionum/itemnum/branch triplet for each item. + # The itemnum can be 'any', meaning next available. + my $selectionCount = @selectedItems; + if (($selectionCount == 0) || (($selectionCount % 3) != 0)) { + $template->param(message=>1, bad_data=>1); + &get_out($query, $cookie, $template->output); } - my $last = @row; - $row[ $last - 1 ]->{'last'} = 1 if $last == $width; - my $fill = ( $width - $last ) * 2; - $fill-- if $fill; - push @typerows, { ROW => \@row, fill => $fill }; -} -$template->param( TYPE_ROWS => \@typerows ); -$width = 2 * $width - 1; -$template->param( totalwidth => 2 * $width - 1, ); -if ( $query->param('place_reserve') ) { - my @bibitems=$query->param('biblioitem'); - my $notes=$query->param('notes'); - my $checkitem=$query->param('checkitem'); - my $found; - - #if we have an item selectionned, and the pickup branch is the same as the holdingbranch of the document, we force the value $rank and $found. - if ($checkitem ne ''){ - $rank = '0' unless C4::Context->preference('ReservesNeedReturns'); - my $item = $checkitem; - $item = GetItem($item); - if ( $item->{'holdingbranch'} eq $branch ){ - $found = 'W' unless C4::Context->preference('ReservesNeedReturns'); + while (@selectedItems) { + my $biblioNum = shift(@selectedItems); + my $itemNum = shift(@selectedItems); + my $branch = shift(@selectedItems); # i.e., branch code, not name + + my $canreserve = 0; + + my $singleBranchMode = C4::Context->preference("singleBranchMode"); + if ( $singleBranchMode || !$OPACChooseBranch ) + { # single branch mode or disabled user choosing + $branch = $borr->{'branchcode'}; } - } - - my $count=@bibitems; - @bibitems=sort @bibitems; - my $i2=1; - my @realbi; - $realbi[0]=$bibitems[0]; - for (my $i=1;$i<$count;$i++) { - my $i3=$i2-1; - if ($realbi[$i3] ne $bibitems[$i]) { - $realbi[$i2]=$bibitems[$i]; - $i2++; + +#item may belong to a host biblio, if yes change biblioNum to hosts bilbionumber + if ( $itemNum ne '' ) { + my $hostbiblioNum = GetBiblionumberFromItemnumber($itemNum); + if ( $hostbiblioNum ne $biblioNum ) { + $biblioNum = $hostbiblioNum; + } } - } - # here we actually do the reserveration. Stage 3. - if ($query->param('request') eq 'any'){ - # place a request on 1st available - AddReserve($branch,$borrowernumber,$biblionumber,'a',\@realbi,$rank,$notes,$bibdata->{'title'},$checkitem,$found); - } else { - AddReserve($branch,$borrowernumber,$biblionumber,'a',\@realbi,$rank,$notes,$bibdata->{'title'},$checkitem, $found); - } - print $query->redirect("/cgi-bin/koha/opac-user.pl"); -} -else { - - # Here we check that the borrower can actually make reserves Stage 1. - my $noreserves = 0; - my $maxoutstanding = C4::Context->preference("maxoutstanding"); - $template->param( noreserve => 1 ) unless $maxoutstanding; - if ( $borr->{'amountoutstanding'} > $maxoutstanding ) { - my $amount = sprintf "\$%.02f", $borr->{'amountoutstanding'}; - $template->param( message => 1 ); - $noreserves = 1; - $template->param( too_much_oweing => $amount ); - } - if ( $borr->{gonenoaddress} eq 1 ) { - $noreserves = 1; - $template->param( - message => 1, - GNA => 1 - ); - } - if ( $borr->{lost} eq 1 ) { - $noreserves = 1; - $template->param( - message => 1, - lost => 1 - ); - } - if ( $borr->{debarred} eq 1 ) { - $noreserves = 1; - $template->param( - message => 1, - debarred => 1 - ); - } - my @reserves = GetReservesFromBorrowernumber( $borrowernumber ); - $template->param( RESERVES => \@reserves ); - if ( scalar(@$reserves) >= $MAXIMUM_NUMBER_OF_RESERVES ) { - $template->param( message => 1 ); - $noreserves = 1; - $template->param( too_many_reserves => scalar($reserves)); - } - foreach my $res (@$reserves) { - if ( $res->{'biblionumber'} == $biblionumber ) { - $template->param( message => 1 ); - $noreserves = 1; - $template->param( already_reserved => 1 ); + + my $biblioData = $biblioDataHash{$biblioNum}; + my $found; + + # Check for user supplied reserve date + my $startdate; + if ( C4::Context->preference('AllowHoldDateInFuture') + && C4::Context->preference('OPACAllowHoldDateInFuture') ) + { + $startdate = $query->param("reserve_date_$biblioNum"); + } + + my $expiration_date = $query->param("expiration_date_$biblioNum"); + + # If a specific item was selected and the pickup branch is the same as the + # holdingbranch, force the value $rank and $found. + my $rank = $biblioData->{rank}; + if ( $itemNum ne '' ) { + $canreserve = 1 if CanItemBeReserved( $borrowernumber, $itemNum ); + $rank = '0' unless C4::Context->preference('ReservesNeedReturns'); + my $item = GetItem($itemNum); + if ( $item->{'holdingbranch'} eq $branch ) { + $found = 'W' + unless C4::Context->preference('ReservesNeedReturns'); + } + } + else { + $canreserve = 1 if CanBookBeReserved( $borrowernumber, $biblioNum ); + + # Inserts a null into the 'itemnumber' field of 'reserves' table. + $itemNum = undef; + } + + if ( $MAXIMUM_NUMBER_OF_RESERVES + && $reserve_cnt >= $MAXIMUM_NUMBER_OF_RESERVES ) + { + $canreserve = 0; + } + + # Here we actually do the reserveration. Stage 3. + if ($canreserve) { + AddReserve( + $branch, $borrowernumber, + $biblioNum, 'a', + [$biblioNum], $rank, + $startdate, $expiration_date, + $notes, $biblioData->{title}, + $itemNum, $found + ); + ++$reserve_cnt; } } - unless ($noreserves) { - $template->param( TYPES => \@types_old ); - $template->param( select_item_types => 1 ); - } + + print $query->redirect("/cgi-bin/koha/opac-user.pl#opac-user-holds"); + exit; } +# +# +# Here we check that the borrower can actually make reserves Stage 1. +# +# +my $noreserves = 0; +my $maxoutstanding = C4::Context->preference("maxoutstanding"); +$template->param( noreserve => 1 ) unless $maxoutstanding; +if ( $borr->{'amountoutstanding'} && ($borr->{'amountoutstanding'} > $maxoutstanding) ) { + my $amount = sprintf "\$%.02f", $borr->{'amountoutstanding'}; + $template->param( message => 1 ); + $noreserves = 1; + $template->param( too_much_oweing => $amount ); +} +if ( $borr->{gonenoaddress} && ($borr->{gonenoaddress} == 1) ) { + $noreserves = 1; + $template->param( + message => 1, + GNA => 1 + ); +} +if ( $borr->{lost} && ($borr->{lost} == 1) ) { + $noreserves = 1; + $template->param( + message => 1, + lost => 1 + ); +} +if ( CheckBorrowerDebarred($borrowernumber) ) { + $noreserves = 1; + $template->param( + message => 1, + debarred => 1 + ); +} -my %itemnumbers_of_biblioitem; -my @itemnumbers = @{ get_itemnumbers_of($biblionumber)->{$biblionumber} }; -my $iteminfos_of = GetItemInfosOf(@itemnumbers); +my @reserves = GetReservesFromBorrowernumber( $borrowernumber ); +$template->param( RESERVES => \@reserves ); +if ( $MAXIMUM_NUMBER_OF_RESERVES && (scalar(@reserves) >= $MAXIMUM_NUMBER_OF_RESERVES) ) { + $template->param( message => 1 ); + $noreserves = 1; + $template->param( too_many_reserves => scalar(@reserves)); +} +foreach my $res (@reserves) { + foreach my $biblionumber (@biblionumbers) { + if ( $res->{'biblionumber'} == $biblionumber && $res->{'borrowernumber'} == $borrowernumber) { +# $template->param( message => 1 ); +# $noreserves = 1; +# $template->param( already_reserved => 1 ); + $biblioDataHash{$biblionumber}->{already_reserved} = 1; + } + } +} -foreach my $itemnumber (@itemnumbers) { - my $biblioitemnumber = $iteminfos_of->{$itemnumber}->{biblioitemnumber}; - push( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} }, $itemnumber ); +unless ($noreserves) { + $template->param( select_item_types => 1 ); } -my @biblioitemnumbers = keys %itemnumbers_of_biblioitem; +# +# +# Build the template parameters that will show the info +# and items for each biblionumber. +# +# my $notforloan_label_of = get_notforloan_label_of(); -my $biblioiteminfos_of = GetBiblioItemInfosOf(@biblioitemnumbers); -my @itemtypes; -foreach my $biblioitemnumber (@biblioitemnumbers) { - push @itemtypes, $biblioiteminfos_of->{$biblioitemnumber}{itemtype}; -} +my $biblioLoop = []; +my $numBibsAvailable = 0; +my $itemdata_enumchron = 0; +my $anyholdable = 0; +my $itemLevelTypes = C4::Context->preference('item-level_itypes'); +$template->param('item_level_itypes' => $itemLevelTypes); -my @bibitemloop; +foreach my $biblioNum (@biblionumbers) { -foreach my $biblioitemnumber (@biblioitemnumbers) { - my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber}; + my $record = GetMarcBiblio($biblioNum); + # Init the bib item with the choices for branch pickup + my %biblioLoopIter = ( branchloop => $branchloop ); - $biblioitem->{description} = - $itemtypes->{ $biblioitem->{itemtype} }{description}; + # Get relevant biblio data. + my $biblioData = $biblioDataHash{$biblioNum}; + if (! $biblioData) { + $template->param(message=>1, bad_biblionumber=>$biblioNum); + &get_out($query, $cookie, $template->output); + } - foreach - my $itemnumber ( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} } ) - { - my $item = $iteminfos_of->{$itemnumber}; + $biblioLoopIter{biblionumber} = $biblioData->{biblionumber}; + $biblioLoopIter{title} = $biblioData->{title}; + $biblioLoopIter{subtitle} = GetRecordValue('subtitle', $record, GetFrameworkCode($biblioData->{biblionumber})); + $biblioLoopIter{author} = $biblioData->{author}; + $biblioLoopIter{rank} = $biblioData->{rank}; + $biblioLoopIter{reservecount} = $biblioData->{reservecount}; + $biblioLoopIter{already_reserved} = $biblioData->{already_reserved}; + + if (!$itemLevelTypes && $biblioData->{itemtype}) { + $biblioLoopIter{description} = $itemTypes->{$biblioData->{itemtype}}{description}; + $biblioLoopIter{imageurl} = getitemtypeimagesrc() . "/". $itemTypes->{$biblioData->{itemtype}}{imageurl}; + } - $item->{homebranchname} = - $branches->{ $item->{homebranch} }{branchname}; + foreach my $itemInfo (@{$biblioData->{itemInfos}}) { + $debug and warn $itemInfo->{'notforloan'}; - # if the holdingbranch is different than the homebranch, we show the - # holdingbranch of the document too - if ( $item->{homebranch} ne $item->{holdingbranch} ) { - $item->{holdingbranchname} = - $branches->{ $item->{holdingbranch} }{branchname}; + # Get reserve fee. + my $fee = GetReserveFee(undef, $borrowernumber, $itemInfo->{'biblionumber'}, 'a', + ( $itemInfo->{'biblioitemnumber'} ) ); + $itemInfo->{'reservefee'} = sprintf "%.02f", ($fee ? $fee : 0.0); + + if ($itemLevelTypes && $itemInfo->{itype}) { + $itemInfo->{description} = $itemTypes->{$itemInfo->{itype}}{description}; + $itemInfo->{imageurl} = getitemtypeimagesrc() . "/". $itemTypes->{$itemInfo->{itype}}{imageurl}; + } + + if (!$itemInfo->{'notforloan'} && !($itemInfo->{'itemnotforloan'} > 0)) { + $biblioLoopIter{forloan} = 1; } - -# add information - $item->{itemcallnumber} = $item->{itemcallnumber}; - - # if the item is currently on loan, we display its return date and - # change the background color - my $issues= GetItemIssue($itemnumber); + } + + $biblioLoopIter{itemLoop} = []; + my $numCopiesAvailable = 0; + foreach my $itemInfo (@{$biblioData->{itemInfos}}) { + my $itemNum = $itemInfo->{itemnumber}; + my $itemLoopIter = {}; + + $itemLoopIter->{itemnumber} = $itemNum; + $itemLoopIter->{barcode} = $itemInfo->{barcode}; + $itemLoopIter->{homeBranchName} = $branches->{$itemInfo->{homebranch}}{branchname}; + $itemLoopIter->{callNumber} = $itemInfo->{itemcallnumber}; + $itemLoopIter->{enumchron} = $itemInfo->{enumchron}; + $itemLoopIter->{copynumber} = $itemInfo->{copynumber}; + if ($itemLevelTypes) { + $itemLoopIter->{description} = $itemInfo->{description}; + $itemLoopIter->{imageurl} = $itemInfo->{imageurl}; + } + + # If the holdingbranch is different than the homebranch, we show the + # holdingbranch of the document too. + if ( $itemInfo->{homebranch} ne $itemInfo->{holdingbranch} ) { + $itemLoopIter->{holdingBranchName} = + $branches->{ $itemInfo->{holdingbranch} }{branchname}; + } + + # If the item is currently on loan, we display its return date and + # change the background color. + my $issues= GetItemIssue($itemNum); if ( $issues->{'date_due'} ) { - $item->{date_due} = format_date($issues->{'date_due'}); - $item->{backgroundcolor} = 'onloan'; + $itemLoopIter->{dateDue} = format_sqlduedatetime($issues->{date_due}); + $itemLoopIter->{backgroundcolor} = 'onloan'; } # checking reserve - my ($reservedate,$reservedfor,$expectedAt) = GetReservesFromItemnumber($itemnumber); + my ($reservedate,$reservedfor,$expectedAt) = GetReservesFromItemnumber($itemNum); my $ItemBorrowerReserveInfo = GetMemberDetails( $reservedfor, 0); + # the item could be reserved for this borrower vi a host record, flag this + if ($reservedfor eq $borrowernumber){ + $itemLoopIter->{already_reserved} = 1; + } + if ( defined $reservedate ) { - $item->{backgroundcolor} = 'reserved'; - $item->{reservedate} = format_date($reservedate); - $item->{ReservedForBorrowernumber} = $reservedfor; - $item->{ReservedForSurname} = $ItemBorrowerReserveInfo->{'surname'}; - $item->{ReservedForFirstname} = $ItemBorrowerReserveInfo->{'firstname'}; - $item->{ExpectedAtLibrary} = $expectedAt; - + $itemLoopIter->{backgroundcolor} = 'reserved'; + $itemLoopIter->{reservedate} = format_date($reservedate); + $itemLoopIter->{ReservedForBorrowernumber} = $reservedfor; + $itemLoopIter->{ReservedForSurname} = $ItemBorrowerReserveInfo->{'surname'}; + $itemLoopIter->{ReservedForFirstname} = $ItemBorrowerReserveInfo->{'firstname'}; + $itemLoopIter->{ExpectedAtLibrary} = $expectedAt; } + $itemLoopIter->{notforloan} = $itemInfo->{notforloan}; + $itemLoopIter->{itemnotforloan} = $itemInfo->{itemnotforloan}; + # Management of the notforloan document - if ( $item->{notforloan} ) { - $item->{backgroundcolor} = 'other'; - $item->{notforloanvalue} = - $notforloan_label_of->{ $item->{notforloan} }; + if ( $itemLoopIter->{notforloan} || $itemLoopIter->{itemnotforloan}) { + $itemLoopIter->{backgroundcolor} = 'other'; + $itemLoopIter->{notforloanvalue} = + $notforloan_label_of->{ $itemLoopIter->{notforloan} }; } # Management of lost or long overdue items - if ( $item->{itemlost} ) { + if ( $itemInfo->{itemlost} ) { # FIXME localized strings should never be in Perl code - $item->{message} = - $item->{itemlost} == 1 ? "(lost)" - : $item->{itemlost} == 2 ? "(long overdue)" + $itemLoopIter->{message} = + $itemInfo->{itemlost} == 1 ? "(lost)" + : $itemInfo->{itemlost} == 2 ? "(long overdue)" : ""; - $item->{backgroundcolor} = 'other'; + $itemInfo->{backgroundcolor} = 'other'; } # Check of the transfered documents my ( $transfertwhen, $transfertfrom, $transfertto ) = - GetTransfers($itemnumber); - - if ( $transfertwhen ne '' ) { - $item->{transfertwhen} = format_date($transfertwhen); - $item->{transfertfrom} = + GetTransfers($itemNum); + if ( $transfertwhen && ($transfertwhen ne '') ) { + $itemLoopIter->{transfertwhen} = format_date($transfertwhen); + $itemLoopIter->{transfertfrom} = $branches->{$transfertfrom}{branchname}; - $item->{transfertto} = $branches->{$transfertto}{branchname}; - $item->{nocancel} = 1; + $itemLoopIter->{transfertto} = $branches->{$transfertto}{branchname}; + $itemLoopIter->{nocancel} = 1; } + # if the items belongs to a host record, show link to host record + if ($itemInfo->{biblionumber} ne $biblioNum){ + $biblioLoopIter{hostitemsflag} = 1; + $itemLoopIter->{hostbiblionumber} = $itemInfo->{biblionumber}; + $itemLoopIter->{hosttitle} = GetBiblioData($itemInfo->{biblionumber})->{title}; + } + # If there is no loan, return and transfer, we show a checkbox. - $item->{notforloan} = $item->{notforloan} || 0; - - # FIXME: every library will define this differently - # An item is available only if: - if ( - not defined $reservedate # not reserved yet - and $issues->{'date_due'} eq '' # not currently on loan - and not $item->{itemlost} # not lost - and not $item->{notforloan} # not forbidden to loan - and $transfertwhen eq '' # not currently on transfert - ) - { - $item->{available} = 1; + $itemLoopIter->{notforloan} = $itemLoopIter->{notforloan} || 0; + + my $branch = ( C4::Context->preference('ReservesControlBranch') eq 'ItemHomeLibrary' ) ? $itemInfo->{'homebranch'} : $borr->{'branchcode'}; + + my $branchitemrule = GetBranchItemRule( $branch, $itemInfo->{'itype'} ); + my $policy_holdallowed = 1; + + if ( $branchitemrule->{'holdallowed'} == 0 || + ( $branchitemrule->{'holdallowed'} == 1 && $borr->{'branchcode'} ne $itemInfo->{'homebranch'} ) ) { + $policy_holdallowed = 0; + } + + if (IsAvailableForItemLevelRequest($itemNum) and $policy_holdallowed and CanItemBeReserved($borrowernumber,$itemNum) and ($itemLoopIter->{already_reserved} ne 1)) { + $itemLoopIter->{available} = 1; + $numCopiesAvailable++; } # FIXME: move this to a pm my $dbh = C4::Context->dbh; - my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W' AND cancellationdate IS NULL"); - $sth2->execute($item->{ReservedForBorrowernumber},$item->{itemnumber}); + my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W'"); + $sth2->execute($itemLoopIter->{ReservedForBorrowernumber}, $itemNum); while (my $wait_hashref = $sth2->fetchrow_hashref) { - $item->{waitingdate} = format_date($wait_hashref->{waitingdate}); + $itemLoopIter->{waitingdate} = format_date($wait_hashref->{waitingdate}); + } + $itemLoopIter->{imageurl} = getitemtypeimagelocation( 'opac', $itemTypes->{ $itemInfo->{itype} }{imageurl} ); + + # Show serial enumeration when needed + if ($itemLoopIter->{enumchron}) { + $itemdata_enumchron = 1; } - $item->{imageurl} = getitemtypeimagesrc() . "/".$itemtypes->{ $item->{itype} }{imageurl}; - push @{ $biblioitem->{itemloop} }, $item; + + push @{$biblioLoopIter{itemLoop}}, $itemLoopIter; + } + $template->param( itemdata_enumchron => $itemdata_enumchron ); + + if ($numCopiesAvailable > 0) { + $numBibsAvailable++; + $biblioLoopIter{bib_available} = 1; + $biblioLoopIter{holdable} = 1; } + if ($biblioLoopIter{already_reserved}) { + $biblioLoopIter{holdable} = undef; + } + if(not CanBookBeReserved($borrowernumber,$biblioNum)){ + $biblioLoopIter{holdable} = undef; + } + if(not C4::Context->preference('AllowHoldsOnPatronsPossessions') and CheckIfIssuedToPatron($borrowernumber,$biblioNum)) { + $biblioLoopIter{holdable} = undef; + $biblioLoopIter{already_patron_possession} = 1; + } + + if( $biblioLoopIter{holdable} ){ $anyholdable++; } - push @bibitemloop, $biblioitem; + push @$biblioLoop, \%biblioLoopIter; } +if ( $numBibsAvailable == 0 || $anyholdable == 0) { + $template->param( none_available => 1 ); +} + +my $itemTableColspan = 7; +if (! $template->{VARS}->{'OPACItemHolds'}) { + $itemTableColspan--; +} +if (! $template->{VARS}->{'singleBranchMode'}) { + $itemTableColspan--; +} +$template->param(itemtable_colspan => $itemTableColspan); + # display infos -$template->param( - bibitemloop => \@bibitemloop, -); +$template->param(bibitemloop => $biblioLoop); +$template->param( showholds=>$show_holds_count); +$template->param( showpriority=>$show_priority); +# can set reserve date in future +if ( + C4::Context->preference( 'AllowHoldDateInFuture' ) && + C4::Context->preference( 'OPACAllowHoldDateInFuture' ) + ) { + $template->param( + reserve_in_future => 1, + ); +} + output_html_with_http_headers $query, $cookie, $template->output; -# Local Variables: -# tab-width: 8 -# End: