#
# 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 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 3 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.
+# 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.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
use strict;
use warnings;
# find Koha's Perl modules
# test carefully before changing this
- use FindBin;
+ use FindBin ();
eval { require "$FindBin::Bin/../kohalib.pl" };
}
-use Getopt::Long;
-use Pod::Usage;
-use Date::Calc qw(Add_Delta_Days);
+use Getopt::Long qw( GetOptions );
+use Pod::Usage qw( pod2usage );
+use Koha::Script -cron;
use C4::Context;
-use C4::Items;
use C4::Letters;
use C4::Overdues;
-use C4::Dates;
-use C4::Calendar;
+use Koha::Calendar;
+use Koha::DateUtils qw( dt_from_string output_pref );
+use Koha::Patrons;
+use Koha::Libraries;
sub usage {
pod2usage( -verbose => 2 );
exit;
}
-die
- "TalkingTechItivaPhoneNotification system preference not activated... dying\n"
+die "TalkingTechItivaPhoneNotification system preference not activated... dying\n"
unless ( C4::Context->preference("TalkingTechItivaPhoneNotification") );
# Database handle
my $library_code;
my $help;
my $outfile;
+my $skip_patrons_with_email;
+my $patron_branchcode;
# maps to convert I-tiva terms to Koha terms
my $type_module_map = {
};
my $type_notice_map = {
- 'PREOVERDUE' => 'PREDUE_PHONE',
- 'OVERDUE' => 'OVERDUE_PHONE',
- 'RESERVE' => 'HOLD_PHONE',
+ 'PREOVERDUE' => 'PREDUE',
+ 'OVERDUE' => 'OVERDUE',
+ 'RESERVE' => 'HOLD',
};
GetOptions(
- 'o|output:s' => \$outfile,
- 'v' => \$verbose,
- 'lang:s' => \$language,
- 'type:s' => \@types,
- 'w|waiting-hold-day:s' => \@holds_waiting_days_to_call,
- 'c|code|library-code:s' => \$library_code,
- 'help|h' => \$help,
+ 'o|output:s' => \$outfile,
+ 'v' => \$verbose,
+ 'lang:s' => \$language,
+ 'type:s' => \@types,
+ 'w|waiting-hold-day:s' => \@holds_waiting_days_to_call,
+ 'c|code|library-code:s' => \$library_code,
+ 's|skip-patrons-with-email' => \$skip_patrons_with_email,
+ 'pb|patron-branchcode:s' => \$patron_branchcode,
+ 'h|help' => \$help,
);
$language = uc($language);
pod2usage( -verbose => 1 ) if $help;
+if ($patron_branchcode) {
+ die("Invalid branchcode '$patron_branchcode' passed in -pb --patron-branchcode parameter")
+ unless Koha::Libraries->search( { branchcode => $patron_branchcode } )->count;
+}
+
# output log or STDOUT
my $OUT;
if ( defined $outfile ) {
open( $OUT, '>', "$outfile" ) || die("Cannot open output file");
-}
-else {
+} else {
print "No output file defined; printing to STDOUT\n"
if ( defined $verbose );
- open( $OUT, '>', "&STDOUT" ) || die("Couldn't duplicate STDOUT: $!");
+ $OUT = *STDOUT || die "Couldn't duplicate STDOUT: $!";
}
my $format = 'V'; # format for phone notifications
foreach my $type (@types) {
$type = uc($type); #just in case lower or mixed-case was supplied
- my $module =
- $type_module_map->{$type}; #since the module is required to get the letter
- my $code = $type_notice_map->{$type}; #to get the Koha name of the notice
+ my $module = $type_module_map->{$type}; #since the module is required to get the letter
+ my $code = $type_notice_map->{$type}; #to get the Koha name of the notice
my @loop;
if ( $type eq 'OVERDUE' ) {
- @loop = GetOverdueIssues();
- }
- elsif ( $type eq 'PREOVERDUE' ) {
- @loop = GetPredueIssues();
- }
- elsif ( $type eq 'RESERVE' ) {
- @loop = GetWaitingHolds();
- }
- else {
+ @loop = GetOverdueIssues( $patron_branchcode );
+ } elsif ( $type eq 'PREOVERDUE' ) {
+ @loop = GetPredueIssues( $patron_branchcode );
+ } elsif ( $type eq 'RESERVE' ) {
+ @loop = GetWaitingHolds( $patron_branchcode );
+ } else {
print "Unknown or unsupported message type $type; skipping...\n"
if ( defined $verbose );
next;
}
+ my $patrons;
foreach my $issues (@loop) {
- my $date = C4::Dates->new( $issues->{'date_due'}, 'iso' );
- my $due_date = $date->output('metric');
+ $patrons->{$issues->{borrowernumber}} ||= Koha::Patrons->find( $issues->{borrowernumber} ) if $skip_patrons_with_email;
+ next if $skip_patrons_with_email && $patrons->{$issues->{borrowernumber}}->notice_email_address;
+
+ my $date_dt = dt_from_string ( $issues->{'date_due'} );
+ my $due_date = output_pref( { dt => $date_dt, dateonly => 1, dateformat =>'metric' } );
my $letter = C4::Letters::GetPreparedLetter(
module => $module,
letter_code => $code,
+ lang => 'default', # It does not sound useful to send a lang here
tables => {
borrowers => $issues->{'borrowernumber'},
biblio => $issues->{'biblionumber'},
- biblioitems => $issues->{'biblionumber'}
+ biblioitems => $issues->{'biblionumber'},
},
+ message_transport_type => 'itiva',
);
die "No letter found for type $type!... dying\n" unless $letter;
my $message_id = 0;
if ($outfile) {
$message_id = C4::Letters::EnqueueLetter(
- {
- letter => $letter,
+ { letter => $letter,
borrowernumber => $issues->{'borrowernumber'},
- message_transport_type => 'phone',
+ message_transport_type => 'itiva',
}
);
}
- print $OUT
-"\"$format\",\"$language\",\"$type\",\"$issues->{level}\",\"$issues->{cardnumber}\",\"$issues->{patron_title}\",\"$issues->{firstname}\",";
- print $OUT
-"\"$issues->{surname}\",\"$issues->{phone}\",\"$issues->{email}\",\"$library_code\",";
- print $OUT
-"\"$issues->{site}\",\"$issues->{site_name}\",\"$issues->{barcode}\",\"$due_date\",\"$issues->{title}\",\"$message_id\"\n";
+ $issues->{title} =~ s/'//g;
+ $issues->{title} =~ s/"//g;
+
+ print $OUT "\"$format\",\"$language\",\"$type\",\"$issues->{level}\",\"$issues->{cardnumber}\",\"$issues->{patron_title}\",\"$issues->{firstname}\",";
+ print $OUT "\"$issues->{surname}\",\"$issues->{phone}\",\"$issues->{email}\",\"$library_code\",";
+ print $OUT "\"$issues->{site}\",\"$issues->{site_name}\",\"$issues->{barcode}\",\"$due_date\",\"$issues->{title}\",\"$message_id\"\n";
}
}
Script to generate Spec C outbound notifications file for Talking Tech i-tiva
phone notification system.
+=over
+
=item B<--help> B<-h>
Prints this help
prompts, to those notices.
This field can be blank if all messages are from a single library.
+=item B<--patron-branchcode> B<--pb>
+
+OPTIONAL
+
+Limits the the patrons to generate notices for based on the patron's home library.
+Items and holds from other libraries will still be included for the given patron.
+
+=back
+
=cut
sub GetOverdueIssues {
- my $query =
-"SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname,
+ my ( $patron_branchcode ) = @_;
+
+ my $patron_branchcode_filter = $patron_branchcode ? "AND borrowers.branchcode = '$patron_branchcode'" : q{};
+
+ my $query = "SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname,
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, issues.date_due,
max(overduerules.branchcode) as rulebranch, TO_DAYS(NOW())-TO_DAYS(date_due) as daysoverdue, delay1, delay2, delay3,
issues.branchcode as site, branches.branchname as site_name
JOIN biblio USING (biblionumber)
JOIN branches ON (issues.branchcode = branches.branchcode)
JOIN overduerules USING (categorycode)
+ JOIN overduerules_transport_types USING ( overduerules_id )
WHERE ( overduerules.branchcode = borrowers.branchcode or overduerules.branchcode = '')
+ AND overduerules_transport_types.message_transport_type = 'itiva'
AND ( (TO_DAYS(NOW())-TO_DAYS(date_due) ) = delay1
OR (TO_DAYS(NOW())-TO_DAYS(date_due) ) = delay2
OR (TO_DAYS(NOW())-TO_DAYS(date_due) ) = delay3 )
+ $patron_branchcode_filter
GROUP BY items.itemnumber
";
my $sth = $dbh->prepare($query);
while ( my $issue = $sth->fetchrow_hashref() ) {
if ( $issue->{'daysoverdue'} == $issue->{'delay1'} ) {
$issue->{'level'} = 1;
- }
- elsif ( $issue->{'daysoverdue'} == $issue->{'delay2'} ) {
+ } elsif ( $issue->{'daysoverdue'} == $issue->{'delay2'} ) {
$issue->{'level'} = 2;
- }
- elsif ( $issue->{'daysoverdue'} == $issue->{'delay3'} ) {
+ } elsif ( $issue->{'daysoverdue'} == $issue->{'delay3'} ) {
$issue->{'level'} = 3;
- }
- else {
+ } else {
# this shouldn't ever happen, based our SQL criteria
}
}
sub GetPredueIssues {
- my $query =
-"SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname,
+ my ( $patron_branchcode ) = @_;
+
+ my $patron_branchcode_filter = $patron_branchcode ? "AND borrowers.branchcode = '$patron_branchcode'" : q{};
+
+ my $query = "SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname,
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, issues.date_due,
issues.branchcode as site, branches.branchname as site_name
FROM borrowers JOIN issues USING (borrowernumber)
JOIN borrower_message_transport_preferences USING (borrower_message_preference_id)
JOIN message_attributes USING (message_attribute_id)
WHERE ( TO_DAYS( date_due ) - TO_DAYS( NOW() ) ) = days_in_advance
- AND message_transport_type = 'phone'
+ AND message_transport_type = 'itiva'
AND message_name = 'Advance_Notice'
+ $patron_branchcode_filter
";
my $sth = $dbh->prepare($query);
$sth->execute();
}
sub GetWaitingHolds {
- my $query =
-"SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname,
+ my ( $patron_branchcode ) = @_;
+
+ my $patron_branchcode_filter = $patron_branchcode ? "AND borrowers.branchcode = '$patron_branchcode'" : q{};
+
+ my $query = "SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname, borrowers.categorycode,
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, reserves.waitingdate,
reserves.branchcode AS site, branches.branchname AS site_name,
TO_DAYS(NOW())-TO_DAYS(reserves.waitingdate) AS days_since_waiting
JOIN borrower_message_transport_preferences USING (borrower_message_preference_id)
JOIN message_attributes USING (message_attribute_id)
WHERE ( reserves.found = 'W' )
- AND message_transport_type = 'phone'
+ AND message_transport_type = 'itiva'
AND message_name = 'Hold_Filled'
+ $patron_branchcode_filter
";
my $pickupdelay = C4::Context->preference("ReservesMaxPickUpDelay");
my $sth = $dbh->prepare($query);
$sth->execute();
my @results;
while ( my $issue = $sth->fetchrow_hashref() ) {
- my @waitingdate = split( /-/, $issue->{'waitingdate'} );
- my @date_due =
- Add_Delta_Days( $waitingdate[0], $waitingdate[1], $waitingdate[2],
- $pickupdelay );
- $issue->{'date_due'} =
- sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] );
- $issue->{'level'} = 1; # only one level for Hold Waiting notifications
+ my $item = Koha::Items->find({ barcode => $issue->{barcode} });
+ my $daysmode = Koha::CirculationRules->get_effective_daysmode(
+ {
+ categorycode => $issue->{categorycode},
+ itemtype => $item->effective_itemtype,
+ branchcode => $issue->{site},
+ }
+ );
+
+ my $calendar = Koha::Calendar->new( branchcode => $issue->{'site'}, days_mode => $daysmode );
+
+ my $waiting_date = dt_from_string( $issue->{waitingdate}, 'sql' );
+ my $pickup_date = $waiting_date->clone->add( days => $pickupdelay );
+ if ( $calendar->is_holiday($pickup_date) ) {
+ $pickup_date = $calendar->next_open_days( $pickup_date, 1 );
+ }
+
+ $issue->{'date_due'} = output_pref({dt => $pickup_date, dateformat => 'iso' });
+ $issue->{'level'} = 1; # only one level for Hold Waiting notifications
my $days_to_subtract = 0;
- my $calendar = C4::Calendar->new( branchcode => $issue->{'site'} );
- while (
- $calendar->isHoliday(
- reverse(
- Add_Delta_Days(
- $waitingdate[0], $waitingdate[1],
- $waitingdate[2], $days_to_subtract
- )
- )
- )
- )
- {
- $days_to_subtract++;
+ if ( $calendar->is_holiday($waiting_date) ) {
+ my $next_open_day = $calendar->next_open_days( $waiting_date, 1 );
+ $days_to_subtract = $calendar->days_between($waiting_date, $next_open_day)->days;
}
- $issue->{'days_since_waiting'} =
- $issue->{'days_since_waiting'} - $days_to_subtract;
-
- if (
- (
- grep $_ eq $issue->{'days_since_waiting'},
- @holds_waiting_days_to_call
- )
- || !scalar(@holds_waiting_days_to_call)
- )
- {
+
+ $issue->{'days_since_waiting'} = $issue->{'days_since_waiting'} - $days_to_subtract;
+
+ if ( ( grep $_ eq $issue->{'days_since_waiting'}, @holds_waiting_days_to_call )
+ || !scalar(@holds_waiting_days_to_call) ) {
push @results, $issue;
}
}