b72fd8e9892a764c17b499ef852164b025cc65cc
[koha.git] / circ / returns.pl
1 #!/usr/bin/perl
2
3 # Copyright 2000-2002 Katipo Communications
4 #           2006 SAN-OP
5 #           2007 BibLibre, Paul POULAIN
6 #
7 # This file is part of Koha.
8 #
9 # Koha is free software; you can redistribute it and/or modify it under the
10 # terms of the GNU General Public License as published by the Free Software
11 # Foundation; either version 2 of the License, or (at your option) any later
12 # version.
13 #
14 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License along with
19 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
20 # Suite 330, Boston, MA  02111-1307 USA
21
22 =head1 returns.pl
23
24 script to execute returns of books
25
26 =cut
27
28 use strict;
29 # use warnings; # FIXME
30
31 use CGI;
32 use C4::Context;
33 use C4::Auth qw/:DEFAULT get_session/;
34 use C4::Output;
35 use C4::Circulation;
36 use C4::Dates qw/format_date/;
37 use Date::Calc qw/Add_Delta_Days/;
38 use C4::Calendar;
39 use C4::Print;
40 use C4::Reserves;
41 use C4::Biblio;
42 use C4::Items;
43 use C4::Members;
44 use C4::Branch; # GetBranchName
45 use C4::Koha;   # FIXME : is it still useful ?
46
47 my $query = new CGI;
48
49 if (!C4::Context->userenv){
50         my $sessionID = $query->cookie("CGISESSID");
51         my $session = get_session($sessionID);
52         if ($session->param('branch') eq 'NO_LIBRARY_SET'){
53                 # no branch set we can't return
54                 print $query->redirect("/cgi-bin/koha/circ/selectbranchprinter.pl");
55                 exit;
56         }
57
58
59 #getting the template
60 my ( $template, $librarian, $cookie ) = get_template_and_user(
61     {
62         template_name   => "circ/returns.tmpl",
63         query           => $query,
64         type            => "intranet",
65         authnotrequired => 0,
66         flagsrequired   => { circulate => "circulate_remaining_permissions" },
67     }
68 );
69
70 #####################
71 #Global vars
72 my $branches = GetBranches();
73 my $printers = GetPrinters();
74
75 #my $branch  = C4::Context->userenv?C4::Context->userenv->{'branch'}:"";
76 my $printer = C4::Context->userenv ? C4::Context->userenv->{'branchprinter'} : "";
77 my $overduecharges = (C4::Context->preference('finesMode') && C4::Context->preference('finesMode') ne 'off');
78
79 my $userenv_branch = C4::Context->userenv->{'branch'} || '';
80 #
81 # Some code to handle the error if there is no branch or printer setting.....
82 #
83
84 # Set up the item stack ....
85 my %returneditems;
86 my %riduedate;
87 my %riborrowernumber;
88 my @inputloop;
89 foreach ( $query->param ) {
90     (next) unless (/ri-(\d*)/);
91     my %input;
92     my $counter = $1;
93     (next) if ( $counter > 20 );
94     my $barcode        = $query->param("ri-$counter");
95     my $duedate        = $query->param("dd-$counter");
96     my $borrowernumber = $query->param("bn-$counter");
97     $counter++;
98
99     # decode barcode
100     $barcode = barcodedecode($barcode) if(C4::Context->preference('itemBarcodeInputFilter'));
101
102     ######################
103     #Are these lines still useful ?
104     $returneditems{$counter}    = $barcode;
105     $riduedate{$counter}        = $duedate;
106     $riborrowernumber{$counter} = $borrowernumber;
107
108     #######################
109     $input{counter}        = $counter;
110     $input{barcode}        = $barcode;
111     $input{duedate}        = $duedate;
112     $input{borrowernumber} = $borrowernumber;
113     push( @inputloop, \%input );
114 }
115
116 ############
117 # Deal with the requests....
118
119 if ($query->param('WT-itemNumber')){
120         updateWrongTransfer ($query->param('WT-itemNumber'),$query->param('WT-waitingAt'),$query->param('WT-From'));
121 }
122
123 if ( $query->param('resbarcode') ) {
124     my $item           = $query->param('itemnumber');
125     my $borrowernumber = $query->param('borrowernumber');
126     my $resbarcode     = $query->param('resbarcode');
127     my $diffBranchReturned = $query->param('diffBranch');
128     # set to waiting....
129     my $iteminfo   = GetBiblioFromItemNumber($item);
130     # fix up item type for display
131     $iteminfo->{'itemtype'} = C4::Context->preference('item-level_itypes') ? $iteminfo->{'itype'} : $iteminfo->{'itemtype'};
132     my $diffBranchSend;
133     
134 #     addin in ModReserveAffect the possibility to check if the document is expected in this library or not,
135 # if not we send a value in reserve waiting for not implementting waiting status
136     if ($userenv_branch ne $diffBranchReturned) {
137         $diffBranchSend = $diffBranchReturned;
138     }
139     else {
140         $diffBranchSend = undef;
141     }
142     ModReserveAffect( $item, $borrowernumber,$diffBranchSend);
143 #   check if we have other reservs for this document, if we have a return send the message of transfer
144     my ( $messages, $nextreservinfo ) = GetOtherReserves($item);
145
146     my ($borr) = GetMemberDetails( $nextreservinfo, 0 );
147     my $borcnum = $borr->{'cardnumber'};
148     my $name    = $borr->{'surname'} . ", " . $borr->{'title'} . " " . $borr->{'firstname'};
149      
150     my $slip = $query->param('resslip');
151
152     if ( $messages->{'transfert'} ) {
153         $template->param(
154             itemtitle      => $iteminfo->{'title'},
155                         itembiblionumber => $iteminfo->{'biblionumber'},
156             iteminfo       => $iteminfo->{'author'},
157             tobranchname   => GetBranchName($messages->{'transfert'}),
158             name           => $name,
159             borrowernumber => $borrowernumber,
160             borcnum        => $borcnum,
161             borfirstname   => $borr->{'firstname'},
162             borsurname     => $borr->{'surname'},
163             diffbranch     => 1
164         );
165     }
166 }
167
168 my $borrower;
169 my $returned = 0;
170 my $messages;
171 my $issueinformation;
172 my $barcode     = $query->param('barcode');
173 my $exemptfine  = $query->param('exemptfine');
174 my $dropboxmode = $query->param('dropboxmode');
175 my $dotransfer  = $query->param('dotransfer');
176 my $calendar    = C4::Calendar->new( branchcode => $userenv_branch );
177         #dropbox: get last open day (today - 1)
178 my $today       = C4::Dates->new();
179 my $today_iso   = $today->output('iso');
180 my $dropboxdate = $calendar->addDate($today, -1);
181 if ($dotransfer){
182         # An item has been returned to a branch other than the homebranch, and the librarian has choosen to initiate a transfer
183         my $transferitem = $query->param('transferitem');
184         my $tobranch     = $query->param('tobranch');
185         ModItemTransfer($transferitem, $userenv_branch, $tobranch); 
186 }
187
188 # actually return book and prepare item table.....
189 if ($barcode) {
190     $barcode = barcodedecode($barcode)  if(C4::Context->preference('itemBarcodeInputFilter'));
191 #
192 # save the return
193 #
194     ( $returned, $messages, $issueinformation, $borrower ) =
195       AddReturn( $barcode, $userenv_branch, $exemptfine, $dropboxmode);
196     # get biblio description
197     my $biblio = GetBiblioFromItemNumber($issueinformation->{'itemnumber'});
198     # fix up item type for display
199     $biblio->{'itemtype'} = C4::Context->preference('item-level_itypes') ? $biblio->{'itype'} : $biblio->{'itemtype'};
200
201     $template->param(
202         title            => $biblio->{'title'},
203         homebranch       => $biblio->{'homebranch'},
204         author           => $biblio->{'author'},
205         itembarcode      => $biblio->{'barcode'},
206         itemtype         => $biblio->{'itemtype'},
207         ccode            => $biblio->{'ccode'},
208         itembiblionumber => $biblio->{'biblionumber'},    
209     );
210
211     if ($returned) {
212         $returneditems{0}    = $barcode;
213         $riborrowernumber{0} = $borrower->{'borrowernumber'};
214         $riduedate{0}        = $issueinformation->{'date_due'};
215         my %input;
216         $input{counter}        = 0;
217         $input{first}          = 1;
218         $input{barcode}        = $barcode;
219         $input{borrowernumber} = $borrower->{'borrowernumber'};
220         $input{duedate}        = $issueinformation->{'date_due'};
221         $input{return_overdue} = 1 if ($issueinformation->{'date_due'} lt $today->output('iso'));
222         push( @inputloop, \%input );
223
224         # check if the branch is the same as homebranch
225         # if not, we want to put a message
226         if ( $biblio->{'homebranch'} ne $userenv_branch ) {
227             $template->param( homebranch => $biblio->{'homebranch'} );
228         }
229     }
230     elsif ( !$messages->{'BadBarcode'} ) {
231         my %input;
232         $input{counter} = 0;
233         $input{first}   = 1;
234         $input{barcode} = $barcode;
235         $input{duedate} = 0;
236
237         $returneditems{0} = $barcode;
238         $riduedate{0}     = 0;
239         if ( $messages->{'wthdrawn'} ) {
240             $input{withdrawn}      = 1;
241             $input{borrowernumber} = 'Item Cancelled';
242             $riborrowernumber{0}   = 'Item Cancelled';
243         }
244         else {
245             $input{borrowernumber} = ' ';
246             $riborrowernumber{0}   = ' ';
247         }
248         push( @inputloop, \%input );
249     }
250 }
251 $template->param( inputloop => \@inputloop );
252
253 my $found    = 0;
254 my $waiting  = 0;
255 my $reserved = 0;
256
257 # new op dev : we check if the document must be returned to his homebranch directly,
258 #  if the document is transfered, we have warning message .
259
260 if ( $messages->{'WasTransfered'} ) {
261     $template->param(
262         found          => 1,
263         transfer       => 1,
264     );
265 }
266
267 if ( $messages->{'NeedsTransfer'} ){
268         $template->param(
269                 found          => 1,
270                 needstransfer  => 1,
271                 itemnumber => $issueinformation->{'itemnumber'}
272         );
273 }
274
275 if ( $messages->{'Wrongbranch'} ){
276         $template->param(
277                 wrongbranch => 1,
278         );
279 }
280
281 # adding a case of wrong transfert, if the document wasn't transfered in the good library (according to branchtransfer (tobranch) BDD)
282
283 if ( $messages->{'WrongTransfer'} and not $messages->{'WasTransfered'}) {
284         $template->param(
285         WrongTransfer  => 1,
286         TransferWaitingAt => $messages->{'WrongTransfer'},
287         WrongTransferItem => $messages->{'WrongTransferItem'},
288     );
289
290     my $reserve    = $messages->{'ResFound'};
291     my $branchname = $branches->{ $reserve->{'branchcode'} }->{'branchname'};
292     my ($borr) = GetMemberDetails( $reserve->{'borrowernumber'}, 0 );
293     my $name = $borr->{'surname'} . ", " . $borr->{'title'} . " " . $borr->{'firstname'};
294     $template->param(
295             wname           => $name,
296             wborfirstname   => $borr->{'firstname'},
297             wborsurname     => $borr->{'surname'},
298             wbortitle       => $borr->{'title'},
299             wborphone       => $borr->{'phone'},
300             wboremail       => $borr->{'email'},
301             wboraddress     => $borr->{'address'},
302             wboraddress2    => $borr->{'address2'},
303             wborcity        => $borr->{'city'},
304             wborzip         => $borr->{'zipcode'},
305             wborrowernumber => $reserve->{'borrowernumber'},
306             wborcnum        => $borr->{'cardnumber'},
307             wtransfertFrom  => $userenv_branch,
308     );
309 }
310
311
312 #
313 # reserve found and item arrived at the expected branch
314 #
315 if ( $messages->{'ResFound'}) {
316     my $reserve    = $messages->{'ResFound'};
317     my $branchname = $branches->{ $reserve->{'branchcode'} }->{'branchname'};
318     my ($borr) = GetMemberDetails( $reserve->{'borrowernumber'}, 0 );
319
320     if ( $reserve->{'ResFound'} eq "Waiting" or $reserve->{'ResFound'} eq "Reserved" ) {
321         if ( $reserve->{'ResFound'} eq "Waiting" ) {
322             $template->param(
323                 waiting      => ($userenv_branch eq $reserve->{'branchcode'} ? 1 : 0 ),
324             );
325         } elsif ( $reserve->{'ResFound'} eq "Reserved" ) {
326             $template->param(
327                 intransit    => ($userenv_branch eq $reserve->{'branchcode'} ? 0 : 1 ),
328                 transfertodo => ($userenv_branch eq $reserve->{'branchcode'} ? 0 : 1 ),
329                 resbarcode   => $barcode,
330                 reserved     => 1,
331             );
332         }
333
334         # same params for Waiting or Reserved
335         $template->param(
336             found          => 1,
337             currentbranch  => $branches->{$userenv_branch}->{'branchname'},
338             destbranchname => $branches->{ $reserve->{'branchcode'} }->{'branchname'},
339             name           => $borr->{'surname'} . ", " . $borr->{'title'} . " " . $borr->{'firstname'},
340             borfirstname   => $borr->{'firstname'},
341             borsurname     => $borr->{'surname'},
342             bortitle       => $borr->{'title'},
343             borphone       => $borr->{'phone'},
344             boremail       => $borr->{'email'},
345             boraddress     => $borr->{'address'},
346             boraddress2    => $borr->{'address2'},
347             borcity        => $borr->{'city'},
348             borzip         => $borr->{'zipcode'},
349             borcnum        => $borr->{'cardnumber'},
350             debarred       => $borr->{'debarred'},
351             gonenoaddress  => $borr->{'gonenoaddress'},
352             barcode        => $barcode,
353             destbranch     => $reserve->{'branchcode'},
354             borrowernumber => $reserve->{'borrowernumber'},
355             itemnumber     => $reserve->{'itemnumber'},
356         );
357     } # else { ; }  # error?
358 }
359
360 # Error Messages
361 my @errmsgloop;
362 foreach my $code ( keys %$messages ) {
363
364     #    warn $code;
365     my %err;
366     my $exit_required_p = 0;
367     if ( $code eq 'BadBarcode' ) {
368         $err{badbarcode} = 1;
369         $err{msg}        = $messages->{'BadBarcode'};
370     }
371     elsif ( $code eq 'NotIssued' ) {
372         $err{notissued} = 1;
373         $err{msg} = $branches->{ $messages->{'IsPermanent'} }->{'branchname'};
374     }
375     elsif ( $code eq 'WasLost' ) {
376         $err{waslost} = 1;
377     }
378     elsif ( $code eq 'ResFound' ) {
379         ;    # FIXME... anything to do here?
380     }
381     elsif ( $code eq 'WasReturned' ) {
382         ;    # FIXME... anything to do here?
383     }
384     elsif ( $code eq 'WasTransfered' ) {
385         ;    # FIXME... anything to do here?
386     }
387     elsif ( $code eq 'wthdrawn' ) {
388         $err{withdrawn} = 1;
389         $exit_required_p = 1;
390     }
391     elsif ( ( $code eq 'IsPermanent' ) && ( not $messages->{'ResFound'} ) ) {
392         if ( $messages->{'IsPermanent'} ne $userenv_branch ) {
393             $err{ispermanent} = 1;
394             $err{msg}         =
395               $branches->{ $messages->{'IsPermanent'} }->{'branchname'};
396         }
397     }
398     elsif ( $code eq 'WrongTransfer' ) {
399         ;    # FIXME... anything to do here?
400     }
401     elsif ( $code eq 'WrongTransferItem' ) {
402         ;    # FIXME... anything to do here?
403     }
404     elsif ( $code eq 'NeedsTransfer' ) {
405     }
406     elsif ( $code eq 'Wrongbranch' ) {
407     }
408                 
409     else {
410         die "Unknown error code $code";    # XXX
411     }
412     if (%err) {
413         push( @errmsgloop, \%err );
414     }
415     last if $exit_required_p;
416 }
417 $template->param( errmsgloop => \@errmsgloop );
418
419 # patrontable ....
420 if ($borrower) {
421     my $flags = $borrower->{'flags'};
422     my @flagloop;
423     my $flagset;
424     foreach my $flag ( sort keys %$flags ) {
425         my %flaginfo;
426         unless ($flagset) { $flagset = 1; }
427         $flaginfo{redfont} = ( $flags->{$flag}->{'noissues'} );
428         $flaginfo{flag}    = $flag;
429         if ( $flag eq 'CHARGES' ) {
430             $flaginfo{msg}            = $flag;
431             $flaginfo{charges}        = 1;
432             $flaginfo{chargeamount}   = $flags->{$flag}->{amount};
433             $flaginfo{borrowernumber} = $borrower->{borrowernumber};
434         }
435         elsif ( $flag eq 'WAITING' ) {
436             $flaginfo{msg}     = $flag;
437             $flaginfo{waiting} = 1;
438             my @waitingitemloop;
439             my $items = $flags->{$flag}->{'itemlist'};
440             foreach my $item (@$items) {
441                 my $biblio = GetBiblioFromItemNumber( $item->{'itemnumber'});
442                 my %waitingitem;
443                 $waitingitem{biblionum} = $biblio->{'biblionumber'};
444                 $waitingitem{barcode}   = $biblio->{'barcode'};
445                 $waitingitem{title}     = $biblio->{'title'};
446                 $waitingitem{brname}    = $branches->{ $biblio->{'holdingbranch'} }->{'branchname'};
447                 push( @waitingitemloop, \%waitingitem );
448             }
449             $flaginfo{itemloop} = \@waitingitemloop;
450         }
451         elsif ( $flag eq 'ODUES' ) {
452             my $items = $flags->{$flag}->{'itemlist'};
453             my @itemloop;
454             foreach my $item ( sort { $a->{'date_due'} cmp $b->{'date_due'} }
455                 @$items )
456             {
457                 my $biblio = GetBiblioFromItemNumber( $item->{'itemnumber'});
458                 my %overdueitem;
459                 $overdueitem{duedate}   = format_date( $item->{'date_due'} );
460                 $overdueitem{biblionum} = $biblio->{'biblionumber'};
461                 $overdueitem{barcode}   = $biblio->{'barcode'};
462                 $overdueitem{title}     = $biblio->{'title'};
463                 $overdueitem{brname}    = $branches->{ $biblio->{'holdingbranch'}} ->{'branchname'};
464                 push( @itemloop, \%overdueitem );
465             }
466             $flaginfo{itemloop} = \@itemloop;
467             $flaginfo{overdue}  = 1;
468         }
469         else {
470             $flaginfo{other} = 1;
471             $flaginfo{msg}   = $flags->{$flag}->{'message'};
472         }
473         push( @flagloop, \%flaginfo );
474     }
475     $template->param(
476         flagset          => $flagset,
477         flagloop         => \@flagloop,
478         riborrowernumber => $borrower->{'borrowernumber'},
479         riborcnum        => $borrower->{'cardnumber'},
480         riborsurname     => $borrower->{'surname'},
481         ribortitle       => $borrower->{'title'},
482         riborfirstname   => $borrower->{'firstname'}
483     );
484 }
485
486 #set up so only the last 8 returned items display (make for faster loading pages)
487 my $returned_counter = ( C4::Context->preference('numReturnedItemsToShow') ) ? C4::Context->preference('numReturnedItemsToShow') : 8;
488 my $count = 0;
489 my @riloop;
490 foreach ( sort { $a <=> $b } keys %returneditems ) {
491     my %ri;
492     if ( $count++ < $returned_counter ) {
493         my $barcode = $returneditems{$_};
494         my $duedate = $riduedate{$_};
495         my $overduetext;
496         my $borrowerinfo;
497         if ($duedate) {
498             my @tempdate = split( /-/, $duedate );
499             $ri{year}  = $tempdate[0];
500             $ri{month} = $tempdate[1];
501             $ri{day}   = $tempdate[2];
502             $ri{duedate} = format_date($duedate);
503             my ($borrower) = GetMemberDetails( $riborrowernumber{$_}, 0 );
504             $ri{return_overdue} = 1 if ($duedate lt $today->output('iso'));
505             $ri{borrowernumber} = $borrower->{'borrowernumber'};
506             $ri{borcnum}        = $borrower->{'cardnumber'};
507             $ri{borfirstname}   = $borrower->{'firstname'};
508             $ri{borsurname}     = $borrower->{'surname'};
509             $ri{bortitle}       = $borrower->{'title'};
510             $ri{bornote}        = $borrower->{'borrowernotes'};
511             $ri{borcategorycode}= $borrower->{'categorycode'};
512         }
513         else {
514             $ri{borrowernumber} = $riborrowernumber{$_};
515         }
516
517         #        my %ri;
518         my $biblio = GetBiblioFromItemNumber(GetItemnumberFromBarcode($barcode));
519         # fix up item type for display
520         $biblio->{'itemtype'} = C4::Context->preference('item-level_itypes') ? $biblio->{'itype'} : $biblio->{'itemtype'};
521         $ri{itembiblionumber} = $biblio->{'biblionumber'};
522         $ri{itemtitle}        = $biblio->{'title'};
523         $ri{itemauthor}       = $biblio->{'author'};
524         $ri{itemtype}         = $biblio->{'itemtype'};
525         $ri{itemnote}         = $biblio->{'itemnotes'};
526         $ri{ccode}            = $biblio->{'ccode'};
527         $ri{itemnumber}       = $biblio->{'itemnumber'};
528         $ri{barcode}          = $barcode;
529     }
530     else {
531         last;
532     }
533     push( @riloop, \%ri );
534 }
535 $template->param( riloop => \@riloop );
536
537 $template->param(
538     genbrname      => $branches->{$userenv_branch}->{'branchname'},
539     genprname      => $printers->{$printer}->{'printername'},
540     branchname     => $branches->{$userenv_branch}->{'branchname'},
541     printer        => $printer,
542     errmsgloop     => \@errmsgloop,
543     exemptfine     => $exemptfine,
544     dropboxmode    => $dropboxmode,
545     dropboxdate    => $dropboxdate->output(),
546     overduecharges => $overduecharges,
547 );
548
549 # actually print the page!
550 output_html_with_http_headers $query, $cookie, $template->output;