1 package SL::Controller::Helper::ReportGenerator;
6 use List::Util qw(max);
7 use Scalar::Util qw(blessed);
11 use SL::ReportGenerator;
13 use Exporter 'import';
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
22 sub _setup_action_bar {
23 my ($self, $type) = @_;
25 my $key = $::form->{CONTROLLER_DISPATCH} ? 'action' : 'report_generator_form.report_generator_dispatch_to';
26 my $value = $::form->{CONTROLLER_DISPATCH} ? $::form->{CONTROLLER_DISPATCH} . "/" : '';
28 for my $bar ($::request->layout->get('actionbar')) {
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}" } ],
35 $::locale->text('Back'),
36 submit => [ '#report_generator_form', { $key => "${value}report_generator_back" } ],
42 sub action_report_generator_export_as_pdf {
45 delete $::form->{action_report_generator_export_as_pdf};
47 if ($::form->{report_generator_pdf_options_set}) {
48 my $saved_form = save_form();
50 $self->report_generator_do('PDF');
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');
61 my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form });
63 $::form->get_lists('printers' => 'ALL_PRINTERS');
64 map { $_->{selected} = $::myconfig{default_printer_id} == $_->{id} } @{ $::form->{ALL_PRINTERS} };
66 $::form->{copies} = max $::myconfig{copies} * 1, 1;
67 $::form->{title} = $::locale->text('PDF export -- options');
69 _setup_action_bar($self, 'pdf'); # Sub not exported, therefore don't call via object.
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, });
77 sub action_report_generator_export_as_csv {
80 delete $::form->{action_report_generator_export_as_csv};
82 if ($::form->{report_generator_csv_options_set}) {
83 $self->report_generator_do('CSV');
87 my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form });
89 $::form->{title} = $::locale->text('CSV export -- options');
91 _setup_action_bar($self, 'csv'); # Sub not exported, therefore don't call via object.
94 print $::form->parse_html_template('report_generator/csv_export_options', { 'HIDDEN' => \@form_values });
97 sub action_report_generator_export_as_chart {
100 delete $::form->{action_report_generator_export_as_chart};
102 if ($::form->{report_generator_chart_options_set}) {
103 $self->report_generator_do('Chart');
107 my $fields = delete $::form->{report_generator_chart_fields};
108 my @form_values = $::form->flatten_variables(grep { ($_ ne 'login') && ($_ ne 'password') } keys %{ $::form });
110 $::form->{title} = $::locale->text('Chart export -- options');
112 _setup_action_bar($self, 'chart'); # Sub not exported, therefore don't call via object.
115 print $::form->parse_html_template('report_generator/chart_export_options', { 'HIDDEN' => \@form_values, fields => $fields });
118 sub action_report_generator_back {
119 $_[0]->report_generator_do('HTML');
122 sub report_generator_do {
123 my ($self, $format) = @_;
125 my $nextsub = $::form->{report_generator_nextsub};
127 $::form->error($::locale->text('report_generator_nextsub is not defined.'));
130 foreach my $key (split m/ +/, $::form->{report_generator_variable_list}) {
131 $::form->{$key} = $::form->{"report_generator_hidden_${key}"};
134 $::form->{report_generator_output_format} = $format;
136 delete @{$::form}{map { "report_generator_$_" } qw(nextsub variable_list)};
138 $self->_run_action($nextsub);
141 sub report_generator_list_objects {
142 my ($self, %params) = @_;
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;
149 my $column_defs = $params{report}->{columns};
150 my @columns = $params{report}->get_visible_columns('HTML');
152 for my $obj (@{ $params{objects} || [] }) {
155 if (blessed($obj) && $obj->isa('SL::Controller::Helper::ReportGenerator::ControlRow::Base')) {
156 $obj->set_data($params{report});
161 my $def = $column_defs->{$_};
163 $tmp->{raw_data} = $def->{raw_data} ? $def->{raw_data}->($obj) : '';
164 $tmp->{data} = $def->{sub} ? $def->{sub}->($obj)
165 : $obj->can($_) ? $obj->$_
167 $tmp->{link} = $def->{obj_link} ? $def->{obj_link}->($obj) : '';
172 $params{data_callback}->(\%data) if $params{data_callback};
174 $params{report}->add_data(\%data);
177 my %options = %{ $params{options} || {} };
178 $options{action_bar} //= $params{action_bar} // 1;
180 if ($params{layout}) {
181 return $params{report}->generate_with_headers(%options);
183 my $html = $params{report}->generate_html_content(action_bar => 0, %options);
184 $self->render(\$html , { layout => 0, process => 0 });
197 SL::Controller::Helper::ReportGenerator - Mixin for controllers that
198 use the L<SL::ReportGenerator> class
202 package SL::Controller::Unicorn;
204 use SL::Controller::Helper::ReportGenerator;
209 # Set up the report generator instance. In this example this is
210 # hidden in "prepare_report".
211 my $report = $self->prepare_report;
213 # Get objects from database.
214 my $orders = SL::DB::Manager::Order->get_all(...);
216 # Let report generator create the output.
217 $self->report_generator_list_objects(
227 =item C<action_report_generator_back>
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'
233 It is never called from a controller manually and should just work
236 =item C<action_report_generator_export_as_csv>
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
243 It is never called from a controller manually and should just work
246 =item C<action_report_generator_export_as_pdf>
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
253 It is never called from a controller manually and should just work
256 =item C<report_generator_do>
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.
264 It is never called from a controller manually and should just work
267 =item C<report_generator_list_objects %params>
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
273 C<%params> can contain the following values:
279 Mandatory. An instance of L<SL::ReportGenerator> that has been set up
280 already (column definitions, title, sort handling etc).
284 Mandatory. An array reference of RDBO models to output.
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>.
291 L<SL::Controller::Helper::ReportGenerator::ControlRow>
292 L<SL::Controller::Helper::ReportGenerator::ControlRow::*>
294 =item C<data_callback>
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>.
304 An optional hash reference that's passed verbatim to the function
305 L<SL::ReportGenerator/generate_with_headers>.
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.
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')>.
326 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>