forgot to add imageurl to OPAC
[koha.git] / opac / opac-reserve.pl
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
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
8 # version.
9 #
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.
13 #
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
17
18 use strict;
19 require Exporter;
20 use CGI;
21 use C4::Biblio;
22 use C4::Auth;    # checkauth, getborrowernumber.
23 use C4::Koha;
24 use C4::Circulation;
25 use C4::Reserves;
26 use C4::Output;
27 use C4::Dates qw/format_date/;
28 use C4::Context;
29 use C4::Members;
30 use C4::Branch; # GetBranches
31 use Data::Dumper;
32
33 my $MAXIMUM_NUMBER_OF_RESERVES = C4::Context->preference("maxreserves");
34
35 my $query = new CGI;
36 my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
37     {
38         template_name   => "opac-reserve.tmpl",
39         query           => $query,
40         type            => "opac",
41         authnotrequired => 0,
42         flagsrequired   => { borrow => 1 },
43         debug           => 1,
44     }
45 );
46
47 # get borrower information ....
48 my ( $borr, $flags ) = GetMemberDetails( $borrowernumber );
49
50 # get branches and itemtypes
51 my $branches = GetBranches();
52 my $itemtypes = GetItemTypes();
53
54 # get biblionumber.....
55 my $biblionumber = $query->param('biblionumber');
56
57 my $bibdata = GetBiblioData($biblionumber);
58 $template->param($bibdata);
59 $template->param( biblionumber => $biblionumber );
60
61 # get the rank number....
62 my ( $rank, $reserves ) = GetReservesFromBiblionumber( $biblionumber);
63 $template->param( reservecount => $rank );
64
65 foreach my $res (@$reserves) {
66     if ( $res->{'found'} eq 'W' ) {
67         $rank--;
68     }
69 }
70
71 $rank++;
72 $template->param( rank => $rank );
73
74 # pass the pickup branch along....
75 my $branch = $query->param('branch');
76 $template->param( branch => $branch );
77
78 # make sure it's a real branch
79 if ( !$branches->{$branch} ) {
80     $branch = '';
81 }
82 $template->param( branchname => $branches->{$branch}->{'branchname'} );
83
84 # make branch selection options...
85 my @branches;
86 my @select_branch;
87 my %select_branches;
88
89 my @CGIbranchlooparray;
90
91 foreach my $branch ( keys %$branches ) {
92     if ($branch) {
93         my %line;
94         $line{branch} = $branches->{$branch}->{'branchname'};
95         $line{value}  = $branch;
96         if ($line{value} eq C4::Context->userenv->{'branch'}) {
97             $line{selected} = 1;
98         }
99         push @CGIbranchlooparray, \%line;
100     }
101 }
102 @CGIbranchlooparray =
103   sort { $a->{branch} cmp $b->{branch} } @CGIbranchlooparray;
104 my $CGIbranchloop = \@CGIbranchlooparray;
105 $template->param( CGIbranch => $CGIbranchloop );
106
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
112 my %types_old;
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'};
119     }
120     else {
121         $types_old{$ity}->{'branchinfo'}->{ $itm->{'branchcode'} }++;
122     }
123 }
124
125 foreach my $type ( values %types_old ) {
126     my $copies = "";
127     foreach my $bc ( keys %{ $type->{'branchinfo'} } ) {
128         $copies .=
129             $branches->{$bc}->{'branchname'} . "("
130           . $type->{'branchinfo'}->{$bc} . ")";
131     }
132     $type->{'copies'} = $copies;
133 }
134
135 my @types_old = values %types_old;
136
137 # end old version
138 ################################
139
140 my @temp;
141 foreach my $itm (@items) {
142     push @temp, $itm if $itm->{'itemtype'};
143 }
144 @items = @temp;
145 my $itemcount = @items;
146 $template->param( itemcount => $itemcount );
147
148 my %types;
149 my %itemtypes;
150 my @duedates;
151 #die @items;
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;
166     }
167     else {
168         unless ( $types{$pty}->{ $itm->{'itemtype'} } ) {
169             $types{$pty}->{'count'}++;
170             $types{$pty}->{ $itm->{'itemtype'} } = 1;
171             push @{ $types{$pty}->{'items'} }, $itm;
172         }
173     }
174 }
175
176 $template->param( ITEMS => \@duedates );
177
178 my $width = keys %types;
179 my @publictypes = sort { $b->{'count'} <=> $a->{'count'} } values %types;
180 my $typecount;
181 foreach my $pt (@publictypes) {
182     $typecount += $pt->{'count'};
183 }
184 $template->param( onlyone => 1 ) if $typecount == 1;
185
186 my @typerows;
187 for ( my $rownum = 0 ; $rownum < $publictypes[0]->{'count'} ; $rownum++ ) {
188     my @row;
189     foreach my $pty (@publictypes) {
190         my @items = @{ $pty->{'items'} };
191         push @row, $items[$rownum] if defined $items[$rownum];
192     }
193     my $last = @row;
194     $row[ $last - 1 ]->{'last'} = 1 if $last == $width;
195     my $fill = ( $width - $last ) * 2;
196     $fill-- if $fill;
197     push @typerows, { ROW => \@row, fill => $fill };
198 }
199 $template->param( TYPE_ROWS => \@typerows );
200 $width = 2 * $width - 1;
201 $template->param( totalwidth => 2 * $width - 1, );
202
203 if ( $query->param('place_reserve') ) {
204     my @bibitems=$query->param('biblioitem');
205     my $notes=$query->param('notes');
206     my $checkitem=$query->param('checkitem');
207     my $found;
208     
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');
216         }
217     }
218         
219         my $count=@bibitems;
220     @bibitems=sort @bibitems;
221     my $i2=1;
222     my @realbi;
223     $realbi[0]=$bibitems[0];
224     for (my $i=1;$i<$count;$i++) {
225         my $i3=$i2-1;
226         if ($realbi[$i3] ne $bibitems[$i]) {
227             $realbi[$i2]=$bibitems[$i];
228             $i2++;
229         }
230     }
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);
235     } else {
236         AddReserve($branch,$borrowernumber,$biblionumber,'a',\@realbi,$rank,$notes,$bibdata->{'title'},$checkitem, $found);
237     }
238     print $query->redirect("/cgi-bin/koha/opac-user.pl");
239 }
240 else {
241
242     # Here we check that the borrower can actually make reserves Stage 1.
243     my $noreserves     = 0;
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 );
249         $noreserves = 1;
250         $template->param( too_much_oweing => $amount );
251     }
252     if ( $borr->{gonenoaddress} eq 1 ) {
253         $noreserves = 1;
254         $template->param(
255             message => 1,
256             GNA     => 1
257         );
258     }
259     if ( $borr->{lost} eq 1 ) {
260         $noreserves = 1;
261         $template->param(
262             message => 1,
263             lost    => 1
264         );
265     }
266     if ( $borr->{debarred} eq 1 ) {
267         $noreserves = 1;
268         $template->param(
269             message  => 1,
270             debarred => 1
271         );
272     }
273     my @reserves = GetReservesFromBorrowernumber( $borrowernumber );
274     $template->param( RESERVES => \@reserves );
275     if ( scalar(@$reserves) >= $MAXIMUM_NUMBER_OF_RESERVES ) {
276         $template->param( message => 1 );
277         $noreserves = 1;
278         $template->param( too_many_reserves => scalar($reserves));
279     }
280     foreach my $res (@$reserves) {
281         if ( $res->{'biblionumber'} == $biblionumber ) {
282             $template->param( message => 1 );
283             $noreserves = 1;
284             $template->param( already_reserved => 1 );
285         }
286     }
287     unless ($noreserves) {
288         $template->param( TYPES             => \@types_old );
289         $template->param( select_item_types => 1 );
290     }
291 }
292
293
294 my %itemnumbers_of_biblioitem;
295 my @itemnumbers  = @{ get_itemnumbers_of($biblionumber)->{$biblionumber} };
296 my $iteminfos_of = GetItemInfosOf(@itemnumbers);
297
298 foreach my $itemnumber (@itemnumbers) {
299     my $biblioitemnumber = $iteminfos_of->{$itemnumber}->{biblioitemnumber};
300     push( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} }, $itemnumber );
301 }
302
303 my @biblioitemnumbers = keys %itemnumbers_of_biblioitem;
304
305 my $notforloan_label_of = get_notforloan_label_of();
306 my $biblioiteminfos_of  = GetBiblioItemInfosOf(@biblioitemnumbers);
307
308 my @itemtypes;
309 foreach my $biblioitemnumber (@biblioitemnumbers) {
310     push @itemtypes, $biblioiteminfos_of->{$biblioitemnumber}{itemtype};
311 }
312
313 my @bibitemloop;
314
315 foreach my $biblioitemnumber (@biblioitemnumbers) {
316     my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber};
317
318     $biblioitem->{description} =
319       $itemtypes->{ $biblioitem->{itemtype} }{description};
320
321     foreach
322       my $itemnumber ( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} } )
323     {
324         my $item = $iteminfos_of->{$itemnumber};
325
326         $item->{homebranchname} =
327           $branches->{ $item->{homebranch} }{branchname};
328
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};
334         }
335         
336 #       add information
337         $item->{itemcallnumber} = $item->{itemcallnumber};
338         
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';
345         }
346
347         # checking reserve
348         my ($reservedate,$reservedfor,$expectedAt) = GetReservesFromItemnumber($itemnumber);
349         my $ItemBorrowerReserveInfo = GetMemberDetails( $reservedfor, 0);
350
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;
358             
359         }
360
361         # Management of the notforloan document
362         if ( $item->{notforloan} ) {
363             $item->{backgroundcolor} = 'other';
364             $item->{notforloanvalue} =
365               $notforloan_label_of->{ $item->{notforloan} };
366         }
367
368         # Management of lost or long overdue items
369         if ( $item->{itemlost} ) {
370
371             # FIXME localized strings should never be in Perl code
372             $item->{message} =
373                 $item->{itemlost} == 1 ? "(lost)"
374               : $item->{itemlost} == 2 ? "(long overdue)"
375               : "";
376             $item->{backgroundcolor} = 'other';
377         }
378
379         # Check of the transfered documents
380         my ( $transfertwhen, $transfertfrom, $transfertto ) =
381           GetTransfers($itemnumber);
382
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;
389         }
390
391         # If there is no loan, return and transfer, we show a checkbox.
392         $item->{notforloan} = $item->{notforloan} || 0;
393
394         # FIXME: every library will define this differently
395         # An item is available only if:
396         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
402           )
403         {
404             $item->{available} = 1;
405         }
406
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});
413         }
414         $item->{imageurl} = getitemtypeimagesrc() . "/".$itemtypes->{ $item->{itype} }{imageurl};
415         push @{ $biblioitem->{itemloop} }, $item;
416     }
417
418     push @bibitemloop, $biblioitem;
419 }
420
421 # display infos
422 $template->param(
423     bibitemloop       => \@bibitemloop,
424 );
425 output_html_with_http_headers $query, $cookie, $template->output;
426
427 # Local Variables:
428 # tab-width: 8
429 # End: