From: Moritz Bunkus Date: Wed, 1 Feb 2017 11:51:32 +0000 (+0100) Subject: SimpleSystemSetting: Controller für die ganzen trivialen CRUD-Masken im System-Menü X-Git-Tag: release-3.5.4~1562 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=916003e3c1f8edc11b79b283252aadbc59ac8757;p=kivitendo-erp.git SimpleSystemSetting: Controller für die ganzen trivialen CRUD-Masken im System-Menü Die Masken und Controller für sehr viele der Einstellungen im System-Menü folgenden Schema F: es sind simple CRUD-Controller. Sinnvoller wäre es, diesen ganzen Code in einem einzigen CRUD-Controller zu vereinheitlichen und die Unterschiede nur anhand eines übergebenen Typen-Parameters auszudrücken. Genau hierfür ist der SimpleSystemSetting-Controller gedacht, und er macht mit Unterstützung für Preisgruppen den Anfang. Andere Typen folgen. --- diff --git a/SL/Controller/Pricegroup.pm b/SL/Controller/Pricegroup.pm deleted file mode 100644 index 047ed658c..000000000 --- a/SL/Controller/Pricegroup.pm +++ /dev/null @@ -1,152 +0,0 @@ -package SL::Controller::Pricegroup; - -use strict; - -use parent qw(SL::Controller::Base); - -use SL::Helper::Flash; -use SL::Locale::String; -use SL::DB::Default; -use SL::DB::Manager::Pricegroup; - -use Rose::Object::MakeMethods::Generic ( - scalar => [ qw(pricegroup) ], - 'scalar --get_set_init' => [ qw(all_pricegroups) ], -); - -__PACKAGE__->run_before('check_auth'); -__PACKAGE__->run_before('load_pricegroup', only => [ qw(edit update delete) ]); - -# -# actions -# - -sub action_list { - my ($self) = @_; - - $self->render('pricegroup/list', - title => t8('Pricegroups'), - ); -} - -sub action_new { - my ($self) = @_; - - $self->pricegroup( SL::DB::Pricegroup->new ); - $self->render('pricegroup/form', - title => t8('Add pricegroup'), - ); -} - -sub action_edit { - my ($self) = @_; - - $self->render('pricegroup/form', - title => t8('Edit pricegroup'), - ); -} - -sub action_create { - my ($self) = @_; - - $self->pricegroup( SL::DB::Pricegroup->new ); - $self->create_or_update; -} - -sub action_update { - my ($self) = @_; - $self->create_or_update; -} - -sub action_delete { - my ($self) = @_; - - if ( !$self->pricegroup->orphaned ) { - flash_later('error', $::locale->text('The pricegroup has been used and cannot be deleted.')); - } elsif ( eval { $self->pricegroup->delete; 1; } ) { - flash_later('info', $::locale->text('The pricegroup has been deleted.')); - } else { - flash_later('error', $::locale->text('The pricegroup has been used and cannot be deleted.')); - }; - $self->redirect_to(action => 'list'); -} - -sub action_reorder { - my ($self) = @_; - - SL::DB::Pricegroup->reorder_list(@{ $::form->{pricegroup_id} || [] }); - $self->render(\'', { type => 'json' }); -} - -# -# filters -# - -sub check_auth { - $::auth->assert('config'); -} - -sub load_pricegroup { - my ($self) = @_; - - $self->pricegroup( SL::DB::Pricegroup->new(id => $::form->{id})->load ); -} - -sub init_all_pricegroups { SL::DB::Manager::Pricegroup->get_all_sorted } - -# -# helpers -# - -sub create_or_update { - my ($self) = @_; - my $is_new = !$self->pricegroup->id; - - my $params = delete($::form->{pricegroup}) || { }; - - $self->pricegroup->assign_attributes(%{ $params }); - - my @errors = $self->pricegroup->validate; - - if (@errors) { - flash('error', @errors); - $self->render('pricegroup/form', - title => $is_new ? t8('Add pricegroup') : t8('Edit pricegroup'), - ); - return; - } - - $self->pricegroup->save; - - flash_later('info', $is_new ? t8('The pricegroup has been created.') : t8('The pricegroup has been saved.')); - $self->redirect_to(action => 'list'); -} - -1; - -__END__ - -=encoding utf-8 - -=head1 NAME - -SL::Controller::Pricegroup - CRUD controller for pricegroups - -=head1 SYNOPSIS - -A new controller to create / edit / delete pricegroups. - -Pricegroups can only be deleted if they haven't been used anywhere. - -=head1 OBSOLETE PRICEGROUPS - -Pricegroups can't be obsoleted while any of the customers still use that -pricegroup as their default pricegroup. Obsoleting a pricegroup means it can't -be selected when editing customers and it can't be selected as a price source -for new records. - -=head1 AUTHOR - -G. Richardson Egrichardson@kivitendo-premium.deE - -=cut diff --git a/SL/Controller/SimpleSystemSetting.pm b/SL/Controller/SimpleSystemSetting.pm new file mode 100644 index 000000000..0c797627b --- /dev/null +++ b/SL/Controller/SimpleSystemSetting.pm @@ -0,0 +1,203 @@ +package SL::Controller::SimpleSystemSetting; + +use strict; +use utf8; + +use parent qw(SL::Controller::Base); + +use SL::Helper::Flash; +use SL::Locale::String; +use SL::DB::Default; +use SL::System::Process; + +use Rose::Object::MakeMethods::Generic ( + scalar => [ qw(type config) ], + 'scalar --get_set_init' => [ qw(defaults object all_objects class manager_class list_attributes list_url supports_reordering) ], +); + +__PACKAGE__->run_before('check_type_and_auth'); +__PACKAGE__->run_before('setup_javascript', only => [ qw(add create edit update delete) ]); + +# Make locales.pl happy: $self->render("simple_system_setting/_default_form") + +my %supported_types = ( + pricegroup => { + # Make locales.pl happy: $self->render("simple_system_setting/_pricegroup_form") + class => 'Pricegroup', + titles => { + list => t8('Pricegroups'), + add => t8('Add pricegroup'), + edit => t8('Edit pricegroup'), + }, + list_attributes => [ + { method => 'pricegroup', title => t8('Description') }, + { method => 'obsolete', title => t8('Obsolete'), formatter => sub { $_[0]->obsolete ? t8('yes') : t8('no') } }, + ], + }, +); + +my @default_list_attributes = ( + { method => 'description', title => t8('Description') }, +); + +# +# actions +# + +sub action_list { + my ($self) = @_; + + $self->render('simple_system_setting/list', title => $self->config->{titles}->{list}); +} + +sub action_new { + my ($self) = @_; + + $self->object($self->class->new); + $self->render_form(title => $self->config->{titles}->{add}); +} + +sub action_edit { + my ($self) = @_; + + $self->render_form(title => $self->config->{titles}->{edit}); +} + +sub action_create { + my ($self) = @_; + + $self->object($self->class->new); + $self->create_or_update; +} + +sub action_update { + my ($self) = @_; + + $self->create_or_update; +} + +sub action_delete { + my ($self) = @_; + + if ($self->object->can('orphaned') && !$self->object->orphaned) { + flash_later('error', t8('The object is in use and cannot be deleted.')); + + } elsif ( eval { $self->object->delete; 1; } ) { + flash_later('info', t8('The object has been deleted.')); + + } else { + flash_later('error', t8('The object is in use and cannot be deleted.')); + } + + $self->redirect_to($self->list_url); +} + +sub action_reorder { + my ($self) = @_; + + $self->class->reorder_list(@{ $::form->{object_id} || [] }); + $self->render(\'', { type => 'json' }); +} + +# +# filters +# + +sub check_type_and_auth { + my ($self) = @_; + + $self->type($::form->{type}); + $self->config($supported_types{$self->type}) || die "Unsupported type"; + + $::auth->assert($self->config->{auth} || 'config'); + + my $pm = (map { s{::}{/}g; "${_}.pm" } $self->class)[0]; + require $pm; + + my $setup = "setup_" . $self->type; + $self->$setup if $self->can($setup); + + 1; +} + +sub setup_javascript { + $::request->layout->use_javascript("${_}.js") for qw(ckeditor/ckeditor ckeditor/adapters/jquery); +} + +sub init_class { "SL::DB::" . $_[0]->config->{class} } +sub init_manager_class { "SL::DB::Manager::" . $_[0]->config->{class} } +sub init_object { $_[0]->class->new(id => $::form->{id})->load } +sub init_all_objects { $_[0]->manager_class->get_all_sorted } +sub init_list_url { $_[0]->url_for(action => 'list', type => $_[0]->type) } +sub init_supports_reordering { $_[0]->class->new->can('reorder_list') } +sub init_defaults { SL::DB::Default->get } + +sub init_list_attributes { + my ($self) = @_; + + my $method = "list_attributes_" . $self->type; + + return $self->$method if $self->can($method); + return $self->config->{list_attributes} // \@default_list_attributes; +} + +# +# helpers +# + +sub create_or_update { + my ($self) = @_; + my $is_new = !$self->object->id; + + my $params = delete($::form->{object}) || { }; + + $self->object->assign_attributes(%{ $params }); + + my @errors; + + push @errors, $self->object->validate if $self->object->can('validate'); + + if (@errors) { + flash('error', @errors); + return $self->render_form(title => $self->config->{titles}->{$is_new ? 'add' : 'edit'}); + } + + $self->object->save; + + flash_later('info', $is_new ? t8('The object has been created.') : t8('The object has been saved.')); + + $self->redirect_to($self->list_url); +} + +sub render_form { + my ($self, %params) = @_; + + my $sub_form_template = SL::System::Process->exe_dir . '/templates/webpages/simple_system_setting/_' . $self->type . '_form.html'; + + $self->render( + 'simple_system_setting/form', + %params, + sub_form_template => (-f $sub_form_template ? $self->type : 'default'), + ); +} + +# +# type-specific helper functions +# + +1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Controller::SimpleSystemSettings — a common CRUD controller for +various settings in the "System" menu + +=head1 AUTHOR + +Moritz Bunkus + +=cut diff --git a/locale/de/all b/locale/de/all index 73e821465..6b6d41d88 100644 --- a/locale/de/all +++ b/locale/de/all @@ -3059,6 +3059,10 @@ $self->{texts} = { 'The next partnumber in the number range already exists!' => 'Die nächste Artikelnummer im Nummernkreis existiert schon!', 'The number of days for full payment' => 'Die Anzahl Tage, bis die Rechnung in voller Höhe bezahlt werden muss', 'The numbering will start at 1 with each requirement spec.' => 'Die Nummerierung beginnt bei jedem Pflichtenheft bei 1.', + 'The object has been created.' => 'Das Objekt wurde angelegt.', + 'The object has been deleted.' => 'Das Objekt wurde gelöscht..', + 'The object has been saved.' => 'Das Objekt wurde gespeichert.', + 'The object is in use and cannot be deleted.' => 'Das Objekt ist in Benutzung und kann nicht gelöscht werden.', 'The option field is empty.' => 'Das Optionsfeld ist leer.', 'The order has been deleted' => 'Der Auftrag wurde gelöscht.', 'The order has been saved' => 'Der Auftrag wurde gespeichert.', @@ -3098,10 +3102,6 @@ $self->{texts} = { 'The price rule has been saved.' => 'Die Preisregel wurde gespeichert.', 'The price rule is not a rule for discounts' => 'Die Preisregel ist keine Regel für Rabatte', 'The price rule is not a rule for prices' => 'Die Preisregel ist keine Regel für Preise', - 'The pricegroup has been created.' => 'Die Preisgruppe wurde erstellt.', - 'The pricegroup has been deleted.' => 'Die Preisgruppe wurde gelöscht.', - 'The pricegroup has been saved.' => 'Die Preisgruppe wurde gespeichert.', - 'The pricegroup has been used and cannot be deleted.' => 'Die Preisgruppe wurde bereits verwendet und kann nicht gelöscht werden.', 'The pricegroup is being used by customers.' => 'Die Preisgruppe wird von Kunden verwendet.', 'The printer could not be deleted.' => 'Der Drucker konnte nicht gelöscht werden.', 'The printer has been created.' => 'Der Drucker wurde angelegt.', diff --git a/menus/user/00-erp.yaml b/menus/user/00-erp.yaml index ced4c586f..2ca178e73 100644 --- a/menus/user/00-erp.yaml +++ b/menus/user/00-erp.yaml @@ -1084,7 +1084,8 @@ name: Pricegroups order: 1120 params: - action: Pricegroup/list + action: SimpleSystemSetting/list + type: pricegroup - parent: system id: system_edit_units name: Edit units diff --git a/templates/webpages/pricegroup/form.html b/templates/webpages/pricegroup/form.html deleted file mode 100644 index 7552caa25..000000000 --- a/templates/webpages/pricegroup/form.html +++ /dev/null @@ -1,50 +0,0 @@ -[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%] - -[% SET style="width: 400px" %] -[% SET size=15 %] - -

[% HTML.escape(title) %]

- -
- -[%- INCLUDE 'common/flash.html' %] - -[%- L.hidden_tag("id", SELF.pricegroup.id) %] - - - - - - [% IF SELF.pricegroup.id %] - - - - - - [% END %] -
[% 'Description' | $T8 %] - [%- L.input_tag("pricegroup.pricegroup", SELF.pricegroup.pricegroup) %] -
[% 'Obsolete' | $T8 %][% L.checkbox_tag('pricegroup.obsolete', checked = SELF.pricegroup.obsolete, for_submit=1) %]
- -

- [% L.hidden_tag("action", "Pricegroup/dispatch") %] - [% L.submit_tag("action_" _ (SELF.pricegroup.id ? "update" : "create"), LxERP.t8('Save'), onclick="return check_prerequisites();") %] - [%- IF SELF.pricegroup.id AND SELF.pricegroup.orphaned -%] - [% L.submit_tag("action_delete", LxERP.t8('Delete')) %] - [%- END %] - [%- LxERP.t8("Cancel") %] -

- -
- - diff --git a/templates/webpages/pricegroup/list.html b/templates/webpages/pricegroup/list.html deleted file mode 100644 index 3584a5b50..000000000 --- a/templates/webpages/pricegroup/list.html +++ /dev/null @@ -1,33 +0,0 @@ -[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%][%- INCLUDE 'common/flash.html' %] - -

[% title %]

- -

- - - - - - - - - - - [%- FOREACH pricegroup = SELF.all_pricegroups %] - - - - - - [%- END %] - -
[ LxERP.t8('reorder item') %][% 'Description' | $T8 %][% 'Obsolete' | $T8 %]
[ LxERP.t8('reorder item') %][% HTML.escape(pricegroup.pricegroup) %][% HTML.escape(pricegroup.obsolete) %]
-

- -
- -[% L.sortable_element('#pricegroup_list tbody', url=SELF.url_for(action='reorder'), with='pricegroup_id') %] - -

- [%- 'Add' | $T8 %] -

diff --git a/templates/webpages/simple_system_setting/_default_form.html b/templates/webpages/simple_system_setting/_default_form.html new file mode 100644 index 000000000..c9bf6573f --- /dev/null +++ b/templates/webpages/simple_system_setting/_default_form.html @@ -0,0 +1,7 @@ +[%- USE LxERP -%][%- USE L -%] + + + + + +
[% LxERP.t8("Description") %][% L.input_tag("object.description", LxERP.t8(SELF.object.description), "data-validate"="required", "data-title"=LxERP.t8("Description")) %]
diff --git a/templates/webpages/simple_system_setting/_pricegroup_form.html b/templates/webpages/simple_system_setting/_pricegroup_form.html new file mode 100644 index 000000000..fd4a905bc --- /dev/null +++ b/templates/webpages/simple_system_setting/_pricegroup_form.html @@ -0,0 +1,13 @@ +[%- USE LxERP -%][%- USE L -%] + + + + + + + + + +
[% LxERP.t8("Description") %] + [%- L.input_tag("object.pricegroup", SELF.object.pricegroup, "data-validate"="required", "data-title"=LxERP.t8("Description")) %] +
[% LxERP.t8("Obsolete") %][% L.checkbox_tag("object.obsolete", checked=SELF.object.obsolete, for_submit=1) %]
diff --git a/templates/webpages/simple_system_setting/form.html b/templates/webpages/simple_system_setting/form.html new file mode 100644 index 000000000..da8e4a299 --- /dev/null +++ b/templates/webpages/simple_system_setting/form.html @@ -0,0 +1,26 @@ +[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%] + +[% SET style="width: 400px" %] +[% SET size=15 %] + +

[% HTML.escape(title) %]

+ +[%- INCLUDE "common/flash.html" %] + + + + [%- L.hidden_tag("type", SELF.type) %] + [%- L.hidden_tag("id", SELF.object.id) %] + + [%- SET sub_file = "simple_system_setting/_" _ sub_form_template _ "_form.html"; + INCLUDE $sub_file %] + +

+ [% L.hidden_tag("action", "SimpleSystemSetting/dispatch") %] + [% L.submit_tag("action_" _ (SELF.object.id ? "update" : "create"), LxERP.t8("Save"), onclick="return kivi.validate_form('#form');") %] + [%- IF SELF.object.id && (!SELF.object.can("orphaned") || SELF.object.orphaned) -%] + [% L.submit_tag("action_delete", LxERP.t8("Delete"), confirm=LxERP.t8("Do you really want to delete this object?")) %] + [%- END %] + [%- LxERP.t8("Cancel") %] +

+
diff --git a/templates/webpages/simple_system_setting/list.html b/templates/webpages/simple_system_setting/list.html new file mode 100644 index 000000000..398124cc9 --- /dev/null +++ b/templates/webpages/simple_system_setting/list.html @@ -0,0 +1,51 @@ +[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%] + +

[% HTML.escape(title) %]

+ +[%- INCLUDE 'common/flash.html' %] + + + + + [% IF SELF.supports_reordering %] + + [% END %] + [% FOREACH attribute = SELF.list_attributes %] + [% HTML.escape(attribute.title) %] + [% END %] + + + + + [%- FOREACH object = SELF.all_objects %] + + [% IF SELF.supports_reordering %] + + [% END %][%# IF SELF.supports_reordering %] + [% FOREACH attribute = SELF.list_attributes %] + + [% IF loop.count == 1 %] + + [% END %][%# IF loop.count == 0 %] + [% SET method = attribute.method + value = attribute.exists('formatter') ? attribute.formatter(object) : object.$method ; + HTML.escape(value) %] + [% IF loop.count == 1 %] + + [% END %][%# IF loop.count == 0 %] + + [% END %][%# FOREACH attribute… %] + + [%- END %][%# FOREACH object… %] + +
[ LxERP.t8('reorder item') %]
[% L.img_tag(src="image/updown.png", alt=LxERP.t8("reorder item")) %]
+ +
+ +

+ [%- "Add" | $T8 %] +

+ +[% IF SELF.supports_reordering %] +[% L.sortable_element("#object_list tbody", url=SELF.url_for(action="reorder", type=SELF.type), with="object_id") %] +[% END %]