|
Lines 115-165
use Koha::Email;
Link Here
|
| 115 |
use Koha::StockRotationRotas; |
115 |
use Koha::StockRotationRotas; |
| 116 |
|
116 |
|
| 117 |
my $admin_email = ''; |
117 |
my $admin_email = ''; |
| 118 |
my $branch = 0; |
118 |
my $branch = 0; |
| 119 |
my $execute = 0; |
119 |
my $execute = 0; |
| 120 |
my $report = 'full'; |
120 |
my $report = 'full'; |
| 121 |
my $send_all = 0; |
121 |
my $send_all = 0; |
| 122 |
my $send_email = 0; |
122 |
my $send_email = 0; |
| 123 |
|
123 |
|
| 124 |
my $ok = GetOptions( |
124 |
my $ok = GetOptions( |
| 125 |
'admin-email|a=s' => \$admin_email, |
125 |
'admin-email|a=s' => \$admin_email, |
| 126 |
'branchcode|b=s' => sub { |
126 |
'branchcode|b=s' => sub { |
| 127 |
my ($opt_name, $opt_value) = @_; |
127 |
my ( $opt_name, $opt_value ) = @_; |
| 128 |
my $branches = Koha::Libraries->search( |
128 |
my $branches = Koha::Libraries->search( {}, |
| 129 |
{}, { order_by => { -asc => 'branchname'} } |
129 |
{ order_by => { -asc => 'branchname' } } ); |
| 130 |
); |
|
|
| 131 |
my $brnch = $branches->find($opt_value); |
130 |
my $brnch = $branches->find($opt_value); |
| 132 |
if ( $brnch ) { |
131 |
if ($brnch) { |
| 133 |
$branch = $brnch; |
132 |
$branch = $brnch; |
| 134 |
return $brnch; |
133 |
return $brnch; |
| 135 |
} else { |
134 |
} |
|
|
135 |
else { |
| 136 |
printf("Option $opt_name should be one of (name -> code):\n"); |
136 |
printf("Option $opt_name should be one of (name -> code):\n"); |
| 137 |
while ( my $candidate = $branches->next ) { |
137 |
while ( my $candidate = $branches->next ) { |
| 138 |
printf( |
138 |
printf( " %-40s -> %s\n", |
| 139 |
" %-40s -> %s\n", $candidate->branchname, |
139 |
$candidate->branchname, $candidate->branchcode ); |
| 140 |
$candidate->branchcode |
|
|
| 141 |
); |
| 142 |
} |
140 |
} |
| 143 |
exit 1 |
141 |
exit 1; |
| 144 |
} |
142 |
} |
| 145 |
}, |
143 |
}, |
| 146 |
'execute|x' => \$execute, |
144 |
'execute|x' => \$execute, |
| 147 |
'report|r=s' => sub { |
145 |
'report|r=s' => sub { |
| 148 |
my ($opt_name, $opt_value) = @_; |
146 |
my ( $opt_name, $opt_value ) = @_; |
| 149 |
if ( $opt_value eq 'full' || $opt_value eq 'email' ) { |
147 |
if ( $opt_value eq 'full' || $opt_value eq 'email' ) { |
| 150 |
$report = $opt_value; |
148 |
$report = $opt_value; |
| 151 |
} else { |
149 |
} |
|
|
150 |
else { |
| 152 |
printf("Option $opt_name should be either 'email' or 'full'.\n"); |
151 |
printf("Option $opt_name should be either 'email' or 'full'.\n"); |
| 153 |
exit 1; |
152 |
exit 1; |
| 154 |
} |
153 |
} |
| 155 |
}, |
154 |
}, |
| 156 |
'send-all|S' => \$send_all, |
155 |
'send-all|S' => \$send_all, |
| 157 |
'send-email|s' => \$send_email, |
156 |
'send-email|s' => \$send_email, |
| 158 |
'help|h|?' => sub { HelpMessage } |
157 |
'help|h|?' => sub { HelpMessage } |
| 159 |
); |
158 |
); |
| 160 |
exit 1 unless ( $ok ); |
159 |
exit 1 unless ($ok); |
| 161 |
|
160 |
|
| 162 |
$send_email++ if ( $send_all ); # if we send all, then we must want emails. |
161 |
$send_email++ if ($send_all); # if we send all, then we must want emails. |
| 163 |
|
162 |
|
| 164 |
=head2 Helpers |
163 |
=head2 Helpers |
| 165 |
|
164 |
|
|
Lines 177-195
This procedure WILL mess with your database.
Link Here
|
| 177 |
=cut |
176 |
=cut |
| 178 |
|
177 |
|
| 179 |
sub execute { |
178 |
sub execute { |
| 180 |
my ( $data ) = @_; |
179 |
my ($data) = @_; |
| 181 |
|
180 |
|
| 182 |
# Begin transaction |
181 |
# Begin transaction |
| 183 |
my $schema = Koha::Database->new->schema; |
182 |
my $schema = Koha::Database->new->schema; |
| 184 |
$schema->storage->txn_begin; |
183 |
$schema->storage->txn_begin; |
| 185 |
|
184 |
|
| 186 |
# Carry out db updates |
185 |
# Carry out db updates |
| 187 |
foreach my $item (@{$data->{items}}) { |
186 |
foreach my $item ( @{ $data->{items} } ) { |
| 188 |
my $reason = $item->{reason}; |
187 |
my $reason = $item->{reason}; |
| 189 |
if ( $reason eq 'repatriation' ) { |
188 |
if ( $reason eq 'repatriation' ) { |
| 190 |
$item->{object}->repatriate; |
189 |
$item->{object}->repatriate; |
| 191 |
} elsif ( grep { $reason eq $_ } |
190 |
} |
| 192 |
qw/in-demand advancement initiation/ ) { |
191 |
elsif ( grep { $reason eq $_ } qw/in-demand advancement initiation/ ) { |
| 193 |
$item->{object}->advance; |
192 |
$item->{object}->advance; |
| 194 |
} |
193 |
} |
| 195 |
} |
194 |
} |
|
Lines 212-221
No data in the database is manipulated by this procedure.
Link Here
|
| 212 |
=cut |
211 |
=cut |
| 213 |
|
212 |
|
| 214 |
sub report_full { |
213 |
sub report_full { |
| 215 |
my ( $data ) = @_; |
214 |
my ($data) = @_; |
| 216 |
|
215 |
|
| 217 |
my $header = ""; |
216 |
my $header = ""; |
| 218 |
my $body = ""; |
217 |
my $body = ""; |
|
|
218 |
|
| 219 |
# Summary |
219 |
# Summary |
| 220 |
$header .= sprintf " |
220 |
$header .= sprintf " |
| 221 |
STOCKROTATION REPORT |
221 |
STOCKROTATION REPORT |
|
Lines 231-266
STOCKROTATION REPORT
Link Here
|
| 231 |
Total items to be repatriated: %5u |
231 |
Total items to be repatriated: %5u |
| 232 |
Total items to be advanced: %5u |
232 |
Total items to be advanced: %5u |
| 233 |
Total items in demand: %5u\n\n", |
233 |
Total items in demand: %5u\n\n", |
| 234 |
$data->{sum_rotas}, $data->{rotas_inactive}, $data->{rotas_active}, |
234 |
$data->{sum_rotas}, $data->{rotas_inactive}, $data->{rotas_active}, |
| 235 |
$data->{sum_items}, $data->{items_inactive}, $data->{stationary}, |
235 |
$data->{sum_items}, $data->{items_inactive}, $data->{stationary}, |
| 236 |
$data->{actionable}, $data->{initiable}, $data->{repatriable}, |
236 |
$data->{actionable}, $data->{initiable}, $data->{repatriable}, |
| 237 |
$data->{advanceable}, $data->{indemand}; |
237 |
$data->{advanceable}, $data->{indemand}; |
| 238 |
|
238 |
|
| 239 |
if (@{$data->{rotas}}) { # Per Rota details |
239 |
if ( @{ $data->{rotas} } ) { # Per Rota details |
| 240 |
$body .= sprintf "ROTAS DETAIL\n------------\n\n"; |
240 |
$body .= sprintf "ROTAS DETAIL\n------------\n\n"; |
| 241 |
foreach my $rota (@{$data->{rotas}}) { |
241 |
foreach my $rota ( @{ $data->{rotas} } ) { |
| 242 |
$body .= sprintf "Details for %s [%s]:\n", |
242 |
$body .= sprintf "Details for %s [%s]:\n", |
| 243 |
$rota->{name}, $rota->{id}; |
243 |
$rota->{name}, $rota->{id}; |
| 244 |
$body .= sprintf "\n Items:"; # Rota item details |
244 |
$body .= sprintf "\n Items:"; # Rota item details |
| 245 |
if (@{$rota->{items}}) { |
245 |
if ( @{ $rota->{items} } ) { |
| 246 |
$body .= join("", map { _print_item($_) } @{$rota->{items}}); |
246 |
$body .= |
| 247 |
} else { |
247 |
join( "", map { _print_item($_) } @{ $rota->{items} } ); |
| 248 |
$body .= sprintf |
|
|
| 249 |
"\n No items to be processed for this rota.\n"; |
| 250 |
} |
248 |
} |
| 251 |
$body .= sprintf "\n Log:"; # Rota log details |
249 |
else { |
| 252 |
if (@{$rota->{log}}) { |
250 |
$body .= |
| 253 |
$body .= join("", map { _print_item($_) } @{$rota->{log}}); |
251 |
sprintf "\n No items to be processed for this rota.\n"; |
| 254 |
} else { |
252 |
} |
|
|
253 |
$body .= sprintf "\n Log:"; # Rota log details |
| 254 |
if ( @{ $rota->{log} } ) { |
| 255 |
$body .= join( "", map { _print_item($_) } @{ $rota->{log} } ); |
| 256 |
} |
| 257 |
else { |
| 255 |
$body .= sprintf "\n No items in log for this rota.\n\n"; |
258 |
$body .= sprintf "\n No items in log for this rota.\n\n"; |
| 256 |
} |
259 |
} |
| 257 |
} |
260 |
} |
| 258 |
} |
261 |
} |
| 259 |
return [ $header, { |
262 |
return [ |
| 260 |
body => $body, # The body of the report |
263 |
$header, |
| 261 |
status => 1, # We have a meaningful report |
264 |
{ |
| 262 |
no_branch_email => 1, # We don't expect branch email in report |
265 |
body => $body, # The body of the report |
| 263 |
} ]; |
266 |
status => 1, # We have a meaningful report |
|
|
267 |
no_branch_email => 1, # We don't expect branch email in report |
| 268 |
} |
| 269 |
]; |
| 264 |
} |
270 |
} |
| 265 |
|
271 |
|
| 266 |
=head3 report_email |
272 |
=head3 report_email |
|
Lines 282-314
No data in the database is manipulated by this procedure.
Link Here
|
| 282 |
sub report_email { |
288 |
sub report_email { |
| 283 |
my ( $data, $branch ) = @_; |
289 |
my ( $data, $branch ) = @_; |
| 284 |
|
290 |
|
| 285 |
my $out = []; |
291 |
my $out = []; |
| 286 |
my $header = ""; |
292 |
my $header = ""; |
|
|
293 |
|
| 287 |
# Summary |
294 |
# Summary |
| 288 |
my $branched = $data->{branched}; |
295 |
my $branched = $data->{branched}; |
| 289 |
my $flag = 0; |
296 |
my $flag = 0; |
| 290 |
|
297 |
|
| 291 |
$header .= sprintf " |
298 |
$header .= sprintf " |
| 292 |
BRANCH-BASED STOCKROTATION REPORT |
299 |
BRANCH-BASED STOCKROTATION REPORT |
| 293 |
---------------------------------\n"; |
300 |
---------------------------------\n"; |
| 294 |
push @{$out}, $header; |
301 |
push @{$out}, $header; |
| 295 |
|
302 |
|
| 296 |
if ( $branch ) { # Branch limited report |
303 |
if ($branch) { # Branch limited report |
| 297 |
push @{$out}, _report_per_branch( |
304 |
push @{$out}, _report_per_branch( $branched->{ $branch->branchcode } ); |
| 298 |
$branched->{$branch->branchcode}, $branch->branchcode, |
305 |
} |
| 299 |
$branch->branchname |
306 |
elsif ( $data->{actionable} ) { # Full email report |
| 300 |
); |
307 |
while ( my ( $branchcode_id, $details ) = each %{$branched} ) { |
| 301 |
} elsif ( $data->{actionable} ) { # Full email report |
308 |
push @{$out}, _report_per_branch($details) |
| 302 |
while ( my ($branchcode_id, $details) = each %{$branched} ) { |
309 |
if ( @{ $details->{items} } ); |
| 303 |
push @{$out}, _report_per_branch( |
|
|
| 304 |
$details, $details->{code}, $details->{name} |
| 305 |
) if ( @{$details->{items}} ); |
| 306 |
} |
310 |
} |
| 307 |
} else { |
311 |
} |
|
|
312 |
else { |
| 308 |
push @{$out}, { |
313 |
push @{$out}, { |
| 309 |
body => sprintf " |
314 |
body => sprintf " |
| 310 |
No actionable items at any libraries.\n\n", # The body of the report |
315 |
No actionable items at any libraries.\n\n", # The body of the report |
| 311 |
no_branch_email => 1, # We don't expect branch email in report |
316 |
no_branch_email => 1, # We don't expect branch email in report |
| 312 |
}; |
317 |
}; |
| 313 |
} |
318 |
} |
| 314 |
return $out; |
319 |
return $out; |
|
Lines 328-358
No data in the database is manipulated by this procedure.
Link Here
|
| 328 |
=cut |
333 |
=cut |
| 329 |
|
334 |
|
| 330 |
sub _report_per_branch { |
335 |
sub _report_per_branch { |
| 331 |
my ( $per_branch, $branchcode, $branchname ) = @_; |
336 |
my ($branch) = @_; |
| 332 |
|
337 |
|
| 333 |
my $out = ""; |
|
|
| 334 |
my $status = 0; |
338 |
my $status = 0; |
|
|
339 |
if ( $branch && @{ $branch->{items} } ) { |
| 340 |
$status = 1; |
| 341 |
} |
| 335 |
|
342 |
|
| 336 |
$out .= sprintf "\nStockrotation report for '%s' [%s]:\n", |
343 |
if ( |
| 337 |
$branchname || "N/A", $branchcode || "N/A"; |
344 |
my $letter = C4::Letters::GetPreparedLetter( |
| 338 |
if ( $per_branch && @{$per_branch->{items}} ) { |
345 |
module => 'circulation', |
| 339 |
$out .= sprintf " |
346 |
letter_code => "SR_SLIP", |
| 340 |
Email: %s |
347 |
message_transport_type => 'email', |
| 341 |
Phone: %s |
348 |
substitute => $branch |
| 342 |
Items:", |
349 |
) |
| 343 |
$per_branch->{email} || "N/A", $per_branch->{phone} || "N/A"; |
350 |
) |
| 344 |
$status++; |
351 |
{ |
| 345 |
} else { |
352 |
return { |
| 346 |
$out .= sprintf "No items to be processed for this branch.\n\n"; |
353 |
letter => $letter, |
|
|
354 |
email_address => $branch->{email}, |
| 355 |
$status |
| 356 |
}; |
| 347 |
} |
357 |
} |
| 348 |
$out .= join("", map { |
358 |
return; |
| 349 |
_print_item($_) unless $_->{reason} eq 'in-demand' |
|
|
| 350 |
} @{$per_branch->{items}}); |
| 351 |
return { |
| 352 |
body => $out, # The body of the report |
| 353 |
email_address => $per_branch->{email}, # The branch email address |
| 354 |
status => $status, # We may have empty report... |
| 355 |
}; |
| 356 |
} |
359 |
} |
| 357 |
|
360 |
|
| 358 |
=head3 _print_item |
361 |
=head3 _print_item |
|
Lines 369-375
No data in the database is manipulated by this procedure.
Link Here
|
| 369 |
=cut |
372 |
=cut |
| 370 |
|
373 |
|
| 371 |
sub _print_item { |
374 |
sub _print_item { |
| 372 |
my ( $item ) = @_; |
375 |
my ($item) = @_; |
| 373 |
return sprintf " |
376 |
return sprintf " |
| 374 |
Title: %s |
377 |
Title: %s |
| 375 |
Author: %s |
378 |
Author: %s |
|
Lines 379-389
sub _print_item {
Link Here
|
| 379 |
On loan?: %s |
382 |
On loan?: %s |
| 380 |
Status: %s |
383 |
Status: %s |
| 381 |
Current Library: %s [%s]\n\n", |
384 |
Current Library: %s [%s]\n\n", |
| 382 |
$item->{title} || "N/A", $item->{author} || "N/A", |
385 |
$item->{title} || "N/A", $item->{author} || "N/A", |
| 383 |
$item->{callnumber} || "N/A", $item->{location} || "N/A", |
386 |
$item->{callnumber} || "N/A", $item->{location} || "N/A", |
| 384 |
$item->{barcode} || "N/A", $item->{onloan} ? 'Yes' : 'No', |
387 |
$item->{barcode} || "N/A", $item->{onloan} ? 'Yes' : 'No', |
| 385 |
$item->{reason} || "N/A", $item->{branch}->branchname, |
388 |
$item->{reason} || "N/A", $item->{branch}->branchname, |
| 386 |
$item->{branch}->branchcode; |
389 |
$item->{branch}->branchcode; |
| 387 |
} |
390 |
} |
| 388 |
|
391 |
|
| 389 |
=head3 emit |
392 |
=head3 emit |
|
Lines 405-411
die.
Link Here
|
| 405 |
=cut |
408 |
=cut |
| 406 |
|
409 |
|
| 407 |
sub emit { |
410 |
sub emit { |
| 408 |
my ( $params ) = @_; |
411 |
my ($params) = @_; |
| 409 |
|
412 |
|
| 410 |
# REPORT is an arrayref of at least 2 elements: |
413 |
# REPORT is an arrayref of at least 2 elements: |
| 411 |
# - The header for the report, which will be repeated for each part |
414 |
# - The header for the report, which will be repeated for each part |
|
Lines 415-486
sub emit {
Link Here
|
| 415 |
# - part->{email_address}: the email address to send the report to |
418 |
# - part->{email_address}: the email address to send the report to |
| 416 |
my $report = $params->{report}; |
419 |
my $report = $params->{report}; |
| 417 |
my $header = shift @{$report}; |
420 |
my $header = shift @{$report}; |
| 418 |
my $parts = $report; |
421 |
my $parts = $report; |
| 419 |
|
422 |
|
| 420 |
foreach my $part (@{$parts}) { |
423 |
my @emails; |
| 421 |
# The final message is the header + body of this part. |
424 |
foreach my $part ( @{$parts} ) { |
| 422 |
my $msg = $header . $part->{body}; |
|
|
| 423 |
$msg .= "No database updates have been performed.\n\n" |
| 424 |
unless ( $params->{execute} ); |
| 425 |
|
| 426 |
if ( $params->{send_email} ) { # Only email if emails requested |
| 427 |
if ( $part->{status} || $params->{send_all} ) { |
| 428 |
# We have a report to send, or we want to send even empty |
| 429 |
# reports. |
| 430 |
my $message = Koha::Email->new; |
| 431 |
|
| 432 |
# Collate 'to' addresses |
| 433 |
my @to = (); |
| 434 |
if ( $part->{email_address} ) { |
| 435 |
push @to, $part->{email_address}; |
| 436 |
} elsif ( !$part->{no_branch_email} ) { |
| 437 |
$msg = "***We tried to send a branch report, but we have no email address for this branch.***\n\n" . $msg; |
| 438 |
push @to, C4::Context->preference('KohaAdminEmailAddress') |
| 439 |
if ( C4::Context->preference('KohaAdminEmailAddress') ); |
| 440 |
} |
| 441 |
push @to, $params->{admin_email} if $params->{admin_email}; |
| 442 |
|
425 |
|
| 443 |
# Create email data. |
426 |
if ( $part->{status} || $params->{send_all} ) { |
| 444 |
my %mail = $message->create_message_headers( |
427 |
|
| 445 |
{ |
428 |
# We have a report to send, or we want to send even empty |
| 446 |
to => join("; ", @to), |
429 |
# reports. |
| 447 |
subject => "Stockrotation Email Report", |
|
|
| 448 |
message => Encode::encode("utf8", $msg), |
| 449 |
contenttype => 'text/plain; charset="utf8"', |
| 450 |
} |
| 451 |
); |
| 452 |
|
430 |
|
| 453 |
# Send or die. |
431 |
# Send to branch |
| 454 |
die($Mail::Sendmail::error) |
432 |
my $addressee; |
| 455 |
unless Mail::Sendmail::sendmail(%mail); |
433 |
if ( $part->{email_address} ) { |
|
|
434 |
$addressee = $part->{email_address}; |
| 456 |
} |
435 |
} |
|
|
436 |
elsif ( !$part->{no_branch_email} ) { |
| 457 |
|
437 |
|
| 458 |
} else { # Else emit to stdout. |
438 |
#push @emails, "***We tried to send a branch report, but we have no email address for this branch.***\n\n"; |
| 459 |
printf $msg; |
439 |
$addressee = C4::Context->preference('KohaAdminEmailAddress') |
|
|
440 |
if ( C4::Context->preference('KohaAdminEmailAddress') ); |
| 441 |
} |
| 442 |
|
| 443 |
if ( $params->{send_email} ) { # Only email if emails requested |
| 444 |
C4::Letters::EnqueueLetter( |
| 445 |
{ |
| 446 |
letter => $part->{letter}, |
| 447 |
to_address => $addressee, |
| 448 |
from_address => |
| 449 |
C4::Context->preference('KohaAdminEmailAddress'), |
| 450 |
message_transport_type => 'email', |
| 451 |
} |
| 452 |
) |
| 453 |
or warn "can't enqueue letter $part->{letter} for $addressee"; |
| 454 |
|
| 455 |
# Copy to admin? |
| 456 |
if ( $params->{admin_email} ) { |
| 457 |
C4::Letters::EnqueueLetter( |
| 458 |
{ |
| 459 |
letter => $part->{letter}, |
| 460 |
to_address => $params->{admin_email}, |
| 461 |
from_address => |
| 462 |
C4::Context->preference('KohaAdminEmailAddress'), |
| 463 |
message_transport_type => 'email', |
| 464 |
} |
| 465 |
) |
| 466 |
or warn |
| 467 |
"can't enqueue letter $part->{letter} for $params->{admin_email}"; |
| 468 |
} |
| 469 |
} |
| 470 |
else { |
| 471 |
my $email = |
| 472 |
"-------- Email message --------" . "\n\n" |
| 473 |
. "From: " |
| 474 |
. C4::Context->preference('KohaAdminEmailAddress') . "\n" |
| 475 |
. "To: " |
| 476 |
. $addressee . "\n" |
| 477 |
. "Subject: " |
| 478 |
. $part->{letter}->{title} . "\n\n" |
| 479 |
. $part->{letter}->{content}; |
| 480 |
push @emails, $email; |
| 481 |
} |
| 460 |
} |
482 |
} |
| 461 |
} |
483 |
} |
|
|
484 |
|
| 485 |
# Emit to stdout instead of email? |
| 486 |
if ( !$params->{send_email} ) { |
| 487 |
|
| 488 |
# The final message is the header + body of this part. |
| 489 |
my $msg = $header; |
| 490 |
$msg .= "No database updates have been performed.\n\n" |
| 491 |
unless ( $params->{execute} ); |
| 492 |
|
| 493 |
# Append email reports to message |
| 494 |
$msg .= join( "\n\n", @emails ); |
| 495 |
printf $msg; |
| 496 |
} |
| 462 |
} |
497 |
} |
| 463 |
|
498 |
|
| 464 |
#### Main Code |
499 |
#### Main Code |
| 465 |
|
500 |
|
| 466 |
# Compile Stockrotation Report data |
501 |
# Compile Stockrotation Report data |
| 467 |
my $rotas = Koha::StockRotationRotas->search; |
502 |
my $rotas = Koha::StockRotationRotas->search; |
| 468 |
my $data = $rotas->investigate; |
503 |
my $data = $rotas->investigate; |
| 469 |
|
504 |
|
| 470 |
# Perform db updates if requested |
505 |
# Perform db updates if requested |
| 471 |
execute($data) if ( $execute ); |
506 |
execute($data) if ($execute); |
| 472 |
|
507 |
|
| 473 |
# Emit Reports |
508 |
# Emit Reports |
| 474 |
my $out_report = {}; |
509 |
my $out_report = {}; |
| 475 |
$out_report = report_email($data, $branch) if $report eq 'email'; |
510 |
$out_report = report_email( $data, $branch ) if $report eq 'email'; |
| 476 |
$out_report = report_full($data, $branch) if $report eq 'full'; |
511 |
$out_report = report_full( $data, $branch ) if $report eq 'full'; |
| 477 |
emit({ |
512 |
emit( |
| 478 |
admin_email => $admin_email, |
513 |
{ |
| 479 |
execute => $execute, |
514 |
admin_email => $admin_email, |
| 480 |
report => $out_report, |
515 |
execute => $execute, |
| 481 |
send_all => $send_all, |
516 |
report => $out_report, |
| 482 |
send_email => $send_email, |
517 |
send_all => $send_all, |
| 483 |
}); |
518 |
send_email => $send_email, |
|
|
519 |
} |
| 520 |
); |
| 484 |
|
521 |
|
| 485 |
=head1 AUTHOR |
522 |
=head1 AUTHOR |
| 486 |
|
523 |
|
| 487 |
- |
|
|