[Koha-devel] [PATCH] Custom Reports

Kyle Hall kyle.m.hall at gmail.com
Tue Jan 26 14:42:50 CET 2010


Hello All,
  I've written a new "Custom Reports" addition for Koha to allow Koha
users to trade more complicated reports that cannot be represented in
pure SQL. Here's how it works:

Each report is downloaded as a .krz file. This filetype is just a zip
file with a specific structure ( sort of like .deb is ).

The structure is like so:
report_dir /
   report.ini
   ( other report files )

Pretty simple, I should say.

The report.ini file looks something like this:
name=Access PA
author=Kyle M Hall
description=A Report of the data necessary to fill out the Access PA
report form.
start=access_pa/step1.pl

When a report.krz file is uploaded into Koha, it is extracted to
KOHA_ROOT/reports/custom_reports/

The custom_reports.pl script reads all the report.ini files it fines
and generates the list of available reports dynamically.

Please let me know what you think. I'm in the process of rewriting all
my php-based reports in perl using this system. I've sent patches for
the three I've done so far. The Access PA report is the only one too
complicated to represent in pure SQL, but I like being able to have
one query and to be able to select the library.

I would suggest making all report forms use GET methods. That way, the
reports can be cronned using a simple wget command.

Please let me know what you think.

Thanks,
Kyle

http://www.kylehall.info
Information Technology
Crawford County Federated Library System ( http://www.ccfls.org )




On Tue, Jan 26, 2010 at 8:32 AM, Kyle M Hall <kyle.m.hall at gmail.com> wrote:
> ---
>  C4/Reports/Custom.pm                               |  138 ++++++++++++++++++++
>  .../prog/en/modules/reports/custom_reports.tmpl    |   58 ++++++++
>  .../en/modules/reports/custom_reports_upload.tmpl  |   66 ++++++++++
>  .../prog/en/modules/reports/reports-home.tmpl      |    5 +
>  reports/custom_reports.pl                          |   52 ++++++++
>  reports/custom_reports_upload.pl                   |   89 +++++++++++++
>  6 files changed, 408 insertions(+), 0 deletions(-)
>  create mode 100644 C4/Reports/Custom.pm
>  create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl
>  create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl
>  create mode 100755 reports/custom_reports.pl
>  create mode 100644 reports/custom_reports/empty
>  create mode 100755 reports/custom_reports_upload.pl
>
> diff --git a/C4/Reports/Custom.pm b/C4/Reports/Custom.pm
> new file mode 100644
> index 0000000..add811c
> --- /dev/null
> +++ b/C4/Reports/Custom.pm
> @@ -0,0 +1,138 @@
> +package C4::Reports::Custom;
> +
> +# Copyright 2010 Kyle Hall
> +#
> +# 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 strict;
> +use warnings;
> +
> +use CGI;
> +use Config::Simple;
> +
> +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
> +
> +use C4::Context;
> +use C4::Output;
> +use C4::Dates;
> +use C4::Debug;
> +
> +BEGIN {
> +       # set the version for version checking
> +       $VERSION = 0.01;
> +       require Exporter;
> +       @ISA = qw(Exporter);
> +       @EXPORT = qw(
> +               GetReports
> +       );
> +}
> +
> +=head1 NAME
> +
> +C4::Reports::Custom - Module for loading and managing custom reports.
> +
> +=head1 SYNOPSIS
> +
> +  use C4::Reports::Custom;
> +
> +=over 2
> +
> +=cut
> +
> +=item GetReports()
> +
> +This will return a list of all the available reports
> +
> +Usage: my ( $reports_hasref, $reports_count ) = C4::Reports::Custom::GetReports();
> +
> +=cut
> +
> +sub GetReports {
> +       my @reports_ini = _GetReportsIniFiles();
> +
> +       my @reports;
> +       foreach my $report_ini ( @reports_ini ) {
> +               my $ini_hashref = _ParseReportIni( $report_ini );
> +               push( @reports, $ini_hashref );
> +       }
> +
> +       my $count = @reports;
> +
> +       return ( \@reports, $count );
> +}
> +
> +=item _GetReportsIniFiles()
> +
> +This will return an array of all the ini files for the custom reports.
> +
> +=cut
> +
> +sub _GetReportsIniFiles {
> +       my $reports_dir = '/home/koha/kohaclone/reports/custom_reports/';
> +       opendir(DIRHANDLE, $reports_dir);
> +       my @reports_dirs = readdir(DIRHANDLE);
> +       closedir(DIRHANDLE);
> +
> +       my @reports;
> +       foreach my $report_dir ( @reports_dirs ) {
> +
> +               my $report_path = $reports_dir . $report_dir;
> +
> +               if ( -d $report_path ) {
> +                       my $ini_path = $report_path . '/report.ini';
> +
> +                       if ( -f $ini_path ) {
> +                               push( @reports, $ini_path );
> +                       }
> +
> +               }
> +
> +       }
> +
> +       return ( @reports );
> +}
> +
> +=item _ParseReportIni( $ini_path )
> +
> +This will return a hasref of key/value pairs found in the ini file
> +
> +=cut
> +
> +sub _ParseReportIni {
> +       my ( $ini_path ) = @_;
> +
> +       my $ini;
> +
> +       open( INIFILE, '<', $ini_path ) or die("Could not open file $ini_path");
> +       foreach my $line ( <INIFILE> ) {
> +               my ( $key, $value );
> +               ( $key, $value ) = split(/=/, $line );
> +               $ini->{$key} = $value;
> +       }
> +
> +       return $ini;
> +}
> +
> +1;
> +__END__
> +
> +=back
> +
> +=head1 AUTHOR
> +
> +Kyle M Hall <kyle.m.hall at gmail.com>
> +
> +=cut
> diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl
> new file mode 100644
> index 0000000..a5db511
> --- /dev/null
> +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl
> @@ -0,0 +1,58 @@
> +<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
> +<title>Koha &rsaquo; Reports &rsaquo; Custom Reports </title>
> +<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
> +<!-- TMPL_INCLUDE NAME="calendar.inc" -->
> +</head>
> +
> +<body>
> +<!-- TMPL_INCLUDE NAME="header.inc" -->
> +<!-- TMPL_INCLUDE NAME="circ-search.inc" -->
> +
> +<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a>
> +&rsaquo; <a href="/cgi-bin/koha/reports/reports-home.pl">Reports</a>
> +&rsaquo; <a href="/cgi-bin/koha/reports/custom_reports.pl">Custom Reports</a>
> +</div>
> +
> +<div id="doc3" class="yui-t1">
> +       <div id="bd">
> +               <div id="yui-main">
> +                       <div class="yui-b">
> +                               <div class="details">
> +                                       <h1>Custom Reports</h1>
> +
> +                                       <!-- TMPL_IF NAME="ERROR_NO_REPORTS" -->
> +                                               <h2>No Custom Reports Exist.</h2>
> +                                               <p>Please upload one or more Koha Custom Reports files (.krz) before using.</p>
> +                                       <!-- TMPL_ELSE -->
> +                                               <table>
> +                                                       <tr>
> +                                                               <th>Name</th>
> +                                                               <th>Description</th>
> +                                                               <th>Run</th>
> +                                                       </tr>
> +
> +                                                       <!-- TMPL_LOOP NAME="REPORTS_LOOP" -->
> +                                                               <tr>
> +                                                                       <td><!-- TMPL_VAR NAME="name" --></td>
> +                                                                       <td><!-- TMPL_VAR NAME="description" --></td>
> +                                                                       <td><a href="custom_reports/<!-- TMPL_VAR NAME="start" -->">Run Report</a></td>
> +                                                               </tr>
> +                                                       <!-- /TMPL_LOOP -->
> +                                               </table>
> +                                       <!-- /TMPL_IF -->
> +                               </div>
> +                       </div>
> +               </div>
> +
> +               <div class="yui-b noprint">
> +                       <div id="navmenu">
> +                               <ul id="navmenulist">
> +                                       <li><a href="custom_reports_upload.pl">Upload A Custom Report</a></li>
> +                               </ul>
> +                       </div>
> +               </div>
> +       </div>
> +</div>
> +
> +
> +<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" -->
> diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl
> new file mode 100644
> index 0000000..30ff908
> --- /dev/null
> +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl
> @@ -0,0 +1,66 @@
> +<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
> +<title>Koha &rsaquo; Reports &rsaquo; Custom Reports &rsaquo; Upload Custom Report
> + </title>
> +<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
> +<!-- TMPL_INCLUDE NAME="calendar.inc" -->
> +</head>
> +
> +<body>
> +<!-- TMPL_INCLUDE NAME="header.inc" -->
> +<!-- TMPL_INCLUDE NAME="circ-search.inc" -->
> +
> +<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a>
> +&rsaquo; <a href="/cgi-bin/koha/reports/reports-home.pl">Reports</a>
> +&rsaquo; <a href="/cgi-bin/koha/reports/custom_reports.pl">Custom Reports</a>
> +&rsaquo; Upload Custom Report
> +</div>
> +
> +<div id="doc3" class="yui-t2">
> +    <div id="bd">
> +        <div id="yui-main">
> +    <div class="yui-b">
> +        <div class="yui-g">
> +            <div class="yui-u first">
> +                <h1>Upload Custom Report</h1>
> +                <!-- TMPL_IF name="ERRORS" -->
> +                <div class="dialog alert">
> +                    <!-- TMPL_LOOP name="ERRORS" -->
> +                        <!-- TMPL_IF name="NOTKRZ" --><li><b>The upload file does not appear to be a krz file.  The extention is not '.krz'.</b></li>
> +                        <!-- TMPL_ELSIF name="NOWRITETEMP" --><li><b>This script is not able to create/write to the necessary temporary directory.</b></li>
> +                        <!-- TMPL_ELSIF name="EMPTYUPLOAD" --><li><b>The upload file appears to be empty.</b></li>
> +                        <!-- TMPL_ELSIF name="UZIPFAIL" --><li><b><!-- TMPL_VAR name="UZIPFAIL" --> failed to unpack.<br />Please verify the integrity of the zip file and retry.</b></li>
> +                        <!-- TMPL_ELSIF name="NOWRITEREPORTS" --><li><b>Cannot unpack file to the custom reports directory.<br />Please verify that the Apache user can write to the custom reports directory.</b></li>
> +                        <!-- TMPL_ELSE --><li><b><!-- TMPL_VAR name ="CORERR" --> An unknown error has occurred.<br />Please review the error log for more details.</b></li><!-- /TMPL_IF -->
> +                    <!-- /TMPL_LOOP -->
> +                </div>
> +                <!-- /TMPL_IF -->
> +               <form method="post" action="/cgi-bin/koha/reports/custom_reports_upload.pl" enctype="multipart/form-data">
> +                   <fieldset class="brief">
> +                        <div class="hint"><b>NOTE:</b> Only KRZ file format is supported.</div>
> +                       <ol>
> +                            <li>
> +                                <label for="uploadfile">Select the file to upload: </label><input type="file" id="uploadfile" name="uploadfile" />
> +                            </li>
> +                       </ol>
> +                                       </li></ol>
> +                   </fieldset>
> +                    <fieldset class="action">
> +                        <input type="hidden" name="op" value="Upload" />
> +                        <input type="submit" value="Upload" class="submit" />
> +                    </fieldset>
> +                </form>
> +
> +            </div>
> +        </div>
> +    </div>
> +</div>
> +<div class="yui-b noprint">
> +<div id="navmenu">
> +       <ul id="navmenulist">
> +               <li><a href="/cgi-bin/koha/reports/custom_reports.pl">Custom Reports Home</a></li>
> +       </ul>
> +</div>
> +
> +</div>
> +</div>
> +<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" -->
> diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl
> index b2d8487..d97c8ef 100644
> --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl
> +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl
> @@ -27,6 +27,11 @@
>                <li><a href="/cgi-bin/koha/reports/dictionary.pl?phase=View%20Dictionary">View Dictionary</a></li>
>        </ul>
>
> +       <h2>Custom Reports</h2>
> +       <ul>
> +               <li><a href="/cgi-bin/koha/reports/custom_reports.pl">Custom Reports</a></li>
> +       </ul>
> +
>        <h2>Statistics wizards</h2>
>        <ul>
>                <li><a href="/cgi-bin/koha/reports/acquisitions_stats.pl">Acquisitions</a></li>
> diff --git a/reports/custom_reports.pl b/reports/custom_reports.pl
> new file mode 100755
> index 0000000..29e23a9
> --- /dev/null
> +++ b/reports/custom_reports.pl
> @@ -0,0 +1,52 @@
> +#!/usr/bin/perl
> +
> +# Copyright 2010 Kyle M Hall <kyle.m.hall at gmail.com>
> +#
> +# 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 strict;
> +use warnings;
> +
> +use CGI;
> +
> +use C4::Reports::Custom;
> +use C4::Auth;
> +use C4::Output;
> +use C4::Dates;
> +use C4::Debug;
> +
> +my $input = new CGI;
> +
> +my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
> +    {
> +        template_name   => "reports/custom_reports.tmpl",
> +        query           => $input,
> +        type            => "intranet",
> +        authnotrequired => 0,
> +        flagsrequired   => { reports => "execute_reports" },
> +        debug           => 1,
> +    }
> +);
> +
> +my ( $reports_loop, $reports_count ) = GetReports();
> +
> +$template->param( REPORTS_LOOP => $reports_loop );
> +
> +unless ( $reports_count ) {
> +  $template->param( ERROR_NO_REPORTS => 1 );
> +}
> +
> +output_html_with_http_headers $input, $cookie, $template->output;
> diff --git a/reports/custom_reports/empty b/reports/custom_reports/empty
> new file mode 100644
> index 0000000..e69de29
> diff --git a/reports/custom_reports_upload.pl b/reports/custom_reports_upload.pl
> new file mode 100755
> index 0000000..5bf98bf
> --- /dev/null
> +++ b/reports/custom_reports_upload.pl
> @@ -0,0 +1,89 @@
> +#!/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 strict;
> +use warnings;
> +
> +use File::Temp;
> +use File::Copy;
> +use CGI;
> +use GD;
> +
> +use C4::Context;
> +use C4::Auth;
> +use C4::Output;
> +use C4::Members;
> +use C4::Debug;
> +
> +my $input = new CGI;
> +
> +my ($template, $loggedinuser, $cookie)
> +       = get_template_and_user({template_name => "reports/custom_reports_upload.tmpl",
> +                                       query => $input,
> +                                       type => "intranet",
> +                                       authnotrequired => 0,
> +                                       flagsrequired => { reports => 'create_report'},
> +                                       debug => 1,
> +                                       });
> +
> +my $uploadfilename      = $input->param('uploadfile');
> +my $uploadfile          = $input->upload('uploadfile');
> +my $op                  = $input->param('op');
> +
> +my ( $total, $handled, @counts, $tempfile, $tfh );
> +
> +my %errors;
> +
> +if ( ($op eq 'Upload') && $uploadfile ) {
> +    my $custom_reports_dir = "/home/koha/kohaclone/reports/custom_reports/";
> +
> +    my $dirname = File::Temp::tempdir( CLEANUP => 1);
> +    $debug and warn "dirname = $dirname";
> +
> +    my $filesuffix = $1 if $uploadfilename =~ m/(\..+)$/i;
> +    ( $tfh, $tempfile ) = File::Temp::tempfile( SUFFIX => $filesuffix, UNLINK => 1 );
> +
> +    $debug and warn "tempfile = $tempfile";
> +
> +    $errors{'NOTKRZ'} = 1 if ( $uploadfilename !~ /\.krz$/i );
> +    $errors{'NOWRITETEMP'} = 1 unless ( -w $dirname );
> +    $errors{'NOWRITEREPORTS'} = 1 unless ( -w $custom_reports_dir );
> +    $errors{'EMPTYUPLOAD'} = 1 unless ( length( $uploadfile ) > 0 );
> +
> +    if ( %errors ) {
> +       $template->param( ERRORS => [ \%errors ] );
> +    } else {
> +       while ( <$uploadfile> ) {
> +           print $tfh $_;
> +        }
> +        close $tfh;
> +        unless (system("unzip $tempfile -d $custom_reports_dir") == 0) {
> +            $errors{'UZIPFAIL'} = $uploadfilename;
> +            $template->param( ERRORS => [ \%errors ] );
> +            output_html_with_http_headers $input, $cookie, $template->output;
> +            exit;
> +        }
> +    }
> +} elsif ( ($op eq 'Upload') && !$uploadfile ) {
> +    warn "Problem uploading file or no file uploaded.";
> +}
> +
> +if ( $uploadfile && !%errors && !$template->param('ERRORS') ) {
> +    print $input->redirect ("/cgi-bin/koha/reports/custom_reports.pl");
> +} else {
> +    output_html_with_http_headers $input, $cookie, $template->output;
> +}
> --
> 1.5.6.5
>
>



More information about the Koha-devel mailing list