3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 2 of the License, or (at your option) any later
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along with
15 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
16 # Suite 330, Boston, MA 02111-1307 USA
22 use C4::Auth; # checkauth, getborrowernumber.
27 use C4::Dates qw/format_date/;
30 use C4::Branch; # GetBranches
33 my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves");
36 my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
38 template_name => "opac-reserve.tmpl",
42 flagsrequired => { borrow => 1 },
47 # get borrower information ....
48 my ( $borr, $flags ) = GetMemberDetails( $borrowernumber );
50 # get branches and itemtypes
51 my $branches = GetBranches();
52 my $itemtypes = GetItemTypes();
54 # get biblionumber.....
55 my $biblionumber = $query->param('biblionumber');
57 my $bibdata = GetBiblioData($biblionumber);
58 $template->param($bibdata);
59 $template->param( biblionumber => $biblionumber );
61 # get the rank number....
62 my ( $rank, $reserves ) = GetReservesFromBiblionumber( $biblionumber);
63 $template->param( reservecount => $rank );
65 foreach my $res (@$reserves) {
66 if ( $res->{'found'} eq 'W' ) {
72 $template->param( rank => $rank );
74 # pass the pickup branch along....
75 my $branch = $query->param('branch');
76 $template->param( branch => $branch );
78 # make sure it's a real branch
79 if ( !$branches->{$branch} ) {
82 $template->param( branchname => $branches->{$branch}->{'branchname'} );
84 # make branch selection options...
89 my @CGIbranchlooparray;
91 foreach my $branch ( keys %$branches ) {
94 $line{branch} = $branches->{$branch}->{'branchname'};
95 $line{value} = $branch;
96 if ($line{value} eq C4::Context->userenv->{'branch'}) {
99 push @CGIbranchlooparray, \%line;
102 @CGIbranchlooparray =
103 sort { $a->{branch} cmp $b->{branch} } @CGIbranchlooparray;
104 my $CGIbranchloop = \@CGIbranchlooparray;
105 $template->param( CGIbranch => $CGIbranchloop );
107 #### THIS IS A BIT OF A HACK BECAUSE THE BIBLIOITEMS DATA IS A LITTLE MESSED UP!
108 # get the itemtype data....
109 my @items = GetItemsInfo($biblionumber);
110 #######################################################
111 # old version, add so that old templates still work
113 foreach my $itm (@items) {
114 my $ity = $itm->{'itemtype'};
115 unless ( $types_old{$ity} ) {
116 $types_old{$ity}->{'itemtype'} = $ity;
117 $types_old{$ity}->{'branchinfo'}->{ $itm->{'branchcode'} } = 1;
118 $types_old{$ity}->{'description'} = $itm->{'description'};
121 $types_old{$ity}->{'branchinfo'}->{ $itm->{'branchcode'} }++;
125 foreach my $type ( values %types_old ) {
127 foreach my $bc ( keys %{ $type->{'branchinfo'} } ) {
129 $branches->{$bc}->{'branchname'} . "("
130 . $type->{'branchinfo'}->{$bc} . ")";
132 $type->{'copies'} = $copies;
135 my @types_old = values %types_old;
138 ################################
141 foreach my $itm (@items) {
142 push @temp, $itm if $itm->{'itemtype'};
145 my $itemcount = @items;
146 $template->param( itemcount => $itemcount );
152 foreach my $itm (@items) {
153 push @duedates, { date_due => format_date( $itm->{'date_due'} ) }
154 if defined $itm->{'date_due'};
155 $itm->{ $itm->{'publictype'} } = 1;
156 my $fee = GetReserveFee( undef, $borrowernumber, $itm->{'biblionumber'},
157 'a', ( $itm->{'biblioitemnumber'} ) );
158 $fee = sprintf "%.02f", $fee;
159 $itm->{'reservefee'} = $fee;
160 my $pty = $itm->{'publictype'};
161 $itemtypes{ $itm->{'itemtype'} } = $itm;
162 unless ( $types{$pty} ) {
163 $types{$pty}->{'count'} = 1;
164 $types{$pty}->{ $itm->{'itemtype'} } = 1;
165 push @{ $types{$pty}->{'items'} }, $itm;
168 unless ( $types{$pty}->{ $itm->{'itemtype'} } ) {
169 $types{$pty}->{'count'}++;
170 $types{$pty}->{ $itm->{'itemtype'} } = 1;
171 push @{ $types{$pty}->{'items'} }, $itm;
176 $template->param( ITEMS => \@duedates );
178 my $width = keys %types;
179 my @publictypes = sort { $b->{'count'} <=> $a->{'count'} } values %types;
181 foreach my $pt (@publictypes) {
182 $typecount += $pt->{'count'};
184 $template->param( onlyone => 1 ) if $typecount == 1;
187 for ( my $rownum = 0 ; $rownum < $publictypes[0]->{'count'} ; $rownum++ ) {
189 foreach my $pty (@publictypes) {
190 my @items = @{ $pty->{'items'} };
191 push @row, $items[$rownum] if defined $items[$rownum];
194 $row[ $last - 1 ]->{'last'} = 1 if $last == $width;
195 my $fill = ( $width - $last ) * 2;
197 push @typerows, { ROW => \@row, fill => $fill };
199 $template->param( TYPE_ROWS => \@typerows );
200 $width = 2 * $width - 1;
201 $template->param( totalwidth => 2 * $width - 1, );
203 if ( $query->param('place_reserve') ) {
204 my @bibitems=$query->param('biblioitem');
205 my $notes=$query->param('notes');
206 my $checkitem=$query->param('checkitem');
209 #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.
210 if ($checkitem ne ''){
211 $rank = '0' unless C4::Context->preference('ReservesNeedReturns');
212 my $item = $checkitem;
213 $item = GetItem($item);
214 if ( $item->{'holdingbranch'} eq $branch ){
215 $found = 'W' unless C4::Context->preference('ReservesNeedReturns');
220 @bibitems=sort @bibitems;
223 $realbi[0]=$bibitems[0];
224 for (my $i=1;$i<$count;$i++) {
226 if ($realbi[$i3] ne $bibitems[$i]) {
227 $realbi[$i2]=$bibitems[$i];
231 # here we actually do the reserveration. Stage 3.
232 if ($query->param('request') eq 'any'){
233 # place a request on 1st available
234 AddReserve($branch,$borrowernumber,$biblionumber,'a',\@realbi,$rank,$notes,$bibdata->{'title'},$checkitem,$found);
236 AddReserve($branch,$borrowernumber,$biblionumber,'a',\@realbi,$rank,$notes,$bibdata->{'title'},$checkitem, $found);
238 print $query->redirect("/cgi-bin/koha/opac-user.pl");
242 # Here we check that the borrower can actually make reserves Stage 1.
244 my $maxoutstanding = C4::Context->preference("maxoutstanding");
245 $template->param( noreserve => 1 ) unless $maxoutstanding;
246 if ( $borr->{'amountoutstanding'} > $maxoutstanding ) {
247 my $amount = sprintf "\$%.02f", $borr->{'amountoutstanding'};
248 $template->param( message => 1 );
250 $template->param( too_much_oweing => $amount );
252 if ( $borr->{gonenoaddress} eq 1 ) {
259 if ( $borr->{lost} eq 1 ) {
266 if ( $borr->{debarred} eq 1 ) {
273 my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
274 $template->param( RESERVES => \@reserves );
275 if ( scalar(@$reserves) >= $MAXIMUM_NUMBER_OF_RESERVES ) {
276 $template->param( message => 1 );
278 $template->param( too_many_reserves => scalar($reserves));
280 foreach my $res (@$reserves) {
281 if ( $res->{'biblionumber'} == $biblionumber ) {
282 $template->param( message => 1 );
284 $template->param( already_reserved => 1 );
287 unless ($noreserves) {
288 $template->param( TYPES => \@types_old );
289 $template->param( select_item_types => 1 );
294 my %itemnumbers_of_biblioitem;
295 my @itemnumbers = @{ get_itemnumbers_of($biblionumber)->{$biblionumber} };
296 my $iteminfos_of = GetItemInfosOf(@itemnumbers);
298 foreach my $itemnumber (@itemnumbers) {
299 my $biblioitemnumber = $iteminfos_of->{$itemnumber}->{biblioitemnumber};
300 push( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} }, $itemnumber );
303 my @biblioitemnumbers = keys %itemnumbers_of_biblioitem;
305 my $notforloan_label_of = get_notforloan_label_of();
306 my $biblioiteminfos_of = GetBiblioItemInfosOf(@biblioitemnumbers);
309 foreach my $biblioitemnumber (@biblioitemnumbers) {
310 push @itemtypes, $biblioiteminfos_of->{$biblioitemnumber}{itemtype};
315 foreach my $biblioitemnumber (@biblioitemnumbers) {
316 my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber};
318 $biblioitem->{description} =
319 $itemtypes->{ $biblioitem->{itemtype} }{description};
322 my $itemnumber ( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} } )
324 my $item = $iteminfos_of->{$itemnumber};
326 $item->{homebranchname} =
327 $branches->{ $item->{homebranch} }{branchname};
329 # if the holdingbranch is different than the homebranch, we show the
330 # holdingbranch of the document too
331 if ( $item->{homebranch} ne $item->{holdingbranch} ) {
332 $item->{holdingbranchname} =
333 $branches->{ $item->{holdingbranch} }{branchname};
337 $item->{itemcallnumber} = $item->{itemcallnumber};
339 # if the item is currently on loan, we display its return date and
340 # change the background color
341 my $issues= GetItemIssue($itemnumber);
342 if ( $issues->{'date_due'} ) {
343 $item->{date_due} = format_date($issues->{'date_due'});
344 $item->{backgroundcolor} = 'onloan';
348 my ($reservedate,$reservedfor,$expectedAt) = GetReservesFromItemnumber($itemnumber);
349 my $ItemBorrowerReserveInfo = GetMemberDetails( $reservedfor, 0);
351 if ( defined $reservedate ) {
352 $item->{backgroundcolor} = 'reserved';
353 $item->{reservedate} = format_date($reservedate);
354 $item->{ReservedForBorrowernumber} = $reservedfor;
355 $item->{ReservedForSurname} = $ItemBorrowerReserveInfo->{'surname'};
356 $item->{ReservedForFirstname} = $ItemBorrowerReserveInfo->{'firstname'};
357 $item->{ExpectedAtLibrary} = $expectedAt;
361 # Management of the notforloan document
362 if ( $item->{notforloan} ) {
363 $item->{backgroundcolor} = 'other';
364 $item->{notforloanvalue} =
365 $notforloan_label_of->{ $item->{notforloan} };
368 # Management of lost or long overdue items
369 if ( $item->{itemlost} ) {
371 # FIXME localized strings should never be in Perl code
373 $item->{itemlost} == 1 ? "(lost)"
374 : $item->{itemlost} == 2 ? "(long overdue)"
376 $item->{backgroundcolor} = 'other';
379 # Check of the transfered documents
380 my ( $transfertwhen, $transfertfrom, $transfertto ) =
381 GetTransfers($itemnumber);
383 if ( $transfertwhen ne '' ) {
384 $item->{transfertwhen} = format_date($transfertwhen);
385 $item->{transfertfrom} =
386 $branches->{$transfertfrom}{branchname};
387 $item->{transfertto} = $branches->{$transfertto}{branchname};
388 $item->{nocancel} = 1;
391 # If there is no loan, return and transfer, we show a checkbox.
392 $item->{notforloan} = $item->{notforloan} || 0;
394 # FIXME: every library will define this differently
395 # An item is available only if:
397 not defined $reservedate # not reserved yet
398 and $issues->{'date_due'} eq '' # not currently on loan
399 and not $item->{itemlost} # not lost
400 and not $item->{notforloan} # not forbidden to loan
401 and $transfertwhen eq '' # not currently on transfert
404 $item->{available} = 1;
407 # FIXME: move this to a pm
408 my $dbh = C4::Context->dbh;
409 my $sth2 = $dbh->prepare("SELECT * FROM reserves WHERE borrowernumber=? AND itemnumber=? AND found='W' AND cancellationdate IS NULL");
410 $sth2->execute($item->{ReservedForBorrowernumber},$item->{itemnumber});
411 while (my $wait_hashref = $sth2->fetchrow_hashref) {
412 $item->{waitingdate} = format_date($wait_hashref->{waitingdate});
414 $item->{imageurl} = getitemtypeimagesrc() . "/".$itemtypes->{ $item->{itype} }{imageurl};
415 push @{ $biblioitem->{itemloop} }, $item;
418 push @bibitemloop, $biblioitem;
423 bibitemloop => \@bibitemloop,
425 output_html_with_http_headers $query, $cookie, $template->output;