bug fix : for item reservation, now the system don't keep the reserve if the document...
[koha.git] / reserve / request.pl
1 #!/usr/bin/perl
2
3 # $Id$
4
5 #script to place reserves/requests
6 #writen 2/1/00 by chris@katipo.oc.nz
7
8
9 # Copyright 2000-2002 Katipo Communications
10 #
11 # This file is part of Koha.
12 #
13 # Koha is free software; you can redistribute it and/or modify it under the
14 # terms of the GNU General Public License as published by the Free Software
15 # Foundation; either version 2 of the License, or (at your option) any later
16 # version.
17 #
18 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
19 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
20 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License along with
23 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
24 # Suite 330, Boston, MA  02111-1307 USA
25
26 use strict;
27 use HTML::Template;
28 use CGI;
29 use Date::Manip;
30 use List::MoreUtils qw/uniq/;
31 use Data::Dumper;
32
33 use C4::Search;
34 use C4::Output;
35 use C4::Interface::CGI::Output;
36 use C4::Auth;
37 use C4::Reserves2;
38 use C4::Biblio;
39 use C4::Koha;
40 use C4::Circulation::Circ2;
41 use C4::Acquisition;
42 use C4::Date;
43 use C4::Members;
44
45 my $dbh = C4::Context->dbh;
46 my $sth;
47 my $input = new CGI;
48 my ($template, $borrowernumber, $cookie)
49     = get_template_and_user({
50         template_name => "reserve/request.tmpl",
51         query => $input,
52         type => "intranet",
53         authnotrequired => 0,
54         flagsrequired => {reserveforothers => 1},
55     });
56
57 # get biblio information....
58 my $bib = $input->param('bib');
59 my $dat = bibdata($bib);
60
61 # Select borrowers infos
62 my $findborrower = $input->param('findborrower');
63 $findborrower =~ s|,| |g;
64 my $cardnumber = $input->param('cardnumber');
65 my %env;
66 my $borrowerslist;
67 my $messageborrower;
68
69 my $date = today();
70
71 if ($findborrower) {
72     my ($count,$borrowers) =  BornameSearch(\%env, $findborrower, 'cardnumber', 'web');
73
74     my @borrowers = @$borrowers;
75
76     if ($#borrowers == -1) {
77         $input->param('findborrower', '');
78         $messageborrower =  "'$findborrower'";
79     }
80     elsif ($#borrowers == 0) {
81         $input->param('cardnumber', $borrowers[0]->{'cardnumber'});
82         $cardnumber = $borrowers[0]->{'cardnumber'};
83     }
84     else {
85         $borrowerslist = \@borrowers;
86     }
87 }
88
89 if ($cardnumber) {
90         my $borrowerinfo = getpatroninformation (\%env,0,$cardnumber);
91         my $expiry;
92         my $diffbranch;
93         my @getreservloop;
94         my $count_reserv = 0;
95         my $maxreserves;
96
97 #       we check the reserves of the borrower, and if he can reserv a document
98 # FIXME At this time we have a simple count of reservs, but, later, we could improve the infos "title" ...
99
100         my $number_reserves =
101             GetNumberReservesFromBorrower($borrowerinfo->{'borrowernumber'});
102
103         if ($number_reserves > C4::Context->preference('maxreserves')) {
104             $maxreserves = 1;
105         }
106
107 # we check the date expiricy of the borrower
108         my $warning=Date_Cmp(ParseDate("today"),format_date($borrowerinfo->{'dateexpiry'}));
109         if ( $warning > 0) {
110                         $expiry = 1;
111         }
112
113 # check if the borrower make the reserv in a different branch
114         if ($borrowerinfo->{'branchcode'} ne C4::Context->userenv->{'branch'}) {
115                 $diffbranch = 1;
116         }
117
118         $template->param(
119                 borrowersurname => $borrowerinfo->{'surname'},
120                 borrowerfirstname => $borrowerinfo->{'firstname'},
121                 borrowerreservs => $count_reserv,
122                 maxreserves => $maxreserves,
123                 expiry => $expiry,
124                 diffbranch => $diffbranch
125         );
126 }
127
128 $template->param(
129     messageborrower => $messageborrower
130 );
131
132 my $CGIselectborrower;
133 if ($borrowerslist) {
134     my @values;
135     my %labels;
136
137     foreach my $borrower (
138         sort {$a->{surname}.$a->{firstname} cmp $b->{surname}.$b->{firstname}}
139             @{$borrowerslist}
140     ) {
141         push @values, $borrower->{cardnumber};
142
143         $labels{ $borrower->{cardnumber} } = sprintf(
144             '%s, %s ... (%s - %s) ... %s',
145             $borrower->{surname},
146             $borrower->{firstname},
147             $borrower->{cardnumber},
148             $borrower->{categorycode},
149             $borrower->{streetaddress},
150         );
151     }
152
153     $CGIselectborrower = CGI::scrolling_list(
154         -name     => 'cardnumber',
155         -values   => \@values,
156         -labels   => \%labels,
157         -size     => 7,
158         -multiple => 0,
159     );
160 }
161
162 # get existing reserves .....
163 my ($count, $reserves) = FindReserves($bib, undef);
164 my $totalcount = $count;
165 my $alreadyreserved;
166
167 # FIXME launch another time getpatroninformation perhaps until
168 my $borrowerinfo = getpatroninformation (\%env,0,$cardnumber);
169
170 foreach my $res (@$reserves) {
171     if (($res->{found} eq 'W') or ($res->{priority} == 0)) {
172         $count--;
173     }
174
175     if ($borrowerinfo->{borrowernumber} eq $res->{borrowernumber}) {
176         $alreadyreserved = 1;
177     }
178 }
179 $template->param(alreadyreserved => $alreadyreserved);
180
181 # make priorities options
182 my @optionloop;
183 for (1 .. $count + 1) {
184     push(
185         @optionloop,
186         {
187             num => $_,
188             selected => ($_ == $count + 1),
189         }
190     );
191 }
192
193 my @branchcodes;
194 my %itemnumbers_of_biblioitem;
195 my @itemnumbers = @{get_itemnumbers_of($bib)->{$bib}};
196 my $iteminfos_of = get_iteminfos_of(@itemnumbers);
197
198 foreach my $itemnumber (@itemnumbers) {
199     push(
200         @branchcodes,
201         $iteminfos_of->{$itemnumber}->{homebranch},
202         $iteminfos_of->{$itemnumber}->{holdingbranch}
203     );
204
205     my $biblioitemnumber = $iteminfos_of->{$itemnumber}->{biblioitemnumber};
206     push(
207         @{ $itemnumbers_of_biblioitem{$biblioitemnumber} },
208         $itemnumber
209     );
210 }
211
212 @branchcodes = uniq @branchcodes;
213
214 my @biblioitemnumbers = keys %itemnumbers_of_biblioitem;
215
216 my $branchinfos_of = get_branchinfos_of(@branchcodes);
217 my $notforloan_label_of = get_notforloan_label_of();
218 my $biblioiteminfos_of = get_biblioiteminfos_of(@biblioitemnumbers);
219
220 my @itemtypes;
221 foreach my $biblioitemnumber (@biblioitemnumbers) {
222     push @itemtypes, $biblioiteminfos_of->{$biblioitemnumber}{itemtype};
223 }
224
225 my $itemtypeinfos_of = get_itemtypeinfos_of(@itemtypes);
226
227 my $return_date_of = get_return_date_of(@itemnumbers);
228
229 my @bibitemloop;
230
231 foreach my $biblioitemnumber (@biblioitemnumbers) {
232     my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber};
233
234     $biblioitem->{description} =
235         $itemtypeinfos_of->{ $biblioitem->{itemtype} }{description};
236
237     foreach my $itemnumber (@{$itemnumbers_of_biblioitem{$biblioitemnumber}}) {
238         my $item = $iteminfos_of->{$itemnumber};
239
240         $item->{homebranchname} =
241             $branchinfos_of->{ $item->{homebranch} }{branchname};
242
243         # if the holdingbranch is different than the homebranch, we show the
244         # holdingbranch of the document too
245         if ($item->{homebranch} ne $item->{holdingbranch}) {
246             $item->{holdingbranchname} =
247                 $branchinfos_of->{ $item->{holdingbranch} }{branchname};
248         }
249
250         # if the item is currently on loan, we display its return date and
251         # change the background color
252         my $date_due;
253
254         if (defined $return_date_of->{$itemnumber}) {
255             $date_due = format_date($return_date_of->{$itemnumber});
256             $item->{date_due} = $date_due;
257             $item->{backgroundcolor} = 'onloan';
258         }
259
260         # checking reserve
261         my $reservedate = GetFirstReserveDateFromItem($itemnumber);
262
263         if (defined $reservedate) {
264             $item->{backgroundcolor} = 'reserved';
265             $item->{reservedate} = format_date($reservedate);
266         }
267
268         # Management of the notforloan document
269         if ($item->{notforloan}) {
270             $item->{backgroundcolor} = 'other';
271             $item->{notforloanvalue} =
272                 $notforloan_label_of->{ $item->{notforloan} };
273         }
274
275         # Management of lost or long overdue items
276         if ($item->{itemlost}) {
277
278             # FIXME localized strings should never be in Perl code
279             $item->{message} = $item->{itemlost} == 1
280                 ? "(lost)"
281                 : $item->{itemlost} == 2
282                     ? "(long overdue)"
283                     : "";
284             $item->{backgroundcolor} = 'other';
285         }
286
287         # Check of the transfered documents 
288         my ($transfertwhen,$transfertfrom,$transfertto) =
289             get_transfert_infos($itemnumber);
290
291         if ($transfertwhen ne '') {
292             $item->{transfertwhen} = format_date($transfertwhen);
293             $item->{transfertfrom} =
294                 $branchinfos_of->{$transfertfrom}{branchname};
295             $item->{transfertto} =
296                 $branchinfos_of->{$transfertto}{branchname};
297         }
298
299         # If there is no loan, return and transfer, we show a checkbox.
300         $item->{notforloan} = $item->{notforloan} || 0;
301
302         # An item is available only if:
303         if (not defined $reservedate      # not reserved yet
304             and $date_due eq ''           # not currently on loan
305             and not $item->{itemlost}     # not lost
306             and not $item->{notforloan}   # not forbidden to loan
307             and $transfertwhen eq ''      # not currently on transfert
308         ) {
309             $item->{available} = 1;
310         }
311
312         push @{$biblioitem->{itemloop}}, $item;
313     }
314
315     push @bibitemloop, $biblioitem;
316 }
317
318
319 # existingreserves building
320 my @reserveloop;
321 my $branches = getbranches();
322 foreach my $res (sort {$a->{found} cmp $b->{found}} @$reserves){
323     my %reserve;
324     my @optionloop;
325     for (my $i=1; $i <= $totalcount; $i++) {
326         push(
327             @optionloop,
328             {
329                 num => $i,
330                 selected => ($i == $res->{priority}),
331             }
332         );
333     }
334     my @branchloop;
335     foreach my $br (keys %$branches) {
336         my %abranch;
337         $abranch{'selected'}=($br eq $res->{'branchcode'});
338         $abranch{'branch'}=$br;
339         $abranch{'branchname'}=$branches->{$br}->{'branchname'};
340         push(@branchloop,\%abranch);
341     }
342
343     if (($res->{'found'} eq 'W') or ($res->{'priority'} eq '0')) {
344         my %env;
345         my $item = $res->{'itemnumber'};
346         $item = getiteminformation(\%env,$item);
347         $reserve{'holdingbranch'}=$item->{'holdingbranch'};
348         $reserve{'barcode'}=$item->{'barcode'};
349         $reserve{'biblionumber'}=$item->{'biblionumber'};
350         $reserve{'wbrcode'} = $res->{'branchcode'};
351         $reserve{'wbrname'} = $branches->{$res->{'branchcode'}}->{'branchname'};
352         if($reserve{'holdingbranch'} eq $reserve{'wbrcode'}){
353             $reserve{'atdestination'} = 1;
354         }
355     }
356
357     $reserve{'date'} = format_date($res->{'reservedate'});
358     $reserve{'borrowernumber'}=$res->{'borrowernumber'};
359     $reserve{'biblionumber'}=$res->{'biblionumber'};
360     $reserve{'bornum'}=$res->{'borrowernumber'};
361     $reserve{'firstname'}=$res->{'firstname'};
362     $reserve{'surname'}=$res->{'surname'};
363     $reserve{'bornum'}=$res->{'borrowernumber'};
364     $reserve{'notes'}=$res->{'reservenotes'};
365     $reserve{'wait'}=(($res->{'found'} eq 'W') or ($res->{'priority'} eq '0'));
366     $reserve{'constrainttypea'}=($res->{'constrainttype'} eq 'a');
367     $reserve{'constrainttypeo'}=($res->{'constrainttype'} eq 'o');
368     $reserve{'voldesc'}=$res->{'volumeddesc'};
369     $reserve{'itemtype'}=$res->{'itemtype'};
370     $reserve{'branchloop'}=\@branchloop;
371     $reserve{'optionloop'}=\@optionloop;
372
373     push(@reserveloop,\%reserve);
374 }
375
376 my $default = C4::Context->userenv->{branch};
377 my @values;
378 my %label_of;
379
380 foreach my $branchcode (keys %{$branches}) {
381     push @values, $branchcode;
382     $label_of{$branchcode} = $branches->{$branchcode}->{branchname};
383 }
384
385 my $CGIbranch = CGI::scrolling_list(
386     -name     => 'pickup',
387     -values   => \@values,
388     -default  => $default,
389     -labels   => \%label_of,
390     -size     => 1,
391     -multiple => 0,
392 );
393
394 # get the time for the form name...
395 my $time = time();
396
397 $template->param(
398     CGIbranch => $CGIbranch,
399     reserveloop => \@reserveloop,
400     time => $time,
401 );
402
403 # setup colors
404 $template->param(
405     optionloop =>\@optionloop,
406     bibitemloop => \@bibitemloop,
407     date => $date,
408     bib => $bib,
409     findborrower => $findborrower,
410     cardnumber => $cardnumber,
411     CGIselectborrower => $CGIselectborrower,
412     title =>$dat->{title},
413 );
414
415 # printout the page
416 print $input->header(
417         -type => C4::Interface::CGI::Output::guesstype($template->output),
418         -expires=>'now'
419 ), $template->output;