commit 5e55cce6abaf16fb9425bcdc5a669eaaddca3319
Author: Moritz Bunkus <m.bunkus@linet.de>
Date:   Wed Feb 1 15:06:16 2017 +0100

    SimpleSystemSetting: Umstellung von »Projekttypen« und »Projekstatus«

diff --git a/SL/Controller/ProjectStatus.pm b/SL/Controller/ProjectStatus.pm
deleted file mode 100644
index 686f75c0b..000000000
--- a/SL/Controller/ProjectStatus.pm
+++ /dev/null
@@ -1,112 +0,0 @@
-package SL::Controller::ProjectStatus;
-
-use strict;
-
-use parent qw(SL::Controller::Base);
-
-use SL::DB::ProjectStatus;
-use SL::Helper::Flash;
-
-use Rose::Object::MakeMethods::Generic
-(
- scalar => [ qw(project_status) ],
-);
-
-__PACKAGE__->run_before('check_auth');
-__PACKAGE__->run_before('load_project_status', only => [ qw(edit update destroy) ]);
-
-#
-# actions
-#
-
-sub action_list {
-  my ($self) = @_;
-
-  $self->render('project_status/list',
-                title          => $::locale->text('Project Status'),
-                PROJECT_STATUS => SL::DB::Manager::ProjectStatus->get_all_sorted);
-}
-
-sub action_new {
-  my ($self) = @_;
-
-  $self->{project_status} = SL::DB::ProjectStatus->new;
-  $self->render('project_status/form', title => $::locale->text('Create a new project status'));
-}
-
-sub action_edit {
-  my ($self) = @_;
-  $self->render('project_status/form', title => $::locale->text('Edit project status'));
-}
-
-sub action_create {
-  my ($self) = @_;
-
-  $self->{project_status} = SL::DB::ProjectStatus->new;
-  $self->create_or_update;
-}
-
-sub action_update {
-  my ($self) = @_;
-  $self->create_or_update;
-}
-
-sub action_destroy {
-  my ($self) = @_;
-
-  if (eval { $self->{project_status}->delete; 1; }) {
-    flash_later('info',  $::locale->text('The project status has been deleted.'));
-  } else {
-    flash_later('error', $::locale->text('The project status is in use and cannot be deleted.'));
-  }
-
-  $self->redirect_to(action => 'list');
-}
-
-sub action_reorder {
-  my ($self) = @_;
-
-  SL::DB::ProjectStatus->reorder_list(@{ $::form->{project_status_id} || [] });
-
-  $self->render(\'', { type => 'json' });
-}
-
-#
-# filters
-#
-
-sub check_auth {
-  $::auth->assert('config');
-}
-
-#
-# helpers
-#
-
-sub create_or_update {
-  my $self   = shift;
-  my $is_new = !$self->{project_status}->id;
-  my $params = delete($::form->{project_status}) || { };
-
-  $self->{project_status}->assign_attributes(%{ $params });
-
-  my @errors = $self->{project_status}->validate;
-
-  if (@errors) {
-    flash('error', @errors);
-    $self->render('project_status/form', title => $is_new ? $::locale->text('Create a new project status') : $::locale->text('Edit project status'));
-    return;
-  }
-
-  $self->{project_status}->save;
-
-  flash_later('info', $is_new ? $::locale->text('The project status has been created.') : $::locale->text('The project status has been saved.'));
-  $self->redirect_to(action => 'list');
-}
-
-sub load_project_status {
-  my ($self) = @_;
-  $self->{project_status} = SL::DB::ProjectStatus->new(id => $::form->{id})->load;
-}
-
-1;
diff --git a/SL/Controller/ProjectType.pm b/SL/Controller/ProjectType.pm
deleted file mode 100644
index e986924e2..000000000
--- a/SL/Controller/ProjectType.pm
+++ /dev/null
@@ -1,112 +0,0 @@
-package SL::Controller::ProjectType;
-
-use strict;
-
-use parent qw(SL::Controller::Base);
-
-use SL::DB::ProjectType;
-use SL::Helper::Flash;
-
-use Rose::Object::MakeMethods::Generic
-(
- scalar => [ qw(project_type) ],
-);
-
-__PACKAGE__->run_before('check_auth');
-__PACKAGE__->run_before('load_project_type', only => [ qw(edit update destroy) ]);
-
-#
-# actions
-#
-
-sub action_list {
-  my ($self) = @_;
-
-  $self->render('project_type/list',
-                title         => $::locale->text('Project Types'),
-                PROJECT_TYPES => SL::DB::Manager::ProjectType->get_all_sorted);
-}
-
-sub action_new {
-  my ($self) = @_;
-
-  $self->{project_type} = SL::DB::ProjectType->new;
-  $self->render('project_type/form', title => $::locale->text('Create a new project type'));
-}
-
-sub action_edit {
-  my ($self) = @_;
-  $self->render('project_type/form', title => $::locale->text('Edit project type'));
-}
-
-sub action_create {
-  my ($self) = @_;
-
-  $self->{project_type} = SL::DB::ProjectType->new;
-  $self->create_or_update;
-}
-
-sub action_update {
-  my ($self) = @_;
-  $self->create_or_update;
-}
-
-sub action_destroy {
-  my ($self) = @_;
-
-  if (eval { $self->{project_type}->delete; 1; }) {
-    flash_later('info',  $::locale->text('The project type has been deleted.'));
-  } else {
-    flash_later('error', $::locale->text('The project type is in use and cannot be deleted.'));
-  }
-
-  $self->redirect_to(action => 'list');
-}
-
-sub action_reorder {
-  my ($self) = @_;
-
-  SL::DB::ProjectType->reorder_list(@{ $::form->{project_type_id} || [] });
-
-  $self->render(\'', { type => 'json' });
-}
-
-#
-# filters
-#
-
-sub check_auth {
-  $::auth->assert('config');
-}
-
-#
-# helpers
-#
-
-sub create_or_update {
-  my $self   = shift;
-  my $is_new = !$self->{project_type}->id;
-  my $params = delete($::form->{project_type}) || { };
-
-  $self->{project_type}->assign_attributes(%{ $params });
-
-  my @errors = $self->{project_type}->validate;
-
-  if (@errors) {
-    flash('error', @errors);
-    $self->render('project_type/form', title => $is_new ? $::locale->text('Create a new project type') : $::locale->text('Edit project type'));
-    return;
-  }
-
-  $self->{project_type}->save;
-
-  flash_later('info', $is_new ? $::locale->text('The project type has been created.') : $::locale->text('The project type has been saved.'));
-  $self->redirect_to(action => 'list');
-}
-
-sub load_project_type {
-  my ($self) = @_;
-  $self->{project_type} = SL::DB::ProjectType->new(id => $::form->{id})->load;
-}
-
-1;
diff --git a/SL/Controller/SimpleSystemSetting.pm b/SL/Controller/SimpleSystemSetting.pm
index fe499e2bb..979c2d298 100644
--- a/SL/Controller/SimpleSystemSetting.pm
+++ b/SL/Controller/SimpleSystemSetting.pm
@@ -122,6 +122,25 @@ my %supported_types = (
       { method => 'obsolete',   title => t8('Obsolete'), formatter => sub { $_[0]->obsolete ? t8('yes') : t8('no') } },
     ],
   },
+
+  project_status => {
+    class  => 'ProjectStatus',
+    titles => {
+      list => t8('Project statuses'),
+      add  => t8('Add project status'),
+      edit => t8('Edit project status'),
+    },
+  },
+
+  project_type => {
+    class  => 'ProjectType',
+    titles => {
+      list => t8('Project types'),
+      add  => t8('Add project type'),
+      edit => t8('Edit project type'),
+    },
+  },
+
 );
 
 my @default_list_attributes = (
diff --git a/locale/de/all b/locale/de/all
index a8dbfadfa..71f09c10f 100755
--- a/locale/de/all
+++ b/locale/de/all
@@ -212,6 +212,8 @@ $self->{texts} = {
   'Add picture'                 => 'Bild hinzufügen',
   'Add picture to text block'   => 'Bild dem Textblock hinzufügen',
   'Add pricegroup'              => 'Preisgruppe hinzufügen',
+  'Add project status'          => 'Projektstatus hinzufügen',
+  'Add project type'            => 'Projekttypen hinzufügen',
   'Add section'                 => 'Abschnitt hinzufügen',
   'Add sub function block'      => 'Unterfunktionsblock hinzufügen',
   'Add taxzone'                 => 'Steuerzone hinzufügen',
@@ -671,8 +673,6 @@ $self->{texts} = {
   'Create a new printer'        => 'Einen neuen Drucker anlegen',
   'Create a new project'        => 'Neues Projekt anlegen',
   'Create a new project and link to it.' => 'Neues Projekt anlegen und damit verknüpfen.',
-  'Create a new project status' => 'Einen neuen Projektstatus anlegen',
-  'Create a new project type'   => 'Einen neuen Projekttypen anlegen',
   'Create a new purchase price rule' => 'Neue Einkaufspreisregel anlegen',
   'Create a new requirement spec' => 'Ein neues Pflichtenheft anlegen',
   'Create a new requirement spec status' => 'Einen neuen Pflichtenheftstatus anlegen',
@@ -711,7 +711,6 @@ $self->{texts} = {
   'Create new client #1'        => 'Neuen Mandanten #1 anlegen',
   'Create new delivery term'    => 'Neue Lieferbedingungen anlegen',
   'Create new payment term'     => 'Neue Zahlungsbedingung anlegen',
-  'Create new project type'     => 'Neuen Projekttypen anlegen',
   'Create new quotation or order' => 'Neues Angebot oder neuen Auftrag anlegen',
   'Create new quotation/order'  => 'Neues Angebot/neuen Auftrag anlegen',
   'Create new qutoation/order'  => 'Neues Angebot/neuen Auftrag anlegen',
@@ -1885,8 +1884,6 @@ $self->{texts} = {
   'No print templates have been created for this client yet. Please do so in the client configuration.' => 'Für diesen Mandanten wurden noch keine Druckvorlagen angelegt. Bitte holen Sie dies in der Mandantenkonfiguration nach.',
   'No printers have been created yet.' => 'Es wurden noch keine Drucker angelegt.',
   'No problems were recognized.' => 'Es wurden keine Probleme gefunden.',
-  'No project status has been created yet.' => 'Es wurde noch kein Projektstatus angelegt.',
-  'No project type has been created yet.' => 'Es wurden noch keine Projekttypen angelegt.',
   'No quotations or orders have been created yet.' => 'Es wurden noch keine Angebote oder Aufträge angelegt.',
   'No report with id #1'        => 'Es gibt keinen Report mit der Id #1',
   'No requirement spec statuses has been created yet.' => 'Es wurden noch keine Pflichtenheftstatus angelegt.',
@@ -2263,7 +2260,9 @@ $self->{texts} = {
   'Project Type'                => 'Projekttyp',
   'Project Types'               => 'Projekttypen',
   'Project link actions'        => 'Projektverknüpfungs-Aktionen',
+  'Project statuses'            => 'Projektstatus',
   'Project type'                => 'Projekttyp',
+  'Project types'               => 'Projekttypen',
   'Projects'                    => 'Projekte',
   'Projecttransactions'         => 'Projektbuchungen',
   'Proposal'                    => 'Vorschlag',
@@ -3085,14 +3084,6 @@ $self->{texts} = {
   'The project link has been updated.' => 'Die Projektverknüpfung wurde aktualisiert.',
   'The project number is already in use.' => 'Die Projektnummer wird bereits verwendet.',
   'The project number is missing.' => 'Die Projektnummer fehlt.',
-  'The project status has been created.' => 'Der Projektstatus wurde angelegt.',
-  'The project status has been deleted.' => 'Der Projektstatus wurde gelöscht.',
-  'The project status has been saved.' => 'Der Projektstatus wurde gespeichert.',
-  'The project status is in use and cannot be deleted.' => 'Der Projektstatus wird verwendet und kann nicht gelöscht werden.',
-  'The project type has been created.' => 'Der Projekttyp wurde angelegt.',
-  'The project type has been deleted.' => 'Der Projekttyp wurde gelöscht.',
-  'The project type has been saved.' => 'Der Projekttyp wurde gespeichert.',
-  'The project type is in use and cannot be deleted.' => 'Der Projekttyp wird verwendet und kann nicht gelöscht werden.',
   'The receivables chart isn\'t a valid chart.' => 'Das Forderungskonto ist kein gültiges Konto',
   'The recipient, subject or body is missing.' => 'Der Empfäger, der Betreff oder der Text ist leer.',
   'The record template \'#1\' has been loaded.' => 'Die Belegvorlage »#1« wurde geladen.',
diff --git a/menus/user/00-erp.yaml b/menus/user/00-erp.yaml
index 5cd935799..3ad003fcf 100644
--- a/menus/user/00-erp.yaml
+++ b/menus/user/00-erp.yaml
@@ -1122,13 +1122,15 @@
   name: Project Types
   order: 1600
   params:
-    action: ProjectType/list
+    action: SimpleSystemSetting/list
+    type: project_type
 - parent: system
   id: system_project_status
   name: Project Status
   order: 1700
   params:
-    action: ProjectStatus/list
+    action: SimpleSystemSetting/list
+    type: project_status
 - parent: system
   id: system_requirement_specs
   name: Requirement specs
diff --git a/templates/webpages/project_status/form.html b/templates/webpages/project_status/form.html
deleted file mode 100644
index 21735168b..000000000
--- a/templates/webpages/project_status/form.html
+++ /dev/null
@@ -1,29 +0,0 @@
-[% USE HTML %][% USE L %][% USE LxERP %]
-<h1>[% FORM.title %]</h1>
-
- <form method="post" action="controller.pl">
-
-[%- INCLUDE 'common/flash.html' %]
-
-  <table>
-   <tr>
-    <td>[% LxERP.t8('Name') %]</td>
-    <td>[% L.input_tag("project_status.name" SELF.project_status.name) %]</td>
-   </tr>
-   <tr>
-    <td>[% LxERP.t8('Description') %]</td>
-    <td>[% L.input_tag("project_status.description" SELF.project_status.description) %]</td>
-   </tr>
-  </table>
-
-  <p>
-   [% L.hidden_tag("id", SELF.project_status.id) %]
-   [% L.hidden_tag("action", "ProjectStatus/dispatch") %]
-   [% L.submit_tag("action_" _ (SELF.project_status.id ? 'update' : 'create'), LxERP.t8('Save')) %]
-   [%- IF SELF.project_status.id %]
-    [% L.submit_tag("action_destroy", LxERP.t8('Delete'), confirm=LxERP.t8('Do you really want to delete this object?')) %]
-   [%- END %]
-   <a href="[% SELF.url_for(action => 'list') %]">[% LxERP.t8('Abort') %]</a>
-  </p>
-
- </form>
diff --git a/templates/webpages/project_status/list.html b/templates/webpages/project_status/list.html
deleted file mode 100644
index 60caa6f2c..000000000
--- a/templates/webpages/project_status/list.html
+++ /dev/null
@@ -1,39 +0,0 @@
-[% USE HTML %][% USE T8 %][% USE L %][% USE LxERP %]
- <h1>[% FORM.title %]</h1>
-
-[%- INCLUDE 'common/flash.html' %]
-
- <form method="post" action="controller.pl">
-  [% IF !PROJECT_STATUS.size %]
-   <p>
-    [%- 'No project status has been created yet.' | $T8 %]
-   </p>
-
-  [%- ELSE %]
-   <table id="project_status_list">
-    <thead>
-    <tr class="listheading">
-     <th align="center"><img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]"></th>
-     <th>[%- 'Name' | $T8 %]</th>
-     <th>[%- 'Description' | $T8 %]</th>
-    </tr>
-    </thead>
-
-    <tbody>
-    [%- FOREACH project_status = PROJECT_STATUS %]
-    <tr class="listrow[% loop.count % 2 %]" id="project_status_id_[% project_status.id %]">
-     <td align="center" class="dragdrop"><img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]"></td>
-     <td><a href="[% SELF.url_for(action => 'edit', id => project_status.id) %]">[% project_status.name | html %]</a></td>
-     <td><a href="[% SELF.url_for(action => 'edit', id => project_status.id) %]">[% project_status.description | html %]</a></td>
-    </tr>
-    [%- END %]
-    </tbody>
-   </table>
-  [%- END %]
-
-  <p>
-   <a href="[% SELF.url_for(action => 'new') %]">[%- 'Create a new project status' | $T8 %]</a>
-  </p>
- </form>
-
- [% L.sortable_element('#project_status_list tbody', url => 'controller.pl?action=ProjectStatus/reorder', with => 'project_status_id') %]
diff --git a/templates/webpages/project_type/form.html b/templates/webpages/project_type/form.html
deleted file mode 100755
index 79bb121fc..000000000
--- a/templates/webpages/project_type/form.html
+++ /dev/null
@@ -1,25 +0,0 @@
-[% USE HTML %][% USE L %][% USE LxERP %]
-<h1>[% FORM.title %]</h1>
-
- <form method="post" action="controller.pl">
-
-[%- INCLUDE 'common/flash.html' %]
-
-  <table>
-   <tr>
-    <td>[% LxERP.t8('Description') %]</td>
-    <td>[% L.input_tag("project_type.description" SELF.project_type.description) %]</td>
-   </tr>
-  </table>
-
-  <p>
-   [% L.hidden_tag("id", SELF.project_type.id) %]
-   [% L.hidden_tag("action", "ProjectType/dispatch") %]
-   [% L.submit_tag("action_" _ (SELF.project_type.id ? 'update' : 'create'), LxERP.t8('Save')) %]
-   [%- IF SELF.project_type.id %]
-    [% L.submit_tag("action_destroy", LxERP.t8('Delete'), confirm=LxERP.t8('Do you really want to delete this object?')) %]
-   [%- END %]
-   <a href="[% SELF.url_for(action => 'list') %]">[% LxERP.t8('Abort') %]</a>
-  </p>
-
- </form>
diff --git a/templates/webpages/project_type/list.html b/templates/webpages/project_type/list.html
deleted file mode 100644
index fb0c8c2fd..000000000
--- a/templates/webpages/project_type/list.html
+++ /dev/null
@@ -1,41 +0,0 @@
-[% USE HTML %][% USE T8 %][% USE L %][% USE LxERP %]
-<h1>[% FORM.title %]</h1>
-
-[%- INCLUDE 'common/flash.html' %]
-
- <form method="post" action="controller.pl">
-  [% IF !PROJECT_TYPES.size %]
-   <p>
-    [%- 'No project type has been created yet.' | $T8 %]
-   </p>
-
-  [%- ELSE %]
-   <table id="project_type_list">
-    <thead>
-    <tr class="listheading">
-     <th align="center"><img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]"></th>
-     <th>[%- 'Description' | $T8 %]</th>
-    </tr>
-    </thead>
-
-    <tbody>
-    [%- FOREACH project_type = PROJECT_TYPES %]
-    <tr class="listrow[% loop.count % 2 %]" id="project_type_id_[% project_type.id %]">
-     <td align="center" class="dragdrop"><img src="image/updown.png" alt="[%- LxERP.t8('reorder item') %]"></td>
-     <td>
-      <a href="[% SELF.url_for(action => 'edit', id => project_type.id) %]">
-       [%- HTML.escape(project_type.description) %]
-      </a>
-     </td>
-    </tr>
-    [%- END %]
-    </tbody>
-   </table>
-  [%- END %]
-
-  <p>
-   <a href="[% SELF.url_for(action => 'new') %]">[%- 'Create new project type' | $T8 %]</a>
-  </p>
- </form>
-
- [% L.sortable_element('#project_type_list tbody', url => 'controller.pl?action=ProjectType/reorder', with => 'project_type_id') %]
