1 package SL::Controller::CustomDataExport;
6 use parent qw(SL::Controller::Base);
8 use DBI qw(:sql_types);
10 use List::UtilsBy qw(sort_by);
11 use POSIX qw(strftime);
14 use SL::DB::CustomDataExportQuery;
15 use SL::Controller::Helper::ReportGenerator;
16 use SL::Locale::String qw(t8);
18 use Rose::Object::MakeMethods::Generic
20 scalar => [ qw(rows) ],
21 'scalar --get_set_init' => [ qw(query queries parameters) ],
24 __PACKAGE__->run_before('check_auth');
25 __PACKAGE__->run_before('setup_javascripts');
34 $self->render('custom_data_export/list', title => $::locale->text('Execute a custom report query'));
40 if (!$::form->{parameters_set}) {
41 $self->setup_export_action_bar;
42 return $self->render('custom_data_export/export', title => t8("Execute custom report '#1'", $self->query->name));
47 if (scalar(@{ $self->rows // [] }) == 1) {
48 $self->setup_empty_result_set_action_bar;
49 return $self->render('custom_data_export/empty_result_set', title => t8("Execute custom report '#1'", $self->query->name));
52 my $report = SL::ReportGenerator->new(\%::myconfig, $::form);
54 my $report_name = $self->query->name;
55 $report_name =~ s{[^[:word:]]+}{_}ig;
56 $report_name .= strftime('_%Y-%m-%d_%H-%M-%S', localtime());
59 std_column_visibility => 1,
60 controller_class => 'CustomDataExport',
61 output_format => 'HTML',
62 top_info_text => $self->query->name,
63 title => $self->query->name,
64 allow_pdf_export => 1,
65 allow_csv_export => 1,
66 allow_chart_export => 1,
67 attachment_basename => $report_name,
71 foreach my $key (@{ $self->rows->[0] }) {
72 $column_defs{$key} = { text => $key, sub => sub { $_[0]->{$key} } };
75 $report->set_columns(%column_defs);
76 $report->set_column_order(@{ $self->rows->[0] });
78 $report->set_export_options(qw(export id parameters_set parameters));
79 $report->set_options_from_form;
81 # Setup data objects (which in this case is an array of hashes).
83 foreach my $set_idx (1..$#{ $self->rows }) {
85 foreach my $key_idx (0..$#{ $self->rows->[0] }) {
86 my $key = $self->rows->[0]->[$key_idx];
87 my $value = $self->rows->[$set_idx]->[$key_idx];
88 $row_set{$key} = $value;
90 push @objects, \%row_set;
93 $self->report_generator_list_objects(report => $report,
96 action_bar_additional_submit_values => { id => $::form->{id}, },
107 $::auth->assert('custom_data_report');
108 $::auth->assert($self->query->access_right) if $self->query->access_right;
111 sub setup_javascripts {
112 $::request->layout->add_javascripts('kivi.Validator.js');
119 sub init_query { $::form->{id} ? SL::DB::CustomDataExportQuery->new(id => $::form->{id})->load : SL::DB::CustomDataExportQuery->new }
120 sub init_parameters { [ sort_by { lc $_->name } @{ $_[0]->query->parameters // [] } ] }
123 my %rights_map = %{ $::auth->load_rights_for_user($::form->{login}) };
124 my @granted_rights = grep { $rights_map{$_} } keys %rights_map;
126 return scalar SL::DB::Manager::CustomDataExportQuery->get_all_sorted(
129 access_right => undef,
131 (access_right => \@granted_rights) x !!@granted_rights,
137 sub setup_export_action_bar {
140 for my $bar ($::request->layout->get('actionbar')) {
144 submit => [ '#form', { action => 'CustomDataExport/export' } ],
145 checks => [ 'kivi.validate_form' ],
146 accesskey => 'enter',
150 call => [ 'kivi.history_back' ],
156 sub setup_empty_result_set_action_bar {
159 for my $bar ($::request->layout->get('actionbar')) {
163 call => [ 'kivi.history_back' ],
172 my $sql_query = $self->query->sql_query;
177 foreach my $parameter (@{ $self->query->parameters // [] }) {
178 my $value = ($::form->{parameters} // {})->{ $parameter->name };
179 $values_by_name{ $parameter->name } = $parameter->parameter_type eq 'number' ? $::form->parse_amount(\%::myconfig, $value) : $value;
182 while ($sql_query =~ m{<\%(.+?)\%>}) {
183 push @values, $values_by_name{$1};
184 substr($sql_query, $-[0], $+[0] - $-[0], '?');
187 return ($sql_query, @values);
193 my ($sql_query, @values) = $self->prepare_query;
194 my $sth = $self->query->db->dbh->prepare($sql_query) || $::form->dberror;
195 $sth->execute(@values) || $::form->dberror;
197 my @names = @{ $sth->{NAME} };
198 my @types = @{ $sth->{TYPE} };
199 my @data = @{ $sth->fetchall_arrayref };
203 foreach my $row (@data) {
204 foreach my $col (0..$#types) {
205 my $type = $types[$col];
207 if ($type == SQL_NUMERIC) {
208 $row->[$col] = $::form->format_amount(\%::myconfig, $row->[$col]);