Adding Circulation and Overdues modules
[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 $env;
701     my $query=qq|    SELECT distinct(notify_id)
702             FROM accountlines
703             WHERE borrowernumber=?|;
704     my @notify;
705     my $sth=$dbh->prepare($query);
706         $sth->execute($borrowernumber);
707           while ( my $numberofotify=$sth->fetchrow_array){
708     push (@notify,$numberofotify);
709     }
710     $sth->finish;
711
712     return (@notify);
713
714 }
715
716 =item AmountNotify
717
718 ($totalnotify) = &AmountNotify($notifyid);
719
720 Returns amount for all file per borrowers
721 C<$notifyid> is the file number
722
723 C<$totalnotify> contains amount of a file
724
725 C<$notify_id> contains the file number for the borrower number nad item number
726
727 =cut
728
729 sub AmountNotify{
730     my ($notifyid)=@_;
731     my $dbh = C4::Context->dbh;
732     my $query=qq|    SELECT sum(amountoutstanding)
733             FROM accountlines
734             WHERE notify_id=?|;
735     my $sth=$dbh->prepare($query);
736         $sth->execute($notifyid);
737           my $totalnotify=$sth->fetchrow;
738     $sth->finish;
739     return ($totalnotify);
740 }
741
742
743 =item GetNotifyId
744
745 ($notify_id) = &GetNotifyId($borrowernumber,$itemnumber);
746
747 Returns the file number per borrower and itemnumber
748
749 C<$borrowernumber> is a reference-to-hash whose keys are all of the fields
750 from the items tables of the Koha database. Thus,
751
752 C<$itemnumber> contains the borrower categorycode
753
754 C<$notify_id> contains the file number for the borrower number nad item number
755
756 =cut
757
758  sub GetNotifyId {
759  my ($borrowernumber,$itemnumber)=@_;
760  my $query=qq|SELECT notify_id 
761            FROM accountlines
762            WHERE borrowernumber=?
763           AND itemnumber=?
764            AND (accounttype='FU' or accounttype='O')|;
765  my $dbh = C4::Context->dbh;
766  my $sth=$dbh->prepare($query);
767  $sth->execute($borrowernumber,$itemnumber);
768  my ($notify_id)=$sth->fetchrow;
769  $sth->finish;
770  return ($notify_id);
771
772  }
773
774 =item CreateItemAccountLine
775
776 () = &CreateItemAccountLine($borrowernumber,$itemnumber,$date,$amount,$description,$accounttype,$amountoutstanding,$timestamp,$notify_id,$level);
777
778 update the account lines with file number or with file level
779
780 C<$items> is a reference-to-hash whose keys are all of the fields
781 from the items tables of the Koha database. Thus,
782
783 C<$itemnumber> contains the item number
784
785 C<$borrowernumber> contains the borrower number
786
787 C<$date> contains the date of the day
788
789 C<$amount> contains item price
790
791 C<$description> contains the descritpion of accounttype 
792
793 C<$accounttype> contains the account type
794
795 C<$amountoutstanding> contains the $amountoutstanding 
796
797 C<$timestamp> contains the timestamp with time and the date of the day
798
799 C<$notify_id> contains the file number
800
801 C<$level> contains the file level
802
803
804 =cut
805
806  sub CreateItemAccountLine {
807   my ($borrowernumber,$itemnumber,$date,$amount,$description,$accounttype,$amountoutstanding,$timestamp,$notify_id,$level)=@_;
808   my $dbh = C4::Context->dbh;
809   my $nextaccntno = getnextacctno($borrowernumber);
810    my $query= "INSERT into accountlines  
811          (borrowernumber,accountno,itemnumber,date,amount,description,accounttype,amountoutstanding,timestamp,notify_id,notify_level)
812           VALUES
813              (?,?,?,?,?,?,?,?,?,?,?)";
814   
815   
816   my $sth=$dbh->prepare($query);
817   $sth->execute($borrowernumber,$nextaccntno,$itemnumber,$date,$amount,$description,$accounttype,$amountoutstanding,$timestamp,$notify_id,$level);
818   $sth->finish;
819  }
820
821 =item UpdateAccountLines
822
823 () = &UpdateAccountLines($notify_id,$notify_level,$borrowernumber,$itemnumber);
824
825 update the account lines with file number or with file level
826
827 C<$items> is a reference-to-hash whose keys are all of the fields
828 from the items tables of the Koha database. Thus,
829
830 C<$itemnumber> contains the item number
831
832 C<$notify_id> contains the file number
833
834 C<$notify_level> contains the file level
835
836 C<$borrowernumber> contains the borrowernumber
837
838 =cut
839
840 sub UpdateAccountLines {
841 my ($notify_id,$notify_level,$borrowernumber,$itemnumber)=@_;
842 my $query;
843 if ($notify_id eq '')
844 {
845
846     $query=qq|UPDATE accountlines
847     SET  notify_level=?
848     WHERE borrowernumber=? AND itemnumber=?
849     AND (accounttype='FU' or accounttype='O')|;
850 }else
851 {
852     $query=qq|UPDATE accountlines
853      SET notify_id=?, notify_level=?
854            WHERE borrowernumber=?
855     AND itemnumber=?
856         AND (accounttype='FU' or accounttype='O')|;
857 }
858  my $dbh = C4::Context->dbh;
859  my $sth=$dbh->prepare($query);
860
861 if ($notify_id eq '')
862 {
863     $sth->execute($notify_level,$borrowernumber,$itemnumber);
864 }else
865 {
866     $sth->execute($notify_id,$notify_level,$borrowernumber,$itemnumber);
867 }
868  $sth->finish;
869
870 }
871
872
873 =item GetItems
874
875 ($items) = &GetItems($itemnumber);
876
877 Returns the list of all delays from overduerules.
878
879 C<$items> is a reference-to-hash whose keys are all of the fields
880 from the items tables of the Koha database. Thus,
881
882 C<$itemnumber> contains the borrower categorycode
883
884 =cut
885
886 sub GetItems {
887     my($itemnumber) = @_;
888     my $query=qq|SELECT *
889              FROM items
890               WHERE itemnumber=?|;
891         my $dbh = C4::Context->dbh;
892         my $sth=$dbh->prepare($query);
893         $sth->execute($itemnumber);
894         my ($items)=$sth->fetchrow_hashref;
895         $sth->finish;
896     return($items);
897 }
898
899 =item GetOverdueDelays
900
901 (@delays) = &GetOverdueDelays($categorycode);
902
903 Returns the list of all delays from overduerules.
904
905 C<@delays> it's an array contains the three delays from overduerules table
906
907 C<$categorycode> contains the borrower categorycode
908
909 =cut
910
911 sub GetOverdueDelays {
912     my($category) = @_;
913     my $dbh = C4::Context->dbh;
914         my $query=qq|SELECT delay1,delay2,delay3
915                 FROM overduerules
916                 WHERE categorycode=?|;
917     my $sth=$dbh->prepare($query);
918         $sth->execute($category);
919         my (@delays)=$sth->fetchrow_array;
920         $sth->finish;
921         return(@delays);
922 }
923
924 =item CheckAccountLineLevelInfo
925
926 ($exist) = &CheckAccountLineLevelInfo($borrowernumber,$itemnumber,$accounttype,notify_level);
927
928 Check and Returns the list of all overdue books.
929
930 C<$exist> contains number of line in accounlines
931 with the same .biblionumber,itemnumber,accounttype,and notify_level
932
933 C<$borrowernumber> contains the borrower number
934
935 C<$itemnumber> contains item number
936
937 C<$accounttype> contains account type
938
939 C<$notify_level> contains the accountline level 
940
941
942 =cut
943
944 sub CheckAccountLineLevelInfo {
945     my($borrowernumber,$itemnumber,$level) = @_;
946     my $dbh = C4::Context->dbh;
947         my $query=    qq|SELECT count(*)
948             FROM accountlines
949             WHERE borrowernumber =?
950             AND itemnumber = ?
951             AND notify_level=?|;
952     my $sth=$dbh->prepare($query);
953         $sth->execute($borrowernumber,$itemnumber,$level);
954         my ($exist)=$sth->fetchrow;
955         $sth->finish;
956         return($exist);
957 }
958
959 =item GetOverduerules
960
961 ($overduerules) = &GetOverduerules($categorycode);
962
963 Returns the value of borrowers (debarred or not) with notify level
964
965 C<$overduerules> return value of debbraed field in overduerules table
966
967 C<$category> contains the borrower categorycode
968
969 C<$notify_level> contains the notify level
970 =cut
971
972
973 sub GetOverduerules{
974     my($category,$notify_level) = @_;
975     my $dbh = C4::Context->dbh;
976         my $query=qq|SELECT debarred$notify_level
977              FROM overduerules
978              WHERE categorycode=?|;
979     my $sth=$dbh->prepare($query);
980         $sth->execute($category);
981         my ($overduerules)=$sth->fetchrow;
982         $sth->finish;
983         return($overduerules);
984 }
985
986
987 =item CheckBorrowerDebarred
988
989 ($debarredstatus) = &CheckBorrowerDebarred($borrowernumber);
990
991 Check if the borrowers is already debarred
992
993 C<$debarredstatus> return 0 for not debarred and return 1 for debarred
994
995 C<$borrowernumber> contains the borrower number
996
997 =cut
998
999
1000 sub CheckBorrowerDebarred{
1001     my($borrowernumber) = @_;
1002     my $dbh = C4::Context->dbh;
1003         my $query=qq|SELECT debarred
1004               FROM borrowers
1005              WHERE borrowernumber=?
1006             |;
1007     my $sth=$dbh->prepare($query);
1008         $sth->execute($borrowernumber);
1009         my ($debarredstatus)=$sth->fetchrow;
1010         $sth->finish;
1011         if ($debarredstatus eq '1'){
1012     return(1);}
1013     else{
1014     return(0);
1015     }
1016 }
1017
1018 =item UpdateBorrowerDebarred
1019
1020 ($borrowerstatut) = &UpdateBorrowerDebarred($borrowernumber);
1021
1022 update status of borrowers in borrowers table (field debarred)
1023
1024 C<$borrowernumber> borrower number
1025
1026 =cut
1027
1028 sub UpdateBorrowerDebarred{
1029     my($borrowernumber) = @_;
1030     my $dbh = C4::Context->dbh;
1031         my $query=qq|UPDATE borrowers
1032              SET debarred='1'
1033                      WHERE borrowernumber=?
1034             |;
1035     my $sth=$dbh->prepare($query);
1036         $sth->execute($borrowernumber);
1037         $sth->finish;
1038         return 1;
1039 }
1040
1041 =item CheckExistantNotifyid
1042
1043   ($exist) = &CheckExistantNotifyid($borrowernumber,$itemnumber,$accounttype,$notify_id);
1044
1045 Check and Returns the notify id if exist else return 0.
1046
1047 C<$exist> contains a notify_id 
1048
1049 C<$borrowernumber> contains the borrower number
1050
1051 C<$date_due> contains the date of item return 
1052
1053
1054 =cut
1055
1056 sub CheckExistantNotifyid {
1057      my($borrowernumber,$date_due) = @_;
1058      my $dbh = C4::Context->dbh;
1059          my $query =  qq|SELECT notify_id FROM issues,accountlines
1060              WHERE accountlines.borrowernumber =?
1061              AND issues.itemnumber= accountlines.itemnumber
1062               AND date_due = ?|;
1063     my $sth=$dbh->prepare($query);
1064          $sth->execute($borrowernumber,$date_due);
1065          my ($exist)=$sth->fetchrow;
1066          $sth->finish;
1067          if ($exist eq '')
1068     {
1069     return(0);
1070     }else
1071         {
1072     return($exist);
1073     }
1074 }
1075
1076 =item CheckAccountLineItemInfo
1077
1078   ($exist) = &CheckAccountLineItemInfo($borrowernumber,$itemnumber,$accounttype,$notify_id);
1079
1080 Check and Returns the list of all overdue items from the same file number(notify_id).
1081
1082 C<$exist> contains number of line in accounlines
1083 with the same .biblionumber,itemnumber,accounttype,notify_id
1084
1085 C<$borrowernumber> contains the borrower number
1086
1087 C<$itemnumber> contains item number
1088
1089 C<$accounttype> contains account type
1090
1091 C<$notify_id> contains the file number 
1092
1093 =cut
1094
1095 sub CheckAccountLineItemInfo {
1096      my($borrowernumber,$itemnumber,$accounttype,$notify_id) = @_;
1097      my $dbh = C4::Context->dbh;
1098          my $query =  qq|SELECT count(*) FROM accountlines
1099              WHERE borrowernumber =?
1100              AND itemnumber = ?
1101               AND accounttype= ?
1102             AND notify_id = ?|;
1103     my $sth=$dbh->prepare($query);
1104          $sth->execute($borrowernumber,$itemnumber,$accounttype,$notify_id);
1105          my ($exist)=$sth->fetchrow;
1106          $sth->finish;
1107          return($exist);
1108  }
1109
1110 =head2 CheckItemNotify
1111
1112 Sql request to check if the document has alreday been notified
1113 this function is not exported, only used with GetOverduesForBranch
1114
1115 =cut
1116
1117 sub CheckItemNotify {
1118         my ($notify_id,$notify_level,$itemnumber) = @_;
1119         my $dbh = C4::Context->dbh;
1120         my $sth = $dbh->prepare("
1121           SELECT COUNT(*) FROM notifys
1122  WHERE notify_id  = ?
1123  AND notify_level  = ? 
1124   AND  itemnumber  =  ? ");
1125  $sth->execute($notify_id,$notify_level,$itemnumber);
1126         my $notified = $sth->fetchrow;
1127 $sth->finish;
1128 return ($notified);
1129 }
1130
1131 =head2 GetOverduesForBranch
1132
1133 Sql request for display all information for branchoverdues.pl
1134 2 possibilities : with or without department .
1135 display is filtered by branch
1136
1137 =cut
1138
1139 sub GetOverduesForBranch {
1140     my ( $branch, $department) = @_;
1141     if ( not $department ) {
1142         my $dbh = C4::Context->dbh;
1143         my $sth = $dbh->prepare("
1144             SELECT 
1145                 borrowers.surname,
1146                 borrowers.firstname,
1147                 biblio.title,
1148                 itemtypes.description,
1149                 issues.date_due,
1150                 issues.returndate,
1151                 branches.branchname,
1152                 items.barcode,
1153                 borrowers.phone,
1154                 borrowers.email,
1155                 items.itemcallnumber,
1156                 borrowers.borrowernumber,
1157                 items.itemnumber,
1158                 biblio.biblionumber,
1159                 issues.branchcode,
1160                 accountlines.notify_id,
1161                 accountlines.notify_level,
1162                 items.location,
1163                 accountlines.amountoutstanding
1164             FROM  issues,borrowers,biblio,biblioitems,itemtypes,items,branches,accountlines
1165             WHERE ( issues.returndate  is null)
1166               AND ( accountlines.amountoutstanding  != '0.000000')
1167               AND ( accountlines.accounttype  = 'FU')
1168               AND ( issues.borrowernumber = accountlines.borrowernumber )
1169               AND ( issues.itemnumber = accountlines.itemnumber )
1170               AND ( borrowers.borrowernumber = issues.borrowernumber )
1171               AND ( biblio.biblionumber = biblioitems.biblionumber )
1172               AND ( biblioitems.biblionumber = items.biblionumber )
1173               AND ( itemtypes.itemtype = biblioitems.itemtype )
1174               AND ( items.itemnumber = issues.itemnumber )
1175               AND ( branches.branchcode = issues.branchcode )
1176               AND (issues.branchcode = ?)
1177               AND (issues.date_due <= NOW())
1178             ORDER BY  borrowers.surname
1179         ");
1180         $sth->execute($branch);
1181         my @getoverdues;
1182         my $i = 0;
1183         while ( my $data = $sth->fetchrow_hashref ) {
1184         #check if the document has already been notified
1185         my $countnotify = CheckItemNotify($data->{'notify_id'},$data->{'notify_level'},$data->{'itemnumber'});
1186         if ($countnotify eq '0'){
1187             $getoverdues[$i] = $data;
1188             $i++;
1189          }
1190         }
1191         return (@getoverdues);
1192         $sth->finish;
1193     }
1194     else {
1195         my $dbh = C4::Context->dbh;
1196         my $sth = $dbh->prepare( "
1197             SELECT  borrowers.surname,
1198                     borrowers.firstname,
1199                     biblio.title,
1200                     itemtypes.description,
1201                     issues.date_due,
1202                     issues.returndate,
1203                     branches.branchname,
1204                     items.barcode,
1205                     borrowers.phone,
1206                     borrowers.email,
1207                     items.itemcallnumber,
1208                     borrowers.borrowernumber,
1209                     items.itemnumber,
1210                     biblio.biblionumber,
1211                     issues.branchcode,
1212                     accountlines.notify_id,
1213                     accountlines.notify_level,
1214                     items.location,
1215                     accountlines.amountoutstanding
1216            FROM  issues,borrowers,biblio,biblioitems,itemtypes,items,branches,accountlines
1217            WHERE ( issues.returndate  is null )
1218              AND ( accountlines.amountoutstanding  != '0.000000')
1219              AND ( accountlines.accounttype  = 'FU')
1220              AND ( issues.borrowernumber = accountlines.borrowernumber )
1221              AND ( issues.itemnumber = accountlines.itemnumber )
1222              AND ( borrowers.borrowernumber = issues.borrowernumber )
1223              AND ( biblio.biblionumber = biblioitems.biblionumber )
1224              AND ( biblioitems.biblionumber = items.biblionumber )
1225              AND ( itemtypes.itemtype = biblioitems.itemtype )
1226              AND ( items.itemnumber = issues.itemnumber )
1227              AND ( branches.branchcode = issues.branchcode )
1228              AND (issues.branchcode = ? AND items.location = ?)
1229              AND (issues.date_due <= NOW())
1230            ORDER BY  borrowers.surname
1231         " );
1232         $sth->execute( $branch, $department);
1233         my @getoverdues;
1234         my $i = 0;
1235         while ( my $data = $sth->fetchrow_hashref ) {
1236         #check if the document has already been notified
1237           my $countnotify = CheckItemNotify($data->{'notify_id'},$data->{'notify_level'},$data->{'itemnumber'});
1238           if ($countnotify eq '0'){                     
1239                 $getoverdues[$i] = $data;
1240                  $i++;
1241          }
1242         }
1243         $sth->finish;
1244         return (@getoverdues); 
1245     }
1246 }
1247
1248
1249 =head2 AddNotifyLine
1250
1251 &AddNotifyLine($borrowernumber, $itemnumber, $overduelevel, $method, $notifyId)
1252
1253 Creat a line into notify, if the method is phone, the notification_send_date is implemented to
1254
1255 =cut
1256
1257 sub AddNotifyLine {
1258     my ( $borrowernumber, $itemnumber, $overduelevel, $method, $notifyId ) = @_;
1259     if ( $method eq "phone" ) {
1260         my $dbh = C4::Context->dbh;
1261         my $sth = $dbh->prepare(
1262             "INSERT INTO notifys (borrowernumber,itemnumber,notify_date,notify_send_date,notify_level,method,notify_id)
1263         VALUES (?,?,now(),now(),?,?,?)"
1264         );
1265         $sth->execute( $borrowernumber, $itemnumber, $overduelevel, $method,
1266             $notifyId );
1267         $sth->finish;
1268     }
1269     else {
1270         my $dbh = C4::Context->dbh;
1271         my $sth = $dbh->prepare(
1272             "INSERT INTO notifys (borrowernumber,itemnumber,notify_date,notify_level,method,notify_id)
1273         VALUES (?,?,now(),?,?,?)"
1274         );
1275         $sth->execute( $borrowernumber, $itemnumber, $overduelevel, $method,
1276             $notifyId );
1277         $sth->finish;
1278     }
1279     return 1;
1280 }
1281
1282 =head2 RemoveNotifyLine
1283
1284 &RemoveNotifyLine( $borrowernumber, $itemnumber, $notify_date );
1285
1286 Cancel a notification
1287
1288 =cut
1289
1290 sub RemoveNotifyLine {
1291     my ( $borrowernumber, $itemnumber, $notify_date ) = @_;
1292     my $dbh = C4::Context->dbh;
1293     my $sth = $dbh->prepare(
1294         "DELETE FROM notifys 
1295             WHERE
1296             borrowernumber=?
1297             AND itemnumber=?
1298             AND notify_date=?"
1299     );
1300     $sth->execute( $borrowernumber, $itemnumber, $notify_date );
1301     $sth->finish;
1302     return 1;
1303 }
1304
1305 1;
1306 __END__
1307
1308 =back
1309
1310 =head1 AUTHOR
1311
1312 Koha Developement team <info@koha.org>
1313
1314 =cut