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