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