Bug Fixing.
[koha.git] / C4 / Overdues.pm
1 package C4::Overdues;
2
3 # $Id$
4
5 # Copyright 2000-2002 Katipo Communications
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 use strict;
23 require Exporter;
24 use C4::Context;
25 use Date::Calc qw/Today/;
26 use vars qw($VERSION @ISA @EXPORT);
27 use C4::Accounts;
28 use Date::Manip qw/UnixDate/;
29 use C4::Log; # logaction
30
31 # set the version for version checking
32 $VERSION = do { my @v = '$Revision$' =~ /\d+/g; 
33 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
34
35 =head1 NAME
36
37 C4::Circulation::Fines - Koha module dealing with fines
38
39 =head1 SYNOPSIS
40
41   use C4::Overdues;
42
43 =head1 DESCRIPTION
44
45 This module contains several functions for dealing with fines for
46 overdue items. It is primarily used by the 'misc/fines2.pl' script.
47
48 =head1 FUNCTIONS
49
50 =over 2
51
52 =cut
53
54 @ISA    = qw(Exporter);
55 # subs to rename (and maybe merge some...)
56 push @EXPORT, qw(
57         &CalcFine
58         &Getoverdues
59         &checkoverdues
60         &CheckAccountLineLevelInfo
61         &CheckAccountLineItemInfo
62         &CheckExistantNotifyid
63         &GetNextIdNotify
64         &GetNotifyId
65         &NumberNotifyId
66         &AmountNotify
67         &UpdateAccountLines
68         &UpdateFine
69         &GetOverdueDelays
70         &GetOverduerules
71         &GetFine
72         &CreateItemAccountLine
73         &ReplacementCost2
74         
75         &CheckItemNotify
76         &GetOverduesForBranch
77         &RemoveNotifyLine
78         &AddNotifyLine
79 );
80 # subs to remove
81 push @EXPORT, qw(
82         &BorType
83 );
84
85 #
86 # All subs to move : check that an equivalent don't exist already before moving
87 #
88
89 # subs to move to Circulation.pm
90 push @EXPORT, qw(
91         &GetIssuingRules
92         &GetIssuesIteminfo
93 );
94 # subs to move to Members.pm
95 push @EXPORT, qw(
96         &CheckBorrowerDebarred
97         &UpdateBorrowerDebarred
98 );
99 # subs to move to Biblio.pm
100 push @EXPORT, qw(
101         &GetItems
102         &ReplacementCost
103 );
104
105 =item Getoverdues
106
107   ($count, $overdues) = &Getoverdues();
108
109 Returns the list of all overdue books.
110
111 C<$count> is the number of elements in C<@{$overdues}>.
112
113 C<$overdues> is a reference-to-array. Each element is a
114 reference-to-hash whose keys are the fields of the issues table in the
115 Koha database.
116
117 =cut
118
119 #'
120 sub Getoverdues {
121     my $dbh = C4::Context->dbh;
122     my $sth = $dbh->prepare(
123         "Select * from issues where date_due < now() and returndate is
124   NULL order by borrowernumber "
125     );
126     $sth->execute;
127
128     # FIXME - Use push @results
129     my $i = 0;
130     my @results;
131     while ( my $data = $sth->fetchrow_hashref ) {
132         $results[$i] = $data;
133         $i++;
134     }
135     $sth->finish;
136
137     #  print @results;
138     # FIXME - Bogus API.
139     return ( $i, \@results );
140 }
141
142 =head2 checkoverdues
143
144 ( $count, $overdueitems )=checkoverdues( $borrowernumber, $dbh );
145
146 Not exported
147
148 =cut
149
150 sub checkoverdues {
151
152 # From Main.pm, modified to return a list of overdueitems, in addition to a count
153 #checks whether a borrower has overdue items
154     my ( $borrowernumber, $dbh ) = @_;
155     my @datearr = localtime;
156     my $today   =
157       ( $datearr[5] + 1900 ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3];
158     my @overdueitems;
159     my $count = 0;
160     my $sth   = $dbh->prepare(
161         "SELECT * FROM issues,biblio,biblioitems,items
162             WHERE items.biblioitemnumber = biblioitems.biblioitemnumber
163                 AND items.biblionumber     = biblio.biblionumber
164                 AND issues.itemnumber      = items.itemnumber
165                 AND issues.borrowernumber  = ?
166                 AND issues.returndate is NULL
167                 AND issues.date_due < ?"
168     );
169     $sth->execute( $borrowernumber, $today );
170     while ( my $data = $sth->fetchrow_hashref ) {
171         push( @overdueitems, $data );
172         $count++;
173     }
174     $sth->finish;
175     return ( $count, \@overdueitems );
176 }
177
178 =item CalcFine
179
180   ($amount, $chargename, $message) =
181     &CalcFine($itemnumber, $borrowercode, $days_overdue);
182
183 Calculates the fine for a book.
184
185 The issuingrules table in the Koha database is a fine matrix, listing
186 the penalties for each type of patron for each type of item and each branch (e.g., the
187 standard fine for books might be $0.50, but $1.50 for DVDs, or staff
188 members might get a longer grace period between the first and second
189 reminders that a book is overdue).
190
191 The fine is calculated as follows: if it is time for the first
192 reminder, the fine is the value listed for the given (branch, item type,
193 borrower code) combination. If it is time for the second reminder, the
194 fine is doubled. Finally, if it is time to send the account to a
195 collection agency, the fine is set to 5 local monetary units (a really
196 good deal for the patron if the library is in Italy). Otherwise, the
197 fine is 0.
198
199 Note that the way this function is currently implemented, it only
200 returns a nonzero value on the notable days listed above. That is, if
201 the categoryitems entry says to send a first reminder 7 days after the
202 book is due, then if you call C<&CalcFine> 7 days after the book is
203 due, it will give a nonzero fine. If you call C<&CalcFine> the next
204 day, however, it will say that the fine is 0.
205
206 C<$itemnumber> is the book's item number.
207
208 C<$borrowercode> is the borrower code of the patron who currently has
209 the book.
210
211 C<$days_overdue> is the number of days elapsed since the book's due
212 date.
213
214 C<&CalcFine> returns a list of three values:
215
216 C<$amount> is the fine owed by the patron (see above).
217
218 C<$chargename> is the chargename field from the applicable record in
219 the categoryitem table, whatever that is.
220
221 C<$message> is a text message, either "First Notice", "Second Notice",
222 or "Final Notice".
223
224 =cut
225
226 #'
227 sub CalcFine {
228     my ( $itemnumber, $bortype, $difference , $dues  ) = @_;
229     my $dbh = C4::Context->dbh;
230     my $data = GetIssuingRules($itemnumber,$bortype);
231     my $amount = 0;
232     my $printout;
233     my $countspecialday=&GetSpecialHolidays($dues,$itemnumber);
234     my $countrepeatableday=&GetRepeatableHolidays($dues,$itemnumber,$difference);    
235     my $countalldayclosed = $countspecialday + $countrepeatableday;
236     my $daycount = $difference - $countalldayclosed;    
237     my $daycounttotal = $daycount - $data->{'firstremind'};
238         if ($data->{'firstremind'} < $daycount)
239     {
240     $amount   = $daycounttotal*$data->{'fine'};
241     }
242  return ( $amount, $data->{'chargename'}, $printout ,$daycounttotal ,$daycount );
243 }
244
245
246 =item GetSpecialHolidays
247
248 &GetSpecialHolidays($date_dues,$itemnumber);
249
250 return number of special days  between date of the day and date due
251
252 C<$date_dues> is the envisaged date of book return.
253
254 C<$itemnumber> is the book's item number.
255
256 =cut
257
258 sub GetSpecialHolidays {
259 my ($date_dues,$itemnumber) = @_;
260 # calcul the today date
261 my $today = join "-", &Today();
262
263 # return the holdingbranch
264 my $iteminfo=GetIssuesIteminfo($itemnumber);
265 # use sql request to find all date between date_due and today
266 my $dbh = C4::Context->dbh;
267 my $query=qq|SELECT DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d')as date 
268 FROM `special_holidays`
269 WHERE DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') >= ?
270 AND   DATE_FORMAT(concat(year,'-',month,'-',day),'%Y-%m-%d') <= ?
271 AND branchcode=?
272 |;
273 my @result=GetWdayFromItemnumber($itemnumber);
274 my @result_date;
275 my $wday;
276 my $dateinsec;
277 my $sth = $dbh->prepare($query);
278 $sth->execute($date_dues,$today,$iteminfo->{'branchcode'});
279
280 while ( my $special_date=$sth->fetchrow_hashref){
281     push (@result_date,$special_date);
282 }
283
284 my $specialdaycount=scalar(@result_date);
285
286     for (my $i=0;$i<scalar(@result_date);$i++){
287         $dateinsec=UnixDate($result_date[$i]->{'date'},"%o");
288         (undef,undef,undef,undef,undef,undef,$wday,undef,undef) =localtime($dateinsec);
289         for (my $j=0;$j<scalar(@result);$j++){
290             if ($wday == ($result[$j]->{'weekday'})){
291             $specialdaycount --;
292             }
293         }
294     }
295
296 return $specialdaycount;
297 }
298
299 =item GetRepeatableHolidays
300
301 &GetRepeatableHolidays($date_dues, $itemnumber, $difference,);
302
303 return number of day closed between date of the day and date due
304
305 C<$date_dues> is the envisaged date of book return.
306
307 C<$itemnumber> is item number.
308
309 C<$difference> numbers of between day date of the day and date due
310
311 =cut
312
313 sub GetRepeatableHolidays{
314 my ($date_dues,$itemnumber,$difference) = @_;
315 my $dateinsec=UnixDate($date_dues,"%o");
316 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =localtime($dateinsec);
317 my @result=GetWdayFromItemnumber($itemnumber);
318 my @dayclosedcount;
319 my $j;
320
321 for (my $i=0;$i<scalar(@result);$i++){
322     my $k=$wday;
323
324         for ( $j=0;$j<$difference;$j++){
325             if ($result[$i]->{'weekday'} == $k)
326                     {
327                     push ( @dayclosedcount ,$k);
328             }
329         $k++;
330         ($k=0) if($k eq 7);
331         }
332     }
333 return scalar(@dayclosedcount);
334 }
335
336
337 =item GetWayFromItemnumber
338
339 &Getwdayfromitemnumber($itemnumber);
340
341 return the different week day from repeatable_holidays table
342
343 C<$itemnumber> is  item number.
344
345 =cut
346
347 sub GetWdayFromItemnumber{
348 my($itemnumber)=@_;
349 my $iteminfo=GetIssuesIteminfo($itemnumber);
350 my @result;
351 my $dbh = C4::Context->dbh;
352 my $query = qq|SELECT weekday  
353     FROM repeatable_holidays
354     WHERE branchcode=?
355 |;
356 my $sth = $dbh->prepare($query);
357     #  print $query;
358
359 $sth->execute($iteminfo->{'branchcode'});
360 while ( my $weekday=$sth->fetchrow_hashref){
361     push (@result,$weekday);
362     }
363 return @result;
364 }
365
366
367 =item GetIssuesIteminfo
368
369 &GetIssuesIteminfo($itemnumber);
370
371 return all data from issues about item
372
373 C<$itemnumber> is  item number.
374
375 =cut
376
377 sub GetIssuesIteminfo{
378 my($itemnumber)=@_;
379 my $dbh = C4::Context->dbh;
380 my $query = qq|SELECT *  
381     FROM issues
382     WHERE itemnumber=?
383 |;
384 my $sth = $dbh->prepare($query);
385 $sth->execute($itemnumber);
386 my ($issuesinfo)=$sth->fetchrow_hashref;
387 return $issuesinfo;
388 }
389
390
391 =item UpdateFine
392
393   &UpdateFine($itemnumber, $borrowernumber, $amount, $type, $description);
394
395 (Note: the following is mostly conjecture and guesswork.)
396
397 Updates the fine owed on an overdue book.
398
399 C<$itemnumber> is the book's item number.
400
401 C<$borrowernumber> is the borrower number of the patron who currently
402 has the book on loan.
403
404 C<$amount> is the current amount owed by the patron.
405
406 C<$type> will be used in the description of the fine.
407
408 C<$description> is a string that must be present in the description of
409 the fine. I think this is expected to be a date in DD/MM/YYYY format.
410
411 C<&UpdateFine> looks up the amount currently owed on the given item
412 and sets it to C<$amount>, creating, if necessary, a new entry in the
413 accountlines table of the Koha database.
414
415 =cut
416
417 #'
418 # FIXME - This API doesn't look right: why should the caller have to
419 # specify both the item number and the borrower number? A book can't
420 # be on loan to two different people, so the item number should be
421 # sufficient.
422 sub UpdateFine {
423     my ( $itemnum, $borrowernumber, $amount, $type, $due ) = @_;
424     my $dbh = C4::Context->dbh;
425     # FIXME - What exactly is this query supposed to do? It looks up an
426     # entry in accountlines that matches the given item and borrower
427     # numbers, where the description contains $due, and where the
428     # account type has one of several values, but what does this _mean_?
429     # Does it look up existing fines for this item?
430     # FIXME - What are these various account types? ("FU", "O", "F", "M")
431     my $sth = $dbh->prepare(
432         "Select * from accountlines where itemnumber=? and
433   borrowernumber=? and (accounttype='FU' or accounttype='O' or
434   accounttype='F' or accounttype='M') and description like ?"
435     );
436     $sth->execute( $itemnum, $borrowernumber, "%$due%" );
437
438     if ( my $data = $sth->fetchrow_hashref ) {
439
440         # I think this if-clause deals with the case where we're updating
441         # an existing fine.
442         #    print "in accounts ...";
443     if ( $data->{'amount'} != $amount ) {
444            
445         #      print "updating";
446             my $diff = $amount - $data->{'amount'};
447             my $out  = $data->{'amountoutstanding'} + $diff;
448             my $sth2 = $dbh->prepare(
449                 "update accountlines set date=now(), amount=?,
450       amountoutstanding=?,accounttype='FU' where
451       borrowernumber=? and itemnumber=?
452       and (accounttype='FU' or accounttype='O') and description like ?"
453             );
454             $sth2->execute( $amount, $out, $data->{'borrowernumber'},
455                 $data->{'itemnumber'}, "%$due%" );
456             $sth2->finish;
457         }
458         else {
459
460             #      print "no update needed $data->{'amount'}"
461         }
462     }
463     else {
464
465         # I think this else-clause deals with the case where we're adding
466         # a new fine.
467         my $sth4 = $dbh->prepare(
468             "select title from biblio,items where items.itemnumber=?
469     and biblio.biblionumber=items.biblionumber"
470         );
471         $sth4->execute($itemnum);
472         my $title = $sth4->fetchrow_hashref;
473         $sth4->finish;
474
475 #         #   print "not in account";
476 #         my $sth3 = $dbh->prepare("Select max(accountno) from accountlines");
477 #         $sth3->execute;
478
479 #         # FIXME - Make $accountno a scalar.
480 #         my @accountno = $sth3->fetchrow_array;
481 #         $sth3->finish;
482 #         $accountno[0]++;
483 # begin transaction
484   my $nextaccntno = getnextacctno($borrowernumber);
485     my $sth2 = $dbh->prepare(
486             "Insert into accountlines
487     (borrowernumber,itemnumber,date,amount,
488     description,accounttype,amountoutstanding,accountno) values
489     (?,?,now(),?,?,'FU',?,?)"
490         );
491         $sth2->execute( $borrowernumber, $itemnum, $amount,
492             "$type $title->{'title'} $due",
493             $amount, $nextaccntno);
494         $sth2->finish;
495     }
496     # logging action
497     &logaction(
498         C4::Context->userenv->{'number'},
499         "FINES",
500         $type,
501         $borrowernumber,
502         "due=".$due."  amount=".$amount." itemnumber=".$itemnum
503         ) if C4::Context->preference("FinesLog");
504
505     $sth->finish;
506 }
507
508 =item BorType
509
510   $borrower = &BorType($borrowernumber);
511
512 Looks up a patron by borrower number.
513
514 C<$borrower> is a reference-to-hash whose keys are all of the fields
515 from the borrowers and categories tables of the Koha database. Thus,
516 C<$borrower> contains all information about both the borrower and
517 category he or she belongs to.
518
519 =cut
520
521 #'
522 sub BorType {
523     my ($borrowernumber) = @_;
524     my $dbh              = C4::Context->dbh;
525     my $sth              = $dbh->prepare(
526         "Select * from borrowers,categories where
527   borrowernumber=? and
528 borrowers.categorycode=categories.categorycode"
529     );
530     $sth->execute($borrowernumber);
531     my $data = $sth->fetchrow_hashref;
532     $sth->finish;
533     return ($data);
534 }
535
536 =item ReplacementCost
537
538   $cost = &ReplacementCost($itemnumber);
539
540 Returns the replacement cost of the item with the given item number.
541
542 =cut
543
544 #'
545 sub ReplacementCost {
546     my ($itemnum) = @_;
547     my $dbh       = C4::Context->dbh;
548     my $sth       =
549       $dbh->prepare("Select replacementprice from items where itemnumber=?");
550     $sth->execute($itemnum);
551
552     # FIXME - Use fetchrow_array or something.
553     my $data = $sth->fetchrow_hashref;
554     $sth->finish;
555     return ( $data->{'replacementprice'} );
556 }
557
558 =item GetFine
559
560 $data->{'sum(amountoutstanding)'} = &GetFine($itemnum,$borrowernumber);
561
562 return the total of fine
563
564 C<$itemnum> is item number
565
566 C<$borrowernumber> is the borrowernumber
567
568 =cut 
569
570
571 sub GetFine {
572     my ( $itemnum, $borrowernumber ) = @_;
573     my $dbh   = C4::Context->dbh();
574     my $query = "SELECT sum(amountoutstanding) FROM accountlines 
575     where accounttype like 'F%'  
576   AND amountoutstanding > 0 AND itemnumber = ? AND borrowernumber=?";
577     my $sth = $dbh->prepare($query);
578     $sth->execute( $itemnum, $borrowernumber );
579     my $data = $sth->fetchrow_hashref();
580     $sth->finish();
581     $dbh->disconnect();
582     return ( $data->{'sum(amountoutstanding)'} );
583 }
584
585
586
587
588 =item GetIssuingRules
589
590 $data = &GetIssuingRules($itemnumber,$categorycode);
591
592 Looks up for all issuingrules an item info 
593
594 C<$itemnumber> is a reference-to-hash whose keys are all of the fields
595 from the borrowers and categories tables of the Koha database. Thus,
596
597 C<$categorycode> contains  information about borrowers category 
598
599 C<$data> contains all information about both the borrower and
600 category he or she belongs to.
601 =cut 
602
603 sub GetIssuingRules {
604    my ($itemnumber,$categorycode)=@_;
605    my $dbh   = C4::Context->dbh();    
606    my $query=qq|SELECT * 
607         FROM items,biblioitems,itemtypes,issuingrules
608         WHERE items.itemnumber=?
609         AND items.biblioitemnumber=biblioitems.biblioitemnumber
610         AND biblioitems.itemtype=itemtypes.itemtype
611         AND issuingrules.itemtype=itemtypes.itemtype
612         AND issuingrules.categorycode=?
613         AND  (items.itemlost <> 1
614         OR items.itemlost is NULL)|;
615     my $sth = $dbh->prepare($query);
616     #  print $query;
617     $sth->execute($itemnumber,$categorycode);
618     my ($data) = $sth->fetchrow_hashref;
619    $sth->finish;
620 return ($data);
621
622 }
623
624
625 sub ReplacementCost2 {
626     my ( $itemnum, $borrowernumber ) = @_;
627     my $dbh   = C4::Context->dbh();
628     my $query = "SELECT amountoutstanding 
629          FROM accountlines
630              WHERE accounttype like 'L'
631          AND amountoutstanding > 0
632          AND itemnumber = ?
633          AND borrowernumber= ?";
634     my $sth = $dbh->prepare($query);
635     $sth->execute( $itemnum, $borrowernumber );
636     my $data = $sth->fetchrow_hashref();
637     $sth->finish();
638     $dbh->disconnect();
639     return ( $data->{'amountoutstanding'} );
640 }
641
642
643 =item GetNextIdNotify
644
645 ($result) = &GetNextIdNotify($reference);
646
647 Returns the new file number
648
649 C<$result> contains the next file number
650
651 C<$reference> contains the beggining of file number
652
653 =cut
654
655
656
657 sub GetNextIdNotify {
658 my ($reference)=@_;
659 my $query=qq|SELECT max(notify_id) 
660          FROM accountlines
661          WHERE notify_id  like \"$reference%\"
662          |;
663 # AND borrowernumber=?|;   
664 my $dbh = C4::Context->dbh;
665 my $sth=$dbh->prepare($query);
666 $sth->execute();
667 my $result=$sth->fetchrow;
668 $sth->finish;
669 my $count;
670     if ($result eq '')
671     {
672     ($result=$reference."01")  ;
673     }else
674     {
675     $count=substr($result,6)+1;
676      
677     if($count<10){
678      ($count = "0".$count);
679      }
680      $result=$reference.$count;
681      }
682 return $result;
683 }
684
685
686 =item AmountNotify
687
688 (@notify) = &AmountNotify($borrowernumber);
689
690 Returns amount for all file per borrowers
691 C<@notify> array contains all file per borrowers
692
693 C<$notify_id> contains the file number for the borrower number nad item number
694
695 =cut
696
697 sub NumberNotifyId{
698     my ($borrowernumber)=@_;
699     my $dbh = C4::Context->dbh;
700     my $query=qq|    SELECT distinct(notify_id)
701             FROM accountlines
702             WHERE borrowernumber=?|;
703     my @notify;
704     my $sth=$dbh->prepare($query);
705         $sth->execute($borrowernumber);
706           while ( my $numberofotify=$sth->fetchrow_array){
707     push (@notify,$numberofotify);
708     }
709     $sth->finish;
710
711     return (@notify);
712
713 }
714
715 =item AmountNotify
716
717 ($totalnotify) = &AmountNotify($notifyid);
718
719 Returns amount for all file per borrowers
720 C<$notifyid> is the file number
721
722 C<$totalnotify> contains amount of a file
723
724 C<$notify_id> contains the file number for the borrower number nad item number
725
726 =cut
727
728 sub AmountNotify{
729     my ($notifyid)=@_;
730     my $dbh = C4::Context->dbh;
731     my $query=qq|    SELECT sum(amountoutstanding)
732             FROM accountlines
733             WHERE notify_id=?|;
734     my $sth=$dbh->prepare($query);
735         $sth->execute($notifyid);
736           my $totalnotify=$sth->fetchrow;
737     $sth->finish;
738     return ($totalnotify);
739 }
740
741
742 =item GetNotifyId
743
744 ($notify_id) = &GetNotifyId($borrowernumber,$itemnumber);
745
746 Returns the file number per borrower and itemnumber
747
748 C<$borrowernumber> is a reference-to-hash whose keys are all of the fields
749 from the items tables of the Koha database. Thus,
750
751 C<$itemnumber> contains the borrower categorycode
752
753 C<$notify_id> contains the file number for the borrower number nad item number
754
755 =cut
756
757  sub GetNotifyId {
758  my ($borrowernumber,$itemnumber)=@_;
759  my $query=qq|SELECT notify_id 
760            FROM accountlines
761            WHERE borrowernumber=?
762           AND itemnumber=?
763            AND (accounttype='FU' or accounttype='O')|;
764  my $dbh = C4::Context->dbh;
765  my $sth=$dbh->prepare($query);
766  $sth->execute($borrowernumber,$itemnumber);
767  my ($notify_id)=$sth->fetchrow;
768  $sth->finish;
769  return ($notify_id);
770
771  }
772
773 =item CreateItemAccountLine
774
775 () = &CreateItemAccountLine($borrowernumber,$itemnumber,$date,$amount,$description,$accounttype,$amountoutstanding,$timestamp,$notify_id,$level);
776
777 update the account lines with file number or with file level
778
779 C<$items> is a reference-to-hash whose keys are all of the fields
780 from the items tables of the Koha database. Thus,
781
782 C<$itemnumber> contains the item number
783
784 C<$borrowernumber> contains the borrower number
785
786 C<$date> contains the date of the day
787
788 C<$amount> contains item price
789
790 C<$description> contains the descritpion of accounttype 
791
792 C<$accounttype> contains the account type
793
794 C<$amountoutstanding> contains the $amountoutstanding 
795
796 C<$timestamp> contains the timestamp with time and the date of the day
797
798 C<$notify_id> contains the file number
799
800 C<$level> contains the file level
801
802
803 =cut
804
805  sub CreateItemAccountLine {
806   my ($borrowernumber,$itemnumber,$date,$amount,$description,$accounttype,$amountoutstanding,$timestamp,$notify_id,$level)=@_;
807   my $dbh = C4::Context->dbh;
808   my $nextaccntno = getnextacctno($borrowernumber);
809    my $query= "INSERT into accountlines  
810          (borrowernumber,accountno,itemnumber,date,amount,description,accounttype,amountoutstanding,timestamp,notify_id,notify_level)
811           VALUES
812              (?,?,?,?,?,?,?,?,?,?,?)";
813   
814   
815   my $sth=$dbh->prepare($query);
816   $sth->execute($borrowernumber,$nextaccntno,$itemnumber,$date,$amount,$description,$accounttype,$amountoutstanding,$timestamp,$notify_id,$level);
817   $sth->finish;
818  }
819
820 =item UpdateAccountLines
821
822 () = &UpdateAccountLines($notify_id,$notify_level,$borrowernumber,$itemnumber);
823
824 update the account lines with file number or with file level
825
826 C<$items> is a reference-to-hash whose keys are all of the fields
827 from the items tables of the Koha database. Thus,
828
829 C<$itemnumber> contains the item number
830
831 C<$notify_id> contains the file number
832
833 C<$notify_level> contains the file level
834
835 C<$borrowernumber> contains the borrowernumber
836
837 =cut
838
839 sub UpdateAccountLines {
840 my ($notify_id,$notify_level,$borrowernumber,$itemnumber)=@_;
841 my $query;
842 if ($notify_id eq '')
843 {
844
845     $query=qq|UPDATE accountlines
846     SET  notify_level=?
847     WHERE borrowernumber=? AND itemnumber=?
848     AND (accounttype='FU' or accounttype='O')|;
849 }else
850 {
851     $query=qq|UPDATE accountlines
852      SET notify_id=?, notify_level=?
853            WHERE borrowernumber=?
854     AND itemnumber=?
855         AND (accounttype='FU' or accounttype='O')|;
856 }
857  my $dbh = C4::Context->dbh;
858  my $sth=$dbh->prepare($query);
859
860 if ($notify_id eq '')
861 {
862     $sth->execute($notify_level,$borrowernumber,$itemnumber);
863 }else
864 {
865     $sth->execute($notify_id,$notify_level,$borrowernumber,$itemnumber);
866 }
867  $sth->finish;
868
869 }
870
871
872 =item GetItems
873
874 ($items) = &GetItems($itemnumber);
875
876 Returns the list of all delays from overduerules.
877
878 C<$items> is a reference-to-hash whose keys are all of the fields
879 from the items tables of the Koha database. Thus,
880
881 C<$itemnumber> contains the borrower categorycode
882
883 =cut
884
885 sub GetItems {
886     my($itemnumber) = @_;
887     my $query=qq|SELECT *
888              FROM items
889               WHERE itemnumber=?|;
890         my $dbh = C4::Context->dbh;
891         my $sth=$dbh->prepare($query);
892         $sth->execute($itemnumber);
893         my ($items)=$sth->fetchrow_hashref;
894         $sth->finish;
895     return($items);
896 }
897
898 =item GetOverdueDelays
899
900 (@delays) = &GetOverdueDelays($categorycode);
901
902 Returns the list of all delays from overduerules.
903
904 C<@delays> it's an array contains the three delays from overduerules table
905
906 C<$categorycode> contains the borrower categorycode
907
908 =cut
909
910 sub GetOverdueDelays {
911     my($category) = @_;
912     my $dbh = C4::Context->dbh;
913         my $query=qq|SELECT delay1,delay2,delay3
914                 FROM overduerules
915                 WHERE categorycode=?|;
916     my $sth=$dbh->prepare($query);
917         $sth->execute($category);
918         my (@delays)=$sth->fetchrow_array;
919         $sth->finish;
920         return(@delays);
921 }
922
923 =item CheckAccountLineLevelInfo
924
925 ($exist) = &CheckAccountLineLevelInfo($borrowernumber,$itemnumber,$accounttype,notify_level);
926
927 Check and Returns the list of all overdue books.
928
929 C<$exist> contains number of line in accounlines
930 with the same .biblionumber,itemnumber,accounttype,and notify_level
931
932 C<$borrowernumber> contains the borrower number
933
934 C<$itemnumber> contains item number
935
936 C<$accounttype> contains account type
937
938 C<$notify_level> contains the accountline level 
939
940
941 =cut
942
943 sub CheckAccountLineLevelInfo {
944     my($borrowernumber,$itemnumber,$level) = @_;
945     my $dbh = C4::Context->dbh;
946         my $query=    qq|SELECT count(*)
947             FROM accountlines
948             WHERE borrowernumber =?
949             AND itemnumber = ?
950             AND notify_level=?|;
951     my $sth=$dbh->prepare($query);
952         $sth->execute($borrowernumber,$itemnumber,$level);
953         my ($exist)=$sth->fetchrow;
954         $sth->finish;
955         return($exist);
956 }
957
958 =item GetOverduerules
959
960 ($overduerules) = &GetOverduerules($categorycode);
961
962 Returns the value of borrowers (debarred or not) with notify level
963
964 C<$overduerules> return value of debbraed field in overduerules table
965
966 C<$category> contains the borrower categorycode
967
968 C<$notify_level> contains the notify level
969 =cut
970
971
972 sub GetOverduerules{
973     my($category,$notify_level) = @_;
974     my $dbh = C4::Context->dbh;
975         my $query=qq|SELECT debarred$notify_level
976              FROM overduerules
977              WHERE categorycode=?|;
978     my $sth=$dbh->prepare($query);
979         $sth->execute($category);
980         my ($overduerules)=$sth->fetchrow;
981         $sth->finish;
982         return($overduerules);
983 }
984
985
986 =item CheckBorrowerDebarred
987
988 ($debarredstatus) = &CheckBorrowerDebarred($borrowernumber);
989
990 Check if the borrowers is already debarred
991
992 C<$debarredstatus> return 0 for not debarred and return 1 for debarred
993
994 C<$borrowernumber> contains the borrower number
995
996 =cut
997
998
999 sub CheckBorrowerDebarred{
1000     my($borrowernumber) = @_;
1001     my $dbh = C4::Context->dbh;
1002         my $query=qq|SELECT debarred
1003               FROM borrowers
1004              WHERE borrowernumber=?
1005             |;
1006     my $sth=$dbh->prepare($query);
1007         $sth->execute($borrowernumber);
1008         my ($debarredstatus)=$sth->fetchrow;
1009         $sth->finish;
1010         if ($debarredstatus eq '1'){
1011     return(1);}
1012     else{
1013     return(0);
1014     }
1015 }
1016
1017 =item UpdateBorrowerDebarred
1018
1019 ($borrowerstatut) = &UpdateBorrowerDebarred($borrowernumber);
1020
1021 update status of borrowers in borrowers table (field debarred)
1022
1023 C<$borrowernumber> borrower number
1024
1025 =cut
1026
1027 sub UpdateBorrowerDebarred{
1028     my($borrowernumber) = @_;
1029     my $dbh = C4::Context->dbh;
1030         my $query=qq|UPDATE borrowers
1031              SET debarred='1'
1032                      WHERE borrowernumber=?
1033             |;
1034     my $sth=$dbh->prepare($query);
1035         $sth->execute($borrowernumber);
1036         $sth->finish;
1037         return 1;
1038 }
1039
1040 =item CheckExistantNotifyid
1041
1042   ($exist) = &CheckExistantNotifyid($borrowernumber,$itemnumber,$accounttype,$notify_id);
1043
1044 Check and Returns the notify id if exist else return 0.
1045
1046 C<$exist> contains a notify_id 
1047
1048 C<$borrowernumber> contains the borrower number
1049
1050 C<$date_due> contains the date of item return 
1051
1052
1053 =cut
1054
1055 sub CheckExistantNotifyid {
1056      my($borrowernumber,$date_due) = @_;
1057      my $dbh = C4::Context->dbh;
1058          my $query =  qq|SELECT notify_id FROM issues,accountlines
1059              WHERE accountlines.borrowernumber =?
1060              AND issues.itemnumber= accountlines.itemnumber
1061               AND date_due = ?|;
1062     my $sth=$dbh->prepare($query);
1063          $sth->execute($borrowernumber,$date_due);
1064          my ($exist)=$sth->fetchrow;
1065          $sth->finish;
1066          if ($exist eq '')
1067     {
1068     return(0);
1069     }else
1070         {
1071     return($exist);
1072     }
1073 }
1074
1075 =item CheckAccountLineItemInfo
1076
1077   ($exist) = &CheckAccountLineItemInfo($borrowernumber,$itemnumber,$accounttype,$notify_id);
1078
1079 Check and Returns the list of all overdue items from the same file number(notify_id).
1080
1081 C<$exist> contains number of line in accounlines
1082 with the same .biblionumber,itemnumber,accounttype,notify_id
1083
1084 C<$borrowernumber> contains the borrower number
1085
1086 C<$itemnumber> contains item number
1087
1088 C<$accounttype> contains account type
1089
1090 C<$notify_id> contains the file number 
1091
1092 =cut
1093
1094 sub CheckAccountLineItemInfo {
1095      my($borrowernumber,$itemnumber,$accounttype,$notify_id) = @_;
1096      my $dbh = C4::Context->dbh;
1097          my $query =  qq|SELECT count(*) FROM accountlines
1098              WHERE borrowernumber =?
1099              AND itemnumber = ?
1100               AND accounttype= ?
1101             AND notify_id = ?|;
1102     my $sth=$dbh->prepare($query);
1103          $sth->execute($borrowernumber,$itemnumber,$accounttype,$notify_id);
1104          my ($exist)=$sth->fetchrow;
1105          $sth->finish;
1106          return($exist);
1107  }
1108
1109 =head2 CheckItemNotify
1110
1111 Sql request to check if the document has alreday been notified
1112 this function is not exported, only used with GetOverduesForBranch
1113
1114 =cut
1115
1116 sub CheckItemNotify {
1117         my ($notify_id,$notify_level,$itemnumber) = @_;
1118         my $dbh = C4::Context->dbh;
1119         my $sth = $dbh->prepare("
1120           SELECT COUNT(*) FROM notifys
1121  WHERE notify_id  = ?
1122  AND notify_level  = ? 
1123   AND  itemnumber  =  ? ");
1124  $sth->execute($notify_id,$notify_level,$itemnumber);
1125         my $notified = $sth->fetchrow;
1126 $sth->finish;
1127 return ($notified);
1128 }
1129
1130 =head2 GetOverduesForBranch
1131
1132 Sql request for display all information for branchoverdues.pl
1133 2 possibilities : with or without location .
1134 display is filtered by branch
1135
1136 =cut
1137
1138 sub GetOverduesForBranch {
1139     my ( $branch, $location) = @_;
1140     if ( not $location ) {
1141         my $dbh = C4::Context->dbh;
1142         my $sth = $dbh->prepare("
1143             SELECT 
1144                 borrowers.surname,
1145                 borrowers.firstname,
1146                 biblio.title,
1147                 itemtypes.description,
1148                 issues.date_due,
1149                 issues.returndate,
1150                 branches.branchname,
1151                 items.barcode,
1152                 borrowers.phone,
1153                 borrowers.email,
1154                 items.itemcallnumber,
1155                 borrowers.borrowernumber,
1156                 items.itemnumber,
1157                 biblio.biblionumber,
1158                 issues.branchcode,
1159                 accountlines.notify_id,
1160                 accountlines.notify_level,
1161                 items.location,
1162                 accountlines.amountoutstanding
1163             FROM  issues,borrowers,biblio,biblioitems,itemtypes,items,branches,accountlines
1164             WHERE ( issues.returndate  is null)
1165               AND ( accountlines.amountoutstanding  != '0.000000')
1166               AND ( accountlines.accounttype  = 'FU')
1167               AND ( issues.borrowernumber = accountlines.borrowernumber )
1168               AND ( issues.itemnumber = accountlines.itemnumber )
1169               AND ( borrowers.borrowernumber = issues.borrowernumber )
1170               AND ( biblio.biblionumber = biblioitems.biblionumber )
1171               AND ( biblioitems.biblionumber = items.biblionumber )
1172               AND ( itemtypes.itemtype = biblioitems.itemtype )
1173               AND ( items.itemnumber = issues.itemnumber )
1174               AND ( branches.branchcode = issues.branchcode )
1175               AND (issues.branchcode = ?)
1176               AND (issues.date_due <= NOW())
1177             ORDER BY  borrowers.surname
1178         ");
1179         $sth->execute($branch);
1180         my @getoverdues;
1181         my $i = 0;
1182         while ( my $data = $sth->fetchrow_hashref ) {
1183         #check if the document has already been notified
1184         my $countnotify = CheckItemNotify($data->{'notify_id'},$data->{'notify_level'},$data->{'itemnumber'});
1185         if ($countnotify eq '0'){
1186             $getoverdues[$i] = $data;
1187             $i++;
1188          }
1189         }
1190         return (@getoverdues);
1191         $sth->finish;
1192     }
1193     else {
1194         my $dbh = C4::Context->dbh;
1195         my $sth = $dbh->prepare( "
1196             SELECT  borrowers.surname,
1197                     borrowers.firstname,
1198                     biblio.title,
1199                     itemtypes.description,
1200                     issues.date_due,
1201                     issues.returndate,
1202                     branches.branchname,
1203                     items.barcode,
1204                     borrowers.phone,
1205                     borrowers.email,
1206                     items.itemcallnumber,
1207                     borrowers.borrowernumber,
1208                     items.itemnumber,
1209                     biblio.biblionumber,
1210                     issues.branchcode,
1211                     accountlines.notify_id,
1212                     accountlines.notify_level,
1213                     items.location,
1214                     accountlines.amountoutstanding
1215            FROM  issues,borrowers,biblio,biblioitems,itemtypes,items,branches,accountlines
1216            WHERE ( issues.returndate  is null )
1217              AND ( accountlines.amountoutstanding  != '0.000000')
1218              AND ( accountlines.accounttype  = 'FU')
1219              AND ( issues.borrowernumber = accountlines.borrowernumber )
1220              AND ( issues.itemnumber = accountlines.itemnumber )
1221              AND ( borrowers.borrowernumber = issues.borrowernumber )
1222              AND ( biblio.biblionumber = biblioitems.biblionumber )
1223              AND ( biblioitems.biblionumber = items.biblionumber )
1224              AND ( itemtypes.itemtype = biblioitems.itemtype )
1225              AND ( items.itemnumber = issues.itemnumber )
1226              AND ( branches.branchcode = issues.branchcode )
1227              AND (issues.branchcode = ? AND items.location = ?)
1228              AND (issues.date_due <= NOW())
1229            ORDER BY  borrowers.surname
1230         " );
1231         $sth->execute( $branch, $location);
1232         my @getoverdues;
1233         my $i = 0;
1234         while ( my $data = $sth->fetchrow_hashref ) {
1235         #check if the document has already been notified
1236           my $countnotify = CheckItemNotify($data->{'notify_id'},$data->{'notify_level'},$data->{'itemnumber'});
1237           if ($countnotify eq '0'){                     
1238                 $getoverdues[$i] = $data;
1239                  $i++;
1240          }
1241         }
1242         $sth->finish;
1243         return (@getoverdues); 
1244     }
1245 }
1246
1247
1248 =head2 AddNotifyLine
1249
1250 &AddNotifyLine($borrowernumber, $itemnumber, $overduelevel, $method, $notifyId)
1251
1252 Creat a line into notify, if the method is phone, the notification_send_date is implemented to
1253
1254 =cut
1255
1256 sub AddNotifyLine {
1257     my ( $borrowernumber, $itemnumber, $overduelevel, $method, $notifyId ) = @_;
1258     if ( $method eq "phone" ) {
1259         my $dbh = C4::Context->dbh;
1260         my $sth = $dbh->prepare(
1261             "INSERT INTO notifys (borrowernumber,itemnumber,notify_date,notify_send_date,notify_level,method,notify_id)
1262         VALUES (?,?,now(),now(),?,?,?)"
1263         );
1264         $sth->execute( $borrowernumber, $itemnumber, $overduelevel, $method,
1265             $notifyId );
1266         $sth->finish;
1267     }
1268     else {
1269         my $dbh = C4::Context->dbh;
1270         my $sth = $dbh->prepare(
1271             "INSERT INTO notifys (borrowernumber,itemnumber,notify_date,notify_level,method,notify_id)
1272         VALUES (?,?,now(),?,?,?)"
1273         );
1274         $sth->execute( $borrowernumber, $itemnumber, $overduelevel, $method,
1275             $notifyId );
1276         $sth->finish;
1277     }
1278     return 1;
1279 }
1280
1281 =head2 RemoveNotifyLine
1282
1283 &RemoveNotifyLine( $borrowernumber, $itemnumber, $notify_date );
1284
1285 Cancel a notification
1286
1287 =cut
1288
1289 sub RemoveNotifyLine {
1290     my ( $borrowernumber, $itemnumber, $notify_date ) = @_;
1291     my $dbh = C4::Context->dbh;
1292     my $sth = $dbh->prepare(
1293         "DELETE FROM notifys 
1294             WHERE
1295             borrowernumber=?
1296             AND itemnumber=?
1297             AND notify_date=?"
1298     );
1299     $sth->execute( $borrowernumber, $itemnumber, $notify_date );
1300     $sth->finish;
1301     return 1;
1302 }
1303
1304 1;
1305 __END__
1306
1307 =back
1308
1309 =head1 AUTHOR
1310
1311 Koha Developement team <info@koha.org>
1312
1313 =cut