Revision 9c785acd
Von Kivitendo Admin vor fast 8 Jahren hinzugefügt
SL/Controller/Part.pm | ||
---|---|---|
872 | 872 |
} |
873 | 873 |
|
874 | 874 |
sub init_all_partsgroups { |
875 |
SL::DB::Manager::PartsGroup->get_all_sorted; |
|
875 |
my ($self) = @_; |
|
876 |
SL::DB::Manager::PartsGroup->get_all_sorted(query => [ or => [ id => $self->part->partsgroup_id, obsolete => 0 ] ]); |
|
876 | 877 |
} |
877 | 878 |
|
878 | 879 |
sub init_all_buchungsgruppen { |
SL/Controller/PartsGroup.pm | ||
---|---|---|
1 |
package SL::Controller::PartsGroup; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::Controller::Base); |
|
6 |
|
|
7 |
use SL::Helper::Flash; |
|
8 |
use SL::Locale::String; |
|
9 |
use SL::DB::Default; |
|
10 |
use SL::DB::Manager::PartsGroup; |
|
11 |
|
|
12 |
use Rose::Object::MakeMethods::Generic ( |
|
13 |
scalar => [ qw(partsgroup) ], |
|
14 |
'scalar --get_set_init' => [ qw(all_partsgroups) ], |
|
15 |
); |
|
16 |
|
|
17 |
__PACKAGE__->run_before('check_auth'); |
|
18 |
__PACKAGE__->run_before('load_partsgroup', only => [ qw(edit update delete) ]); |
|
19 |
|
|
20 |
# |
|
21 |
# actions |
|
22 |
# |
|
23 |
|
|
24 |
sub action_list { |
|
25 |
my ($self) = @_; |
|
26 |
|
|
27 |
$self->render('partsgroup/list', |
|
28 |
title => t8('Partsgroups'), |
|
29 |
); |
|
30 |
} |
|
31 |
|
|
32 |
sub action_new { |
|
33 |
my ($self) = @_; |
|
34 |
|
|
35 |
$self->partsgroup( SL::DB::PartsGroup->new ); |
|
36 |
$self->render('partsgroup/form', |
|
37 |
title => t8('Add partsgroup'), |
|
38 |
); |
|
39 |
} |
|
40 |
|
|
41 |
sub action_edit { |
|
42 |
my ($self) = @_; |
|
43 |
|
|
44 |
$self->render('partsgroup/form', |
|
45 |
title => t8('Edit partsgroup'), |
|
46 |
); |
|
47 |
} |
|
48 |
|
|
49 |
sub action_create { |
|
50 |
my ($self) = @_; |
|
51 |
|
|
52 |
$self->partsgroup( SL::DB::PartsGroup->new ); |
|
53 |
$self->create_or_update; |
|
54 |
} |
|
55 |
|
|
56 |
sub action_update { |
|
57 |
my ($self) = @_; |
|
58 |
$self->create_or_update; |
|
59 |
} |
|
60 |
|
|
61 |
sub action_delete { |
|
62 |
my ($self) = @_; |
|
63 |
|
|
64 |
if ( !$self->partsgroup->orphaned ) { |
|
65 |
flash_later('error', $::locale->text('The partsgroup has been used and cannot be deleted.')); |
|
66 |
} elsif ( eval { $self->partsgroup->delete; 1; } ) { |
|
67 |
flash_later('info', $::locale->text('The partsgroup has been deleted.')); |
|
68 |
} else { |
|
69 |
flash_later('error', $::locale->text('The partsgroup has been used and cannot be deleted.')); |
|
70 |
}; |
|
71 |
$self->redirect_to(action => 'list'); |
|
72 |
} |
|
73 |
|
|
74 |
sub action_reorder { |
|
75 |
my ($self) = @_; |
|
76 |
|
|
77 |
SL::DB::PartsGroup->reorder_list(@{ $::form->{partsgroup_id} || [] }); |
|
78 |
$self->render(\'', { type => 'json' }); |
|
79 |
} |
|
80 |
|
|
81 |
# |
|
82 |
# filters |
|
83 |
# |
|
84 |
|
|
85 |
sub check_auth { |
|
86 |
$::auth->assert('config'); |
|
87 |
} |
|
88 |
|
|
89 |
sub load_partsgroup { |
|
90 |
my ($self) = @_; |
|
91 |
|
|
92 |
$self->partsgroup( SL::DB::PartsGroup->new(id => $::form->{id})->load ); |
|
93 |
} |
|
94 |
|
|
95 |
sub init_all_partsgroups { SL::DB::Manager::PartsGroup->get_all_sorted } |
|
96 |
|
|
97 |
# |
|
98 |
# helpers |
|
99 |
# |
|
100 |
|
|
101 |
sub create_or_update { |
|
102 |
my ($self) = @_; |
|
103 |
my $is_new = !$self->partsgroup->id; |
|
104 |
|
|
105 |
my $params = delete($::form->{partsgroup}) || { }; |
|
106 |
|
|
107 |
$self->partsgroup->assign_attributes(%{ $params }); |
|
108 |
|
|
109 |
my @errors = $self->partsgroup->validate; |
|
110 |
|
|
111 |
if (@errors) { |
|
112 |
flash('error', @errors); |
|
113 |
$self->render('partsgroup/form', |
|
114 |
title => $is_new ? t8('Add partsgroup') : t8('Edit partsgroup'), |
|
115 |
); |
|
116 |
return; |
|
117 |
} |
|
118 |
|
|
119 |
$self->partsgroup->save; |
|
120 |
|
|
121 |
flash_later('info', $is_new ? t8('The partsgroup has been created.') : t8('The partsgroup has been saved.')); |
|
122 |
$self->redirect_to(action => 'list'); |
|
123 |
} |
|
124 |
|
|
125 |
1; |
|
126 |
|
|
127 |
__END__ |
|
128 |
|
|
129 |
=encoding utf-8 |
|
130 |
|
|
131 |
=head1 NAME |
|
132 |
|
|
133 |
SL::Controller::PartsGroup - CRUD controller for partsgroups |
|
134 |
|
|
135 |
=head1 SYNOPSIS |
|
136 |
|
|
137 |
A new controller to create / edit / delete partsgroups. |
|
138 |
|
|
139 |
Partsgroups can only be deleted if they haven't been used anywhere. |
|
140 |
|
|
141 |
=head1 OBSOLETE PARTSGROUPS |
|
142 |
|
|
143 |
A partsgroup can be deleted if it hasn't been used anywhere / is orphaned. |
|
144 |
|
|
145 |
A partsgroup can be set to obsolete, which means new items can't be assigned |
|
146 |
that partsgroup, but old items with that partsgroup can keep it. And you can |
|
147 |
also still filter for these obsolete partsgroups in reports. |
|
148 |
|
|
149 |
=head1 ISSUES |
|
150 |
|
|
151 |
Unlike the old version (pe.pl/PE.pm), there is no way to filter/search the |
|
152 |
partsgroups in the overview page, it always shows the complete (ordered) list, |
|
153 |
ordered by sortkey. |
|
154 |
|
|
155 |
=head1 AUTHOR |
|
156 |
|
|
157 |
G. Richardson E<lt>grichardson@kivitendo-premium.deE<gt> |
|
158 |
|
|
159 |
=cut |
SL/DB/Manager/PartsGroup.pm | ||
---|---|---|
12 | 12 |
__PACKAGE__->make_manager_methods; |
13 | 13 |
|
14 | 14 |
sub _sort_spec { |
15 |
return ( default => [ 'partsgroup', 1 ],
|
|
15 |
return ( default => [ 'sortkey', 1 ],
|
|
16 | 16 |
columns => { SIMPLE => 'ALL' }); |
17 | 17 |
} |
18 | 18 |
|
SL/DB/MetaSetup/PartsGroup.pm | ||
---|---|---|
12 | 12 |
id => { type => 'integer', not_null => 1, sequence => 'id' }, |
13 | 13 |
itime => { type => 'timestamp', default => 'now()' }, |
14 | 14 |
mtime => { type => 'timestamp' }, |
15 |
obsolete => { type => 'boolean', default => 'false' }, |
|
15 | 16 |
partsgroup => { type => 'text' }, |
17 |
sortkey => { type => 'integer', not_null => 1 }, |
|
16 | 18 |
); |
17 | 19 |
|
18 | 20 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
SL/DB/PartsGroup.pm | ||
---|---|---|
7 | 7 |
|
8 | 8 |
use SL::DB::MetaSetup::PartsGroup; |
9 | 9 |
use SL::DB::Manager::PartsGroup; |
10 |
use SL::DB::Helper::ActsAsList; |
|
10 | 11 |
|
11 | 12 |
__PACKAGE__->meta->add_relationship( |
12 | 13 |
custom_variable_configs => { |
... | ... | |
23 | 24 |
return join ' ', grep $_, $self->id, $self->partsgroup; |
24 | 25 |
} |
25 | 26 |
|
27 |
sub validate { |
|
28 |
my ($self) = @_; |
|
29 |
require SL::DB::Customer; |
|
30 |
|
|
31 |
my @errors; |
|
32 |
|
|
33 |
push @errors, $::locale->text('The description is missing.') if $self->id and !$self->partsgroup; |
|
34 |
|
|
35 |
return @errors; |
|
36 |
} |
|
37 |
|
|
38 |
sub orphaned { |
|
39 |
my ($self) = @_; |
|
40 |
die 'not an accessor' if @_ > 1; |
|
41 |
|
|
42 |
return 1 unless $self->id; |
|
43 |
|
|
44 |
my @relations = qw( |
|
45 |
SL::DB::Part |
|
46 |
SL::DB::CustomVariableConfigPartsgroup |
|
47 |
); |
|
48 |
|
|
49 |
for my $class (@relations) { |
|
50 |
eval "require $class"; |
|
51 |
return 0 if $class->_get_manager_class->get_all_count(query => [ partsgroup_id => $self->id ]); |
|
52 |
} |
|
53 |
|
|
54 |
return 1; |
|
55 |
} |
|
56 |
|
|
26 | 57 |
1; |
locale/de/all | ||
---|---|---|
204 | 204 |
'Add new price rule item' => 'Neue Bedingung hinzufügen', |
205 | 205 |
'Add note' => 'Notiz erfassen', |
206 | 206 |
'Add part' => 'Artikel hinzufügen', |
207 |
'Add partsgroup' => 'Warengruppe hinzufügen', |
|
207 | 208 |
'Add picture' => 'Bild hinzufügen', |
208 | 209 |
'Add picture to text block' => 'Bild dem Textblock hinzufügen', |
209 | 210 |
'Add pricegroup' => 'Preisgruppe hinzufügen', |
... | ... | |
1109 | 1110 |
'Edit general settings' => 'Grundeinstellungen bearbeiten', |
1110 | 1111 |
'Edit greetings' => 'Anreden bearbeiten', |
1111 | 1112 |
'Edit note' => 'Notiz bearbeiten', |
1113 |
'Edit partsgroup' => 'Warengruppe bearbeiten', |
|
1112 | 1114 |
'Edit payment term' => 'Zahlungsbedingungen bearbeiten', |
1113 | 1115 |
'Edit picture' => 'Bild bearbeiten', |
1114 | 1116 |
'Edit predefined text' => 'Vordefinierten Textblock bearbeiten', |
... | ... | |
2041 | 2043 |
'Parts, services and assemblies' => 'Waren, Dienstleistungen und Erzeugnisse', |
2042 | 2044 |
'Partsgroup (database ID)' => 'Warengruppe (Datenbank-ID)', |
2043 | 2045 |
'Partsgroup (name)' => 'Warengruppe (Name)', |
2046 |
'Partsgroups' => 'Warengruppen', |
|
2044 | 2047 |
'Partsgroups where variables are shown' => 'Warengruppen, bei denen Variablen angezeigt werden', |
2045 | 2048 |
'Password' => 'Passwort', |
2046 | 2049 |
'Paste' => 'Einfügen', |
... | ... | |
2982 | 2985 |
'The parts have been removed.' => 'Die Waren wurden aus dem Lager entnommen.', |
2983 | 2986 |
'The parts have been stocked.' => 'Die Artikel wurden eingelagert.', |
2984 | 2987 |
'The parts have been transferred.' => 'Die Waren wurden umgelagert.', |
2988 |
'The partsgroup has been created.' => 'Die Warengruppe wurde erstellt.', |
|
2989 |
'The partsgroup has been deleted.' => 'Die Warengruppe wurde gelöscht.', |
|
2990 |
'The partsgroup has been saved.' => 'Die Warengruppe wurde gespeichert.', |
|
2991 |
'The partsgroup has been used and cannot be deleted.' => 'Die Warengruppe wurde bereits verwendet und kann nicht gelöscht werden.', |
|
2985 | 2992 |
'The password is too long (maximum length: #1).' => 'Das Passwort ist zu lang (maximale Länge: #1).', |
2986 | 2993 |
'The password is too short (minimum length: #1).' => 'Das Password ist zu kurz (minimale Länge: #1).', |
2987 | 2994 |
'The password is weak (e.g. it can be found in a dictionary).' => 'Das Passwort ist schwach (z.B. wenn es in einem Wörterbuch steht).', |
locale/en/all | ||
---|---|---|
158 | 158 |
'Add Follow-Up' => '', |
159 | 159 |
'Add Follow-Up for #1' => '', |
160 | 160 |
'Add General Ledger Transaction' => '', |
161 |
'Add Group' => '', |
|
162 | 161 |
'Add Language' => '', |
163 | 162 |
'Add Lead' => '', |
164 | 163 |
'Add Letter' => '', |
... | ... | |
203 | 202 |
'Add new price rule item' => '', |
204 | 203 |
'Add note' => '', |
205 | 204 |
'Add part' => '', |
205 |
'Add partsgroup' => '', |
|
206 | 206 |
'Add picture' => '', |
207 | 207 |
'Add picture to text block' => '', |
208 | 208 |
'Add pricegroup' => '', |
... | ... | |
1106 | 1106 |
'Edit general settings' => '', |
1107 | 1107 |
'Edit greetings' => '', |
1108 | 1108 |
'Edit note' => '', |
1109 |
'Edit partsgroup' => '', |
|
1109 | 1110 |
'Edit payment term' => '', |
1110 | 1111 |
'Edit picture' => '', |
1111 | 1112 |
'Edit predefined text' => '', |
... | ... | |
2032 | 2033 |
'Parts Master Data' => '', |
2033 | 2034 |
'Parts with existing part numbers' => '', |
2034 | 2035 |
'Parts, services and assemblies' => '', |
2036 |
'Partsgroup' => '', |
|
2035 | 2037 |
'Partsgroup (database ID)' => '', |
2036 | 2038 |
'Partsgroup (name)' => '', |
2039 |
'Partsgroups' => '', |
|
2037 | 2040 |
'Partsgroups where variables are shown' => '', |
2038 | 2041 |
'Password' => '', |
2039 | 2042 |
'Paste' => '', |
... | ... | |
2976 | 2979 |
'The parts have been removed.' => '', |
2977 | 2980 |
'The parts have been stocked.' => '', |
2978 | 2981 |
'The parts have been transferred.' => '', |
2982 |
'The partsgroup has been created.' => '', |
|
2983 |
'The partsgroup has been deleted.' => '', |
|
2984 |
'The partsgroup has been saved.' => '', |
|
2985 |
'The partsgroup has been used and cannot be deleted.' => '', |
|
2979 | 2986 |
'The password is too long (maximum length: #1).' => '', |
2980 | 2987 |
'The password is too short (minimum length: #1).' => '', |
2981 | 2988 |
'The password is weak (e.g. it can be found in a dictionary).' => '', |
menus/user/00-erp.yaml | ||
---|---|---|
1081 | 1081 |
params: |
1082 | 1082 |
action: BankAccount/list |
1083 | 1083 |
- parent: system |
1084 |
id: system_groups |
|
1085 |
name: Groups
|
|
1084 |
id: system_partsgroups
|
|
1085 |
name: Partsgroups
|
|
1086 | 1086 |
order: 900 |
1087 |
module: pe.pl |
|
1088 | 1087 |
params: |
1089 |
action: search |
|
1090 |
type: partsgroup |
|
1088 |
action: PartsGroup/list |
|
1091 | 1089 |
- parent: system |
1092 | 1090 |
id: system_pricegroups |
1093 | 1091 |
name: Pricegroups |
sql/Pg-upgrade2/partsgroup_sortkey_obsolete.sql | ||
---|---|---|
1 |
-- @tag: partsgroup_sortkey_obsolete |
|
2 |
-- @description: Sortierreihenfolge und ungültig für Warengruppen |
|
3 |
-- @charset: UTF-8 |
|
4 |
-- @depends: release_3_4_1 |
|
5 |
-- @ignore: 0 |
|
6 |
|
|
7 |
ALTER TABLE partsgroup ADD COLUMN obsolete BOOLEAN DEFAULT FALSE; |
|
8 |
ALTER TABLE partsgroup ADD COLUMN sortkey INTEGER; |
|
9 |
|
|
10 |
CREATE SEQUENCE tmp_counter; |
|
11 |
UPDATE partsgroup SET sortkey = nextval('tmp_counter'); |
|
12 |
DROP SEQUENCE tmp_counter; |
|
13 |
ALTER TABLE partsgroup ALTER COLUMN sortkey SET NOT NULL; |
templates/webpages/partsgroup/form.html | ||
---|---|---|
1 |
[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%] |
|
2 |
|
|
3 |
[% SET style="width: 400px" %] |
|
4 |
[% SET size=15 %] |
|
5 |
|
|
6 |
<h1>[% HTML.escape(title) %]</h1> |
|
7 |
|
|
8 |
<form action="controller.pl" method="post"> |
|
9 |
|
|
10 |
[%- INCLUDE 'common/flash.html' %] |
|
11 |
|
|
12 |
[%- L.hidden_tag("id", SELF.partsgroup.id) %] |
|
13 |
|
|
14 |
<table> |
|
15 |
<tr> |
|
16 |
<th align="right">[% 'Description' | $T8 %]</th> |
|
17 |
<td> |
|
18 |
[%- L.input_tag("partsgroup.partsgroup", SELF.partsgroup.partsgroup) %] |
|
19 |
</td> |
|
20 |
[% IF SELF.partsgroup.id %] |
|
21 |
<tr> |
|
22 |
<th align="right">[% 'Obsolete' | $T8 %]</th> |
|
23 |
<td>[% L.checkbox_tag('partsgroup.obsolete', checked = SELF.partsgroup.obsolete, for_submit=1) %]</td> |
|
24 |
</tr> |
|
25 |
</tr> |
|
26 |
[% END %] |
|
27 |
</table> |
|
28 |
|
|
29 |
<p> |
|
30 |
[% L.hidden_tag("action", "PartsGroup/dispatch") %] |
|
31 |
[% L.submit_tag("action_" _ (SELF.partsgroup.id ? "update" : "create"), LxERP.t8('Save'), onclick="return check_prerequisites();") %] |
|
32 |
[%- IF SELF.partsgroup.id AND SELF.partsgroup.orphaned -%] |
|
33 |
[% L.submit_tag("action_delete", LxERP.t8('Delete')) %] |
|
34 |
[%- END %] |
|
35 |
<a href="[% SELF.url_for(action='list') %]">[%- LxERP.t8("Cancel") %]</a> |
|
36 |
</p> |
|
37 |
|
|
38 |
<hr> |
|
39 |
|
|
40 |
<script type="text/javascript"> |
|
41 |
<!-- |
|
42 |
function check_prerequisites() { |
|
43 |
if ($('#partsgroup_partsgroup').val() === "") { |
|
44 |
alert(kivi.t8('The description is missing.')); |
|
45 |
return false; |
|
46 |
} |
|
47 |
return true; |
|
48 |
} |
|
49 |
--> |
|
50 |
</script> |
Auch abrufbar als: Unified diff
Warengruppen - Umstellung auf Controller, sortkey, obsolete
Neuer CRUD-Controller nur für Warengruppen
Die Reihenfolge der Warengruppen kann nun eingestellt werden, und man kann
Warengruppen auf ungültig setzen, sofern sie nicht mehr aktiv bei Artikeln in
Verwendung sind, so daß sie bei neuen Waren nicht mehr ausgewählt werden
können.