New feature from SAN Ouest Provence: ability to reserve a specific item in
[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 warn '[Debub Pierrick] $bib: ', $bib;
60 my $dat = bibdata($bib);
61
62 # Select borrowers infos
63 my $findborrower = $input->param('findborrower');
64 $findborrower =~ s|,| |g;
65 my $cardnumber = $input->param('cardnumber');
66 my %env;
67 my $borrowerslist;
68 my $messageborrower;
69
70 my $date = today();
71
72 if ($findborrower) {
73     my ($count,$borrowers) =  BornameSearch(\%env, $findborrower, 'cardnumber', 'web');
74
75     my @borrowers = @$borrowers;
76
77     if ($#borrowers == -1) {
78         $input->param('findborrower', '');
79         $messageborrower =  "'$findborrower'";
80     }
81     elsif ($#borrowers == 0) {
82         $input->param('cardnumber', $borrowers[0]->{'cardnumber'});
83         $cardnumber = $borrowers[0]->{'cardnumber'};
84     }
85     else {
86         $borrowerslist = \@borrowers;
87     }
88 }
89
90 if ($cardnumber) {
91         my $borrowerinfo = getpatroninformation (\%env,0,$cardnumber);
92         my $expiry;
93         my $diffbranch;
94         my @getreservloop;
95         my $count_reserv = 0;
96         my $maxreserves;
97
98 #       we check the reserves of the borrower, and if he can reserv a document
99 # FIXME At this time we have a simple count of reservs, but, later, we could improve the infos "title" ...
100
101         my $number_reserves =
102             GetNumberReservesFromBorrower($borrowerinfo->{'borrowernumber'});
103
104         if ($number_reserves > C4::Context->preference('maxreserves')) {
105             $maxreserves = 1;
106         }
107
108 # we check the date expiricy of the borrower
109         my $warning=Date_Cmp(ParseDate("today"),format_date($borrowerinfo->{'expiry'}));
110         if ( $warning > 0) {
111                         $expiry = 1;
112         }
113
114 # check if the borrower make the reserv in a different branch
115         if ($borrowerinfo->{'branchcode'} ne C4::Context->userenv->{'branch'}) {
116                 $diffbranch = 1;
117         }
118
119         $template->param(
120                 borrowersurname => $borrowerinfo->{'surname'},
121                 borrowerfirstname => $borrowerinfo->{'firstname'},
122                 borrowerreservs => $count_reserv,
123                 maxreserves => $maxreserves,
124                 expiry => $expiry,
125                 diffbranch => $diffbranch
126         );
127 }
128
129 $template->param(
130     messageborrower => $messageborrower
131 );
132
133 my $CGIselectborrower;
134 if ($borrowerslist) {
135     my @values;
136     my %labels;
137
138     foreach my $borrower (
139         sort {$a->{surname}.$a->{firstname} cmp $b->{surname}.$b->{firstname}}
140             @{$borrowerslist}
141     ) {
142         push @values, $borrower->{cardnumber};
143
144         $labels{ $borrower->{cardnumber} } = sprintf(
145             '%s, %s ... (%s - %s) ... %s',
146             $borrower->{surname},
147             $borrower->{firstname},
148             $borrower->{cardnumber},
149             $borrower->{categorycode},
150             $borrower->{streetaddress},
151         );
152     }
153
154     $CGIselectborrower = CGI::scrolling_list(
155         -name     => 'cardnumber',
156         -values   => \@values,
157         -labels   => \%labels,
158         -size     => 7,
159         -multiple => 0,
160     );
161 }
162
163 # get existing reserves .....
164 my ($count, $reserves) = FindReserves($bib, undef);
165 my $totalcount = $count;
166 my $alreadyreserved;
167
168 # FIXME launch another time getpatroninformation perhaps until
169 my $borrowerinfo = getpatroninformation (\%env,0,$cardnumber);
170
171 foreach my $res (@$reserves) {
172     if (($res->{found} eq 'W') or ($res->{priority} == 0)) {
173         $count--;
174     }
175
176     if ($borrowerinfo->{borrowernumber} eq $res->{borrowernumber}) {
177         $alreadyreserved = 1;
178     }
179 }
180 $template->param(alreadyreserved => $alreadyreserved);
181
182 # make priorities options
183 my @optionloop;
184 for (1 .. $count + 1) {
185     push(
186         @optionloop,
187         {
188             num => $_,
189             selected => ($_ == $count + 1),
190         }
191     );
192 }
193
194 my @branchcodes;
195 my %itemnumbers_of_biblioitem;
196 my @itemnumbers = @{get_itemnumbers_of($bib)->{$bib}};
197 my $iteminfos_of = get_iteminfos_of(@itemnumbers);
198
199 foreach my $itemnumber (@itemnumbers) {
200     push(
201         @branchcodes,
202         $iteminfos_of->{$itemnumber}->{homebranch},
203         $iteminfos_of->{$itemnumber}->{holdingbranch}
204     );
205
206     my $biblioitemnumber = $iteminfos_of->{$itemnumber}->{biblioitemnumber};
207     push(
208         @{ $itemnumbers_of_biblioitem{$biblioitemnumber} },
209         $itemnumber
210     );
211 }
212
213 @branchcodes = uniq @branchcodes;
214
215 my @biblioitemnumbers = keys %itemnumbers_of_biblioitem;
216
217 my $branchinfos_of = get_branchinfos_of(@branchcodes);
218 my $notforloan_label_of = get_notforloan_label_of();
219 my $biblioiteminfos_of = get_biblioiteminfos_of(@biblioitemnumbers);
220
221 my @itemtypes;
222 foreach my $biblioitemnumber (@biblioitemnumbers) {
223     push @itemtypes, $biblioiteminfos_of->{$biblioitemnumber}{itemtype};
224 }
225
226 my $itemtypeinfos_of = get_itemtypeinfos_of(@itemtypes);
227
228 my $return_date_of = get_return_date_of(@itemnumbers);
229
230 my @bibitemloop;
231
232 foreach my $biblioitemnumber (@biblioitemnumbers) {
233     my $biblioitem = $biblioiteminfos_of->{$biblioitemnumber};
234
235     $biblioitem->{description} =
236         $itemtypeinfos_of->{ $biblioitem->{itemtype} }{description};
237
238     foreach my $itemnumber (@{$itemnumbers_of_biblioitem{$biblioitemnumber}}) {
239         my $item = $iteminfos_of->{$itemnumber};
240
241         $item->{homebranchname} =
242             $branchinfos_of->{ $item->{homebranch} }{branchname};
243
244         # if the holdingbranch is different than the homebranch, we show the
245         # holdingbranch of the document too
246         if ($item->{homebranch} ne $item->{holdingbranch}) {
247             $item->{holdingbranchname} =
248                 $branchinfos_of->{ $item->{holdingbranch} }{branchname};
249         }
250
251         # if the item is currently on loan, we display its return date and
252         # change the background color
253         my $date_due;
254
255         if (defined $return_date_of->{$itemnumber}) {
256             $date_due = format_date($return_date_of->{$itemnumber});
257
258             $item->{backgroundcolor} = 'onloan';
259         }
260
261         # checking reserve
262         my $reservedate = GetFirstReserveDateFromItem($itemnumber);
263
264         if (defined $reservedate) {
265             $item->{backgroundcolor} = 'reserved';
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;