|
Lines 19-25
Link Here
|
| 19 |
|
19 |
|
| 20 |
use strict; |
20 |
use strict; |
| 21 |
use warnings; |
21 |
use warnings; |
|
|
22 |
|
| 22 |
BEGIN { |
23 |
BEGIN { |
|
|
24 |
|
| 23 |
# find Koha's Perl modules |
25 |
# find Koha's Perl modules |
| 24 |
# test carefully before changing this |
26 |
# test carefully before changing this |
| 25 |
use FindBin; |
27 |
use FindBin; |
|
Lines 42-48
sub usage {
Link Here
|
| 42 |
exit; |
44 |
exit; |
| 43 |
} |
45 |
} |
| 44 |
|
46 |
|
| 45 |
die "TalkingTechItivaPhoneNotification system preference not activated... dying\n" unless (C4::Context->preference("TalkingTechItivaPhoneNotification")); |
47 |
die |
|
|
48 |
"TalkingTechItivaPhoneNotification system preference not activated... dying\n" |
| 49 |
unless ( C4::Context->preference("TalkingTechItivaPhoneNotification") ); |
| 46 |
|
50 |
|
| 47 |
# Database handle |
51 |
# Database handle |
| 48 |
my $dbh = C4::Context->dbh; |
52 |
my $dbh = C4::Context->dbh; |
|
Lines 57-80
my $help;
Link Here
|
| 57 |
my $outfile; |
61 |
my $outfile; |
| 58 |
|
62 |
|
| 59 |
# maps to convert I-tiva terms to Koha terms |
63 |
# maps to convert I-tiva terms to Koha terms |
| 60 |
my $type_module_map = { 'PREOVERDUE' => 'circulation', |
64 |
my $type_module_map = { |
| 61 |
'OVERDUE' => 'circulation', |
65 |
'PREOVERDUE' => 'circulation', |
| 62 |
'RESERVE' => 'reserves', |
66 |
'OVERDUE' => 'circulation', |
| 63 |
}; |
67 |
'RESERVE' => 'reserves', |
| 64 |
|
68 |
}; |
| 65 |
my $type_notice_map = { 'PREOVERDUE' => 'PREDUE_PHONE', |
69 |
|
| 66 |
'OVERDUE' => 'OVERDUE_PHONE', |
70 |
my $type_notice_map = { |
| 67 |
'RESERVE' => 'HOLD_PHONE', |
71 |
'PREOVERDUE' => 'PREDUE_PHONE', |
| 68 |
}; |
72 |
'OVERDUE' => 'OVERDUE_PHONE', |
|
|
73 |
'RESERVE' => 'HOLD_PHONE', |
| 74 |
}; |
| 69 |
|
75 |
|
| 70 |
GetOptions( |
76 |
GetOptions( |
| 71 |
'o|output:s' => \$outfile, |
77 |
'o|output:s' => \$outfile, |
| 72 |
'v' => \$verbose, |
78 |
'v' => \$verbose, |
| 73 |
'lang:s' => \$language, |
79 |
'lang:s' => \$language, |
| 74 |
'type:s' => \@types, |
80 |
'type:s' => \@types, |
| 75 |
'w|waiting-hold-day:s' => \@holds_waiting_days_to_call, |
81 |
'w|waiting-hold-day:s' => \@holds_waiting_days_to_call, |
| 76 |
'c|code|library-code:s' => \$library_code, |
82 |
'c|code|library-code:s' => \$library_code, |
| 77 |
'help|h' => \$help, |
83 |
'help|h' => \$help, |
| 78 |
); |
84 |
); |
| 79 |
|
85 |
|
| 80 |
$language = uc($language); |
86 |
$language = uc($language); |
|
Lines 83-141
$library_code ||= '';
Link Here
|
| 83 |
pod2usage( -verbose => 1 ) if $help; |
89 |
pod2usage( -verbose => 1 ) if $help; |
| 84 |
|
90 |
|
| 85 |
# output log or STDOUT |
91 |
# output log or STDOUT |
| 86 |
if (defined $outfile) { |
92 |
my $OUT; |
| 87 |
open (OUT, ">$outfile") || die ("Cannot open output file"); |
93 |
if ( defined $outfile ) { |
| 88 |
} else { |
94 |
open( $OUT, '>', "$outfile" ) || die("Cannot open output file"); |
| 89 |
print "No output file defined; printing to STDOUT\n" if (defined $verbose); |
95 |
} |
| 90 |
open(OUT, ">&STDOUT") || die ("Couldn't duplicate STDOUT: $!"); |
96 |
else { |
|
|
97 |
print "No output file defined; printing to STDOUT\n" |
| 98 |
if ( defined $verbose ); |
| 99 |
open( $OUT, '>', "&STDOUT" ) || die("Couldn't duplicate STDOUT: $!"); |
| 91 |
} |
100 |
} |
| 92 |
|
101 |
|
| 93 |
my $format = 'V'; # format for phone notifications |
102 |
my $format = 'V'; # format for phone notifications |
| 94 |
|
103 |
|
| 95 |
foreach my $type (@types) { |
104 |
foreach my $type (@types) { |
| 96 |
$type = uc($type); #just in case lower or mixed-case was supplied |
105 |
$type = uc($type); #just in case lower or mixed-case was supplied |
| 97 |
my $module = $type_module_map->{$type}; #since the module is required to get the letter |
106 |
my $module = |
| 98 |
my $code = $type_notice_map->{$type}; #to get the Koha name of the notice |
107 |
$type_module_map->{$type}; #since the module is required to get the letter |
| 99 |
|
108 |
my $code = $type_notice_map->{$type}; #to get the Koha name of the notice |
| 100 |
my @loop; |
109 |
|
| 101 |
if ($type eq 'OVERDUE') { |
110 |
my @loop; |
| 102 |
@loop = GetOverdueIssues(); |
111 |
if ( $type eq 'OVERDUE' ) { |
| 103 |
} elsif ($type eq 'PREOVERDUE') { |
112 |
@loop = GetOverdueIssues(); |
| 104 |
@loop = GetPredueIssues(); |
113 |
} |
| 105 |
} elsif ($type eq 'RESERVE') { |
114 |
elsif ( $type eq 'PREOVERDUE' ) { |
| 106 |
@loop = GetWaitingHolds(); |
115 |
@loop = GetPredueIssues(); |
| 107 |
} else { |
116 |
} |
| 108 |
print "Unknown or unsupported message type $type; skipping...\n" if (defined $verbose); |
117 |
elsif ( $type eq 'RESERVE' ) { |
| 109 |
next; |
118 |
@loop = GetWaitingHolds(); |
| 110 |
} |
119 |
} |
| 111 |
|
120 |
else { |
| 112 |
foreach my $issues (@loop) { |
121 |
print "Unknown or unsupported message type $type; skipping...\n" |
| 113 |
my $date = C4::Dates->new($issues->{'date_due'}, 'iso'); |
122 |
if ( defined $verbose ); |
| 114 |
my $due_date = $date->output('metric'); |
123 |
next; |
| 115 |
|
124 |
} |
| 116 |
# gets the placeholder message, and enqueues the letter |
125 |
|
| 117 |
my $letter = getletter($module, $code); |
126 |
foreach my $issues (@loop) { |
| 118 |
die "No letter found for type $type!... dying\n" unless $letter; |
127 |
my $date = C4::Dates->new( $issues->{'date_due'}, 'iso' ); |
| 119 |
# covers basic variable parsing in letter |
128 |
my $due_date = $date->output('metric'); |
| 120 |
$letter = C4::Letters::parseletter($letter, 'borrowers', $issues->{'borrowernumber'}); |
129 |
|
| 121 |
$letter = C4::Letters::parseletter($letter, 'biblio', $issues->{'biblionumber'}); |
130 |
# gets the placeholder message, and enqueues the letter |
| 122 |
$letter = C4::Letters::parseletter($letter, 'biblioitems', $issues->{'biblionumber'}); |
131 |
my $letter = getletter( $module, $code ); |
| 123 |
|
132 |
die "No letter found for type $type!... dying\n" unless $letter; |
| 124 |
my $message_id = 0; |
133 |
|
| 125 |
if ($outfile) { |
134 |
# covers basic variable parsing in letter |
| 126 |
$message_id = C4::Letters::EnqueueLetter( { letter => $letter, |
135 |
$letter = |
| 127 |
borrowernumber => $issues->{'borrowernumber'}, |
136 |
C4::Letters::parseletter( $letter, 'borrowers', |
| 128 |
message_transport_type => 'phone', |
137 |
$issues->{'borrowernumber'} ); |
| 129 |
}); |
138 |
$letter = |
| 130 |
} |
139 |
C4::Letters::parseletter( $letter, 'biblio', |
| 131 |
|
140 |
$issues->{'biblionumber'} ); |
| 132 |
print OUT "\"$format\",\"$language\",\"$type\",\"$issues->{level}\",\"$issues->{cardnumber}\",\"$issues->{patron_title}\",\"$issues->{firstname}\","; |
141 |
$letter = |
| 133 |
print OUT "\"$issues->{surname}\",\"$issues->{phone}\",\"$issues->{email}\",\"$library_code\","; |
142 |
C4::Letters::parseletter( $letter, 'biblioitems', |
| 134 |
print OUT "\"$issues->{site}\",\"$issues->{site_name}\",\"$issues->{barcode}\",\"$due_date\",\"$issues->{title}\",\"$message_id\"\n"; |
143 |
$issues->{'biblionumber'} ); |
| 135 |
} |
144 |
|
|
|
145 |
my $message_id = 0; |
| 146 |
if ($outfile) { |
| 147 |
$message_id = C4::Letters::EnqueueLetter( |
| 148 |
{ |
| 149 |
letter => $letter, |
| 150 |
borrowernumber => $issues->{'borrowernumber'}, |
| 151 |
message_transport_type => 'phone', |
| 152 |
} |
| 153 |
); |
| 154 |
} |
| 155 |
|
| 156 |
print $OUT |
| 157 |
"\"$format\",\"$language\",\"$type\",\"$issues->{level}\",\"$issues->{cardnumber}\",\"$issues->{patron_title}\",\"$issues->{firstname}\","; |
| 158 |
print $OUT |
| 159 |
"\"$issues->{surname}\",\"$issues->{phone}\",\"$issues->{email}\",\"$library_code\","; |
| 160 |
print $OUT |
| 161 |
"\"$issues->{site}\",\"$issues->{site_name}\",\"$issues->{barcode}\",\"$due_date\",\"$issues->{title}\",\"$message_id\"\n"; |
| 162 |
} |
| 136 |
} |
163 |
} |
| 137 |
|
164 |
|
| 138 |
|
|
|
| 139 |
=head1 NAME |
165 |
=head1 NAME |
| 140 |
|
166 |
|
| 141 |
TalkingTech_itiva_outbound.pl |
167 |
TalkingTech_itiva_outbound.pl |
|
Lines 194-200
This field can be blank if all messages are from a single library.
Link Here
|
| 194 |
=cut |
220 |
=cut |
| 195 |
|
221 |
|
| 196 |
sub GetOverdueIssues { |
222 |
sub GetOverdueIssues { |
| 197 |
my $query = "SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname, |
223 |
my $query = |
|
|
224 |
"SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname, |
| 198 |
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, issues.date_due, |
225 |
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, issues.date_due, |
| 199 |
max(overduerules.branchcode) as rulebranch, TO_DAYS(NOW())-TO_DAYS(date_due) as daysoverdue, delay1, delay2, delay3, |
226 |
max(overduerules.branchcode) as rulebranch, TO_DAYS(NOW())-TO_DAYS(date_due) as daysoverdue, delay1, delay2, delay3, |
| 200 |
issues.branchcode as site, branches.branchname as site_name |
227 |
issues.branchcode as site, branches.branchname as site_name |
|
Lines 209-234
sub GetOverdueIssues {
Link Here
|
| 209 |
OR (TO_DAYS(NOW())-TO_DAYS(date_due) ) = delay3 ) |
236 |
OR (TO_DAYS(NOW())-TO_DAYS(date_due) ) = delay3 ) |
| 210 |
GROUP BY items.itemnumber |
237 |
GROUP BY items.itemnumber |
| 211 |
"; |
238 |
"; |
| 212 |
my $sth = $dbh->prepare($query); |
239 |
my $sth = $dbh->prepare($query); |
| 213 |
$sth->execute(); |
240 |
$sth->execute(); |
| 214 |
my @results; |
241 |
my @results; |
| 215 |
while( my $issue = $sth->fetchrow_hashref() ) { |
242 |
while ( my $issue = $sth->fetchrow_hashref() ) { |
| 216 |
if ( $issue->{'daysoverdue'} == $issue->{'delay1'} ) { |
243 |
if ( $issue->{'daysoverdue'} == $issue->{'delay1'} ) { |
| 217 |
$issue->{'level'} = 1; |
244 |
$issue->{'level'} = 1; |
| 218 |
} elsif ( $issue->{'daysoverdue'} == $issue->{'delay2'} ) { |
245 |
} |
| 219 |
$issue->{'level'} = 2; |
246 |
elsif ( $issue->{'daysoverdue'} == $issue->{'delay2'} ) { |
| 220 |
} elsif ( $issue->{'daysoverdue'} == $issue->{'delay3'} ) { |
247 |
$issue->{'level'} = 2; |
| 221 |
$issue->{'level'} = 3; |
248 |
} |
| 222 |
} else { |
249 |
elsif ( $issue->{'daysoverdue'} == $issue->{'delay3'} ) { |
| 223 |
# this shouldn't ever happen, based our SQL criteria |
250 |
$issue->{'level'} = 3; |
| 224 |
} |
251 |
} |
| 225 |
push @results, $issue; |
252 |
else { |
| 226 |
} |
253 |
|
| 227 |
return @results; |
254 |
# this shouldn't ever happen, based our SQL criteria |
|
|
255 |
} |
| 256 |
push @results, $issue; |
| 257 |
} |
| 258 |
return @results; |
| 228 |
} |
259 |
} |
| 229 |
|
260 |
|
| 230 |
sub GetPredueIssues { |
261 |
sub GetPredueIssues { |
| 231 |
my $query = "SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname, |
262 |
my $query = |
|
|
263 |
"SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname, |
| 232 |
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, issues.date_due, |
264 |
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, issues.date_due, |
| 233 |
issues.branchcode as site, branches.branchname as site_name |
265 |
issues.branchcode as site, branches.branchname as site_name |
| 234 |
FROM borrowers JOIN issues USING (borrowernumber) |
266 |
FROM borrowers JOIN issues USING (borrowernumber) |
|
Lines 242-259
sub GetPredueIssues {
Link Here
|
| 242 |
AND message_transport_type = 'phone' |
274 |
AND message_transport_type = 'phone' |
| 243 |
AND message_name = 'Advance_Notice' |
275 |
AND message_name = 'Advance_Notice' |
| 244 |
"; |
276 |
"; |
| 245 |
my $sth = $dbh->prepare($query); |
277 |
my $sth = $dbh->prepare($query); |
| 246 |
$sth->execute(); |
278 |
$sth->execute(); |
| 247 |
my @results; |
279 |
my @results; |
| 248 |
while( my $issue = $sth->fetchrow_hashref() ) { |
280 |
while ( my $issue = $sth->fetchrow_hashref() ) { |
| 249 |
$issue->{'level'} = 1; # only one level for Predue notifications |
281 |
$issue->{'level'} = 1; # only one level for Predue notifications |
| 250 |
push @results, $issue; |
282 |
push @results, $issue; |
| 251 |
} |
283 |
} |
| 252 |
return @results; |
284 |
return @results; |
| 253 |
} |
285 |
} |
| 254 |
|
286 |
|
| 255 |
sub GetWaitingHolds { |
287 |
sub GetWaitingHolds { |
| 256 |
my $query = "SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname, |
288 |
my $query = |
|
|
289 |
"SELECT borrowers.borrowernumber, borrowers.cardnumber, borrowers.title as patron_title, borrowers.firstname, borrowers.surname, |
| 257 |
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, reserves.waitingdate, |
290 |
borrowers.phone, borrowers.email, borrowers.branchcode, biblio.biblionumber, biblio.title, items.barcode, reserves.waitingdate, |
| 258 |
reserves.branchcode AS site, branches.branchname AS site_name, |
291 |
reserves.branchcode AS site, branches.branchname AS site_name, |
| 259 |
TO_DAYS(NOW())-TO_DAYS(reserves.waitingdate) AS days_since_waiting |
292 |
TO_DAYS(NOW())-TO_DAYS(reserves.waitingdate) AS days_since_waiting |
|
Lines 268-295
sub GetWaitingHolds {
Link Here
|
| 268 |
AND message_transport_type = 'phone' |
301 |
AND message_transport_type = 'phone' |
| 269 |
AND message_name = 'Hold_Filled' |
302 |
AND message_name = 'Hold_Filled' |
| 270 |
"; |
303 |
"; |
| 271 |
my $pickupdelay = C4::Context->preference("ReservesMaxPickUpDelay"); |
304 |
my $pickupdelay = C4::Context->preference("ReservesMaxPickUpDelay"); |
| 272 |
my $sth = $dbh->prepare($query); |
305 |
my $sth = $dbh->prepare($query); |
| 273 |
$sth->execute(); |
306 |
$sth->execute(); |
| 274 |
my @results; |
307 |
my @results; |
| 275 |
while( my $issue = $sth->fetchrow_hashref() ) { |
308 |
while ( my $issue = $sth->fetchrow_hashref() ) { |
| 276 |
my @waitingdate = split( /-/, $issue->{'waitingdate'} ); |
309 |
my @waitingdate = split( /-/, $issue->{'waitingdate'} ); |
| 277 |
my @date_due = Add_Delta_Days( $waitingdate[0], $waitingdate[1], $waitingdate[2], $pickupdelay ); |
310 |
my @date_due = |
| 278 |
$issue->{'date_due'} = sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] ); |
311 |
Add_Delta_Days( $waitingdate[0], $waitingdate[1], $waitingdate[2], |
| 279 |
$issue->{'level'} = 1; # only one level for Hold Waiting notifications |
312 |
$pickupdelay ); |
| 280 |
|
313 |
$issue->{'date_due'} = |
| 281 |
my $days_to_subtract = 0; |
314 |
sprintf( "%04d-%02d-%02d", $date_due[0], $date_due[1], $date_due[2] ); |
| 282 |
my $calendar = C4::Calendar->new( branchcode => $issue->{'site'} ); |
315 |
$issue->{'level'} = 1; # only one level for Hold Waiting notifications |
| 283 |
while( $calendar->isHoliday( reverse( Add_Delta_Days( $waitingdate[0], $waitingdate[1], $waitingdate[2], $days_to_subtract ) ) ) ) { |
316 |
|
| 284 |
$days_to_subtract++; |
317 |
my $days_to_subtract = 0; |
| 285 |
} |
318 |
my $calendar = C4::Calendar->new( branchcode => $issue->{'site'} ); |
| 286 |
$issue->{'days_since_waiting'} = $issue->{'days_since_waiting'} - $days_to_subtract; |
319 |
while ( |
| 287 |
|
320 |
$calendar->isHoliday( |
| 288 |
if ( ( grep $_ eq $issue->{'days_since_waiting'}, @holds_waiting_days_to_call ) || !scalar( @holds_waiting_days_to_call ) ) { |
321 |
reverse( |
| 289 |
push @results, $issue; |
322 |
Add_Delta_Days( |
| 290 |
} |
323 |
$waitingdate[0], $waitingdate[1], |
| 291 |
} |
324 |
$waitingdate[2], $days_to_subtract |
| 292 |
return @results; |
325 |
) |
| 293 |
|
326 |
) |
|
|
327 |
) |
| 328 |
) |
| 329 |
{ |
| 330 |
$days_to_subtract++; |
| 331 |
} |
| 332 |
$issue->{'days_since_waiting'} = |
| 333 |
$issue->{'days_since_waiting'} - $days_to_subtract; |
| 334 |
|
| 335 |
if ( |
| 336 |
( |
| 337 |
grep $_ eq $issue->{'days_since_waiting'}, |
| 338 |
@holds_waiting_days_to_call |
| 339 |
) |
| 340 |
|| !scalar(@holds_waiting_days_to_call) |
| 341 |
) |
| 342 |
{ |
| 343 |
push @results, $issue; |
| 344 |
} |
| 345 |
} |
| 346 |
return @results; |
| 294 |
|
347 |
|
| 295 |
} |
348 |
} |
| 296 |
- |
|
|