]> wagnertech.de Git - mfinanz.git/blob - SL/Controller/Helper/ReportGenerator.pm
Merge branch 'master' of http://wagnertech.de/git/mfinanz
[mfinanz.git] / SL / Controller / Helper / ReportGenerator.pm
1 package SL::Controller::Helper::ReportGenerator;
2
3 use strict;
4
5 use Carp;
6 use List::Util qw(max);
7 use Scalar::Util qw(blessed);
8
9 use SL::Common;
10 use SL::MoreCommon;
11 use SL::ReportGenerator;
12
13 use Exporter 'import';
14 our @EXPORT = qw(
15   action_report_generator_export_as_pdf
16   action_report_generator_export_as_csv
17   action_report_generator_export_as_chart
18   action_report_generator_back report_generator_do
19   report_generator_list_objects
20 );
21
22 sub _setup_action_bar {
23   my ($self, $type) = @_;
24
25   my $key   = $::form->{CONTROLLER_DISPATCH} ? 'action'                             : 'report_generator_form.report_generator_dispatch_to';
26   my $value = $::form->{CONTROLLER_DISPATCH} ? $::form->{CONTROLLER_DISPATCH} . "/" : '';
27
28   for my $bar ($::request->layout->get('actionbar')) {
29     $bar->add(
30       action => [
31         $type eq 'pdf' ? $::locale->text('PDF export') : $type eq 'csv' ? $::locale->text('CSV export') : $::locale->text('Chart export'),
32         submit => [ '#report_generator_form', { $key => "${value}report_generator_export_as_${type}" } ],
33       ],
34       action => [
35         $::locale->text('Back'),
36         submit => [ '#report_generator_form', { $key => "${value}report_generator_back" } ],
37       ],
38     );
39   }
40 }
41
42 sub action_report_generator_export_as_pdf {
43   my ($self) = @_;
44
45   delete $::form->{action_report_generator_export_as_pdf};
46
47   if ($::form->{report_generator_pdf_options_set}) {
48     my $saved_form = save_form();
49
50     $self->report_generator_do('PDF');
51
52     if ($::form->{report_generator_printed}) {
53       restore_form($saved_form);
54       $::form->{MESSAGE} = $::locale->text('The list has been printed.');
55       $self->report_generator_do('HTML');
56     }
57
58     return;
59   }
60
61   my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form });
62
63   $::form->get_lists('printers' => 'ALL_PRINTERS');
64   map { $_->{selected} = $::myconfig{default_printer_id} == $_->{id} } @{ $::form->{ALL_PRINTERS} };
65
66   $::form->{copies} = max $::myconfig{copies} * 1, 1;
67   $::form->{title} = $::locale->text('PDF export -- options');
68
69   _setup_action_bar($self, 'pdf'); # Sub not exported, therefore don't call via object.
70
71   $::form->header;
72   print $::form->parse_html_template('report_generator/pdf_export_options', {
73     'HIDDEN'               => \@form_values,
74     'ALLOW_FONT_SELECTION' => SL::ReportGenerator->check_for_pdf_api, });
75 }
76
77 sub action_report_generator_export_as_csv {
78   my ($self) = @_;
79
80   delete $::form->{action_report_generator_export_as_csv};
81
82   if ($::form->{report_generator_csv_options_set}) {
83     $self->report_generator_do('CSV');
84     return;
85   }
86
87   my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form });
88
89   $::form->{title} = $::locale->text('CSV export -- options');
90
91   _setup_action_bar($self, 'csv'); # Sub not exported, therefore don't call via object.
92
93   $::form->header;
94   print $::form->parse_html_template('report_generator/csv_export_options', { 'HIDDEN' => \@form_values });
95 }
96
97 sub action_report_generator_export_as_chart {
98   my ($self) = @_;
99
100   delete $::form->{action_report_generator_export_as_chart};
101
102   if ($::form->{report_generator_chart_options_set}) {
103     $self->report_generator_do('Chart');
104     return;
105   }
106
107   my $fields      = delete $::form->{report_generator_chart_fields};
108   my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form });
109
110   $::form->{title} = $::locale->text('Chart export -- options');
111
112   _setup_action_bar($self, 'chart'); # Sub not exported, therefore don't call via object.
113
114   $::form->header;
115   print $::form->parse_html_template('report_generator/chart_export_options', { 'HIDDEN' => \@form_values, fields => $fields });
116 }
117
118 sub action_report_generator_back {
119   $_[0]->report_generator_do('HTML');
120 }
121
122 sub report_generator_do {
123   my ($self, $format)  = @_;
124
125   my $nextsub = $::form->{report_generator_nextsub};
126   if (!$nextsub) {
127     $::form->error($::locale->text('report_generator_nextsub is not defined.'));
128   }
129
130   foreach my $key (split m/ +/, $::form->{report_generator_variable_list}) {
131     $::form->{$key} = $::form->{"report_generator_hidden_${key}"};
132   }
133
134   $::form->{report_generator_output_format} = $format;
135
136   delete @{$::form}{map { "report_generator_$_" } qw(nextsub variable_list)};
137
138   $self->_run_action($nextsub);
139 }
140
141 sub report_generator_list_objects {
142   my ($self, %params) = @_;
143
144   croak "Parameter 'objects' must exist and be an array reference"                if                      ref($params{objects}) ne 'ARRAY';
145   croak "Parameter 'report' must exist and be an instance of SL::ReportGenerator" if                      ref($params{report})  ne 'SL::ReportGenerator';
146   croak "Parameter 'options', if exists, must be a hash reference"                if $params{options} && (ref($params{options}) ne 'HASH');
147   $params{layout} //= 1;
148
149   my $column_defs = $params{report}->{columns};
150   my @columns     = $params{report}->get_visible_columns('HTML');
151
152   for my $obj (@{ $params{objects} || [] }) {
153     my %data;
154
155     if (blessed($obj) && $obj->isa('SL::Controller::Helper::ReportGenerator::ControlRow::Base')) {
156       $obj->set_data($params{report});
157       next;
158
159     } else {
160       %data = map {
161         my $def = $column_defs->{$_};
162         my $tmp;
163         $tmp->{raw_data} = $def->{raw_data} ? $def->{raw_data}->($obj) : '';
164         $tmp->{data}     = $def->{sub}      ? $def->{sub}->($obj)
165                          : $obj->can($_)    ? $obj->$_
166                          :                    $obj->{$_};
167         $tmp->{link}     = $def->{obj_link} ? $def->{obj_link}->($obj) : '';
168         $_ => $tmp;
169       } @columns;
170     }
171
172     $params{data_callback}->(\%data) if $params{data_callback};
173
174     $params{report}->add_data(\%data);
175   }
176
177   my %options            = %{ $params{options} || {} };
178   $options{action_bar} //= $params{action_bar} // 1;
179
180   if ($params{layout}) {
181     return $params{report}->generate_with_headers(%options);
182   } else {
183     my $html = $params{report}->generate_html_content(action_bar => 0, %options);
184     $self->render(\$html , { layout => 0, process => 0 });
185   }
186 }
187
188 1;
189 __END__
190
191 =pod
192
193 =encoding utf8
194
195 =head1 NAME
196
197 SL::Controller::Helper::ReportGenerator - Mixin for controllers that
198 use the L<SL::ReportGenerator> class
199
200 =head1 SYNOPSIS
201
202   package SL::Controller::Unicorn;
203
204   use SL::Controller::Helper::ReportGenerator;
205
206   sub action_list {
207     my ($self) = @_;
208
209     # Set up the report generator instance. In this example this is
210     # hidden in "prepare_report".
211     my $report = $self->prepare_report;
212
213     # Get objects from database.
214     my $orders = SL::DB::Manager::Order->get_all(...);
215
216     # Let report generator create the output.
217     $self->report_generator_list_objects(
218       report  => $report,
219       objects => $orders,
220     );
221   }
222
223 =head1 FUNCTIONS
224
225 =over 4
226
227 =item C<action_report_generator_back>
228
229 This is the controller action that's called from the one of the report
230 generator's 'export options' pages when the user clicks on the 'back'
231 button.
232
233 It is never called from a controller manually and should just work
234 as-is.
235
236 =item C<action_report_generator_export_as_csv>
237
238 This is the controller action that's called from the generated report
239 when the user wants to export as CSV. First the CSV export options are
240 shown and afterwards the CSV file is generated and offered for
241 download.
242
243 It is never called from a controller manually and should just work
244 as-is.
245
246 =item C<action_report_generator_export_as_pdf>
247
248 This is the controller action that's called from the generated report
249 when the user wants to export as PDF. First the PDF export options are
250 shown and afterwards the PDF file is generated and offered for
251 download.
252
253 It is never called from a controller manually and should just work
254 as-is.
255
256 =item C<report_generator_do>
257
258 This is a common function that's called from
259 L<action_report_generator_back>,
260 L<action_report_generator_export_as_csv> and
261 L<action_report_generator_export_as_pdf>. It handles common options
262 and report generation after options have been set.
263
264 It is never called from a controller manually and should just work
265 as-is.
266
267 =item C<report_generator_list_objects %params>
268
269 Iterates over all objects, creates the actual rows of data, hands them
270 over to the report generator and lets the report generator create the
271 output.
272
273 C<%params> can contain the following values:
274
275 =over 2
276
277 =item C<report>
278
279 Mandatory. An instance of L<SL::ReportGenerator> that has been set up
280 already (column definitions, title, sort handling etc).
281
282 =item C<objects>
283
284 Mandatory. An array reference of RDBO models to output.
285
286 An element of the array can also be an instance of a control row, i.e.
287 an instance of a class derived from
288 C<SL::Controller::Helper::ReportGenerator::ControlRow::Base>.
289 See also:
290
291 L<SL::Controller::Helper::ReportGenerator::ControlRow>
292 L<SL::Controller::Helper::ReportGenerator::ControlRow::*>
293
294 =item C<data_callback>
295
296 Optional. A callback handler (code reference) that gets called for
297 each row before it is passed to the report generator. The row passed
298 will be the handler's first and only argument (a hash reference). It's
299 the same hash reference that's passed to
300 L<SL::ReportGenrator/add_data>.
301
302 =item C<options>
303
304 An optional hash reference that's passed verbatim to the function
305 L<SL::ReportGenerator/generate_with_headers>.
306
307 =item C<action_bar>
308
309 If the buttons for exporting PDF and/or CSV variants are included in
310 the action bar. Otherwise they're rendered at the bottom of the page.
311
312 The value can be either a specific action bar instance or simply 1 in
313 which case the default action bar is used:
314 C<$::request-E<gt>layout-E<gt>get('actionbar')>.
315
316 =back
317
318 =back
319
320 =head1 BUGS
321
322 Nothing here yet.
323
324 =head1 AUTHOR
325
326 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
327
328 =cut