Add a referer variable so we can have a back button
[koha.git] / reports / guided_reports.pl
1 #!/usr/bin/perl
2
3 # Copyright 2007 Liblime ltd
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA  02111-1307 USA
19 use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
20 use strict;
21 use C4::Auth;
22 use CGI;
23 use C4::Output;
24 use C4::Reports;
25
26 =head1 NAME
27
28 Script to control the guided report creation
29
30 =head1 DESCRIPTION
31
32
33 =over2
34
35 =cut
36
37 my $input = new CGI;
38 my $referer = $input->referer();
39 my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
40     {
41         template_name   => "reports/guided_reports_start.tmpl",
42         query           => $input,
43         type            => "intranet",
44         authnotrequired => 0,
45         flagsrequired   => { editcatalogue => 1 },
46         debug           => 1,
47     }
48 );
49
50 my $phase = $input->param('phase');
51 my $no_html = 0; # this will be set if we dont want to print out an html::template
52
53 if ( !$phase ) {
54     $template->param( 'start' => 1 );
55
56     # show welcome page
57 }
58
59 elsif ( $phase eq 'Build new' ) {
60
61     # build a new report
62     $template->param( 'build1' => 1 );
63
64     # get report areas
65     my $areas = C4::Reports::get_report_areas();
66     $template->param( 'areas' => $areas );
67
68 }
69
70 elsif ( $phase eq 'Used saved' ) {
71
72     # use a saved report
73     # get list of reports and display them
74     $template->param( 'saved1' => 1 );
75     my $reports = get_saved_reports();
76     $template->param( 'savedreports' => $reports );
77 }
78
79 elsif ( $phase eq 'Report on this Area' ) {
80
81     # they have choosen a new report and the area to report on
82     # get area
83     my $area = $input->param('areas');
84     $template->param(
85         'build2' => 1,
86         'area'   => $area
87     );
88
89     # get report types
90     my $types = C4::Reports::get_report_types();
91     $template->param( 'types' => $types );
92 }
93
94 elsif ( $phase eq 'Choose this type' ) {
95
96     # they have chosen type and area
97     # get area and type and pass them to the template
98     my $area = $input->param('area');
99     my $type = $input->param('types');
100     $template->param(
101         'build3' => 1,
102         'area'   => $area,
103         'type'   => $type,
104     );
105
106     # get columns
107     my $columns = get_columns($area);
108     $template->param( 'columns' => $columns );
109 }
110
111 elsif ( $phase eq 'Choose these columns' ) {
112
113     # we now know type, area, and columns
114     # next step is the constraints
115     my $area    = $input->param('area');
116     my $type    = $input->param('type');
117     my @columns = $input->param('columns');
118     my $column  = join( ',', @columns );
119         my $definitions = get_from_dictionary($area);
120     $template->param(
121         'build4' => 1,
122         'area'   => $area,
123         'type'   => $type,
124         'column' => $column,
125     );
126     my $criteria = get_criteria($area);
127     $template->param( 'criteria' => $criteria,
128         'definitions' => $definitions);
129 }
130
131 elsif ( $phase eq 'Choose these criteria' ) {
132     my $area     = $input->param('area');
133     my $type     = $input->param('type');
134     my $column   = $input->param('column');
135         my @definitions = $input->param('definition');
136         my $definition = join (',',@definitions);
137     my @criteria = $input->param('criteria_column');
138         my $query_criteria;
139     foreach my $crit (@criteria) {
140         my $value = $input->param( $crit . "_value" );
141         if ($value) {
142             $query_criteria .= " AND $crit='$value'";
143         }
144     }
145
146     $template->param(
147         'build5'         => 1,
148         'area'           => $area,
149         'type'           => $type,
150         'column'         => $column,
151                 'definition'     => $definition,
152         'criteriastring' => $query_criteria,
153     );
154
155     # get columns
156     my @columns = split( ',', $column );
157     my @total_by;
158
159     # build structue for use by tmpl_loop to choose columns to order by
160     # need to do something about the order of the order :)
161         # we also want to use the %columns hash to get the plain english names
162     foreach my $col (@columns) {
163         my %total;
164         $total{'name'} = $col;
165         my @selects;
166         my %select1;
167         $select1{'value'} = 'sum';
168         push @selects, \%select1;
169         my %select2;
170         $select2{'value'} = 'min';
171         push @selects, \%select2;
172         my %select3;
173         $select3{'value'} = 'max';
174         push @selects, \%select3;
175         my %select4;
176         $select4{'value'} = 'avg';
177         push @selects, \%select4;
178         my %select5;
179         $select5{'value'} = 'count';
180         push @selects, \%select5;
181
182         $total{'select'} = \@selects;
183         push @total_by, \%total;
184     }
185
186     $template->param( 'total_by' => \@total_by );
187 }
188
189 elsif ( $phase eq 'Choose Totals' ) {
190     my $area     = $input->param('area');
191     my $type     = $input->param('type');
192     my $column   = $input->param('column');
193     my $criteria = $input->param('criteria');
194         my $definition = $input->param('definition');
195     my @total_by = $input->param('total_by');
196     my $totals;
197     foreach my $total (@total_by) {
198         my $value = $input->param( $total . "_tvalue" );
199         $totals .= "$value($total),";
200     }
201
202     $template->param(
203         'build6'         => 1,
204         'area'           => $area,
205         'type'           => $type,
206         'column'         => $column,
207         'criteriastring' => $criteria,
208         'totals'         => $totals,
209                 'definition'    => $definition,
210     );
211
212     # get columns
213     my @columns = split( ',', $column );
214     my @order_by;
215
216     # build structue for use by tmpl_loop to choose columns to order by
217     # need to do something about the order of the order :)
218     foreach my $col (@columns) {
219         my %order;
220         $order{'name'} = $col;
221         my @selects;
222         my %select1;
223         $select1{'value'} = 'asc';
224         push @selects, \%select1;
225         my %select2;
226         $select2{'value'} = 'desc';
227         push @selects, \%select2;
228         $order{'select'} = \@selects;
229         push @order_by, \%order;
230     }
231
232     $template->param( 'order_by' => \@order_by );
233 }
234
235 elsif ( $phase eq 'Build Report' ) {
236
237     # now we have all the info we need and can build the sql
238     my $area     = $input->param('area');
239     my $type     = $input->param('type');
240     my $column   = $input->param('column');
241     my $crit     = $input->param('criteria');
242     my $totals   = $input->param('totals');
243         my $definition = $input->param('definition');
244 #    my @criteria = split( ',', $crit );
245     my $query_criteria=$crit;
246     # split the columns up by ,
247     my @columns = split( ',', $column );
248     my @order_by = $input->param('order_by');
249
250     my $query_orderby;
251     foreach my $order (@order_by) {
252         my $value = $input->param( $order . "_ovalue" );
253         if ($query_orderby) {
254             $query_orderby .= ",$order $value";
255         }
256         else {
257             $query_orderby = " ORDER BY $order $value";
258         }
259     }
260
261     # get the sql
262     my $sql =
263       build_query( \@columns, $query_criteria, $query_orderby, $area, $totals, $definition );
264     $template->param(
265         'showreport' => 1,
266         'sql'        => $sql,
267         'type'       => $type
268     );
269 }
270
271 elsif ( $phase eq 'Save' ) {
272         # Save the report that has just been built
273     my $sql  = $input->param('sql');
274     my $type = $input->param('type');
275     $template->param(
276         'save' => 1,
277         'sql'  => $sql,
278         'type' => $type
279     );
280 }
281
282 elsif ( $phase eq 'Save Report' ) {
283     # save the sql pasted in by a user 
284     my $sql  = $input->param('sql');
285     my $name = $input->param('reportname');
286     my $type = $input->param('type');
287         my $notes = $input->param('notes');
288     save_report( $sql, $name, $type, $notes );
289 }
290
291 elsif ( $phase eq 'Execute' ) {
292         # run the sql, and output results in a template 
293     my $sql     = $input->param('sql');
294     my $type    = $input->param('type');
295     my $results = execute_query($sql,$type);
296     $template->param(
297         'results' => $results,
298                 'sql' => $sql,
299         'execute' => 1
300     );
301 }
302
303 elsif ($phase eq 'Run this report'){
304     # execute a saved report
305         my $report = $input->param('reports');
306         my ($sql,$type) = get_saved_report($report);
307         my $results = execute_query($sql,$type);
308     $template->param(
309         'results' => $results,
310                 'sql' => $sql,
311         'execute' => 1
312     );
313 }       
314
315 elsif ($phase eq 'Export'){
316         # export results to tab separated text
317         my $sql     = $input->param('sql');
318         $no_html=1;
319         print $input->header(   -type => 'application/octet-stream',
320                   -attachment=>'reportresults.csv');
321         my $format=$input->param('format');
322         my $results = execute_query($sql,1,$format);
323         print $results;
324         
325 }
326
327 elsif ($phase eq 'Create report from SQL'){
328         # alllow the user to paste in sql 
329         $template->param('create' => 1);
330          my $types = C4::Reports::get_report_types();
331         $template->param( 'types' => $types ); 
332 }
333
334 elsif ($phase eq 'Create Compound Report'){
335         my $reports = get_saved_reports();  
336         $template->param( 'savedreports' => $reports,
337                 'compound' => 1,
338         );
339 }
340
341 elsif ($phase eq 'Save Compound'){
342     my $master = $input->param('master');
343         my $subreport = $input->param('subreport');
344 #       my $compound_report = create_compound($master,$subreport);
345 #       my $results = run_compound($compound_report);
346         my ($mastertables,$subtables) = create_compound($master,$subreport);
347         $template->param( 'save_compound' => 1,
348                 master=>$mastertables,
349                 subsql=>$subtables
350         );
351 }
352
353 elsif ($phase eq 'View Dictionary'){
354         # view the dictionary we use to set up abstract variables such as all borrowers over fifty who live in a certain town
355         ( $template, $borrowernumber, $cookie ) = get_template_and_user(
356     {
357         template_name   => "reports/dictionary.tmpl",
358         query           => $input,
359         type            => "intranet",
360         authnotrequired => 0,
361         flagsrequired   => { editcatalogue => 1 },
362         debug           => 1,
363     }
364         );
365         my $areas = C4::Reports::get_report_areas();
366         my $definitions = get_from_dictionary();
367         $template->param( 'areas' => $areas ,
368                 'start_dictionary' => 1,
369                 'definitions' => $definitions,
370         );
371 }
372 elsif ($phase eq 'Add New Definition'){
373         # display form allowing them to add a new definition
374         ( $template, $borrowernumber, $cookie ) = get_template_and_user(
375     {
376         template_name   => "reports/dictionary.tmpl",
377         query           => $input,
378         type            => "intranet",
379         authnotrequired => 0,
380         flagsrequired   => { editcatalogue => 1 },
381         debug           => 1,
382     }
383         );
384
385         $template->param( 'new_dictionary' => 1,
386                 );
387 }
388
389 elsif ($phase eq 'New Term step 2'){
390         # Choosing the area
391         ( $template, $borrowernumber, $cookie ) = get_template_and_user(
392     {
393         template_name   => "reports/dictionary.tmpl",
394         query           => $input,
395         type            => "intranet",
396         authnotrequired => 0,
397         flagsrequired   => { editcatalogue => 1 },
398         debug           => 1,
399     }
400         );
401         my $areas = C4::Reports::get_report_areas();
402         my $definition_name=$input->param('definition_name');
403         my $definition_description=$input->param('definition_description');             
404         $template->param( 'step_2' => 1,
405                 'areas' => $areas,
406                 'definition_name' => $definition_name,
407                 'definition_description' => $definition_description,
408         );
409 }
410
411 elsif ($phase eq 'New Term step 3'){
412         # Choosing the columns
413         ( $template, $borrowernumber, $cookie ) = get_template_and_user(
414     {
415         template_name   => "reports/dictionary.tmpl",
416         query           => $input,
417         type            => "intranet",
418         authnotrequired => 0,
419         flagsrequired   => { editcatalogue => 1 },
420         debug           => 1,
421     }
422         );
423         my $area = $input->param('areas');
424         my $columns = get_columns($area);
425         my $definition_name=$input->param('definition_name');
426         my $definition_description=$input->param('definition_description');             
427         $template->param( 'step_3' => 1,
428                 'area' => $area,
429                 'columns' => $columns,
430                 'definition_name' => $definition_name,
431                 'definition_description' => $definition_description,
432         );
433 }
434
435 elsif ($phase eq 'New Term step 4'){
436         # Choosing the values
437         ( $template, $borrowernumber, $cookie ) = get_template_and_user(
438     {
439         template_name   => "reports/dictionary.tmpl",
440         query           => $input,
441         type            => "intranet",
442         authnotrequired => 0,
443         flagsrequired   => { editcatalogue => 1 },
444         debug           => 1,
445     }
446         );
447         my $area=$input->param('area');
448         my $definition_name=$input->param('definition_name');
449         my $definition_description=$input->param('definition_description');             
450     my @columns = $input->param('columns');
451         my $columnstring = join (',',@columns);
452         my @column_loop;
453         foreach my $column (@columns){
454                 my %tmp_hash;
455                 $tmp_hash{'name'}=$column;
456                 my $type =get_column_type($column);
457                 if ($type eq 'distinct'){
458                         my $values = get_distinct_values($column);
459                         $tmp_hash{'values'} = $values;
460                         $tmp_hash{'distinct'} = 1;
461                           
462                 }
463                 if ($type eq 'DATE'){
464                         $tmp_hash{'date'}=1;
465                 }
466                 if ($type eq 'TEXT'){
467                         $tmp_hash{'text'}=1;
468                 }
469 #               else {
470 #                       warn $type;#
471 #                       }
472                 push @column_loop,\%tmp_hash;
473                 }
474
475         $template->param( 'step_4' => 1,
476                 'area' => $area,
477                 'definition_name' => $definition_name,
478                 'definition_description' => $definition_description,
479                 'columns' => \@column_loop,
480                 'columnstring' => $columnstring,
481
482         );
483 }
484
485 elsif ($phase eq 'New Term step 5'){
486         # Confirmation screen
487         ( $template, $borrowernumber, $cookie ) = get_template_and_user(
488     {
489         template_name   => "reports/dictionary.tmpl",
490         query           => $input,
491         type            => "intranet",
492         authnotrequired => 0,
493         flagsrequired   => { editcatalogue => 1 },
494         debug           => 1,
495     }
496         );
497         my $area = $input->param('area');
498         my $columnstring = $input->param('columnstring');
499         my $definition_name=$input->param('definition_name');
500         my $definition_description=$input->param('definition_description');     
501         my @criteria = $input->param('criteria_column'); 
502         my $query_criteria;
503         my @criteria_loop;
504         foreach my $crit (@criteria) {
505                 my $value = $input->param( $crit . "_value" );
506                 if ($value) {
507                         $query_criteria .= " AND $crit='$value'";
508                         my %tmp_hash;
509                         $tmp_hash{'name'}=$crit;
510                         $tmp_hash{'value'} = $value;
511                         push @criteria_loop,\%tmp_hash;
512                 }
513                 
514                 $value = $input->param( $crit . "_start_value" );
515                 if ($value) {
516                         $query_criteria .= " AND $crit > '$value'";
517                         my %tmp_hash;
518                         $tmp_hash{'name'}="$crit Start";
519                         $tmp_hash{'value'} = $value;
520                         push @criteria_loop,\%tmp_hash;
521                 }
522                 $value = $input->param( $crit . "_end_value" );
523                 if ($value) {
524                         $query_criteria .= " AND $crit <= '$value'";
525                         my %tmp_hash;
526                         $tmp_hash{'name'}="$crit End";
527                         $tmp_hash{'value'} = $value;
528                         push @criteria_loop,\%tmp_hash;
529                 }                 
530         }
531         $template->param( 'step_5' => 1,
532                 'area' => $area,
533                 'definition_name' => $definition_name,
534                 'definition_description' => $definition_description,
535                 'query' => $query_criteria,
536                 'columnstring' => $columnstring,
537                 'criteria_loop' => \@criteria_loop,
538         );
539 }
540
541 elsif ($phase eq 'New Term step 6'){
542         # Saving
543         my $area = $input->param('area');
544         my $definition_name=$input->param('definition_name');
545         my $definition_description=$input->param('definition_description');             
546         my $sql=$input->param('sql');
547         save_dictionary($definition_name,$definition_description,$sql,$area);
548         $no_html=1;
549         print $input->redirect("/cgi-bin/koha/reports/guided_reports.pl?phase=View%20Dictionary");      
550
551 }
552 elsif ($phase eq 'Delete Definition'){
553         $no_html=1;
554         my $id = $input->param('id');
555         delete_definition($id);
556         print $input->redirect("/cgi-bin/koha/reports/guided_reports.pl?phase=View%20Dictionary");
557         }
558
559 $template->param( 'referer' => $referer );
560
561
562 if (!$no_html){
563         output_html_with_http_headers $input, $cookie, $template->output;
564 }