SimpleSystemSetting: Umstellung von »Sprachen«
[kivitendo-erp.git] / SL / Controller / SimpleSystemSetting.pm
1 package SL::Controller::SimpleSystemSetting;
2
3 use strict;
4 use utf8;
5
6 use parent qw(SL::Controller::Base);
7
8 use SL::Helper::Flash;
9 use SL::Locale::String;
10 use SL::DB::Default;
11 use SL::System::Process;
12
13 use Rose::Object::MakeMethods::Generic (
14   scalar                  => [ qw(type config) ],
15   'scalar --get_set_init' => [ qw(defaults object all_objects class manager_class list_attributes list_url supports_reordering) ],
16 );
17
18 __PACKAGE__->run_before('check_type_and_auth');
19 __PACKAGE__->run_before('setup_javascript', only => [ qw(add create edit update delete) ]);
20
21 # Make locales.pl happy: $self->render("simple_system_setting/_default_form")
22
23 my %supported_types = (
24   bank_account => {
25     # Make locales.pl happy: $self->render("simple_system_setting/_bank_account_form")
26     class  => 'BankAccount',
27     titles => {
28       list => t8('Bank accounts'),
29       add  => t8('Add bank account'),
30       edit => t8('Edit bank account'),
31     },
32     list_attributes => [
33       { method => 'name',                                      title => t8('Name'), },
34       { method => 'iban',                                      title => t8('IBAN'), },
35       { method => 'bank',                                      title => t8('Bank'), },
36       { method => 'bank_code',                                 title => t8('Bank code'), },
37       { method => 'bic',                                       title => t8('BIC'), },
38       { method => 'reconciliation_starting_date_as_date',      title => t8('Date'),    align => 'right' },
39       { method => 'reconciliation_starting_balance_as_number', title => t8('Balance'), align => 'right' },
40     ],
41   },
42
43   business => {
44     # Make locales.pl happy: $self->render("simple_system_setting/_business_form")
45     class  => 'Business',
46     titles => {
47       list => t8('Businesses'),
48       add  => t8('Add business'),
49       edit => t8('Edit business'),
50     },
51     list_attributes => [
52       { method => 'description',         title => t8('Description'), },
53       {                                  title => t8('Discount'), formatter => sub { $_[0]->discount_as_percent . ' %' }, align => 'right' },
54       { method => 'customernumberinit',  title => t8('Customernumberinit'), },
55     ],
56   },
57
58   department => {
59     class  => 'Department',
60     titles => {
61       list => t8('Departments'),
62       add  => t8('Add department'),
63       edit => t8('Edit department'),
64     },
65   },
66
67   language => {
68     # Make locales.pl happy: $self->render("simple_system_setting/_language_form")
69     class  => 'Language',
70     titles => {
71       list => t8('Languages'),
72       add  => t8('Add language'),
73       edit => t8('Edit language'),
74     },
75     list_attributes => [
76       { method => 'description',   title => t8('Description'), },
77       { method => 'template_code', title => t8('Template Code'), },
78       { method => 'article_code',  title => t8('Article Code'), },
79       {                            title => t8('Number Format'), formatter => sub { $_[0]->output_numberformat || t8('use program settings') } },
80       {                            title => t8('Date Format'),   formatter => sub { $_[0]->output_dateformat   || t8('use program settings') } },
81       {                            title => t8('Long Dates'),    formatter => sub { $_[0]->output_longdates ? t8('yes') : t8('no') } },
82     ],
83   },
84
85   part_classification => {
86     # Make locales.pl happy: $self->render("simple_system_setting/_part_classification_form")
87     class  => 'PartClassification',
88     titles => {
89       list => t8('Part classifications'),
90       add  => t8('Add part classification'),
91       edit => t8('Edit part classification'),
92     },
93     list_attributes => [
94       { title => t8('Description'),       formatter => sub { t8($_[0]->description) } },
95       { title => t8('Type abbreviation'), formatter => sub { t8($_[0]->abbreviation) } },
96       { title => t8('Used for Purchase'), formatter => sub { $_[0]->used_for_purchase ? t8('yes') : t8('no') } },
97       { title => t8('Used for Sale'),     formatter => sub { $_[0]->used_for_sale     ? t8('yes') : t8('no') } },
98       { title => t8('Report separately'), formatter => sub { $_[0]->report_separate   ? t8('yes') : t8('no') } },
99     ],
100   },
101
102   parts_group => {
103     # Make locales.pl happy: $self->render("simple_system_setting/_parts_group_form")
104     class  => 'PartsGroup',
105     titles => {
106       list => t8('Partsgroups'),
107       add  => t8('Add partsgroup'),
108       edit => t8('Edit partsgroup'),
109     },
110     list_attributes => [
111       { method => 'partsgroup', title => t8('Description') },
112       { method => 'obsolete',   title => t8('Obsolete'), formatter => sub { $_[0]->obsolete ? t8('yes') : t8('no') } },
113     ],
114   },
115
116   price_factor => {
117     # Make locales.pl happy: $self->render("simple_system_setting/_price_factor_form")
118     class  => 'PriceFactor',
119     titles => {
120       list => t8('Price Factors'),
121       add  => t8('Add Price Factor'),
122       edit => t8('Edit Price Factor'),
123     },
124     list_attributes => [
125       { method => 'description',      title => t8('Description') },
126       { method => 'factor_as_number', title => t8('Factor'), align => 'right' },
127     ],
128   },
129
130   pricegroup => {
131     # Make locales.pl happy: $self->render("simple_system_setting/_pricegroup_form")
132     class  => 'Pricegroup',
133     titles => {
134       list => t8('Pricegroups'),
135       add  => t8('Add pricegroup'),
136       edit => t8('Edit pricegroup'),
137     },
138     list_attributes => [
139       { method => 'pricegroup', title => t8('Description') },
140       { method => 'obsolete',   title => t8('Obsolete'), formatter => sub { $_[0]->obsolete ? t8('yes') : t8('no') } },
141     ],
142   },
143
144   project_status => {
145     class  => 'ProjectStatus',
146     titles => {
147       list => t8('Project statuses'),
148       add  => t8('Add project status'),
149       edit => t8('Edit project status'),
150     },
151   },
152
153   project_type => {
154     class  => 'ProjectType',
155     titles => {
156       list => t8('Project types'),
157       add  => t8('Add project type'),
158       edit => t8('Edit project type'),
159     },
160   },
161
162   requirement_spec_acceptance_status => {
163     # Make locales.pl happy: $self->render("simple_system_setting/_requirement_spec_acceptance_status_form")
164     class  => 'RequirementSpecAcceptanceStatus',
165     titles => {
166       list => t8('Acceptance Statuses'),
167       add  => t8('Add acceptance status'),
168       edit => t8('Edit acceptance status'),
169     },
170     list_attributes => [
171       { method => 'name',        title => t8('Name') },
172       { method => 'description', title => t8('Description') },
173     ],
174   },
175
176   requirement_spec_complexity => {
177     class  => 'RequirementSpecComplexity',
178     titles => {
179       list => t8('Complexities'),
180       add  => t8('Add complexity'),
181       edit => t8('Edit complexity'),
182     },
183   },
184
185   requirement_spec_predefined_text => {
186     # Make locales.pl happy: $self->render("simple_system_setting/_requirement_spec_predefined_text_form")
187     class  => 'RequirementSpecPredefinedText',
188     titles => {
189       list => t8('Pre-defined Texts'),
190       add  => t8('Add pre-defined text'),
191       edit => t8('Edit pre-defined text'),
192     },
193     list_attributes => [
194       { method => 'description', title => t8('Description') },
195       { method => 'title',       title => t8('Title') },
196       {                          title => t8('Content'),                 formatter => sub { my $t = $_[0]->text_as_stripped_html; length($t) > 50 ? substr($t, 0, 50) . '…' : $t } },
197       {                          title => t8('Useable for text blocks'), formatter => sub { $_[0]->useable_for_text_blocks ? t8('yes') : t8('no') } },
198       {                          title => t8('Useable for sections'),    formatter => sub { $_[0]->useable_for_sections    ? t8('yes') : t8('no') } },
199     ],
200   },
201
202   requirement_spec_risk => {
203     class  => 'RequirementSpecRisk',
204     titles => {
205       list => t8('Risk levels'),
206       add  => t8('Add risk level'),
207       edit => t8('Edit risk level'),
208     },
209   },
210
211   requirement_spec_status => {
212     # Make locales.pl happy: $self->render("simple_system_setting/_requirement_spec_status_form")
213     class  => 'RequirementSpecStatus',
214     titles => {
215       list => t8('Requirement Spec Statuses'),
216       add  => t8('Add requirement spec status'),
217       edit => t8('Edit requirement spec status'),
218     },
219     list_attributes => [
220       { method => 'name',        title => t8('Name') },
221       { method => 'description', title => t8('Description') },
222     ],
223   },
224
225   requirement_spec_type => {
226     # Make locales.pl happy: $self->render("simple_system_setting/_requirement_spec_type_form")
227     class  => 'RequirementSpecType',
228     titles => {
229       list => t8('Requirement Spec Types'),
230       add  => t8('Add requirement spec type'),
231       edit => t8('Edit requirement spec type'),
232     },
233     list_attributes => [
234       { method => 'description',                  title => t8('Description') },
235       { method => 'section_number_format',        title => t8('Section number format') },
236       { method => 'function_block_number_format', title => t8('Function block number format') },
237     ],
238   },
239
240 );
241
242 my @default_list_attributes = (
243   { method => 'description', title => t8('Description') },
244 );
245
246 #
247 # actions
248 #
249
250 sub action_list {
251   my ($self) = @_;
252
253   $self->render('simple_system_setting/list', title => $self->config->{titles}->{list});
254 }
255
256 sub action_new {
257   my ($self) = @_;
258
259   $self->object($self->class->new);
260   $self->render_form(title => $self->config->{titles}->{add});
261 }
262
263 sub action_edit {
264   my ($self) = @_;
265
266   $self->render_form(title => $self->config->{titles}->{edit});
267 }
268
269 sub action_create {
270   my ($self) = @_;
271
272   $self->object($self->class->new);
273   $self->create_or_update;
274 }
275
276 sub action_update {
277   my ($self) = @_;
278
279   $self->create_or_update;
280 }
281
282 sub action_delete {
283   my ($self) = @_;
284
285   if ($self->object->can('orphaned') && !$self->object->orphaned) {
286     flash_later('error', t8('The object is in use and cannot be deleted.'));
287
288   } elsif ( eval { $self->object->delete; 1; } ) {
289     flash_later('info',  t8('The object has been deleted.'));
290
291   } else {
292     flash_later('error', t8('The object is in use and cannot be deleted.'));
293   }
294
295   $self->redirect_to($self->list_url);
296 }
297
298 sub action_reorder {
299   my ($self) = @_;
300
301   $self->class->reorder_list(@{ $::form->{object_id} || [] });
302   $self->render(\'', { type => 'json' });
303 }
304
305 #
306 # filters
307 #
308
309 sub check_type_and_auth {
310   my ($self) = @_;
311
312   $self->type($::form->{type});
313   $self->config($supported_types{$self->type}) || die "Unsupported type";
314
315   $::auth->assert($self->config->{auth} || 'config');
316
317   my $pm = (map { s{::}{/}g; "${_}.pm" } $self->class)[0];
318   require $pm;
319
320   my $setup = "setup_" . $self->type;
321   $self->$setup if $self->can($setup);
322
323   1;
324 }
325
326 sub setup_javascript {
327   $::request->layout->use_javascript("${_}.js") for qw(ckeditor/ckeditor ckeditor/adapters/jquery);
328 }
329
330 sub init_class               { "SL::DB::"          . $_[0]->config->{class}                  }
331 sub init_manager_class       { "SL::DB::Manager::" . $_[0]->config->{class}                  }
332 sub init_object              { $_[0]->class->new(id => $::form->{id})->load                  }
333 sub init_all_objects         { $_[0]->manager_class->get_all_sorted                          }
334 sub init_list_url            { $_[0]->url_for(action => 'list', type => $_[0]->type)         }
335 sub init_supports_reordering { $_[0]->class->new->can('reorder_list')                        }
336 sub init_defaults            { SL::DB::Default->get                                          }
337
338 sub init_list_attributes {
339   my ($self) = @_;
340
341   my $method = "list_attributes_" . $self->type;
342
343   return $self->$method if $self->can($method);
344   return $self->config->{list_attributes} // \@default_list_attributes;
345 }
346
347 #
348 # helpers
349 #
350
351 sub create_or_update {
352   my ($self) = @_;
353   my $is_new = !$self->object->id;
354
355   my $params = delete($::form->{object}) || { };
356
357   $self->object->assign_attributes(%{ $params });
358
359   my @errors;
360
361   push @errors, $self->object->validate if $self->object->can('validate');
362
363   if (@errors) {
364     flash('error', @errors);
365     return $self->render_form(title => $self->config->{titles}->{$is_new ? 'add' : 'edit'});
366   }
367
368   $self->object->save;
369
370   flash_later('info', $is_new ? t8('The object has been created.') : t8('The object has been saved.'));
371
372   $self->redirect_to($self->list_url);
373 }
374
375 sub render_form {
376   my ($self, %params) = @_;
377
378   my $sub_form_template = SL::System::Process->exe_dir . '/templates/webpages/simple_system_setting/_' . $self->type . '_form.html';
379
380   $self->render(
381     'simple_system_setting/form',
382     %params,
383     sub_form_template => (-f $sub_form_template ? $self->type : 'default'),
384   );
385 }
386
387 #
388 # type-specific helper functions
389 #
390
391 sub setup_requirement_spec_acceptance_status {
392   my ($self) = @_;
393
394   no warnings 'once';
395   $self->{valid_names} = \@SL::DB::RequirementSpecAcceptanceStatus::valid_names;
396 }
397
398 sub setup_requirement_spec_status {
399   my ($self) = @_;
400
401   no warnings 'once';
402   $self->{valid_names} = \@SL::DB::RequirementSpecStatus::valid_names;
403 }
404
405 sub setup_language {
406   my ($self) = @_;
407
408   $self->{numberformats} = [ '1,000.00', '1000.00', '1.000,00', '1000,00', "1'000.00" ];
409   $self->{dateformats}   = [ qw(mm/dd/yy dd/mm/yy dd.mm.yy yyyy-mm-dd) ];
410 }
411
412 1;
413
414 __END__
415
416 =encoding utf-8
417
418 =head1 NAME
419
420 SL::Controller::SimpleSystemSettings — a common CRUD controller for
421 various settings in the "System" menu
422
423 =head1 AUTHOR
424
425 Moritz Bunkus <m.bunkus@linet-services.de>
426
427 =cut