Bug 7993: Save reports with Group/Subgroup hierarchy

This should make saved reports more manageable.
Group/Subgroup hierarchy is stored in authorised_values,
categories REPORT_GROUP and REPORT_SUBGROUP, connected by
REPORT_SUBGROUP.lib_opac -> REPORT_GROUP.authorised_value

Database changes:
* authorised_values: expanded category to 16 chars
* created default set of REPORT_GROUP authorised values to match
  hardcoded report areas
* reports_dictionary: replaced area int with report_area text, converted
  values
* saved_sql: added report_area, report_group and report_subgroup;
  report_area is not currently used, saved for the record

C4/Reports/Guided.pm:
* Replaced Area numeric values with the mnemonic codes
* get_report_areas(): returns hardcoded areas list
* created get_report_areas(): returns full hierarchy (groups with belonging
  subgroups)
* save_report(): changed iterface, accepts fields hashref as input
* update_sql(): changed iterface, accepts id and fields hashref as input
* get_saved_reports():]
- join to authorised_values to pick group and subgroup name
- accept group and subgroup filter params
* get_saved_report():
- changed iterface, return record hashref
- join to authorised_values to pick group and subgroup name
* build_authorised_value_list(): new sub, moved code from
  reports/guided_reports.pl
* Updated interfaces in:
cronjobs/runreport.pl, svc/report, opac/svc/report: get_saved_report()
reports/dictionary.pl: get_report_areas()
reports/guided_reports.pl

reports/guided_reports_start.tt:
* Reports list:
- added group/subgroup filter
- display area/group/subgroup for the reports
* Create report wizard:
- carry area to the end
- select group and subgroup when saving the report; group defaults to area,
  useful when report groups match areas
* Update report and Create from SQL: added group/subgroup
* Amended reports/guided_reports.pl accordingly

Conflicts:

    C4/Reports/Guided.pm
    admin/authorised_values.pl
    installer/data/mysql/kohastructure.sql
    installer/data/mysql/updatedatabase.pl
    koha-tmpl/intranet-tmpl/prog/en/modules/reports/dictionary.tmpl
    koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tmpl
    misc/cronjobs/runreport.pl
    reports/dictionary.pl
    reports/guided_reports.pl

Signed-off-by: Delaye Stephane <stephane.delaye@biblibre.com>
Signed-off-by: Paul Poulain <paul.poulain@biblibre.com>
This commit is contained in:
Srdjan 2012-09-10 13:14:01 +12:00 committed by Paul Poulain
parent b0ab204bfd
commit 42acfbf75b
11 changed files with 958 additions and 605 deletions

View file

@ -26,7 +26,8 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
use C4::Context;
use C4::Dates qw/format_date format_date_in_iso/;
use C4::Templates qw/themelanguage/;
use C4::Dates;
use C4::Koha;
use C4::Output;
use XML::Simple;
use XML::Dumper;
use C4::Debug;
@ -39,70 +40,77 @@ BEGIN {
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(
get_report_types get_report_areas get_columns build_query get_criteria
get_report_types get_report_areas get_report_groups get_columns build_query get_criteria
save_report get_saved_reports execute_query get_saved_report create_compound run_compound
get_column_type get_distinct_values save_dictionary get_from_dictionary
delete_definition delete_report format_results get_sql
nb_rows update_sql
nb_rows update_sql build_authorised_value_list
);
}
our %table_areas;
$table_areas{'1'} =
[ 'borrowers', 'statistics','items', 'biblioitems' ]; # circulation
$table_areas{'2'} = [ 'items', 'biblioitems', 'biblio' ]; # catalogue
$table_areas{'3'} = [ 'borrowers' ]; # patrons
$table_areas{'4'} = ['aqorders', 'biblio', 'items']; # acquisitions
$table_areas{'5'} = [ 'borrowers', 'accountlines' ]; # accounts
our %keys;
$keys{'1'} = [
'statistics.borrowernumber=borrowers.borrowernumber',
=item get_report_areas()
This will return a list of all the available report areas
=cut
my @REPORT_AREA = (
[CIRC => "Circulation"],
[CAT => "Catalogue"],
[PAT => "Patrons"],
[ACQ => "Acquisition"],
[ACC => "Accounts"],
);
my $AREA_NAME_SQL_SNIPPET
= "CASE report_area " .
join (" ", map "WHEN '$_->[0]' THEN '$_->[1]'", @REPORT_AREA) .
" END AS areaname";
sub get_report_areas {
return \@REPORT_AREA
}
my %table_areas = (
CIRC => [ 'borrowers', 'statistics', 'items', 'biblioitems' ],
CAT => [ 'items', 'biblioitems', 'biblio' ],
PAT => ['borrowers'],
ACQ => [ 'aqorders', 'biblio', 'items' ],
ACC => [ 'borrowers', 'accountlines' ],
);
my %keys = (
CIRC => [ 'statistics.borrowernumber=borrowers.borrowernumber',
'items.itemnumber = statistics.itemnumber',
'biblioitems.biblioitemnumber = items.biblioitemnumber'
];
$keys{'2'} = [
'items.biblioitemnumber=biblioitems.biblioitemnumber',
'biblioitems.biblionumber=biblio.biblionumber'
];
$keys{'3'} = [ ];
$keys{'4'} = [
'aqorders.biblionumber=biblio.biblionumber',
'biblio.biblionumber=items.biblionumber'
];
$keys{'5'} = ['borrowers.borrowernumber=accountlines.borrowernumber'];
'biblioitems.biblioitemnumber = items.biblioitemnumber' ],
CAT => [ 'items.biblioitemnumber=biblioitems.biblioitemnumber',
'biblioitems.biblionumber=biblio.biblionumber' ],
PAT => [],
ACQ => [ 'aqorders.biblionumber=biblio.biblionumber',
'biblio.biblionumber=items.biblionumber' ],
ACC => ['borrowers.borrowernumber=accountlines.borrowernumber'],
);
# have to do someting here to know if its dropdown, free text, date etc
our %criteria;
# reports on circulation
$criteria{'1'} = [
'statistics.type', 'borrowers.categorycode',
'statistics.branch',
'biblioitems.publicationyear|date',
'items.dateaccessioned|date'
];
# reports on catalogue
$criteria{'2'} =
[ 'items.itemnumber|textrange', 'items.biblionumber|textrange', 'items.barcode|textrange',
'biblio.frameworkcode', 'items.holdingbranch', 'items.homebranch',
'biblio.datecreated|daterange', 'biblio.timestamp|daterange', 'items.onloan|daterange',
'items.ccode', 'items.itemcallnumber|textrange', 'items.itype',
'items.itemlost', 'items.location' ];
# reports on borrowers
$criteria{'3'} = ['borrowers.branchcode', 'borrowers.categorycode'];
# reports on acquisition
$criteria{'4'} = ['aqorders.datereceived|date'];
# reports on accounting
$criteria{'5'} = ['borrowers.branchcode', 'borrowers.categorycode'];
my %criteria = (
CIRC => [ 'statistics.type', 'borrowers.categorycode', 'statistics.branch',
'biblioitems.publicationyear|date', 'items.dateaccessioned|date' ],
CAT => [ 'items.itemnumber|textrange', 'items.biblionumber|textrange',
'items.barcode|textrange', 'biblio.frameworkcode',
'items.holdingbranch', 'items.homebranch',
'biblio.datecreated|daterange', 'biblio.timestamp|daterange',
'items.onloan|daterange', 'items.ccode',
'items.itemcallnumber|textrange', 'items.itype', 'items.itemlost',
'items.location' ],
PAT => [ 'borrowers.branchcode', 'borrowers.categorycode' ],
ACQ => ['aqorders.datereceived|date'],
ACC => [ 'borrowers.branchcode', 'borrowers.categorycode' ],
);
# Adds itemtypes to criteria, according to the syspref
if ( C4::Context->preference('item-level_itypes') ) {
unshift @{ $criteria{'1'} }, 'items.itype';
unshift @{ $criteria{'2'} }, 'items.itype';
unshift @{ $criteria{'CIRC'} }, 'items.itype';
unshift @{ $criteria{'CAT'} }, 'items.itype';
} else {
unshift @{ $criteria{'1'} }, 'biblioitems.itemtype';
unshift @{ $criteria{'2'} }, 'biblioitems.itemtype';
unshift @{ $criteria{'CIRC'} }, 'biblioitems.itemtype';
unshift @{ $criteria{'CAT'} }, 'biblioitems.itemtype';
}
=head1 NAME
@ -145,26 +153,33 @@ sub get_report_types {
}
=item get_report_areas()
=item get_report_groups()
This will return a list of all the available report areas
This will return a list of all the available report areas with groups
=cut
sub get_report_areas {
sub get_report_groups {
my $dbh = C4::Context->dbh();
# FIXME these should be in the database
my @reports = ( 'Circulation', 'Catalog', 'Patrons', 'Acquisitions', 'Accounts');
my @reports2;
for ( my $i = 0 ; $i < 5 ; $i++ ) {
my %hashrep;
$hashrep{id} = $i + 1;
$hashrep{name} = $reports[$i];
push @reports2, \%hashrep;
}
return ( \@reports2 );
my $groups = GetAuthorisedValues('REPORT_GROUP');
my $subgroups = GetAuthorisedValues('REPORT_SUBGROUP');
my %groups_with_subgroups = map { $_->{authorised_value} => {
name => $_->{lib},
groups => {}
} } @$groups;
foreach (@$subgroups) {
my $sg = $_->{authorised_value};
my $g = $_->{lib_opac}
or warn( qq{REPORT_SUBGROUP "$sg" without REPORT_GROUP (lib_opac)} ),
next;
my $g_sg = $groups_with_subgroups{$g}
or warn( qq{REPORT_SUBGROUP "$sg" with invalid REPORT_GROUP "$g"} ),
next;
$g_sg->{subgroups}{$sg} = $_->{lib};
}
return \%groups_with_subgroups
}
=item get_all_tables()
@ -197,7 +212,9 @@ sub get_columns {
# this calls the internal fucntion _get_columns
my ( $area, $cgi ) = @_;
my $tables = $table_areas{$area};
my $tables = $table_areas{$area}
or die qq{Unsuported report area "$area"};
my @allcolumns;
my $first = 1;
foreach my $table (@$tables) {
@ -383,7 +400,7 @@ sub nb_rows($) {
=item execute_query
($results, $total, $error) = execute_query($sql, $offset, $limit)
($results, $error) = execute_query($sql, $offset, $limit)
When passed C<$sql>, this function returns an array ref containing a result set
@ -505,13 +522,23 @@ Returns id of the newly created report
=cut
sub save_report {
my ( $borrowernumber, $sql, $name, $type, $notes, $cache_expiry, $public ) = @_;
$cache_expiry ||= 300;
my ($fields) = @_;
my $borrowernumber = $fields->{borrowernumber};
my $sql = $fields->{sql};
my $name = $fields->{name};
my $type = $fields->{type};
my $notes = $fields->{notes};
my $area = $fields->{area};
my $group = $fields->{group};
my $subgroup = $fields->{subgroup};
my $cache_expiry = $fields->{cache_expiry} || 300;
my $public = $fields->{public};
my $dbh = C4::Context->dbh();
$sql =~ s/(\s*\;\s*)$//; # removes trailing whitespace and /;/
my $query =
"INSERT INTO saved_sql (borrowernumber,date_created,last_modified,savedsql,report_name,type,notes,cache_expiry, public) VALUES (?,now(),now(),?,?,?,?,?,?)";
$dbh->do( $query, undef, $borrowernumber, $sql, $name, $type, $notes, $cache_expiry, $public );
my $query = "INSERT INTO saved_sql (borrowernumber,date_created,last_modified,savedsql,report_name,report_area,report_group,report_subgroup,type,notes,cache_expiry,public) VALUES (?,now(),now(),?,?,?,?,?,?,?,?,?)";
$dbh->do($query, undef, $borrowernumber, $sql, $name, $area, $group, $subgroup, $type, $notes, $cache_expiry, $public);
my $id = $dbh->selectrow_array("SELECT max(id) FROM saved_sql WHERE borrowernumber=? AND report_name=?", undef,
$borrowernumber, $name);
return $id;
@ -519,23 +546,23 @@ sub save_report {
sub update_sql {
my $id = shift || croak "No Id given";
my $sql = shift;
my $reportname = shift;
my $notes = shift;
my $cache_expiry = shift;
my $public = shift;
my $fields = shift;
my $sql = $fields->{sql};
my $name = $fields->{name};
my $notes = $fields->{notes};
my $group = $fields->{group};
my $subgroup = $fields->{subgroup};
my $cache_expiry = $fields->{cache_expiry};
my $public = $fields->{public};
# not entirely a magic number, Cache::Memcached::Set assumed any expiry >= (60*60*24*30) is an absolute unix timestamp (rather than relative seconds)
if( $cache_expiry >= 2592000 ){
die "Please specify a cache expiry less than 30 days\n";
}
my $dbh = C4::Context->dbh();
$sql =~ s/(\s*\;\s*)$//; # removes trailing whitespace and /;/
my $query = "UPDATE saved_sql SET savedsql = ?, last_modified = now(), report_name = ?, notes = ?, cache_expiry = ?, public = ? WHERE id = ? ";
my $sth = $dbh->prepare($query);
$sth->execute( $sql, $reportname, $notes, $cache_expiry, $public, $id );
$sth->finish();
my $query = "UPDATE saved_sql SET savedsql = ?, last_modified = now(), report_name = ?, report_group = ?, report_subgroup = ?, notes = ?, cache_expiry = ?, public = ? WHERE id = ? ";
$dbh->do($query, undef, $sql, $name, $group, $subgroup, $notes, $cache_expiry, $public, $id );
}
sub store_results {
@ -589,23 +616,27 @@ sub delete_report {
$sth->execute($id);
}
# $filter is either { date => $d, author => $a, keyword => $kw }
# or $keyword. Optional.
my $SAVED_REPORTS_BASE_QRY = <<EOQ;
SELECT s.*, r.report, r.date_run, $AREA_NAME_SQL_SNIPPET, av_g.lib AS groupname, av_sg.lib AS subgroupname,
b.firstname AS borrowerfirstname, b.surname AS borrowersurname
FROM saved_sql s
LEFT JOIN saved_reports r ON r.report_id = s.id
LEFT OUTER JOIN authorised_values av_g ON (av_g.category = 'REPORT_GROUP' AND av_g.authorised_value = s.report_group)
LEFT OUTER JOIN authorised_values av_sg ON (av_sg.category = 'REPORT_SUBGROUP' AND av_sg.lib_opac = s.report_group AND av_sg.authorised_value = s.report_subgroup)
LEFT OUTER JOIN borrowers b USING (borrowernumber)
EOQ
my $DATE_FORMAT = "%d/%m/%Y";
sub get_saved_reports {
# $filter is either { date => $d, author => $a, keyword => $kw, }
# or $keyword. Optional.
my ($filter) = @_;
$filter = { keyword => $filter } if $filter && !ref( $filter );
my ($group, $subgroup) = @_;
my $dbh = C4::Context->dbh();
my $query = $SAVED_REPORTS_BASE_QRY;
my (@cond,@args);
my $query = "SELECT saved_sql.id, report_id, report,
date_run, date_created, last_modified, savedsql, last_run,
report_name, type, notes,
borrowernumber, surname as borrowersurname, firstname as borrowerfirstname,
cache_expiry, public
FROM saved_sql
LEFT JOIN saved_reports ON saved_reports.report_id = saved_sql.id
LEFT OUTER JOIN borrowers USING (borrowernumber)";
if ($filter) {
if (my $date = $filter->{date}) {
$date = format_date_in_iso($date);
@ -629,6 +660,14 @@ sub get_saved_reports {
savedsql LIKE ?";
push @args, $keyword, $keyword, $keyword, $keyword;
}
if ($filter->{group}) {
push @cond, "report_group = ?";
push @args, $filter->{group};
}
if ($filter->{subgroup}) {
push @cond, "report_subgroup = ?";
push @args, $filter->{subgroup};
}
}
$query .= " WHERE ".join( " AND ", map "($_)", @cond ) if @cond;
$query .= " ORDER by date_created";
@ -642,7 +681,6 @@ sub get_saved_reports {
sub get_saved_report {
my $dbh = C4::Context->dbh();
my $query;
my $sth;
my $report_arg;
if ($#_ == 0 && ref $_[0] ne 'HASH') {
($report_arg) = @_;
@ -661,10 +699,7 @@ sub get_saved_report {
} else {
return;
}
$sth = $dbh->prepare($query);
$sth->execute($report_arg);
my $data = $sth->fetchrow_hashref();
return ( $data->{'savedsql'}, $data->{'type'}, $data->{'report_name'}, $data->{'notes'}, $data->{'cache_expiry'}, $data->{'public'}, $data->{'id'} );
return $dbh->selectrow_hashref($query, undef, $report_arg);
}
=item create_compound($masterID,$subreportID)
@ -676,9 +711,14 @@ This will take 2 reports and create a compound report using both of them
sub create_compound {
my ( $masterID, $subreportID ) = @_;
my $dbh = C4::Context->dbh();
# get the reports
my ($mastersql,$mastertype) = get_saved_report($masterID);
my ($subsql,$subtype) = get_saved_report($subreportID);
my $master = get_saved_report($masterID);
my $mastersql = $master->{savedsql};
my $mastertype = $master->{type};
my $sub = get_saved_report($subreportID);
my $subsql = $master->{savedsql};
my $subtype = $master->{type};
# now we have to do some checking to see how these two will fit together
# or if they will
@ -741,39 +781,37 @@ sub get_distinct_values {
sub save_dictionary {
my ( $name, $description, $sql, $area ) = @_;
my $dbh = C4::Context->dbh();
my $query = "INSERT INTO reports_dictionary (name,description,saved_sql,area,date_created,date_modified)
my $query = "INSERT INTO reports_dictionary (name,description,saved_sql,report_area,date_created,date_modified)
VALUES (?,?,?,?,now(),now())";
my $sth = $dbh->prepare($query);
$sth->execute($name,$description,$sql,$area) || return 0;
return 1;
}
my $DICTIONARY_BASE_QRY = <<EOQ;
SELECT d.*, $AREA_NAME_SQL_SNIPPET
FROM reports_dictionary d
EOQ
sub get_from_dictionary {
my ( $area, $id ) = @_;
my $dbh = C4::Context->dbh();
my $query = "SELECT * FROM reports_dictionary";
my $query = $DICTIONARY_BASE_QRY;
if ($area) {
$query.= " WHERE area = ?";
}
elsif ($id){
$query.= " WHERE id = ?"
$query .= " WHERE report_area = ?";
} elsif ($id) {
$query .= " WHERE id = ?";
}
my $sth = $dbh->prepare($query);
if ($id) {
$sth->execute($id);
}
elsif ($area) {
} elsif ($area) {
$sth->execute($area);
}
else {
} else {
$sth->execute();
}
my @loop;
my @reports = ( 'Circulation', 'Catalog', 'Patrons', 'Acquisitions', 'Accounts');
while ( my $data = $sth->fetchrow_hashref() ) {
$data->{'areaname'}=$reports[$data->{'area'}-1];
push @loop, $data;
}
return ( \@loop );
}
@ -815,6 +853,72 @@ sub _get_column_defs {
close COLUMNS;
return \%columns;
}
=item build_authorised_value_list($authorised_value)
Returns an arrayref - hashref pair. The hashref consists of
various code => name lists depending on the $authorised_value.
The arrayref is the hashref keys, in appropriate order
=cut
sub build_authorised_value_list {
my ( $authorised_value ) = @_;
my $dbh = C4::Context->dbh;
my @authorised_values;
my %authorised_lib;
# builds list, depending on authorised value...
if ( $authorised_value eq "branches" ) {
my $branches = GetBranchesLoop();
foreach my $thisbranch (@$branches) {
push @authorised_values, $thisbranch->{value};
$authorised_lib{ $thisbranch->{value} } = $thisbranch->{branchname};
}
} elsif ( $authorised_value eq "itemtypes" ) {
my $sth = $dbh->prepare("SELECT itemtype,description FROM itemtypes ORDER BY description");
$sth->execute;
while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) {
push @authorised_values, $itemtype;
$authorised_lib{$itemtype} = $description;
}
} elsif ( $authorised_value eq "cn_source" ) {
my $class_sources = GetClassSources();
my $default_source = C4::Context->preference("DefaultClassificationSource");
foreach my $class_source ( sort keys %$class_sources ) {
next
unless $class_sources->{$class_source}->{'used'}
or ( $class_source eq $default_source );
push @authorised_values, $class_source;
$authorised_lib{$class_source} = $class_sources->{$class_source}->{'description'};
}
} elsif ( $authorised_value eq "categorycode" ) {
my $sth = $dbh->prepare("SELECT categorycode, description FROM categories ORDER BY description");
$sth->execute;
while ( my ( $categorycode, $description ) = $sth->fetchrow_array ) {
push @authorised_values, $categorycode;
$authorised_lib{$categorycode} = $description;
}
#---- "true" authorised value
} else {
my $authorised_values_sth = $dbh->prepare("SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib");
$authorised_values_sth->execute($authorised_value);
while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) {
push @authorised_values, $value;
$authorised_lib{$value} = $lib;
# For item location, we show the code and the libelle
$authorised_lib{$value} = $lib;
}
}
return (\@authorised_values, \%authorised_lib);
}
1;
__END__

View file

@ -197,8 +197,9 @@ sub default_form {
push( @category_list, $category );
$categories{$category} = 1;
}
# push koha system categories
foreach (qw(Asort1 Asort2 Bsort1 Bsort2 SUGGEST DAMAGED LOST)) {
foreach (qw(Asort1 Asort2 Bsort1 Bsort2 SUGGEST DAMAGED LOST REPORT_GROUP REPORT_SUBGROUP)) {
push @category_list, $_ unless $categories{$_};
}

View file

@ -97,7 +97,7 @@ CREATE TABLE `auth_types` (
DROP TABLE IF EXISTS `authorised_values`;
CREATE TABLE `authorised_values` ( -- stores values for authorized values categories and values
`id` int(11) NOT NULL auto_increment, -- unique key, used to identify the authorized value
`category` varchar(10) NOT NULL default '', -- key used to identify the authorized value category
`category` varchar(16) NOT NULL default '', -- key used to identify the authorized value category
`authorised_value` varchar(80) NOT NULL default '', -- code use to identify the authorized value
`lib` varchar(200) default NULL, -- authorized value description as printed in the staff client
`lib_opac` varchar(200) default NULL, -- authorized value description as printed in the OPAC
@ -1626,8 +1626,9 @@ CREATE TABLE reports_dictionary ( -- definitions (or snippets of SQL) stored for
`date_created` datetime default NULL, -- date and time this definition was created
`date_modified` datetime default NULL, -- date and time this definition was last modified
`saved_sql` text, -- SQL snippet for us in reports
`area` int(11) default NULL, -- Koha module this definition is for (1 = Circulation, 2 = Catalog, 3 = Patrons, 4 = Acquistions, 5 = Accounts)
PRIMARY KEY (`id`)
report_area varchar(6) DEFAULT NULL, -- Koha module this definition is for Circulation, Catalog, Patrons, Acquistions, Accounts)
PRIMARY KEY (id),
KEY dictionary_area_idx (report_area)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
@ -1725,7 +1726,11 @@ CREATE TABLE saved_sql ( -- saved sql reports
`notes` text, -- the notes or description given to this report
`cache_expiry` int NOT NULL default 300,
`public` boolean NOT NULL default FALSE,
report_area varchar(6) default NULL,
report_group varchar(80) default NULL,
report_subgroup varchar(80) default NULL,
PRIMARY KEY (`id`),
KEY sql_area_group_idx (report_group, report_subgroup),
KEY boridx (`borrowernumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View file

@ -5827,6 +5827,38 @@ if(C4::Context->preference("Version") < TransformToNum($DBversion) ) {
SetVersion($DBversion);
}
$DBversion = "3.09.00.XXX";
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
$dbh->do("ALTER TABLE authorised_values MODIFY category varchar(16) NOT NULL DEFAULT '';");
$dbh->do("INSERT INTO authorised_values (category, authorised_value, lib) VALUES
('REPORT_GROUP', 'CIRC', 'Circulation'),
('REPORT_GROUP', 'CAT', 'Catalog'),
('REPORT_GROUP', 'PAT', 'Patrons'),
('REPORT_GROUP', 'ACQ', 'Acquisitions'),
('REPORT_GROUP', 'ACC', 'Accounts');");
$dbh->do("ALTER TABLE reports_dictionary ADD report_area varchar(6) DEFAULT NULL;");
$dbh->do("UPDATE reports_dictionary SET report_area = CASE area
WHEN 1 THEN 'CIRC'
WHEN 2 THEN 'CAT'
WHEN 3 THEN 'PAT'
WHEN 4 THEN 'ACQ'
WHEN 5 THEN 'ACC'
END;");
$dbh->do("ALTER TABLE reports_dictionary DROP area;");
$dbh->do("ALTER TABLE reports_dictionary ADD KEY dictionary_area_idx (report_area);");
$dbh->do("ALTER TABLE saved_sql ADD report_area varchar(6) DEFAULT NULL;");
$dbh->do("ALTER TABLE saved_sql ADD report_group varchar(80) DEFAULT NULL;");
$dbh->do("ALTER TABLE saved_sql ADD report_subgroup varchar(80) DEFAULT NULL;");
$dbh->do("ALTER TABLE saved_sql ADD KEY sql_area_group_idx (report_group, report_subgroup);");
print "Upgrade to $DBversion done saved_sql new fields report_group and report_area; authorised_values.category 16 char \n";
SetVersion($DBversion);
}
=head1 FUNCTIONS
=head2 TableExists($table)

View file

@ -33,7 +33,7 @@
<form action="/cgi-bin/koha/reports/dictionary.pl" method="post">
<input type="hidden" name="phase" value="View Dictionary" />
[% IF ( areas ) %]
Filter by area <select name="areas">
Filter by area <select name="area">
<option value="">All</option>
[% FOREACH area IN areas %]
[% IF ( area.selected ) %]
@ -103,7 +103,7 @@
<ol><li><input type="hidden" name="phase" value="New Term step 3" />
<input type="hidden" name="definition_name" value="[% definition_name %]" />
<input type="hidden" name="definition_description" value="[% definition_description %]" />
<label for="areas">Select table </label><select name="areas" id="areas">
<label for="area">Select table </label><select name="area" id="area">
[% FOREACH area IN areas %]
<option value="[% area.id %]">[% area.name %]</option>
[% END %]

View file

@ -24,6 +24,25 @@
<script type="text/javascript">
//<![CDATA[
var group_subgroups = {};
var no_subgroup_label = _( "(None)" );
function load_group_subgroups () {
var group = $("#group").val();
var sg = $("#subgroup");
var has_subgroups = false;
$(sg).empty().append('<option value="">' + no_subgroup_label + '</option>');
if (group) {
$.each( group_subgroups[group], function(index, value) {
has_subgroups = true;
$('<option value="' + value[0] + '">' + value[1] + '</option>').appendTo(sg);
} );
}
if (has_subgroups) {
$(sg).show();
} else {
$(sg).hide();
}
}
$(document).ready(function(){
[% IF ( showsql ) %]
$("#sql").focus(function() {
@ -138,6 +157,9 @@ canned reports and writing custom SQL reports.</p>
<th>ID</th>
<th>Report name</th>
<th>Type</th>
<th>Area</th>
<th>Group</th>
<th>Subgroup</th>
<th>Notes</th>
<th>Author</th>
<th>Creation date</th>
@ -155,6 +177,9 @@ canned reports and writing custom SQL reports.</p>
<td>[% savedreport.id %]</td>
<td>[% savedreport.report_name %]</td>
<td>[% savedreport.type %]</td>
<td>[% savedreport.areaname %]</td>
<td>[% savedreport.groupname %]</td>
<td>[% savedreport.subgroupname %]</td>
<td>[% savedreport.notes %]</td>
<td>[% savedreport.borrowersurname %][% IF ( savedreport.borrowerfirstname ) %], [% savedreport.borrowerfirstname %][% END %] ([% savedreport.borrowernumber %])</td>
<td>[% savedreport.date_created %]</td>
@ -219,7 +244,7 @@ canned reports and writing custom SQL reports.</p>
<form action="/cgi-bin/koha/reports/guided_reports.pl">
<fieldset class="rows">
<legend>Step 1 of 6: Choose a module to report on,[% IF (usecache) %] Set cache expiry, [% END %] and Choose report visibility </legend>
<ol><li><label for="areas">Choose: </label><select name="areas" id="areas">
<ol><li><label for="area">Choose: </label><select name="area" id="area">
[% FOREACH area IN areas %]
<option value="[% area.id %]">[% area.name %]</option>
[% END %]
@ -485,12 +510,38 @@ canned reports and writing custom SQL reports.</p>
<form action="/cgi-bin/koha/reports/guided_reports.pl" method="post">
<input type="hidden" name="sql" value="[% sql |html %]" />
<input type="hidden" name="type" value="[% type %]" />
<input type="hidden" name="area" value="[% area %]" />
<input type="hidden" name="public" value="[% public %]" />
<input type="hidden" name="cache_expiry" value="[% cache_expiry %]" />
<fieldset class="rows">
<legend>Save your custom report</legend>
<ol>
<li><label for="reportname">Report name: </label><input type="text" id="reportname" name="reportname" /></li>
[% IF groups_with_subgroups %]
<li><label for="group">Report group: </label><select name="group" id="group" onChange="load_group_subgroups();">
[% FOR g IN groups_with_subgroups %]
[% IF g.selected %]
<option value="[% g.id %]" selected>[% g.name %]</option>
[% ELSE %]
<option value="[% g.id %]">[% g.name %]</option>
[% END %]
<script type="text/javascript">
var g_sg = new Array();
[% FOR sg IN g.subgroups %]
g_sg.push(["[% sg.id %]", "[% sg.name %]"]);
[% IF sg.selected %]
$(document).ready(function() {
$("#subgroup").val("[% sg.id %]");
});
[% END %]
[% END %]
group_subgroups["[% g.id %]"] = g_sg;
</script>
[% END %]
</select></li>
<li><label for="subgroup">Report subgroup: </label><select name="subgroup" id="subgroup">
</select></li>
[% END %]
<li><label for="notes">Notes:</label> <textarea name="notes" id="notes"></textarea></li>
</ol></fieldset>
<fieldset class="action"><input type="hidden" name="phase" value="Save Report" />
@ -553,6 +604,11 @@ canned reports and writing custom SQL reports.</p>
[% END %]
[% IF ( create ) %]
<script type="text/javascript">
$(document).ready(function() {
load_group_subgroups();
});
</script>
<form action="/cgi-bin/koha/reports/guided_reports.pl" method="post">
<fieldset class="rows">
<legend>Create report from SQL</legend>
@ -561,6 +617,31 @@ canned reports and writing custom SQL reports.</p>
[% IF ( reportname ) %]<input type="text" id="reportname" name="reportname" value="[% reportname %]" />
[% ELSE %]<input type="text" id="reportname" name="reportname" />[% END %]
</li>
[% IF groups_with_subgroups %]
<li><label for="group">Report group: </label><select name="group" id="group" onChange="load_group_subgroups();">
[% FOR g IN groups_with_subgroups %]
[% IF g.selected %]
<option value="[% g.id %]" selected>[% g.name %]</option>
[% ELSE %]
<option value="[% g.id %]">[% g.name %]</option>
[% END %]
<script type="text/javascript">
var g_sg = new Array();
[% FOR sg IN g.subgroups %]
g_sg.push(["[% sg.id %]", "[% sg.name %]"]);
[% IF sg.selected %]
$(document).ready(function() {
$("#subgroup").val("[% sg.id %]");
});
[% END %]
[% END %]
group_subgroups["[% g.id %]"] = g_sg;
</script>
[% END %]
</select></li>
<li><label for="subgroup">Report subgroup: </label><select name="subgroup" id="subgroup">
</select></li>
[% END %]
[% IF (public) %]
<li><label for="public">Report is public:</label><select id="public" name="public"> <option value="0">No (default)</option> <option value="1" selected="selected">Yes</public> </select></li>
[% ELSE %]
@ -645,6 +726,11 @@ Sub report:<select name="subreport">
[% END %]
[% IF ( editsql ) %]
<script type="text/javascript">
$(document).ready(function() {
load_group_subgroups();
});
</script>
<form action="/cgi-bin/koha/reports/guided_reports.pl" method="post">
<input type="hidden" name="phase" value="Update SQL" />
<input type="hidden" name="id" value="[% id %]"/>
@ -652,6 +738,31 @@ Sub report:<select name="subreport">
<legend>Edit SQL report</legend>
<ol>
<li><label for="reportname">Report name:</label><input type="text" id="reportname" name="reportname" value="[% reportname %]" size="50" /></li>
[% IF groups_with_subgroups %]
<li><label for="group">Report group: </label><select name="group" id="group" onChange="load_group_subgroups();">
[% FOR g IN groups_with_subgroups %]
[% IF g.selected %]
<option value="[% g.id %]" selected>[% g.name %]</option>
[% ELSE %]
<option value="[% g.id %]">[% g.name %]</option>
[% END %]
<script type="text/javascript">
var g_sg = new Array();
[% FOR sg IN g.subgroups %]
g_sg.push(["[% sg.id %]", "[% sg.name %]"]);
[% IF sg.selected %]
$(document).ready(function() {
$("#subgroup").val("[% sg.id %]");
});
[% END %]
[% END %]
group_subgroups["[% g.id %]"] = g_sg;
</script>
[% END %]
</select></li>
<li><label for="subgroup">Report subgroup: </label><select name="subgroup" id="subgroup">
</select></li>
[% END %]
[% IF (public) %]
<li><label for="public">Report is public:</label><select id="public" name="public"> <option value="0">No (default)</option> <option value="1" selected="selected">Yes</public> </select></li>
[% ELSE %]
@ -719,12 +830,43 @@ Sub report:<select name="subreport">
[% IF ( saved1 ) %]
<div id="saved-reports-filter">
<script type="text/javascript">
$(document).ready(function() {
no_subgroup_label = _( "-- All --" );
load_group_subgroups();
});
</script>
<form action="/cgi-bin/koha/reports/guided_reports.pl" method="get">
<input type="hidden" name="phase" value="Use saved" />
<input type="hidden" name="filter_set" value="1" />
<fieldset class="brief">
<h3>Filter</h3>
<ol>
<li><label for="group">Choose Group and Subgroup: </label>
<select name="group" id="group" onChange="load_group_subgroups();">
<option value="">-- All --</option>
[% FOR g IN groups_with_subgroups %]
[% IF g.selected %]
<option value="[% g.id %]" selected>[% g.name %]</option>
[% ELSE %]
<option value="[% g.id %]">[% g.name %]</option>
[% END %]
<script type="text/javascript">
var g_sg = new Array();
[% FOR sg IN g.subgroups %]
g_sg.push(["[% sg.id %]", "[% sg.name %]"]);
[% IF sg.selected %]
$(document).ready(function() {
$("#subgroup").val("[% sg.id %]");
});
[% END %]
[% END %]
group_subgroups["[% g.id %]"] = g_sg;
</script>
[% END %]
</select>
<select name="subgroup" id="subgroup"></select>
</li>
<li><label for="filter_date">Date:</label> <input type="text" id="filter_date" name="filter_date" size="10" value="[% filter_date %]" class="datepicker" />
<div class="hint">[% INCLUDE 'date-format.inc' %]</div>

View file

@ -186,14 +186,26 @@ unless (scalar(@ARGV)) {
($verbose) and print scalar(@ARGV), " argument(s) after options: " . join(" ", @ARGV) . "\n";
foreach my $report (@ARGV) {
my ($sql, $type) = get_saved_report($report);
unless ($sql) {
carp "ERROR: No saved report $report found";
foreach my $report_id (@ARGV) {
my $report = get_saved_report($report_id);
unless ($report) {
warn "ERROR: No saved report $report_id found";
next;
}
my $sql => $report->{savedsql};
my $report_name => $report->{report_name};
my $type => $report->{type};
$verbose and print "SQL: $sql\n\n";
# my $results = execute_query($sql, undef, 0, 99999, $format, $report);
if (defined($report_name) and $report_name ne "")
{
$subject = $report_name ;
}
else
{
$subject = 'Koha Saved Report';
}
# my $results = execute_query($sql, undef, 0, 99999, $format, $report_id);
my ($sth) = execute_query($sql);
# execute_query(sql, , 0, 20, , )
my $count = scalar($sth->rows);

View file

@ -31,38 +31,34 @@ my $query = CGI->new();
my $report_id = $query->param('id');
my $report_name = $query->param('name');
my $cache;
my $sql;
my $type;
my $notes;
my $cache_expiry;
my $public;
my $report_rec = get_saved_report( $report_name ? { 'name' => $report_name } : { 'id' => $report_id } );
die "Sorry this report is not public\n" unless $report_rec->{public};
( $sql, $type, $report_name, $notes, $cache_expiry, $public, $report_id ) =
get_saved_report($report_name ? { 'name' => $report_name } : { 'id' => $report_id } );
die "Sorry this report is not public\n" unless $public;
if (Koha::Cache->is_cache_active) {
$cache = Koha::Cache->new(
);
my $page = $cache->get_from_cache("opac:report:$report_id");
if ($page) {
print $query->header;
print $page;
exit;
}
my $cache_active = Koha::Cache->is_cache_active;
my ($cache_key, $cache, $json_text);
if ($cache_active) {
$cache_key = "opac:report:".($report_name ? "name:$report_name" : "id:$report_id");
$cache = Koha::Cache->new();
$json_text = $cache->get_from_cache($cache_key);
}
print $query->header;
if ($sql) {
unless ($json_text) {
my $offset = 0;
my $limit = C4::Context->preference("SvcMaxReportRows") || 10;
my ( $sth, $errors ) = execute_query( $sql, $offset, $limit );
my ( $sth, $errors ) = execute_query( $report_rec->{savedsql}, $offset, $limit );
if ($sth) {
my $lines = $sth->fetchall_arrayref;
my $json_text = to_json($lines);
print $json_text;
$json_text = to_json($lines);
if (Koha::Cache->is_cache_active) {
$cache->set_in_cache( "opac:report:$report_id", $json_text, $cache_expiry );
if ($cache_active) {
$cache->set_in_cache( $cache_key, $json_text, $report_rec->{cache_expiry} );
}
}
else {
$json_text = to_json($errors);
}
}
print $query->header;
print $json_text;

View file

@ -37,11 +37,12 @@ my $input = new CGI;
my $referer = $input->referer();
my $phase = $input->param('phase') || 'View Dictionary';
my $area = $input->param('areas') || '';
my $definition_name = $input->param('definition_name');
my $definition_description = $input->param('definition_description');
my $area = $input->param('area') || '';
my $no_html = 0; # this will be set if we dont want to print out an html::template
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
{
template_name => "reports/dictionary.tmpl",
{ template_name => "reports/dictionary.tmpl",
query => $input,
type => "intranet",
authnotrequired => 0,
@ -52,41 +53,35 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
if ($phase eq 'View Dictionary'){
# view the dictionary we use to set up abstract variables such as all borrowers over fifty who live in a certain town
my $areas = get_report_areas();
foreach (@{ $areas }) {
$_->{selected} = 1 if $_->{id} eq $area; # mark active area
}
my $definitions = get_from_dictionary($area);
$template->param( 'areas' => $areas ,
$template->param(
'areas'=> areas(),
'start_dictionary' => 1,
'definitions' => $definitions,
);
}
elsif ($phase eq 'Add New Definition'){
} elsif ( $phase eq 'Add New Definition' ) {
# display form allowing them to add a new definition
$template->param( 'new_dictionary' => 1,
);
$template->param( 'new_dictionary' => 1, );
}
elsif ( $phase eq 'New Term step 2' ) {
# Choosing the area
my $areas = C4::Reports::Guided::get_report_areas();
my $definition_name=$input->param('definition_name');
my $definition_description=$input->param('definition_description');
$template->param( 'step_2' => 1,
'areas' => $areas,
$template->param(
'step_2' => 1,
'areas' => areas(),
'definition_name' => $definition_name,
'definition_description' => $definition_description,
);
}
elsif ( $phase eq 'New Term step 3' ) {
# Choosing the columns
my $area = $input->param('areas');
my $columns = get_columns( $area, $input );
my $definition_name=$input->param('definition_name');
my $definition_description=$input->param('definition_description');
$template->param( 'step_3' => 1,
$template->param(
'step_3' => 1,
'area' => $area,
'columns' => $columns,
'definition_name' => $definition_name,
@ -95,10 +90,8 @@ elsif ($phase eq 'New Term step 3'){
}
elsif ( $phase eq 'New Term step 4' ) {
# Choosing the values
my $area=$input->param('area');
my $definition_name=$input->param('definition_name');
my $definition_description=$input->param('definition_description');
my @columns = $input->param('columns');
my $columnstring = join( ',', @columns );
my @column_loop;
@ -115,9 +108,10 @@ elsif ($phase eq 'New Term step 4'){
if ( $type eq 'DATE' || $type eq 'DATETIME' ) {
$tmp_hash{'date'} = 1;
}
if ($type eq 'TEXT' || $type eq 'MEDIUMTEXT'){
if ( $type eq 'TEXT' ) {
$tmp_hash{'text'} = 1;
}
# else {
# warn $type;#
# }
@ -136,15 +130,11 @@ elsif ($phase eq 'New Term step 4'){
elsif ( $phase eq 'New Term step 5' ) {
# Confirmation screen
my $areas = C4::Reports::Guided::get_report_areas();
my $area = $input->param('area');
my $areaname = $areas->[$area - 1]->{'name'};
my $columnstring = $input->param('columnstring');
my $definition_name=$input->param('definition_name');
my $definition_description=$input->param('definition_description');
my @criteria = $input->param('criteria_column');
my $query_criteria;
my @criteria_loop;
foreach my $crit (@criteria) {
my $value = $input->param( $crit . "_value" );
if ($value) {
@ -183,9 +173,11 @@ elsif ($phase eq 'New Term step 5'){
$query_criteria .= " AND $crit <= '$value'";
}
}
$template->param( 'step_5' => 1,
my %report_areas = map @$_, get_report_areas();
$template->param(
'step_5' => 1,
'area' => $area,
'areaname' => $areaname,
'areaname' => $report_areas{$area},
'definition_name' => $definition_name,
'definition_description' => $definition_description,
'query' => $query_criteria,
@ -197,15 +189,12 @@ elsif ($phase eq 'New Term step 5'){
elsif ( $phase eq 'New Term step 6' ) {
# Saving
my $area = $input->param('area');
my $definition_name=$input->param('definition_name');
my $definition_description=$input->param('definition_description');
my $sql = $input->param('sql');
save_dictionary( $definition_name, $definition_description, $sql, $area );
$no_html = 1;
print $input->redirect("/cgi-bin/koha/reports/dictionary.pl?phase=View%20Dictionary");
}
elsif ($phase eq 'Delete Definition'){
} elsif ( $phase eq 'Delete Definition' ) {
$no_html = 1;
my $id = $input->param('id');
delete_definition($id);
@ -218,3 +207,16 @@ $template->param( 'referer' => $referer );
if (!$no_html){
output_html_with_http_headers $input, $cookie, $template->output;
}
sub areas {
my $areas = get_report_areas();
my @a;
foreach (@$areas) {
push @a, {
id => $_->[0],
name => $_->[1],
selected => ($_->[0] eq $area),
};
}
return \@a;
}

View file

@ -18,14 +18,15 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use strict;
#use warnings; FIXME - Bug 2505
use warnings;
use CGI;
use Text::CSV;
use URI::Escape;
use C4::Reports::Guided;
use C4::Auth qw/:DEFAULT get_session/;
use C4::Output;
use C4::Dates;
use C4::Dates qw/format_date/;
use C4::Debug;
use C4::Branch; # XXX subfield_is_koha_internal_p
@ -68,7 +69,7 @@ my $session = $cookie ? get_session($cookie->value) : undef;
my $filter;
if ( $input->param("filter_set") ) {
$filter = {};
$filter->{$_} = $input->param("filter_$_") foreach qw/date author keyword/;
$filter->{$_} = $input->param("filter_$_") foreach qw/date author keyword group subgroup/;
$session->param('report_filter', $filter) if $session;
$template->param( 'filter_set' => 1 );
}
@ -85,21 +86,27 @@ if ( !$phase ) {
elsif ( $phase eq 'Build new' ) {
# build a new report
$template->param( 'build1' => 1 );
$template->param( 'areas' => get_report_areas(), 'usecache' => $usecache, 'cache_expiry' => 300, 'public' => '0' );
}
elsif ( $phase eq 'Use saved' ) {
my $areas = get_report_areas();
$template->param(
'areas' => [map { id => $_->[0], name => $_->[1] }, @$areas],
'usecache' => $usecache,
'cache_expiry' => 300,
'public' => '0',
);
} elsif ( $phase eq 'Use saved' ) {
# use a saved report
# get list of reports and display them
my $group = $input->param('group');
my $subgroup = $input->param('subgroup');
$filter->{group} = $group;
$filter->{subgroup} = $subgroup;
$template->param(
'saved1' => 1,
'savedreports' => get_saved_reports($filter),
'usecache' => $usecache,
'groups_with_subgroups'=> groups_with_subgroups($group, $subgroup),
);
if ($filter) {
while ( my ($k, $v) = each %$filter ) {
$template->param( "filter_$k" => $v ) if $v;
}
}
}
elsif ( $phase eq 'Delete Saved') {
@ -114,12 +121,12 @@ elsif ( $phase eq 'Delete Saved') {
elsif ( $phase eq 'Show SQL'){
my $id = $input->param('reports');
my ($sql,$type,$reportname,$notes) = get_saved_report($id);
my $report = get_saved_report($id);
$template->param(
'id' => $id,
'reportname' => $reportname,
'notes' => $notes,
'sql' => $sql,
'reportname' => $report->{report_name},
'notes' => $report->{notes},
'sql' => $report->{savedsql},
'showsql' => 1,
);
}
@ -127,14 +134,17 @@ elsif ( $phase eq 'Show SQL'){
elsif ( $phase eq 'Edit SQL'){
my $id = $input->param('reports');
my ($sql,$type,$reportname,$notes, $cache_expiry, $public) = get_saved_report($id);
my $report = get_saved_report($id);
my $group = $report->{report_group};
my $subgroup = $report->{report_subgroup};
$template->param(
'sql' => $sql,
'reportname' => $reportname,
'notes' => $notes,
'sql' => $report->{savedsql},
'reportname' => $report->{report_name},
'groups_with_subgroups' => groups_with_subgroups($group, $subgroup),
'notes' => $report->{notes},
'id' => $id,
'cache_expiry' => $cache_expiry,
'public' => $public,
'cache_expiry' => $report->{cache_expiry},
'public' => $report->{public},
'usecache' => $usecache,
'editsql' => 1,
);
@ -144,6 +154,8 @@ elsif ( $phase eq 'Update SQL'){
my $id = $input->param('id');
my $sql = $input->param('sql');
my $reportname = $input->param('reportname');
my $group = $input->param('group');
my $subgroup = $input->param('subgroup');
my $notes = $input->param('notes');
my $cache_expiry = $input->param('cache_expiry');
my $cache_expiry_units = $input->param('cache_expiry_units');
@ -177,16 +189,22 @@ elsif ( $phase eq 'Update SQL'){
'errors' => \@errors,
'sql' => $sql,
);
}
else {
update_sql( $id, $sql, $reportname, $notes, $cache_expiry, $public );
} else {
update_sql( $id, {
sql => $sql,
name => $reportname,
group => $group,
subgroup => $subgroup,
notes => $notes,
cache_expiry => $cache_expiry,
public => $public,
} );
$template->param(
'save_successful' => 1,
'reportname' => $reportname,
'id' => $id,
);
}
}
elsif ($phase eq 'retrieve results') {
@ -228,7 +246,7 @@ elsif ( $phase eq 'Report on this Area' ) {
# they have choosen a new report and the area to report on
$template->param(
'build2' => 1,
'area' => $input->param('areas'),
'area' => $input->param('area'),
'types' => get_report_types(),
'cache_expiry' => $cache_expiry,
'public' => $input->param('public'),
@ -412,6 +430,7 @@ elsif ( $phase eq 'Build report' ) {
build_query( \@columns, $query_criteria, $query_orderby, $area, $totals, $definition );
$template->param(
'showreport' => 1,
'area' => $area,
'sql' => $sql,
'type' => $type,
'cache_expiry' => $input->param('cache_expiry'),
@ -421,19 +440,25 @@ elsif ( $phase eq 'Build report' ) {
elsif ( $phase eq 'Save' ) {
# Save the report that has just been built
my $area = $input->param('area');
my $sql = $input->param('sql');
my $type = $input->param('type');
$template->param(
'save' => 1,
'area' => $area,
'sql' => $sql,
'type' => $type,
'cache_expiry' => $input->param('cache_expiry'),
'public' => $input->param('public'),
'groups_with_subgroups' => groups_with_subgroups($area), # in case we have a report group that matches area
);
}
elsif ( $phase eq 'Save Report' ) {
# save the sql pasted in by a user
my $area = $input->param('area');
my $group = $input->param('group');
my $subgroup = $input->param('subgroup');
my $sql = $input->param('sql');
my $name = $input->param('reportname');
my $type = $input->param('types');
@ -454,7 +479,7 @@ elsif ( $phase eq 'Save Report' ) {
}
}
# check $cache_expiry isnt too large, Memcached::set requires it to be less than 30 days or it will be treated as if it were an absolute time stamp
if( $cache_expiry >= 2592000 ){
if( $cache_expiry && $cache_expiry >= 2592000 ){
push @errors, {cache_expiry => $cache_expiry};
}
## FIXME this is AFTER entering a name to save the report under
@ -462,7 +487,7 @@ elsif ( $phase eq 'Save Report' ) {
push @errors, {sqlerr => $1};
}
elsif ($sql !~ /^(SELECT)/i) {
push @errors, {queryerr => 1};
push @errors, {queryerr => "No SELECT"};
}
if (@errors) {
$template->param(
@ -476,12 +501,19 @@ elsif ( $phase eq 'Save Report' ) {
);
}
else {
my $id = save_report( $borrowernumber, $sql, $name, $type, $notes, $cache_expiry, $public );
$template->param(
'save_successful' => 1,
'reportname' => $name,
'id' => $id,
);
save_report( {
borrowernumber => $borrowernumber,
sql => $sql,
name => $name,
area => $area,
group => $group,
subgroup => $subgroup,
type => $type,
notes => $notes,
cache_expiry => $cache_expiry,
public => $public,
} );
$template->param( 'save_successful' => 1, );
}
}
@ -489,16 +521,19 @@ elsif ($phase eq 'Run this report'){
# execute a saved report
my $limit = 20; # page size. # TODO: move to DB or syspref?
my $offset = 0;
my $report = $input->param('reports');
my $report_id = $input->param('reports');
my @sql_params = $input->param('sql_params');
# offset algorithm
if ($input->param('page')) {
$offset = ($input->param('page') - 1) * $limit;
}
my ($sql,$type,$name,$notes) = get_saved_report($report);
unless ($sql) {
push @errors, {no_sql_for_id=>$report};
}
my ( $sql, $type, $name, $notes );
if (my $report = get_saved_report($report_id)) {
$sql = $report->{savedsql};
$name = $report->{report_name};
$notes = $report->{notes};
my @rows = ();
# if we have at least 1 parameter, and it's not filled, then don't execute but ask for parameters
if ($sql =~ /<</ && !@sql_params) {
@ -577,7 +612,6 @@ elsif ($phase eq 'Run this report'){
-multiple => 0,
-tabindex => 1,
);
} else {
$input = "text";
}
@ -587,7 +621,7 @@ elsif ($phase eq 'Run this report'){
'name' => $name,
'sql_params' => \@tmpl_parameters,
'enter_params' => 1,
'reports' => $report,
'reports' => $report_id,
);
} else {
# OK, we have parameters, or there are none, we run the report
@ -604,7 +638,7 @@ elsif ($phase eq 'Run this report'){
my ($sth, $errors) = execute_query($sql, $offset, $limit);
my $total = nb_rows($sql) || 0;
unless ($sth) {
die "execute_query failed to return sth for report $report: $sql";
die "execute_query failed to return sth for report $report_id: $sql";
} else {
my $headref = $sth->{NAME} || [];
my @headers = map { +{ cell => $_ } } @$headref;
@ -616,14 +650,14 @@ elsif ($phase eq 'Run this report'){
}
my $totpages = int($total/$limit) + (($total % $limit) > 0 ? 1 : 0);
my $url = "/cgi-bin/koha/reports/guided_reports.pl?reports=$report&amp;phase=Run%20this%20report";
my $url = "/cgi-bin/koha/reports/guided_reports.pl?reports=$report_id&amp;phase=Run%20this%20report";
if (@sql_params) {
$url = join('&amp;sql_params=', $url, map { URI::Escape::uri_escape($_) } @sql_params);
}
$template->param(
'results' => \@rows,
'sql' => $sql,
'id' => $report,
'id' => $report_id,
'execute' => 1,
'name' => $name,
'notes' => $notes,
@ -633,6 +667,10 @@ elsif ($phase eq 'Run this report'){
);
}
}
else {
push @errors, { no_sql_for_id => $report_id };
}
}
elsif ($phase eq 'Export'){
binmode STDOUT, ':encoding(UTF-8)';
@ -681,15 +719,25 @@ elsif ($phase eq 'Export'){
}
elsif ( $phase eq 'Create report from SQL' ) {
my ($group, $subgroup);
# allow the user to paste in sql
if ( $input->param('sql') ) {
$group = $input->param('report_group');
$subgroup = $input->param('report_subgroup');
$template->param(
'sql' => $input->param('sql'),
'reportname' => $input->param('reportname'),
'notes' => $input->param('notes'),
);
}
$template->param('create' => 1, 'public' => '0', 'cache_expiry' => 300, 'usecache' => $usecache);
$template->param(
'create' => 1,
'groups_with_subgroups' => groups_with_subgroups($group, $subgroup),
'public' => '0',
'cache_expiry' => 300,
'usecache' => $usecache,
);
}
elsif ($phase eq 'Create Compound Report'){
@ -728,3 +776,29 @@ $template->param( 'referer' => $input->referer(),
);
output_html_with_http_headers $input, $cookie, $template->output;
sub groups_with_subgroups {
my ($group, $subgroup) = @_;
my $groups_with_subgroups = get_report_groups();
my @g_sg;
while (my ($g_id, $v) = each %$groups_with_subgroups) {
my @subgroups;
if (my $sg = $v->{subgroups}) {
while (my ($sg_id, $n) = each %$sg) {
push @subgroups, {
id => $sg_id,
name => $n,
selected => ($group && $g_id eq $group && $subgroup && $sg_id eq $subgroup ),
};
}
}
push @g_sg, {
id => $g_id,
name => $v->{name},
selected => ($group && $g_id eq $group),
subgroups => \@subgroups,
};
}
return \@g_sg;
}

View file

@ -33,13 +33,6 @@ my $query = CGI->new();
my $report_id = $query->param('id');
my $report_name = $query->param('name');
my $cache;
my $sql;
my $type;
my $notes;
my $cache_expiry;
my $public;
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
{
template_name => "intranet-main.tmpl",
@ -50,39 +43,31 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
}
);
if (Koha::Cache->is_cache_active) {
if ($report_name) { # When retrieving by name, we have to hit the
# database to get the ID before we can check
# the cache. Yuck.
( $sql, $type, $report_name, $notes, $cache_expiry, $public, $report_id ) =
get_saved_report( { 'name' => $report_name } );
}
my $cache_active = Koha::Cache->is_cache_active;
my ($cache_key, $cache, $json_text);
if ($cache_active) {
$cache_key = "intranet:report:".($report_name ? "name:$report_name" : "id:$report_id");
$cache = Koha::Cache->new();
my $page = $cache->get_from_cache("intranet:report:$report_id");
if ($page) {
print $query->header;
print $page;
exit;
}
$json_text = $cache->get_from_cache($cache_key);
}
print $query->header;
# $public isnt used for intranet
unless ($sql) {
( $sql, $type, $report_name, $notes, $cache_expiry, $public, $report_id ) =
get_saved_report($report_name ? { 'name' => $report_name } : { 'id' => $report_id } );
}
if ($sql) {
unless ($json_text) {
my $report_rec = get_saved_report($report_name ? { 'name' => $report_name } : { 'id' => $report_id });
my $offset = 0;
my $limit = C4::Context->preference("SvcMaxReportRows") || 10;
my ( $sth, $errors ) = execute_query( $sql, $offset, $limit );
my ( $sth, $errors ) = execute_query( $report_rec->{savedsql}, $offset, $limit );
if ($sth) {
my $lines = $sth->fetchall_arrayref;
my $json_text = to_json($lines);
print $json_text;
$json_text = to_json($lines);
if (Koha::Cache->is_cache_active) {
$cache->set_in_cache( "intranet:report:$report_id", $json_text, $cache_expiry );
if ($cache_active) {
$cache->set_in_cache( $cache_key, $json_text, $report_rec->{cache_expiry} );
}
}
else {
$json_text = to_json($errors);
}
}
print $query->header;
print $json_text;