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