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