+++ /dev/null
-#!/usr/bin/perl
-
-# This file is part of Koha.
-#
-# Koha is free software; you can redistribute it and/or modify it under the
-# terms of the GNU General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
-#
-# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-# Suite 330, Boston, MA 02111-1307 USA
-
-
-use C4::Members;
-use C4::Circulation;
-use C4::Overdues;
-use Date::Manip;
-
-use Mail::Sendmail;
-use Mail::RFC822::Address;
-use C4::Biblio;
-use strict;
-
-
-#levyFines(); # Do not levy real fines in testing situation.
-notifyOverdues();
-
-
-
-# Todo
-# - Need to calculate the fine on each book; no idea how to get this information from Koha
-# - Need to diffentricate between the total_fines including replacement costs,
-# and the total fines if the books are returned in the day 29 notices (see above).
-# - clean up the %actions hash creation code.
-
-#Done
-# - preferedcont field in borrowers hash; does this do anything?
-# - logging
-# - which 'address' to send sms to?
-# - senders returning success or fail
-
-
-
-sub levyFines {
- # Look at the current overdues, and levy fines on the offenders.
- # arguments:
- # $date
- # $maxfine
-
- # Work out what today is as an integer value.
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =localtime(time);
- $mon++; $year=$year+1900;
- my $date=Date_DaysSince1BC($mon,$mday,$year);
- my $maxfine =5;
-
-
- # Retrieve an array of overdues.
- my ($count, $overduesReference) = Getoverdues();
- print "$count overdue items where found.\n\n";
- my @overdues=@$overduesReference;
-
- foreach my $overdue (@overdues) {
- my @dates=split('-',$overdue->{'date_due'});
- my $due_day=Date_DaysSince1BC($dates[1],$dates[2],$dates[0]);
-
-
- # Check that the item is really overdue. The output of Getoverdues() will normally
- # always be overdue items. However, if you are running this script with a value of $date other than the current time, this check is needed.
- if ($due_day <= $date) {
- my $difference=$date-$due_day;
- print "Itemnumber ".$overdue->{'itemnumber'}." is issued to ".$overdue->{'borrowernumber'}." is overdue by $difference days.\n";
-
- # Calculate the cost of this overdue.
- # Fines vary according to borrower type, but cannot exceed the maximum fine.
- print $overdue->{'borrowernumber'};
- my $borrower=BorType($overdue->{'borrowernumber'});
-
- my ($amount,$type,$printout)=CalcFine($overdue->{'itemnumber'}, $borrower->{'categorycode'}, $difference);
- if ($amount > $maxfine){
- $amount=$maxfine;
- }
-
- if ($amount > 0){
- my $due="$dates[2]/$dates[1]/$dates[0]";
- UpdateFine($overdue->{'itemnumber'}, $overdue->{'borrowernumber'}, $amount, $type, $due);
- print $overdue->{'borrowernumber'}." has been fined $amount for itemnumber ".$overdue->{'itemnumber'}." overdue for $difference days.\n";
- }
-
-
-
- # After 28 days, the item is marked lost and the replacement charge is added as a fine
- if ($difference >= 28) {
- my $borrower=BorType($overdue->{'borrowernumber'});
- if ($borrower->{'cardnumber'} ne ''){
- my $cost=ReplacementCost($overdue->{'itemnumber'});
- my $dbh=C4Connect();
- my $accountno=C4::Circulation::getnextacctno($overdue->{'borrowernumber'});
- my $item=GetBiblioFromItemNumber($overdue->{'itemnumber'});
- if ($item->{'itemlost'} ne '1' && $item->{'itemlost'} ne '2' ){
- $item->{'title'}=~ s/\'/\\'/g;
- my $query="Insert into accountlines (borrowernumber,itemnumber,accountno,date,amount, description,accounttype,amountoutstanding)
- values ($overdue->{'borrowernumber'}, $overdue->{'itemnumber'},
- '$accountno',now(),'$cost','Lost item $item->{'title'} $item->{'barcode'}','L','$cost')";
-
- my $sth=$dbh->prepare($query);
- $sth->execute();
- $sth->finish();
-
- $query="update items set itemlost=2 where itemnumber='$overdue->{'itemnumber'}'";
- $sth=$dbh->prepare($query);
- $sth->execute();
- $sth->finish();
- }
- }
- }
- }
- }
-
- return 1;
- }
-
-
-
-
-
-
-sub notifyOverdues {
- # Look up the overdues for today.
- # Capture overdues which fall on our dates of interest.
-
-
-
-
-####################################################################################################
-# Creating a big hash of available templates
-my %email;
-%email->{'template'}='email-8.txt';
-my %sms;
-%sms->{'template'}='sms-8.txt';
-
-my %fax1;
-%fax1->{'template'}='fax-8.html';
-
-my %firstReminder->{'email'} = \%email;
-%firstReminder->{'sms'} = \%sms;
-%firstReminder->{'fax'} = \%fax1;
-
-my %email2;
-%email2->{'template'}='email-15.txt';
-
-my %fax2;
-%fax2->{'template'}='fax-15.html';
-
-my %letter2;
-%letter2->{'template'}='fax-15.html';
-
-my %sms2->{'template'}='sms-15.txt';
-my %secondReminder->{'email'} = \%email2;
-%secondReminder->{'sms'} = \%sms2;
-%secondReminder->{'fax'} = \%fax2;
-%secondReminder->{'letter'} = \%letter2;
-
-
-my %email3;
-%email3->{'template'}='email-29.txt';
-my %fax3;
-%fax3->{'template'}='fax-29.html';
-my %letter3;
-%letter3->{'template'}='letter-29.html';
-
-my %finalReminder->{'email'} = \%email3;
-%finalReminder->{'fax'} = \%fax3;
-%finalReminder->{'letter'} = \%letter3;
-
-my $fines;
-my %actions;
-%actions->{'8'}=\%firstReminder;
-%actions->{'15'}=\%secondReminder;
-%actions->{'29'}=\%finalReminder;
-
-##################################################################################################################
-
-
- # Work out what today is as an integer value.
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =localtime(time);
- $mon++; $year=$year+1900;
- my $date=Date_DaysSince1BC($mon,$mday,$year);
-
-
- # Retrieve an array of overdues.
- my ($count, $overduesReference) = Getoverdues();
- print "$count overdue items where found.\n\n";
- my @overdues=@$overduesReference;
-
-
- # We're going to build a hash of arrays, containing the items requiring action.
- # ->borrowernumber, date, @overdues
- my %actionItems;
- foreach my $actionday (keys(%actions)) {
- my @items=();
- %actionItems->{$actionday} = \@items;
- }
-
-
-
- foreach my $overdue (@overdues) {
- my @dates=split('-',$overdue->{'date_due'});
- my $due_day=Date_DaysSince1BC($dates[1],$dates[2],$dates[0]);
-
- my $difference=$date-$due_day;
-# $overdue->{'fine'}=GetFine($overdue->{'itemnumber'});
- # If does this item fall on a day of interest?
- $overdue->{'difference'}=$difference;
- foreach my $actiondate (keys(%actions)) {
- if ($actiondate == $difference) {
- my @items = @{%actionItems->{$actiondate}};
-
- my %o = %$overdue;
- push (@items, \%o);
- %actionItems->{$actiondate} = \@items;
- }
- }
- }
-
-
-
-
- # We now have a hash containing overdues which need actioning, we can step through each set.
- # Work from earilest to latest. We only wish to send the most urgent message.
- my %messages;
- my %borritem;
-
- foreach my $actiondate (sort {$a <=> $b} (keys(%actions))) {
- print "\n\nThe following items are $actiondate days overdue.\n";
- my @items = @{%actionItems->{$actiondate}};
-
-
- foreach my $overdue (@items) {
- if ($overdue->{'difference'} eq $actiondate) {
- # Detemine which borrower is responsible for this overdue;
- # if the offender is a child, then the garentor is the person to notify
- my $borrower=responsibleBorrower($overdue);
-
-
- my ($method, $address) = preferedContactMethod($borrower);
- if ($method) {
-
- # Do we have to send something, using this method on this day?
- if (%actions->{$actiondate}->{$method}->{'template'}) {
- # If this user has one overdue, then they may have offers as well.
- # No point in sending a notice without mentioning all of the items.
- my @alloverdues;
- foreach my $over (@overdues) {
- my $responisble= responsibleBorrower($over);
- if ($responisble->{'borrowernumber'} eq $borrower->{'borrowernumber'}) {
- $over->{'borrowernumber'}=$responisble->{'borrowernumber'};
- my %o = %$over;
- push (@alloverdues, \%o);
- }
- }
-
- my $dbh=C4Connect(); # FIXME disconnect this
-
- # Template the message
- my $template = HTML::Template->new(filename => 'templates/'.%actions->{$actiondate}->{$method}->{'template'}, die_on_bad_params => 0);
-
- my @bookdetails;
- my $total_fines = 0;
- foreach my $over (@alloverdues) {
- my %row_data;
- if ( my $item = GetBiblioFromItemNumber( $over->{'itemnumber'})){
- print "getting fine ($over->{'itemnumber'} $overdue->{'borrowernumber'} $over->{'borrowernumber'}\n";
- my $fine = GetFine($over->{'itemnumber'},$overdue->{'borrowernumber'});
-
-
- print "fine=$fine ";
-
- my $rep = ReplacementCost2($over->{'itemnumber'},$overdue->{'borrowernumber'});
-
- if ($rep){
- $rep+=0.00;
- }
- if ($fine){
- $fine+=0.00;
- $borritem{"$over->{'itemnumber'} $over->{'borrowernumber'}"}=$fine;
- } else {
- $borritem{"$over->{'itemnumber'} $over->{'borrowernumber'}"}+=$fine;
- }
- print $borritem{"$over->{'itemnumber'} $over->{'borrowernumber'}"},"\n";
- $total_fines += $borritem{"$over->{'itemnumber'} $over->{'borrowernumber'}"};
- $item->{'title'}=substr($item->{'title'},0,25);
- my $len=length($item->{'title'});
- if ($len < 25){
- my $diff=25-$len;
- $item->{'title'}.=" " x $diff;
- }
-
- $row_data{'BARCODE'}=$item->{'barcode'};
- $row_data{'TITLE'}=$item->{'title'};
- $row_data{'DATE_DUE'}=$over->{'date_due'};
- $row_data{'FINE'}=$borritem{"$over->{'itemnumber'} $over->{'borrowernumber'}"};
- $row_data{'REP'}=$rep;
-
- push(@bookdetails, \%row_data);
- } else {
- print "Missing item $over->{'itemnumber'}\n";
- }
- }
-
- $template->param(BOOKDETAILS => \@bookdetails);
- my %params;
- %params->{'borrowernumber'} = $overdue->{'borrowernumber'};
- my ($total, $acctlines, $count) = &GetMemberAccountRecords($overdue->{'borrowernumber'});
- $template->param(FINES_TOTAL => $total_fines);
- $template->param(OWING => $total);
- my $name= "$borrower->{'firstname'} $borrower->{'surname'}";
- $template->param(NAME=> $name);
-
- %messages->{$borrower->{'borrowernumber'}} = $template->output();
- }
- else {
- print "No $method needs to be sent at $overdue->{'difference'} days; not sending\n";
- }
-
- }
- else {
- print "This borrower has an overdue item, but no means of contact\n";
- }
-
- } #end of 'if this overdue falls on an action date'
-
- } #end of 'foreach overdue'
-
- } # end of foreach actiondate
-
-
- # How that all of the messsages to be sent have been composed, send them.
- foreach my $borrowernumber (keys(%messages)) {
- print "$borrowernumber\n";
-
- my $borrower=BorType($borrowernumber);
- my ($method, $address) = preferedContactMethod($borrower);
-
- my $result=0;
- if ($method eq 'email') {
- $result = sendEmail($address, 'lep@library.org.nz', 'Overdue Library Items', %messages->{$borrowernumber});
- }
- elsif ($method eq 'sms') {
- $result = sendSMS($address, %messages->{$borrowernumber});
- }
- elsif ($method eq 'fax') {
- $result = sendFax($address, %messages->{$borrowernumber});
- }
- elsif ($method eq 'letter') {
- $result = printLetter($address, %messages->{$borrowernumber});
- }
-
-
- #print %messages->{$borrowernumber}; # debug
-
-
- # Log the outcome of this attempt
- logContact($borrowernumber, $method, $address, $result, %messages->{$borrowernumber});
- }
-
-
-
- return 1;
- }
-
-
-
-
-
-
-
-
-
-
-sub responsibleBorrower {
- # Given an overdue item, return the details of the borrower responible as a hash of database columns.
- my $overdue=$_[0];
-
- if ($overdue->{'borrowernumber'}) {
- my $borrower=BorType($overdue->{'borrowernumber'});
-
-
- # Overdue books assigned to children have notices sent to the guarantor.
- if ($borrower->{'categorycode'} eq 'C') {
- my $dbh=C4Connect();
- my $query="Select borrowernumber from borrowers
- where borrowernumber=?";
-
- my $sth=$dbh->prepare($query);
- $sth->execute($borrower->{'guarantor'});
-
- my $tdata=$sth->fetchrow_hashref();
- $sth->finish();
- $dbh->disconnect();
-
- my $guarantor=BorType($tdata->{'borrowernumber'});
- $borrower = $guarantor;
- }
-
- return $borrower;
- }
-
- }
-
-
-
-
-
-
-
-
-
-sub preferedContactMethod {
- # Given a reference to borrower details, in the format
- # returned by BorType(), determine the prefered contact method, and address to use.
- my $borrower=$_[0];
-# print "finding borrower method $borrower->{'preferredcont'} $borrower->{'emailaddress'} $borrower->{'streetaddress'}\n";
-
- # Possible contact methods, in order of preference are:
- my @methods = ('email', 'sms', 'fax', 'letter');
-
- my $method='';
- my $address='';
-
-
- # Does this borrower have a borrower.preferredcont set?
- # If so, push it to the head of our array of methods to try.
- # If it's a method unheard of by this system, then we'll drop though to the prefined methods above.
- # Note use of unshift to push onto the front of the array.
- if ($borrower->{'preferredcont'}) {
- unshift(@methods, $borrower->{'preferredcont'});
- }
-
-
- # Cycle through the possible methods until one is accepted
- while ((@methods) and (!$address)) {
- $method=shift(@methods);
-
-
- if ($method eq 'email') {
- if (($borrower->{'emailaddress'}) and (Mail::RFC822::Address::valid($borrower->{'emailaddress'}))) {
- $address = $borrower->{'emailaddress'};
- }
- }
- elsif ($method eq 'fax') {
- if ($borrower->{'faxnumber'}) {
- $address = $borrower->{'faxnumber'};
- }
- }
- elsif ($method eq 'sms') {
- if ($borrower->{'textmessaging'}) {
- $address = $borrower->{'textmessaging'};
- }
- }
- elsif ($method eq 'letter') {
- if ($borrower->{'streetaddress'}) {
- $address = mailingAddress($borrower);
- }
- }
- }
-print "$method, $address\n";
- return ($method, $address);
- }
-
-
-
-
-
-
-
-
-sub logContact {
- # Given the details of an attempt to contact a borrower,
- # log them in the attempted_contacts table of the koha database.
- my ($borrowernumber, $method, $address, $result, $message) = @_;
-
- my $dbh=C4Connect(); # FIXME - disconnect me
- my $querystring = " insert into attempted_contacts
- (borrowernumber, method, address, result, message, date)
- values (?, ?, ?, ?, ?, now())";
- my $sth= $dbh->prepare($querystring);
- $sth->execute($borrowernumber, $method, $address, $result, $message);
- $sth->finish();
- }
-
-
-
-
-
-
-
-
-sub mailingAddress {
- # Given a hash of borrower information, such as that returned by BorType,
- # return a mailing address.
- my $borrower=$_[0];
-
- my $address = $borrower->{'firstname'}."\n".
- $borrower->{'streetaddress'}."\n".
- $borrower->{'streetcity'};
-
- return $address;
- }
-
-
-
-
-
-
-
-sub itemFine {
- # Given an overdue item, return the current fines on it
- my $overdue=$_[0];
- # FIXME
- return 1;
- }
-
-
-
-
-
-
-
-
-
-sub sendEmail {
- # Given an email address, and a subject and message, attempt to send email.
- my $to=$_[0];
- my $from=$_[1];
- my $subject=$_[2];
- my $message=$_[3];
-
-# print "in email area";
-
-# print "\nSending Email To: $to\n$message\n";
-
- my %mail = ( To => $to,
-# CC => 'rosalie@library.org.nz',
- From => $from,
- Subject => $subject,
- Message => $message);
-
-
- if (not(sendmail %mail)) {
- warn "sendEmail to $to failed.";
- return 0;
- }
-
- return 1;
-# die "got to here";
- }
-
-
-sub sendSMS {
- # Given a cell number and a message, attempt to send an SMS message.
- # FIXME - needs information about how to do this at HLT
- return 1;
- }
-
-
-sub sendFax {
- print "in fax \n";
- # Given a fax number, and a message, attempt to send a fax.
- # FIXME - needs information about how to do this at HLT
- # This is fairly easy.
- # We will be past the body of the fax as HTML.
- # We can pass this through html2ps to generate Postscript suitable
- # for passing to the fax server.
- return 1;
- }
-
-
-sub printLetter {
- # Print a letter
- # FIXME - needs information about how to do this at HLT
- return 1;
- }