Revision e713c314
Von Moritz Bunkus vor etwa 7 Jahren hinzugefügt
SL/Controller/CustomDataExport.pm | ||
---|---|---|
1 |
package SL::Controller::CustomDataExport; |
|
2 |
|
|
3 |
use strict; |
|
4 |
use utf8; |
|
5 |
|
|
6 |
use parent qw(SL::Controller::Base); |
|
7 |
|
|
8 |
use DBI qw(:sql_types); |
|
9 |
use File::Temp (); |
|
10 |
use List::UtilsBy qw(sort_by); |
|
11 |
use POSIX qw(strftime); |
|
12 |
use Text::CSV_XS; |
|
13 |
|
|
14 |
use SL::DB::CustomDataExportQuery; |
|
15 |
use SL::Locale::String qw(t8); |
|
16 |
|
|
17 |
use Rose::Object::MakeMethods::Generic |
|
18 |
( |
|
19 |
scalar => [ qw(rows) ], |
|
20 |
'scalar --get_set_init' => [ qw(query queries parameters today) ], |
|
21 |
); |
|
22 |
|
|
23 |
__PACKAGE__->run_before('check_auth'); |
|
24 |
__PACKAGE__->run_before('setup_javascripts'); |
|
25 |
|
|
26 |
# |
|
27 |
# actions |
|
28 |
# |
|
29 |
|
|
30 |
sub action_list { |
|
31 |
my ($self) = @_; |
|
32 |
|
|
33 |
$self->render('custom_data_export/list', title => $::locale->text('Execute a custom data export query')); |
|
34 |
} |
|
35 |
|
|
36 |
sub action_export { |
|
37 |
my ($self) = @_; |
|
38 |
|
|
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)); |
|
42 |
} |
|
43 |
|
|
44 |
$self->execute_query; |
|
45 |
|
|
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)); |
|
49 |
} |
|
50 |
|
|
51 |
|
|
52 |
my $method = "export_as_" . $::form->{format}; |
|
53 |
$self->$method; |
|
54 |
} |
|
55 |
|
|
56 |
# |
|
57 |
# filters |
|
58 |
# |
|
59 |
|
|
60 |
sub check_auth { |
|
61 |
my ($self) = @_; |
|
62 |
$::auth->assert($self->query->access_right) if $self->query->access_right; |
|
63 |
} |
|
64 |
|
|
65 |
sub setup_javascripts { |
|
66 |
$::request->layout->add_javascripts('kivi.Validator.js'); |
|
67 |
} |
|
68 |
|
|
69 |
# |
|
70 |
# helpers |
|
71 |
# |
|
72 |
|
|
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 // [] } ] } |
|
75 |
sub init_today { DateTime->today_local } |
|
76 |
|
|
77 |
sub init_queries { |
|
78 |
my %rights_map = %{ $::auth->load_rights_for_user($::form->{login}) }; |
|
79 |
my @granted_rights = grep { $rights_map{$_} } keys %rights_map; |
|
80 |
|
|
81 |
return scalar SL::DB::Manager::CustomDataExportQuery->get_all_sorted( |
|
82 |
where => [ |
|
83 |
or => [ |
|
84 |
access_right => undef, |
|
85 |
access_right => '', |
|
86 |
(access_right => \@granted_rights) x !!@granted_rights, |
|
87 |
], |
|
88 |
], |
|
89 |
) |
|
90 |
} |
|
91 |
|
|
92 |
sub setup_export_action_bar { |
|
93 |
my ($self) = @_; |
|
94 |
|
|
95 |
for my $bar ($::request->layout->get('actionbar')) { |
|
96 |
$bar->add( |
|
97 |
action => [ |
|
98 |
t8('Export'), |
|
99 |
submit => [ '#form', { action => 'CustomDataExport/export' } ], |
|
100 |
checks => [ 'kivi.validate_form' ], |
|
101 |
accesskey => 'enter', |
|
102 |
], |
|
103 |
action => [ |
|
104 |
t8('Back'), |
|
105 |
call => [ 'kivi.history_back' ], |
|
106 |
], |
|
107 |
); |
|
108 |
} |
|
109 |
} |
|
110 |
|
|
111 |
sub setup_empty_result_set_action_bar { |
|
112 |
my ($self) = @_; |
|
113 |
|
|
114 |
for my $bar ($::request->layout->get('actionbar')) { |
|
115 |
$bar->add( |
|
116 |
action => [ |
|
117 |
t8('Back'), |
|
118 |
call => [ 'kivi.history_back' ], |
|
119 |
], |
|
120 |
); |
|
121 |
} |
|
122 |
} |
|
123 |
|
|
124 |
sub prepare_query { |
|
125 |
my ($self) = @_; |
|
126 |
|
|
127 |
my $sql_query = $self->query->sql_query; |
|
128 |
my @values; |
|
129 |
|
|
130 |
my %values_by_name; |
|
131 |
|
|
132 |
foreach my $parameter (@{ $self->query->parameters // [] }) { |
|
133 |
my $value = ($::form->{parameters} // {})->{ $parameter->name }; |
|
134 |
$values_by_name{ $parameter->name } = $parameter->parameter_type eq 'number' ? $::form->parse_amount(\%::myconfig, $value) : $value; |
|
135 |
} |
|
136 |
|
|
137 |
while ($sql_query =~ m{<\%(.+?)\%>}) { |
|
138 |
push @values, $values_by_name{$1}; |
|
139 |
substr($sql_query, $-[0], $+[0] - $-[0], '?'); |
|
140 |
} |
|
141 |
|
|
142 |
return ($sql_query, @values); |
|
143 |
} |
|
144 |
|
|
145 |
sub execute_query { |
|
146 |
my ($self) = @_; |
|
147 |
|
|
148 |
my ($sql_query, @values) = $self->prepare_query; |
|
149 |
my $sth = $self->query->db->dbh->prepare($sql_query) || $::form->dberror; |
|
150 |
$sth->execute(@values) || $::form->dberror; |
|
151 |
|
|
152 |
my @names = @{ $sth->{NAME} }; |
|
153 |
my @types = @{ $sth->{TYPE} }; |
|
154 |
my @data = @{ $sth->fetchall_arrayref }; |
|
155 |
|
|
156 |
$sth->finish; |
|
157 |
|
|
158 |
foreach my $row (@data) { |
|
159 |
foreach my $col (0..$#types) { |
|
160 |
my $type = $types[$col]; |
|
161 |
|
|
162 |
if ($type == SQL_NUMERIC) { |
|
163 |
$row->[$col] = $::form->format_amount(\%::myconfig, $row->[$col]); |
|
164 |
} |
|
165 |
} |
|
166 |
} |
|
167 |
|
|
168 |
$self->rows([ |
|
169 |
\@names, |
|
170 |
@data, |
|
171 |
]); |
|
172 |
} |
|
173 |
|
|
174 |
sub export_as_csv { |
|
175 |
my ($self) = @_; |
|
176 |
|
|
177 |
my $csv = Text::CSV_XS->new({ |
|
178 |
binary => 1, |
|
179 |
sep_char => ';', |
|
180 |
eol => "\n", |
|
181 |
}); |
|
182 |
|
|
183 |
my ($file_handle, $file_name) = File::Temp::tempfile; |
|
184 |
|
|
185 |
binmode $file_handle, ":encoding(utf8)"; |
|
186 |
|
|
187 |
$csv->print($file_handle, $_) for @{ $self->rows }; |
|
188 |
|
|
189 |
$file_handle->close; |
|
190 |
|
|
191 |
my $report_name = $self->query->name; |
|
192 |
$report_name =~ s{[^[:word:]]+}{_}ig; |
|
193 |
$report_name .= strftime('_%Y-%m-%d_%H-%M-%S.csv', localtime()); |
|
194 |
|
|
195 |
$self->send_file( |
|
196 |
$file_name, |
|
197 |
content_type => 'text/csv', |
|
198 |
name => $report_name, |
|
199 |
); |
|
200 |
} |
|
201 |
|
|
202 |
1; |
SL/Controller/CustomDataExportDesigner.pm | ||
---|---|---|
1 |
package SL::Controller::CustomDataExportDesigner; |
|
2 |
|
|
3 |
use strict; |
|
4 |
use utf8; |
|
5 |
|
|
6 |
use parent qw(SL::Controller::Base); |
|
7 |
|
|
8 |
use List::UtilsBy qw(sort_by); |
|
9 |
|
|
10 |
use SL::DB::CustomDataExportQuery; |
|
11 |
use SL::Helper::Flash qw(flash_later); |
|
12 |
use SL::Locale::String qw(t8); |
|
13 |
|
|
14 |
use Rose::Object::MakeMethods::Generic |
|
15 |
( |
|
16 |
'scalar --get_set_init' => [ qw(query queries access_rights) ], |
|
17 |
); |
|
18 |
|
|
19 |
__PACKAGE__->run_before('check_auth'); |
|
20 |
__PACKAGE__->run_before('setup_javascripts'); |
|
21 |
|
|
22 |
# |
|
23 |
# actions |
|
24 |
# |
|
25 |
|
|
26 |
sub action_list { |
|
27 |
my ($self) = @_; |
|
28 |
|
|
29 |
$self->setup_list_action_bar; |
|
30 |
$self->render('custom_data_export_designer/list', title => $::locale->text('Design custom data export queries')); |
|
31 |
} |
|
32 |
|
|
33 |
sub action_edit { |
|
34 |
my ($self) = @_; |
|
35 |
|
|
36 |
my $title = $self->query->id ? t8('Edit custom data export query') : t8('Add custom data export query'); |
|
37 |
|
|
38 |
$self->setup_edit_action_bar; |
|
39 |
$self->render('custom_data_export_designer/edit', title => $title); |
|
40 |
} |
|
41 |
|
|
42 |
sub action_edit_parameters { |
|
43 |
my ($self) = @_; |
|
44 |
|
|
45 |
my $title = $self->query->id ? t8('Edit custom data export query') : t8('Add custom data export query'); |
|
46 |
my @parameters = $self->gather_query_data; |
|
47 |
|
|
48 |
$self->setup_edit_parameters_action_bar; |
|
49 |
$self->render('custom_data_export_designer/edit_parameters', title => $title, PARAMETERS => \@parameters); |
|
50 |
} |
|
51 |
|
|
52 |
sub action_save { |
|
53 |
my ($self) = @_; |
|
54 |
|
|
55 |
my @parameters = $self->gather_query_data; |
|
56 |
|
|
57 |
$self->query->parameters(\@parameters); |
|
58 |
|
|
59 |
$self->query->save; |
|
60 |
|
|
61 |
flash_later('info', t8('The custom data export has been saved.')); |
|
62 |
|
|
63 |
$self->redirect_to($self->url_for(action => 'list')); |
|
64 |
} |
|
65 |
|
|
66 |
sub action_delete { |
|
67 |
my ($self) = @_; |
|
68 |
|
|
69 |
$self->query->delete; |
|
70 |
|
|
71 |
flash_later('info', t8('The custom data export has been deleted.')); |
|
72 |
|
|
73 |
$self->redirect_to($self->url_for(action => 'list')); |
|
74 |
} |
|
75 |
|
|
76 |
# |
|
77 |
# filters |
|
78 |
# |
|
79 |
|
|
80 |
sub check_auth { |
|
81 |
$::auth->assert('custom_data_export_designer'); |
|
82 |
} |
|
83 |
|
|
84 |
sub setup_javascripts { |
|
85 |
$::request->layout->add_javascripts('kivi.Validator.js'); |
|
86 |
} |
|
87 |
|
|
88 |
# |
|
89 |
# helpers |
|
90 |
# |
|
91 |
|
|
92 |
sub init_query { $::form->{id} ? SL::DB::CustomDataExportQuery->new(id => $::form->{id})->load : SL::DB::CustomDataExportQuery->new } |
|
93 |
sub init_queries { scalar SL::DB::Manager::CustomDataExportQuery->get_all_sorted } |
|
94 |
|
|
95 |
sub init_access_rights { |
|
96 |
my @rights = ([ '', t8('Available to all users') ]); |
|
97 |
my $category; |
|
98 |
|
|
99 |
foreach my $right ($::auth->all_rights_full) { |
|
100 |
# name, description, category |
|
101 |
|
|
102 |
if ($right->[2]) { |
|
103 |
$category = t8($right->[1]); |
|
104 |
} elsif ($category) { |
|
105 |
push @rights, [ $right->[0], sprintf('%s → %s [%s]', $category, t8($right->[1]), $right->[0]) ]; |
|
106 |
} |
|
107 |
} |
|
108 |
|
|
109 |
return \@rights; |
|
110 |
} |
|
111 |
|
|
112 |
sub setup_list_action_bar { |
|
113 |
my ($self) = @_; |
|
114 |
|
|
115 |
for my $bar ($::request->layout->get('actionbar')) { |
|
116 |
$bar->add( |
|
117 |
link => [ |
|
118 |
t8('Add'), |
|
119 |
link => $self->url_for(action => 'edit'), |
|
120 |
accesskey => 'enter', |
|
121 |
], |
|
122 |
); |
|
123 |
} |
|
124 |
} |
|
125 |
|
|
126 |
sub setup_edit_action_bar { |
|
127 |
my ($self) = @_; |
|
128 |
|
|
129 |
for my $bar ($::request->layout->get('actionbar')) { |
|
130 |
$bar->add( |
|
131 |
action => [ |
|
132 |
t8('Continue'), |
|
133 |
submit => [ '#form', { action => 'CustomDataExportDesigner/edit_parameters' } ], |
|
134 |
checks => [ 'kivi.validate_form' ], |
|
135 |
accesskey => 'enter', |
|
136 |
], |
|
137 |
action => [ |
|
138 |
t8('Delete'), |
|
139 |
submit => [ '#form', { action => 'CustomDataExportDesigner/delete' } ], |
|
140 |
confirm => t8('Do you really want to delete this object?'), |
|
141 |
disabled => !$self->query->id ? t8('This object has not been saved yet.') |
|
142 |
: undef, |
|
143 |
], |
|
144 |
action => [ |
|
145 |
t8('Back'), |
|
146 |
call => [ 'kivi.history_back' ], |
|
147 |
], |
|
148 |
); |
|
149 |
} |
|
150 |
} |
|
151 |
|
|
152 |
sub setup_edit_parameters_action_bar { |
|
153 |
my ($self) = @_; |
|
154 |
|
|
155 |
for my $bar ($::request->layout->get('actionbar')) { |
|
156 |
$bar->add( |
|
157 |
action => [ |
|
158 |
t8('Save'), |
|
159 |
submit => [ '#form', { action => 'CustomDataExportDesigner/save' } ], |
|
160 |
checks => [ 'kivi.validate_form' ], |
|
161 |
accesskey => 'enter', |
|
162 |
], |
|
163 |
action => [ |
|
164 |
t8('Back'), |
|
165 |
call => [ 'kivi.history_back' ], |
|
166 |
], |
|
167 |
); |
|
168 |
} |
|
169 |
} |
|
170 |
|
|
171 |
sub gather_query_data { |
|
172 |
my ($self) = @_; |
|
173 |
|
|
174 |
$self->query->$_($::form->{query}->{$_}) for qw(name description sql_query access_right); |
|
175 |
return $self->gather_query_parameters; |
|
176 |
} |
|
177 |
|
|
178 |
sub gather_query_parameters { |
|
179 |
my ($self) = @_; |
|
180 |
|
|
181 |
my %used_parameter_names = map { ($_ => 1) } $self->query->used_parameter_names; |
|
182 |
my @existing_parameters = grep { $used_parameter_names{$_->name} } @{ $self->query->parameters // [] }; |
|
183 |
my %parameters_by_name = map { ($_->name => $_) } @existing_parameters; |
|
184 |
$parameters_by_name{$_} //= SL::DB::CustomDataExportQueryParameter->new(name => $_, parameter_type => 'text') for keys %used_parameter_names; |
|
185 |
|
|
186 |
foreach my $parameter_data (@{ $::form->{parameters} // [] }) { |
|
187 |
my $parameter_obj = $parameters_by_name{ $parameter_data->{name} }; |
|
188 |
next unless $parameter_obj; |
|
189 |
|
|
190 |
$parameter_obj->$_($parameter_data->{$_}) for qw(parameter_type description); |
|
191 |
} |
|
192 |
|
|
193 |
return sort_by { lc $_->name } values %parameters_by_name; |
|
194 |
} |
|
195 |
|
|
196 |
1; |
SL/DB/CustomDataExportQuery.pm | ||
---|---|---|
1 |
package SL::DB::CustomDataExportQuery; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use SL::DB::MetaSetup::CustomDataExportQuery; |
|
6 |
use SL::DB::Manager::CustomDataExportQuery; |
|
7 |
|
|
8 |
__PACKAGE__->meta->add_relationship( |
|
9 |
parameters => { |
|
10 |
type => 'one to many', |
|
11 |
class => 'SL::DB::CustomDataExportQueryParameter', |
|
12 |
column_map => { id => 'query_id' }, |
|
13 |
}, |
|
14 |
); |
|
15 |
|
|
16 |
__PACKAGE__->meta->initialize; |
|
17 |
|
|
18 |
sub used_parameter_names { |
|
19 |
my ($self) = @_; |
|
20 |
|
|
21 |
my %parameters; |
|
22 |
|
|
23 |
my $sql_query = $self->sql_query // ''; |
|
24 |
$parameters{$1} = 1 while $sql_query =~ m{<\%(.+?)\%>}g; |
|
25 |
|
|
26 |
return sort keys %parameters; |
|
27 |
} |
|
28 |
|
|
29 |
1; |
SL/DB/CustomDataExportQueryParameter.pm | ||
---|---|---|
1 |
# This file has been auto-generated only because it didn't exist. |
|
2 |
# Feel free to modify it at will; it will not be overwritten automatically. |
|
3 |
|
|
4 |
package SL::DB::CustomDataExportQueryParameter; |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use SL::DB::MetaSetup::CustomDataExportQueryParameter; |
|
9 |
use SL::DB::Manager::CustomDataExportQueryParameter; |
|
10 |
|
|
11 |
__PACKAGE__->meta->initialize; |
|
12 |
|
|
13 |
1; |
SL/DB/Helper/ALL.pm | ||
---|---|---|
32 | 32 |
use SL::DB::CsvImportReportRow; |
33 | 33 |
use SL::DB::CsvImportReportStatus; |
34 | 34 |
use SL::DB::Currency; |
35 |
use SL::DB::CustomDataExportQuery; |
|
36 |
use SL::DB::CustomDataExportQueryParameter; |
|
35 | 37 |
use SL::DB::CustomVariable; |
36 | 38 |
use SL::DB::CustomVariableConfig; |
37 | 39 |
use SL::DB::CustomVariableConfigPartsgroup; |
SL/DB/Helper/Mappings.pm | ||
---|---|---|
117 | 117 |
csv_import_report_rows => 'csv_import_report_row', |
118 | 118 |
csv_import_report_status => 'csv_import_report_status', |
119 | 119 |
currencies => 'currency', |
120 |
custom_data_export_queries => 'CustomDataExportQuery', |
|
121 |
custom_data_export_query_parameters => 'CustomDataExportQueryParameter', |
|
120 | 122 |
custom_variable_config_partsgroups => 'custom_variable_config_partsgroup', |
121 | 123 |
custom_variable_configs => 'custom_variable_config', |
122 | 124 |
custom_variables => 'custom_variable', |
SL/DB/Manager/CustomDataExportQuery.pm | ||
---|---|---|
1 |
package SL::DB::Manager::CustomDataExportQuery; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::DB::Helper::Manager); |
|
6 |
|
|
7 |
use SL::DB::Helper::Sorted; |
|
8 |
|
|
9 |
sub object_class { 'SL::DB::CustomDataExportQuery' } |
|
10 |
|
|
11 |
__PACKAGE__->make_manager_methods; |
|
12 |
|
|
13 |
sub _sort_spec { |
|
14 |
return ( default => [ 'name', 1 ], |
|
15 |
name => 'lower(custom_data_export_queries.name)', |
|
16 |
columns => { SIMPLE => 'ALL' }); |
|
17 |
} |
|
18 |
|
|
19 |
1; |
SL/DB/Manager/CustomDataExportQueryParameter.pm | ||
---|---|---|
1 |
# This file has been auto-generated only because it didn't exist. |
|
2 |
# Feel free to modify it at will; it will not be overwritten automatically. |
|
3 |
|
|
4 |
package SL::DB::Manager::CustomDataExportQueryParameter; |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use parent qw(SL::DB::Helper::Manager); |
|
9 |
|
|
10 |
sub object_class { 'SL::DB::CustomDataExportQueryParameter' } |
|
11 |
|
|
12 |
__PACKAGE__->make_manager_methods; |
|
13 |
|
|
14 |
1; |
SL/DB/MetaSetup/CustomDataExportQuery.pm | ||
---|---|---|
1 |
# This file has been auto-generated. Do not modify it; it will be overwritten |
|
2 |
# by rose_auto_create_model.pl automatically. |
|
3 |
package SL::DB::CustomDataExportQuery; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use parent qw(SL::DB::Object); |
|
8 |
|
|
9 |
__PACKAGE__->meta->table('custom_data_export_queries'); |
|
10 |
|
|
11 |
__PACKAGE__->meta->columns( |
|
12 |
access_right => { type => 'text' }, |
|
13 |
description => { type => 'text', not_null => 1 }, |
|
14 |
id => { type => 'serial', not_null => 1 }, |
|
15 |
itime => { type => 'timestamp', default => 'now()', not_null => 1 }, |
|
16 |
mtime => { type => 'timestamp', default => 'now()', not_null => 1 }, |
|
17 |
name => { type => 'text', not_null => 1 }, |
|
18 |
sql_query => { type => 'text', not_null => 1 }, |
|
19 |
); |
|
20 |
|
|
21 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
|
22 |
|
|
23 |
__PACKAGE__->meta->allow_inline_column_values(1); |
|
24 |
|
|
25 |
1; |
|
26 |
; |
SL/DB/MetaSetup/CustomDataExportQueryParameter.pm | ||
---|---|---|
1 |
# This file has been auto-generated. Do not modify it; it will be overwritten |
|
2 |
# by rose_auto_create_model.pl automatically. |
|
3 |
package SL::DB::CustomDataExportQueryParameter; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use parent qw(SL::DB::Object); |
|
8 |
|
|
9 |
__PACKAGE__->meta->table('custom_data_export_query_parameters'); |
|
10 |
|
|
11 |
__PACKAGE__->meta->columns( |
|
12 |
description => { type => 'text' }, |
|
13 |
id => { type => 'serial', not_null => 1 }, |
|
14 |
itime => { type => 'timestamp', default => 'now()', not_null => 1 }, |
|
15 |
mtime => { type => 'timestamp', default => 'now()', not_null => 1 }, |
|
16 |
name => { type => 'text', not_null => 1 }, |
|
17 |
parameter_type => { type => 'enum', check_in => [ 'text', 'number', 'date', 'timestamp' ], db_type => 'custom_data_export_query_parameter_type_enum', not_null => 1 }, |
|
18 |
query_id => { type => 'integer', not_null => 1 }, |
|
19 |
); |
|
20 |
|
|
21 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
|
22 |
|
|
23 |
__PACKAGE__->meta->allow_inline_column_values(1); |
|
24 |
|
|
25 |
__PACKAGE__->meta->foreign_keys( |
|
26 |
query => { |
|
27 |
class => 'SL::DB::CustomDataExportQuery', |
|
28 |
key_columns => { query_id => 'id' }, |
|
29 |
}, |
|
30 |
); |
|
31 |
|
|
32 |
1; |
|
33 |
; |
locale/de/all | ||
---|---|---|
196 | 196 |
'Add booking group' => 'Buchungsgruppe erfassen', |
197 | 197 |
'Add business' => 'Kunden-/Lieferantentyp hinzufügen', |
198 | 198 |
'Add complexity' => 'Komplexitätsgrad hinzufügen', |
199 |
'Add custom data export query' => 'Benutzerdefinierte Datenexport-Abfrage erfassen', |
|
199 | 200 |
'Add custom variable' => 'Benutzerdefinierte Variable erfassen', |
200 | 201 |
'Add department' => 'Abteilung hinzufügen', |
201 | 202 |
'Add empty line (csv_import)' => 'Leere Zeile einfügen', |
... | ... | |
367 | 368 |
'Available Prices' => 'Mögliche Preise', |
368 | 369 |
'Available identity fields' => 'Verfügbare Felder', |
369 | 370 |
'Available qty' => 'Lagerbestand', |
371 |
'Available to all users' => 'Für alle BenutzerInnen verfügbar', |
|
370 | 372 |
'BALANCE SHEET' => 'BILANZ', |
371 | 373 |
'BB Balance' => 'Saldo Bank', |
372 | 374 |
'BIC' => 'BIC', |
... | ... | |
788 | 790 |
'Currently #1 delivery orders can be converted into invoices and printed.' => 'Momentan können #1 Lieferscheine in Rechnungen umgewandelt werden.', |
789 | 791 |
'Custom CSV format' => 'Eigenes CSV-Format', |
790 | 792 |
'Custom Variables' => 'Benutzerdefinierte Variablen', |
793 |
'Custom data export' => 'Benutzerdefinierter Datenexport', |
|
791 | 794 |
'Custom shipto' => 'Individuelle Lieferadresse', |
792 | 795 |
'Custom variables for module' => 'Benutzerdefinierte Variablen für Modul', |
793 | 796 |
'Customer' => 'Kunde', |
... | ... | |
975 | 978 |
'Description (translation for #1)' => 'Beschreibung (Übersetzung für #1)', |
976 | 979 |
'Description missing!' => 'Beschreibung fehlt.', |
977 | 980 |
'Description of #1' => 'Beschreibung von #1', |
981 |
'Design custom data export queries' => 'Benutzerdefinierte Datenexport-Abfragen designen', |
|
978 | 982 |
'Destination BIC' => 'Ziel-BIC', |
979 | 983 |
'Destination IBAN' => 'Ziel-IBAN', |
980 | 984 |
'Destination bin' => 'Ziellagerplatz', |
... | ... | |
1150 | 1154 |
'Edit booking group' => 'Buchungsgruppe bearbeiten', |
1151 | 1155 |
'Edit business' => 'Kunden-/Lieferantentyp bearbeiten', |
1152 | 1156 |
'Edit complexity' => 'Komplexitätsgrad bearbeiten', |
1157 |
'Edit custom data export query' => 'Benutzerdefinierte Datenexport-Abfrage bearbeiten', |
|
1153 | 1158 |
'Edit custom shipto' => 'Individuelle Lieferadresse bearbeiten', |
1154 | 1159 |
'Edit custom variable' => 'Benutzerdefinierte Variable bearbeiten', |
1155 | 1160 |
'Edit delivery term' => 'Lieferbedingungen bearbeiten', |
... | ... | |
1314 | 1319 |
'Exchangerate for payment missing!' => 'Es fehlt der Wechselkurs für die Bezahlung!', |
1315 | 1320 |
'Exchangerate missing!' => 'Es fehlt der Wechselkurs!', |
1316 | 1321 |
'Execute' => 'Ausführen', |
1322 |
'Execute a custom data export query' => 'Benutzerdefinierte Datenexport-Abfrage ausführen', |
|
1323 |
'Execute custom data export \'#1\'' => 'Benutzerdefinierter Datenexport »#1« ausführen', |
|
1317 | 1324 |
'Executed' => 'Ausgeführt', |
1318 | 1325 |
'Execution date' => 'Ausführungsdatum', |
1319 | 1326 |
'Execution date from' => 'Ausführungsdatum von', |
... | ... | |
1941 | 1948 |
'No clients have been created yet.' => 'Es wurden noch keine Mandanten angelegt.', |
1942 | 1949 |
'No contact selected to delete' => 'Keine Ansprechperson zum Löschen ausgewählt', |
1943 | 1950 |
'No contra account selected!' => 'Kein Gegenkonto ausgewählt!', |
1951 |
'No custom data exports have been created yet.' => 'Es wurden noch keine benutzerdefinierten Datenexporte angelegt.', |
|
1944 | 1952 |
'No customer has been selected yet.' => 'Es wurde noch kein Kunde ausgewählt.', |
1945 | 1953 |
'No data was found.' => 'Es wurden keine Daten gefunden.', |
1946 | 1954 |
'No default currency' => 'Keine Standardwährung', |
... | ... | |
2011 | 2019 |
'Not done yet' => 'Noch nicht fertig', |
2012 | 2020 |
'Not obsolete' => 'Gültig', |
2013 | 2021 |
'Note' => 'Hinweis', |
2022 |
'Note that parameter names must not be quoted.' => 'Beachten Sie, dass Parameternamen nicht in Anführungszeichen stehen dürfen.', |
|
2014 | 2023 |
'Note: Taxkeys must have a "valid from" date, and will not behave correctly without.' => 'Hinweis: Steuerschlüssel sind fehlerhaft ohne "Gültig ab" Datum', |
2015 | 2024 |
'Note: the object is already in use. Therefore some values cannot be changed.' => 'Anmerkung: das Objekt ist bereits in Benutzung. Einige Werte können daher nicht geändert werden.', |
2016 | 2025 |
'Notes' => 'Bemerkungen', |
... | ... | |
2059 | 2068 |
'On' => 'An', |
2060 | 2069 |
'On Hand' => 'Auf Lager', |
2061 | 2070 |
'On Order' => 'Ist bestellt', |
2071 |
'On the next page the type of all variables can be set.' => 'Auf der folgenden Seite können die Typen aller Variablen gesetzt werden.', |
|
2062 | 2072 |
'One OB-transaction' => 'Eine EB-Buchung', |
2063 | 2073 |
'One SB-transaction' => 'Eine SB-Buchung', |
2064 | 2074 |
'One of the columns "qty" or "target_qty" must be given. If "target_qty" is given, the quantity to transfer for each transfer will be calculate, so that the quantity for this part, warehouse and bin will result in the given "target_qty" after each transfer.' => 'Eine der Spalten "qty" oder "target_qty" muss angegeben werden. Wird "target_qty" angegeben, so wird die zu bewegende Menge für jede Lagerbewegung so berechnet, dass die Lagermenge für diesen Artikel, Lager und Lagerplatz nach jeder Lagerbewegung der angegebenen Zielmenge entspricht.', |
... | ... | |
2428 | 2438 |
'Quarter' => 'Quartal', |
2429 | 2439 |
'Quarterly' => 'quartalsweise', |
2430 | 2440 |
'Query Type' => 'Art der Abfrage', |
2441 |
'Query parameters' => 'Abfrageparameter', |
|
2431 | 2442 |
'Queue' => 'Warteschlange', |
2432 | 2443 |
'Quick Search' => 'Schnellsuche', |
2433 | 2444 |
'Quick Searches that will be shown in the header in this client' => 'Schnellsuchen, die in der Kopfzeile in diesem Mandanten gezeigt werden sollen', |
... | ... | |
2539 | 2550 |
'Requests for Quotation' => 'Preisanfragen', |
2540 | 2551 |
'Require a transaction description in purchase and sales records' => 'Vorgangsbezeichnung in Einkaufs- und Verkaufsbelegen erzwingen', |
2541 | 2552 |
'Require stock out to consider a delivery order position delivered?' => 'Muss eine Lieferscheinposition ausgelagert sein um als geliefert zu gelten?', |
2553 |
'Required access right' => 'Benötigtes Zugriffsrecht', |
|
2542 | 2554 |
'Required by' => 'Lieferdatum', |
2543 | 2555 |
'Requirement Spec Status' => 'Pflichtenheftstatus', |
2544 | 2556 |
'Requirement Spec Statuses' => 'Pflichtenheftstatus', |
... | ... | |
2596 | 2608 |
'SEPA message ID' => 'SEPA-Nachrichten-ID', |
2597 | 2609 |
'SEPA message IDs' => 'SEPA-Nachrichten-IDs', |
2598 | 2610 |
'SEPA strings' => 'SEPA-Überweisungen', |
2611 |
'SQL query' => 'SQL-Abfrage', |
|
2599 | 2612 |
'SWIFT MT940 format' => 'SWIFT-MT940-Format', |
2600 | 2613 |
'Saldo' => 'Saldo', |
2601 | 2614 |
'Saldo Credit' => 'Saldo Haben', |
... | ... | |
2911 | 2924 |
'Status' => 'Status', |
2912 | 2925 |
'Status Shoptransfer' => 'Status Shoptransfer', |
2913 | 2926 |
'Status Shopupload' => 'Status Shopupload', |
2927 |
'Step #1/#2' => 'Schritt #1/#2', |
|
2914 | 2928 |
'Step 1 -- limit number of delivery orders to process' => 'Schritt 1 -- Anzahl zu verarbeitender Lieferscheine begrenzen', |
2915 | 2929 |
'Step 2' => 'Schritt 2', |
2916 | 2930 |
'Step 2 -- Watch status' => 'Schritt 2 -- Status beobachten', |
... | ... | |
3026 | 3040 |
'Templates' => 'Vorlagen', |
3027 | 3041 |
'Terms missing in row ' => '+Tage fehlen in Zeile ', |
3028 | 3042 |
'Test database connectivity' => 'Datenbankverbindung testen', |
3043 |
'Text' => 'Text', |
|
3029 | 3044 |
'Text block actions' => 'Textblockaktionen', |
3030 | 3045 |
'Text block picture actions' => 'Aktionen für Textblockbilder', |
3031 | 3046 |
'Text blocks' => 'Textblöcke', |
... | ... | |
3059 | 3074 |
'The PDF has been printed' => 'Das PDF-Dokument wurde gedruckt.', |
3060 | 3075 |
'The SEPA export has been created.' => 'Der SEPA-Export wurde erstellt', |
3061 | 3076 |
'The SEPA strings have been saved.' => 'Die bei SEPA-Überweisungen verwendeten Begriffe wurden gespeichert.', |
3077 |
'The SQL query can be parameterized with variables named as follows: <%name%>.' => 'Die SQL-Abfrage kann mittels Variablen wie folgt parametrisiert werden: <%Variablenname%>.', |
|
3078 |
'The SQL query does not contain any parameter that need to be configured.' => 'Die SQL-Abfrage enthält keine Parameter, die angegeben werden müssten.', |
|
3062 | 3079 |
'The URL is missing.' => 'URL fehlt', |
3063 | 3080 |
'The WebDAV feature has been used.' => 'Das WebDAV-Feature wurde benutzt.', |
3064 | 3081 |
'The abbreviation is missing.' => 'Abkürzung fehlt', |
... | ... | |
3124 | 3141 |
'The contact person attribute "birthday" is converted from a free-form text field into a date field.' => 'Das Kontaktpersonenfeld "Geburtstag" wird von einem freien Textfeld auf ein Datumsfeld umgestellt.', |
3125 | 3142 |
'The creation of the authentication database failed:' => 'Das Anlegen der Authentifizierungsdatenbank schlug fehl:', |
3126 | 3143 |
'The credentials (username & password) for connecting database are wrong.' => 'Die Daten (Benutzername & Passwort) für das Login zur Datenbank sind falsch.', |
3144 |
'The custom data export has been deleted.' => 'Der benutzerdefinierte Datenexport wurde gelöscht.', |
|
3145 |
'The custom data export has been saved.' => 'Der benutzerdefinierte Datenexport wurde gespeichert.', |
|
3127 | 3146 |
'The custom variable has been created.' => 'Die benutzerdefinierte Variable wurde erfasst.', |
3128 | 3147 |
'The custom variable has been deleted.' => 'Die benutzerdefinierte Variable wurde gelöscht.', |
3129 | 3148 |
'The custom variable has been saved.' => 'Die benutzerdefinierte Variable wurde gespeichert.', |
... | ... | |
3262 | 3281 |
'The project link has been updated.' => 'Die Projektverknüpfung wurde aktualisiert.', |
3263 | 3282 |
'The project number is already in use.' => 'Die Projektnummer wird bereits verwendet.', |
3264 | 3283 |
'The project number is missing.' => 'Die Projektnummer fehlt.', |
3284 |
'The query did not return any data.' => 'Die Abfrage lieferte keine Daten', |
|
3265 | 3285 |
'The receivables chart isn\'t a valid chart.' => 'Das Forderungskonto ist kein gültiges Konto', |
3266 | 3286 |
'The recipient, subject or body is missing.' => 'Der Empfäger, der Betreff oder der Text ist leer.', |
3267 | 3287 |
'The record template \'#1\' has been loaded.' => 'Die Belegvorlage »#1« wurde geladen.', |
... | ... | |
3789 | 3809 |
'You cannot create an invoice for delivery orders from different vendors.' => 'Sie können keine Rechnung aus Lieferscheinen von verschiedenen Lieferanten erstellen.', |
3790 | 3810 |
'You cannot modify individual assigments from additional articles to line items.' => 'Eine individuelle Zuordnung der zusätzlichen Artikel zu Positionen kann nicht vorgenommen werden.', |
3791 | 3811 |
'You cannot paste function blocks or sub function blocks if there is no section.' => 'Sie können keine Funktionsblöcke oder Unterfunktionsblöcke einfügen, wenn es noch keinen Abschnitt gibt.', |
3812 |
'You do not have access to any custom data export.' => 'Sie haben auf keine benutzerdefinierten Datenexporte Zugriff.', |
|
3792 | 3813 |
'You do not have permission to access this entry.' => 'Sie verfügen nicht über die Berechtigung, auf diesen Eintrag zuzugreifen.', |
3793 | 3814 |
'You do not have the permissions to access this function.' => 'Sie verfügen nicht über die notwendigen Rechte, um auf diese Funktion zuzugreifen.', |
3794 | 3815 |
'You don\'t have the rights to edit this customer.' => 'Sie verfügen nicht über die erforderlichen Rechte, um diesen Kunden zu bearbeiten.', |
menus/user/10-custom-data-export.yaml | ||
---|---|---|
1 |
--- |
|
2 |
- parent: reports |
|
3 |
id: custom_data_export |
|
4 |
name: Custom data export |
|
5 |
order: 9000 |
|
6 |
params: |
|
7 |
action: CustomDataExport/list |
|
8 |
- parent: system |
|
9 |
id: custom_data_export_designer |
|
10 |
name: Custom data export |
|
11 |
order: 2250 |
|
12 |
access: custom_data_export_designer |
|
13 |
params: |
|
14 |
action: CustomDataExportDesigner/list |
sql/Pg-upgrade2-auth/custom_data_export_rights.pl | ||
---|---|---|
1 |
# @tag: custom_data_export_rights |
|
2 |
# @description: Rechte für benutzerdefinierten Datenexport |
|
3 |
# @depends: release_3_5_0 |
|
4 |
package SL::DBUpgrade2::Auth::custom_data_export_rights; |
|
5 |
|
|
6 |
use strict; |
|
7 |
use utf8; |
|
8 |
|
|
9 |
use parent qw(SL::DBUpgrade2::Base); |
|
10 |
|
|
11 |
sub run { |
|
12 |
my ($self) = @_; |
|
13 |
my $right = 'custom_data_export_designer'; |
|
14 |
|
|
15 |
$self->db_query("INSERT INTO auth.master_rights (position, name, description) VALUES (4275, '${right}', 'Custom data export')"); |
|
16 |
|
|
17 |
my $groups = $::auth->read_groups; |
|
18 |
|
|
19 |
foreach my $group (grep { $_->{rights}->{admin} } values %{$groups}) { |
|
20 |
$group->{rights}->{$right} = 1; |
|
21 |
$::auth->save_group($group); |
|
22 |
} |
|
23 |
|
|
24 |
return 1; |
|
25 |
} |
|
26 |
|
|
27 |
1; |
sql/Pg-upgrade2/custom_data_export.sql | ||
---|---|---|
1 |
-- @tag: custom_data_export |
|
2 |
-- @description: Benutzerdefinierter Datenexport |
|
3 |
-- @depends: release_3_5_0 |
|
4 |
CREATE TYPE custom_data_export_query_parameter_type_enum AS ENUM ('text', 'number', 'date', 'timestamp'); |
|
5 |
|
|
6 |
CREATE TABLE custom_data_export_queries ( |
|
7 |
id SERIAL, |
|
8 |
name TEXT NOT NULL, |
|
9 |
description TEXT NOT NULL, |
|
10 |
sql_query TEXT NOT NULL, |
|
11 |
access_right TEXT, |
|
12 |
itime TIMESTAMP NOT NULL DEFAULT now(), |
|
13 |
mtime TIMESTAMP NOT NULL DEFAULT now(), |
|
14 |
|
|
15 |
PRIMARY KEY (id) |
|
16 |
); |
|
17 |
|
|
18 |
CREATE TABLE custom_data_export_query_parameters ( |
|
19 |
id SERIAL, |
|
20 |
query_id INTEGER NOT NULL, |
|
21 |
name TEXT NOT NULL, |
|
22 |
description TEXT, |
|
23 |
parameter_type custom_data_export_query_parameter_type_enum NOT NULL, |
|
24 |
itime TIMESTAMP NOT NULL DEFAULT now(), |
|
25 |
mtime TIMESTAMP NOT NULL DEFAULT now(), |
|
26 |
|
|
27 |
PRIMARY KEY (id), |
|
28 |
FOREIGN KEY (query_id) REFERENCES custom_data_export_queries (id) ON DELETE CASCADE |
|
29 |
); |
|
30 |
|
|
31 |
CREATE TRIGGER mtime_custom_data_export_queries |
|
32 |
BEFORE UPDATE ON custom_data_export_queries |
|
33 |
FOR EACH ROW EXECUTE PROCEDURE set_mtime(); |
|
34 |
|
|
35 |
CREATE TRIGGER mtime_custom_data_export_query_parameters |
|
36 |
BEFORE UPDATE ON custom_data_export_query_parameters |
|
37 |
FOR EACH ROW EXECUTE PROCEDURE set_mtime(); |
templates/webpages/custom_data_export/empty_result_set.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
<p> |
|
8 |
[% LxERP.t8("The query did not return any data.") %] |
|
9 |
</p> |
templates/webpages/custom_data_export/export.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
<form method="post" action="controller.pl" id="form"> |
|
8 |
[% L.hidden_tag("id", SELF.query.id) %] |
|
9 |
[% L.hidden_tag("format", "csv") %] |
|
10 |
|
|
11 |
[% IF !SELF.parameters.size %] |
|
12 |
<p> |
|
13 |
[% LxERP.t8("The SQL query does not contain any parameter that need to be configured.") %] |
|
14 |
</p> |
|
15 |
|
|
16 |
[% ELSE %] |
|
17 |
|
|
18 |
<table> |
|
19 |
<thead> |
|
20 |
<tr class="listheading"> |
|
21 |
<th>[% LxERP.t8("Variable Name") %]</th> |
|
22 |
<th>[% LxERP.t8("Type") %]</th> |
|
23 |
<th>[% LxERP.t8("Value") %]</th> |
|
24 |
<th>[% LxERP.t8("Description") %]</th> |
|
25 |
</tr> |
|
26 |
</thead> |
|
27 |
|
|
28 |
<tbody> |
|
29 |
[% FOREACH parameter = SELF.parameters %] |
|
30 |
<tr class="listrow"> |
|
31 |
<td> |
|
32 |
[% HTML.escape(parameter.name) %] |
|
33 |
</td> |
|
34 |
|
|
35 |
[% IF parameter.parameter_type == "number" %] |
|
36 |
<td>[% LxERP.t8("Number") %]</td> |
|
37 |
<td>[% L.input_tag("parameters." _ parameter.name, "", style="width: 300px", "data-validate"="required") %]</td> |
|
38 |
|
|
39 |
[% ELSIF parameter.parameter_type == "date" %] |
|
40 |
<td>[% LxERP.t8("Date") %]</td> |
|
41 |
<td>[% L.date_tag("parameters." _ parameter.name, SELF.today.to_kivitendo, style="width: 300px", "data-validate"="required") %]</td> |
|
42 |
|
|
43 |
[% ELSE %] |
|
44 |
<td>[% LxERP.t8("Text") %]</td> |
|
45 |
<td>[% L.input_tag("parameters." _ parameter.name, "", style="width: 300px", "data-validate"="required") %]</td> |
|
46 |
[% END %] |
|
47 |
|
|
48 |
<td>[% HTML.escape(parameter.description) %]</td> |
|
49 |
</tr> |
|
50 |
[% END %] |
|
51 |
</tbody> |
|
52 |
[% END %] |
|
53 |
</form> |
templates/webpages/custom_data_export/list.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
[% IF !SELF.queries.size %] |
|
8 |
<p> |
|
9 |
[%- LxERP.t8("You do not have access to any custom data export.") %] |
|
10 |
</p> |
|
11 |
|
|
12 |
[%- ELSE %] |
|
13 |
<table width="100%"> |
|
14 |
<thead> |
|
15 |
<tr class="listheading"> |
|
16 |
<th>[% LxERP.t8("Name") %]</th> |
|
17 |
<th>[% LxERP.t8("Description") %]</th> |
|
18 |
</tr> |
|
19 |
</thead> |
|
20 |
|
|
21 |
<tbody> |
|
22 |
[%- FOREACH query = SELF.queries %] |
|
23 |
<tr class="listrow"> |
|
24 |
<td>[% L.link(SELF.url_for(action="export", id=query.id), query.name) %]</td> |
|
25 |
<td>[% IF query.description %][% L.link(SELF.url_for(action="export", id=query.id), query.description) %][% END %]</td> |
|
26 |
</tr> |
|
27 |
[%- END %] |
|
28 |
</tbody> |
|
29 |
</table> |
|
30 |
[%- END %] |
templates/webpages/custom_data_export_designer/edit.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %] — [% LxERP.t8("Step #1/#2", 1, 2) %] — [% LxERP.t8("Basic Data") %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
<form method="post" action="controller.pl" id="form"> |
|
8 |
[% L.hidden_tag("id", SELF.query.id) %] |
|
9 |
|
|
10 |
<table> |
|
11 |
<tr> |
|
12 |
<th align="right">[%- LxERP.t8("Name") %]</th> |
|
13 |
<td>[% L.input_tag("query.name", SELF.query.name, style="width: 800px", "data-validate"="required") %]</td> |
|
14 |
</tr> |
|
15 |
|
|
16 |
<tr> |
|
17 |
<th align="right">[%- LxERP.t8("Required access right") %]</th> |
|
18 |
<td>[% L.select_tag("query.access_right", SELF.access_rights, default=SELF.query.access_right, style="width: 800px") %]</td> |
|
19 |
</tr> |
|
20 |
|
|
21 |
<tr> |
|
22 |
<th valign="top" align="right">[%- LxERP.t8("Description") %]</th> |
|
23 |
<td valign="top">[% L.textarea_tag("query.description", SELF.query.description, rows=5, style="width: 800px") %]</td> |
|
24 |
</tr> |
|
25 |
|
|
26 |
<tr> |
|
27 |
<th valign="top" align="right">[%- LxERP.t8("SQL query") %]</th> |
|
28 |
<td valign="top">[% L.textarea_tag("query.sql_query", SELF.query.sql_query, rows=20, style="width: 800px", "data-validate"="required") %]</td> |
|
29 |
</tr> |
|
30 |
</table> |
|
31 |
</form> |
|
32 |
|
|
33 |
<p> |
|
34 |
[% LxERP.t8("The SQL query can be parameterized with variables named as follows: <%name%>.") %] |
|
35 |
[% LxERP.t8("On the next page the type of all variables can be set.") %] |
|
36 |
[% LxERP.t8("Note that parameter names must not be quoted.") %] |
|
37 |
[% LxERP.t8("Example") %]: |
|
38 |
</p> |
|
39 |
|
|
40 |
<pre> |
|
41 |
SELECT extract(YEAR FROM oe.transdate) AS "Jahr", SUM(oe.amount) AS "Angebotssumme" |
|
42 |
FROM oe |
|
43 |
LEFT JOIN employee ON (oe.employee_id = employee.id) |
|
44 |
WHERE (oe.customer_id IS NOT NULL) |
|
45 |
AND COALESCE(oe.quotation, FALSE) |
|
46 |
AND (employee.login = <%Benutzer-Login%>) |
|
47 |
GROUP BY "Jahr" |
|
48 |
ORDER BY "Jahr" |
|
49 |
</pre> |
templates/webpages/custom_data_export_designer/edit_parameters.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %] — [% LxERP.t8("Step #1/#2", 2, 2) %] — [% LxERP.t8("Query parameters") %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
<form method="post" action="controller.pl" id="form"> |
|
8 |
[% L.hidden_tag("id", SELF.query.id) %] |
|
9 |
[% L.hidden_tag("query.name", SELF.query.name) %] |
|
10 |
[% L.hidden_tag("query.access_right", SELF.query.access_right) %] |
|
11 |
[% L.hidden_tag("query.description", SELF.query.description) %] |
|
12 |
[% L.hidden_tag("query.sql_query", SELF.query.sql_query) %] |
|
13 |
|
|
14 |
[% IF !PARAMETERS.size %] |
|
15 |
<p> |
|
16 |
[% LxERP.t8("The SQL query does not contain any parameter that need to be configured.") %] |
|
17 |
</p> |
|
18 |
|
|
19 |
[% ELSE %] |
|
20 |
|
|
21 |
<table> |
|
22 |
<thead> |
|
23 |
<tr class="listheading"> |
|
24 |
<th>[% LxERP.t8("Variable Name") %]</th> |
|
25 |
<th>[% LxERP.t8("Type") %]</th> |
|
26 |
<th>[% LxERP.t8("Description") %]</th> |
|
27 |
</tr> |
|
28 |
</thead> |
|
29 |
|
|
30 |
<tbody> |
|
31 |
[% FOREACH parameter = PARAMETERS %] |
|
32 |
<tr class="listrow"> |
|
33 |
<td> |
|
34 |
[% L.hidden_tag("parameters[+].name", parameter.name) %] |
|
35 |
[% HTML.escape(parameter.name) %] |
|
36 |
</td> |
|
37 |
<td> |
|
38 |
[% L.select_tag("parameters[].parameter_type", [ [ "text", LxERP.t8("Text") ], [ "number", LxERP.t8("Number") ], [ "date", LxERP.t8("Date") ] ], default=parameter.parameter_type) %] |
|
39 |
</td> |
|
40 |
<td>[% L.input_tag("parameters[].description", parameter.description, size=100) %]</td> |
|
41 |
</tr> |
|
42 |
[% END %] |
|
43 |
</tbody> |
|
44 |
[% END %] |
|
45 |
</form> |
templates/webpages/custom_data_export_designer/list.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
[% IF !SELF.queries.size %] |
|
8 |
<p> |
|
9 |
[%- LxERP.t8("No custom data exports have been created yet.") %] |
|
10 |
</p> |
|
11 |
|
|
12 |
[%- ELSE %] |
|
13 |
<table width="100%"> |
|
14 |
<thead> |
|
15 |
<tr class="listheading"> |
|
16 |
<th>[% LxERP.t8("Name") %]</th> |
|
17 |
<th>[% LxERP.t8("Description") %]</th> |
|
18 |
</tr> |
|
19 |
</thead> |
|
20 |
|
|
21 |
<tbody> |
|
22 |
[%- FOREACH query = SELF.queries %] |
|
23 |
<tr class="listrow"> |
|
24 |
<td>[% L.link(SELF.url_for(action="edit", id=query.id), query.name) %]</td> |
|
25 |
<td>[% IF query.description %][% L.link(SELF.url_for(action="edit", id=query.id), query.description) %][% END %]</td> |
|
26 |
</tr> |
|
27 |
[%- END %] |
|
28 |
</tbody> |
|
29 |
</table> |
|
30 |
[%- END %] |
Auch abrufbar als: Unified diff
Benutzerdefinierte Datenexporte zu CSV anlegen und ausführen können