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::Locale::String qw(t8);
 
  17 use Rose::Object::MakeMethods::Generic
 
  19   scalar                  => [ qw(rows) ],
 
  20   'scalar --get_set_init' => [ qw(query queries parameters) ],
 
  23 __PACKAGE__->run_before('check_auth');
 
  24 __PACKAGE__->run_before('setup_javascripts');
 
  33   $self->render('custom_data_export/list', title => $::locale->text('Execute a custom data export query'));
 
  39   if (!$::form->{format}) {
 
  40     $self->setup_export_action_bar;
 
  41     return $self->render('custom_data_export/export', title => t8("Execute custom data export '#1'", $self->query->name));
 
  46   if (scalar(@{ $self->rows // [] }) == 1) {
 
  47     $self->setup_empty_result_set_action_bar;
 
  48     return $self->render('custom_data_export/empty_result_set', title => t8("Execute custom data export '#1'", $self->query->name));
 
  52   my $method = "export_as_" . $::form->{format};
 
  62   $::auth->assert($self->query->access_right) if $self->query->access_right;
 
  65 sub setup_javascripts {
 
  66   $::request->layout->add_javascripts('kivi.Validator.js');
 
  73 sub init_query      { $::form->{id} ? SL::DB::CustomDataExportQuery->new(id => $::form->{id})->load : SL::DB::CustomDataExportQuery->new }
 
  74 sub init_parameters { [ sort_by { lc $_->name } @{ $_[0]->query->parameters // [] } ] }
 
  77   my %rights_map     = %{ $::auth->load_rights_for_user($::form->{login}) };
 
  78   my @granted_rights = grep { $rights_map{$_} } keys %rights_map;
 
  80   return scalar SL::DB::Manager::CustomDataExportQuery->get_all_sorted(
 
  83         access_right => undef,
 
  85         (access_right => \@granted_rights) x !!@granted_rights,
 
  91 sub setup_export_action_bar {
 
  94   for my $bar ($::request->layout->get('actionbar')) {
 
  98         submit    => [ '#form', { action => 'CustomDataExport/export' } ],
 
  99         checks    => [ 'kivi.validate_form' ],
 
 100         accesskey => 'enter',
 
 104         call => [ 'kivi.history_back' ],
 
 110 sub setup_empty_result_set_action_bar {
 
 113   for my $bar ($::request->layout->get('actionbar')) {
 
 117         call => [ 'kivi.history_back' ],
 
 126   my $sql_query = $self->query->sql_query;
 
 131   foreach my $parameter (@{ $self->query->parameters // [] }) {
 
 132     my $value                           = ($::form->{parameters} // {})->{ $parameter->name };
 
 133     $values_by_name{ $parameter->name } = $parameter->parameter_type eq 'number' ? $::form->parse_amount(\%::myconfig, $value) : $value;
 
 136   while ($sql_query =~ m{<\%(.+?)\%>}) {
 
 137     push @values, $values_by_name{$1};
 
 138     substr($sql_query, $-[0], $+[0] - $-[0], '?');
 
 141   return ($sql_query, @values);
 
 147   my ($sql_query, @values) = $self->prepare_query;
 
 148   my $sth                  = $self->query->db->dbh->prepare($sql_query) || $::form->dberror;
 
 149   $sth->execute(@values)                                                || $::form->dberror;
 
 151   my @names = @{ $sth->{NAME} };
 
 152   my @types = @{ $sth->{TYPE} };
 
 153   my @data  = @{ $sth->fetchall_arrayref };
 
 157   foreach my $row (@data) {
 
 158     foreach my $col (0..$#types) {
 
 159       my $type = $types[$col];
 
 161       if ($type == SQL_NUMERIC) {
 
 162         $row->[$col] = $::form->format_amount(\%::myconfig, $row->[$col]);
 
 176   my $csv = Text::CSV_XS->new({
 
 182   my ($file_handle, $file_name) = File::Temp::tempfile;
 
 184   binmode $file_handle, ":encoding(utf8)";
 
 186   $csv->print($file_handle, $_) for @{ $self->rows };
 
 190   my $report_name =  $self->query->name;
 
 191   $report_name    =~ s{[^[:word:]]+}{_}ig;
 
 192   $report_name   .=  strftime('_%Y-%m-%d_%H-%M-%S.csv', localtime());
 
 196     content_type => 'text/csv',
 
 197     name         => $report_name,