Bug 26922: Regression tests
[koha.git] / misc / cronjobs / runreport.pl
blob3e81e08a97900957fb290a8f08102d2fdef16a96
1 #!/usr/bin/perl
3 # Copyright 2008 Liblime
4 # Copyright 2014 Foundations Bible College, Inc.
6 # This file is part of Koha.
8 # Koha is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # Koha is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with Koha; if not, see <http://www.gnu.org/licenses>.
21 use Modern::Perl;
23 use Koha::Script -cron;
24 use C4::Reports::Guided; # 0.12
25 use Koha::Reports;
26 use C4::Context;
27 use C4::Log;
28 use Koha::Email;
29 use Koha::DateUtils;
30 use Koha::SMTP::Servers;
32 use Getopt::Long qw(:config auto_help auto_version);
33 use Pod::Usage;
34 use Text::CSV::Encoded;
35 use CGI qw ( -utf8 );
36 use Carp;
37 use Encode;
38 use JSON qw( to_json );
39 use Try::Tiny;
41 BEGIN {
42 # find Koha's Perl modules
43 # test carefully before changing this
44 use FindBin;
45 eval { require "$FindBin::Bin/../kohalib.pl" };
48 =head1 NAME
50 runreport.pl - Run pre-existing saved reports
52 =head1 SYNOPSIS
54 runreport.pl [ -h | -m ] [ -v ] reportID [ reportID ... ]
56 Options:
57 -h --help brief help message
58 -m --man full documentation, same as --help --verbose
59 -v --verbose verbose output
61 --format=s selects format. Choice of text, html, csv or tsv
63 -e --email whether to use e-mail (implied by --to or --from)
64 -a --attachment additionally attach the report as a file. cannot be used with html format
65 --username username to pass to the SMTP server for authentication
66 --password password to pass to the SMTP server for authentication
67 --method method is the type of authentication. Ie. LOGIN, DIGEST-MD5, etc.
68 --to=s e-mail address to send report to
69 --from=s e-mail address to send report from
70 --subject=s subject for the e-mail
71 --param=s parameters for the report
72 --store-results store the result of the report
73 --csv-header add column names as first line of csv output
76 Arguments:
77 reportID report ID Number from saved_sql.id, multiple ID's may be specified
79 =head1 OPTIONS
81 =over
83 =item B<--help>
85 Print a brief help message and exits.
87 =item B<--man>
89 Prints the manual page and exits.
91 =item B<-v>
93 Verbose. Without this flag set, only fatal errors are reported.
95 =item B<--format>
97 Current options are text, html, csv, and tsv. At the moment, text and tsv both produce tab-separated tab-separated output.
99 =item B<--email>
101 Whether to use e-mail (implied by --to or --from).
103 =item B<--username>
105 Username to pass to the SMTP server for authentication
107 =item B<--password>
109 Password to pass to the SMTP server for authentication
111 =item B<--method>
113 Method is the type of authentication. Ie. LOGIN, DIGEST-MD5, etc.
115 =item B<--to>
117 E-mail address to send report to. Defaults to KohaAdminEmailAddress.
119 =item B<--from>
121 E-mail address to send report from. Defaults to KohaAdminEmailAddress.
123 =item B<--subject>
125 Subject for the e-mail message. Defaults to "Koha Saved Report"
127 =item B<--param>
129 Repeatable, should provide one param per param requested for the report.
130 Report params are not combined as on the staff side, so you may need to repeat
131 params.
133 =item B<--store-results>
135 Store the result of the report into the saved_reports DB table.
137 To access the results, go on Reports > Guided reports > Saved report.
139 =back
141 =head1 DESCRIPTION
143 This script is designed to run existing Saved Reports.
145 =head1 USAGE EXAMPLES
147 B<runreport.pl 16>
149 In the most basic form, runs the report specified by ID number from
150 saved_sql.id, in this case #16, outputting the results to STDOUT.
152 B<runreport.pl 16 17>
154 Same as above, but also runs report #17.
156 =head1 TO DO
158 =over
161 =item *
163 Allow Saved Results option.
166 =back
168 =head1 SEE ALSO
170 Reports - Guided Reports
172 =cut
174 # These variables can be set by command line options,
175 # initially set to default values.
177 my $help = 0;
178 my $man = 0;
179 my $verbose = 0;
180 my $send_email = 0;
181 my $attachment = 0;
182 my $format = "text";
183 my $to = "";
184 my $from = "";
185 my $subject = "";
186 my @params = ();
187 my $separator = ',';
188 my $quote = '"';
189 my $store_results = 0;
190 my $csv_header = 0;
192 my $username = undef;
193 my $password = undef;
194 my $method = 'LOGIN';
196 GetOptions(
197 'help|?' => \$help,
198 'man' => \$man,
199 'verbose' => \$verbose,
200 'format=s' => \$format,
201 'to=s' => \$to,
202 'from=s' => \$from,
203 'subject=s' => \$subject,
204 'param=s' => \@params,
205 'email' => \$send_email,
206 'a|attachment' => \$attachment,
207 'username:s' => \$username,
208 'password:s' => \$password,
209 'method:s' => \$method,
210 'store-results' => \$store_results,
211 'csv-header' => \$csv_header,
213 ) or pod2usage(2);
214 pod2usage( -verbose => 2 ) if ($man);
215 pod2usage( -verbose => 2 ) if ($help and $verbose);
216 pod2usage(1) if $help;
218 cronlogaction();
220 unless ($format) {
221 $verbose and print STDERR "No format specified, assuming 'text'\n";
222 $format = 'text';
225 if ($format eq 'tsv' || $format eq 'text') {
226 $format = 'csv';
227 $separator = "\t";
230 if ($to or $from or $send_email) {
231 $send_email = 1;
232 $from or $from = C4::Context->preference('KohaAdminEmailAddress');
233 $to or $to = C4::Context->preference('KohaAdminEmailAddress');
236 unless (scalar(@ARGV)) {
237 print STDERR "ERROR: No reportID(s) specified\n";
238 pod2usage(1);
240 ($verbose) and print scalar(@ARGV), " argument(s) after options: " . join(" ", @ARGV) . "\n";
242 my $today = dt_from_string();
243 my $date = $today->ymd();
245 foreach my $report_id (@ARGV) {
246 my $report = Koha::Reports->find( $report_id );
247 unless ($report) {
248 warn "ERROR: No saved report $report_id found";
249 next;
251 my $sql = $report->savedsql;
252 my $report_name = $report->report_name;
253 my $type = $report->type;
255 $verbose and print "SQL: $sql\n\n";
256 if ( $subject eq "" )
258 if ( defined($report_name) and $report_name ne "")
260 $subject = $report_name ;
262 else
264 $subject = 'Koha Saved Report';
268 # convert SQL parameters to placeholders
269 my $params_needed = ( $sql =~ s/(<<[^>]+>>)/\?/g );
270 die("You supplied ". scalar @params . " parameter(s) and $params_needed are required by the report") if scalar @params != $params_needed;
272 my ($sth) = execute_query( $sql, undef, undef, \@params, $report_id );
273 my $count = scalar($sth->rows);
274 unless ($count) {
275 print "NO OUTPUT: 0 results from execute_query\n";
276 next;
278 $verbose and print "$count results from execute_query\n";
280 my $message;
281 my @rows_to_store;
282 if ($format eq 'html') {
283 my $cgi = CGI->new();
284 my @rows;
285 while (my $line = $sth->fetchrow_arrayref) {
286 foreach (@$line) { defined($_) or $_ = ''; } # catch undef values, replace w/ ''
287 push @rows, $cgi->TR( join('', $cgi->td($line)) ) . "\n";
288 push @rows_to_store, [@$line] if $store_results;
290 $message = $cgi->table(join "", @rows);
291 } elsif ($format eq 'csv') {
292 my $csv = Text::CSV::Encoded->new({
293 encoding_out => 'utf8',
294 binary => 1,
295 quote_char => $quote,
296 sep_char => $separator,
299 if ( $csv_header ) {
300 my @fields = map { decode( 'utf8', $_ ) } @{ $sth->{NAME} };
301 $csv->combine( @fields );
302 $message .= $csv->string() . "\n";
303 push @rows_to_store, [@fields] if $store_results;
306 while (my $line = $sth->fetchrow_arrayref) {
307 $csv->combine(@$line);
308 $message .= $csv->string() . "\n";
309 push @rows_to_store, [@$line] if $store_results;
311 $message = Encode::decode_utf8($message);
313 if ( $store_results ) {
314 my $json = to_json( \@rows_to_store );
315 C4::Reports::Guided::store_results( $report_id, $json );
317 if ($send_email) {
319 my $email = Koha::Email->new(
321 to => $to,
322 from => $from,
323 subject => $subject,
327 if ( $format eq 'html' ) {
328 $message = "<html><head><style>tr:nth-child(2n+1) { background-color: #ccc;}</style></head><body>$message</body></html>";
329 $email->html_body($message);
331 else {
332 $email->text_body($message);
335 $email->attach(
336 Encode::encode_utf8($message),
337 content_type => "text/$format",
338 name => "report$report_id-$date.$format",
339 disposition => 'attachment',
340 ) if $attachment;
342 my $smtp_server = Koha::SMTP::Servers->get_default;
343 $smtp_server->set(
345 user_name => $username,
346 password => $password,
349 if $username;
351 $email->transport( $smtp_server->transport );
352 try {
353 $email->send_or_die;
355 catch {
356 carp "Mail not sent: $_";
359 else {
360 print $message;