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