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