Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 65d2537d

Von Martin Helmling martin.helmling@octosoft.eu vor fast 8 Jahren hinzugefügt

  • ID 65d2537d658b99b005a18c6663bc1293b41a1d83
  • Vorgänger 2ee7cc2f
  • Nachfolger 219d88ab

Artikel-Klassifizierung

Die Klassifizierung von Artikeln dient einer weiteren Gliederung um zum Beispiel den Einkauf vom Verkauf zu trennen, etc.
Gekennzeichnet durch eine Beschreibung (z.B. "Einkauf") und ein Kürzel (z.B. "E")
Flexibel änderbar und erweiterbar.
- Neue Datenbanktablle und Rose-Objekte, sowie Controller zum Bearbeiten der Tabelle
- Zwei-Zeichen Abkürzung:
Der Typ des Artikel und die Klassifizierung werden durch zwei Buchstaben dargestellt.
Der erste Buchstabe ist eine Lokalisierung des Typs des Artikel ('P','A','S') ,
deutch 'W', 'E', und 'D' für Ware Erzeugnis oder Dienstleistung, ggf. weitere Typen.
Der zweite Buchstabe ist eine Lokalisierung der Klassifizierungsabkürzung (abbreviation).
Die Abkürzungen sind aus dem Part Presenter abholbar:
- SL::Presenter::Part->type_abbreviation($part_type)
- SL::Presenter::Part->classification_abbreviation($classification_id)
Anpassung des CSV Import,
nun wird alternativ zur 'part_type'-Spalte die 'pclass'-Spalte mit zwei Buchstaben geparsed und entsprechend
classification_id, part_type gesetzt.

Unterschiede anzeigen:

SL/Controller/CsvImport/Part.pm
23 23
use Rose::Object::MakeMethods::Generic
24 24
(
25 25
 scalar                  => [ qw(table makemodel_columns) ],
26
 'scalar --get_set_init' => [ qw(bg_by settings parts_by price_factors_by units_by partsgroups_by
26
 'scalar --get_set_init' => [ qw(bg_by settings parts_by price_factors_by classification_by units_by partsgroups_by
27 27
                                 warehouses_by bins_by
28 28
                                 translation_columns all_pricegroups) ],
29 29
);
......
40 40
                       article_number_policy     => 'update_prices',
41 41
                       shoparticle_if_missing    => '0',
42 42
                       part_type                 => 'part',
43
                       part_classification       => 0,
43 44
                       default_buchungsgruppe    => ($bugru ? $bugru->id : undef),
44 45
                       apply_buchungsgruppe      => 'all',
45 46
                      );
......
58 59
  return { map { my $col = $_; ( $col => { map { ( $_->$col => $_ ) } @{ $all_bg } } ) } qw(id description) };
59 60
}
60 61

  
62
sub init_classification_by {
63
  my ($self) = @_;
64
  my $all_classifications = SL::DB::Manager::PartClassification->get_all;
65
  $_->abbreviation($::locale->text($_->abbreviation)) for @{ $all_classifications };
66
  return { map { my $col = $_; ( $col => { map { ( $_->$col => $_ ) } @{ $all_classifications } } ) } qw(id abbreviation) };
67
}
68

  
61 69
sub init_price_factors_by {
62 70
  my ($self) = @_;
63 71

  
......
126 134

  
127 135
  return { map { ( $_ => $self->controller->profile->get($_) ) } qw(apply_buchungsgruppe default_buchungsgruppe article_number_policy
128 136
                                                                    sellprice_places sellprice_adjustment sellprice_adjustment_type
129
                                                                    shoparticle_if_missing part_type default_unit) };
137
                                                                    shoparticle_if_missing part_type classification_id default_unit) };
130 138
}
131 139

  
132 140
sub init_all_cvar_configs {
......
174 182
    $i++;
175 183
  }
176 184

  
177
  $self->add_columns(qw(part_type)) if $self->settings->{part_type} eq 'mixed';
185
  $self->add_columns(qw(part_type classification_id)) if $self->settings->{part_type} eq 'mixed';
178 186
  $self->add_columns(qw(buchungsgruppen_id unit));
179 187
  $self->add_columns(map { "${_}_id" } grep { exists $self->controller->data->[0]->{raw_data}->{$_} } qw (price_factor payment partsgroup warehouse bin));
180 188
  $self->add_columns(qw(shop)) if $self->settings->{shoparticle_if_missing};
......
413 421
  # $bg  ||= SL::DB::Buchungsgruppe->new(inventory_accno_id => 1); # does this case ever occur?
414 422

  
415 423
  my $part_type = $self->settings->{part_type};
416
  if ($part_type eq 'mixed') {
417
    $part_type = $entry->{raw_data}->{part_type} =~ m/^p/i ? 'part'
418
               : $entry->{raw_data}->{part_type} =~ m/^s/i ? 'service'
424
  if ($part_type eq 'mixed' && $entry->{raw_data}->{part_type}) {
425
    $part_type = $entry->{raw_data}->{part_type} =~ m/^p/i     ? 'part'
426
               : $entry->{raw_data}->{part_type} =~ m/^s/i     ? 'service'
419 427
               : $entry->{raw_data}->{part_type} =~ m/^assem/i ? 'assembly'
420 428
               : $entry->{raw_data}->{part_type} =~ m/^assor/i ? 'assortment'
421
               : undef;
429
               :                                                 $self->settings->{part_type};
430
  }
431
  my $classification_id = $self->settings->{classification_id};
432

  
433
  if ( $entry->{raw_data}->{pclass} && length($entry->{raw_data}->{pclass}) >= 2 ) {
434
    my $abbr1 = substr($entry->{raw_data}->{pclass},0,1);
435
    my $abbr2 = substr($entry->{raw_data}->{pclass},1);
436

  
437
    if ( $self->classification_by->{abbreviation}->{$abbr2} ) {
438
      my $tmp_classification_id = $self->classification_by->{abbreviation}->{$abbr2}->id;
439
      $classification_id = $tmp_classification_id if $tmp_classification_id;
440
    }
441
    if ($part_type eq 'mixed') {
442
      $part_type = $abbr1 eq $::locale->text('Part (typeabbreviation)') ? 'part'
443
        : $abbr1 eq $::locale->text('Service (typeabbreviation)')       ? 'service'
444
        : $abbr1 eq $::locale->text('Assembly (typeabbreviation)')      ? 'assembly'
445
        : $abbr1 eq $::locale->text('Assortment (typeabbreviation)')    ? 'assortment'
446
        :                                                                 undef;
447
    }
422 448
  }
423 449

  
424 450
  # when saving income_accno_id or expense_accno_id use ids from the selected
......
443 469
  }
444 470

  
445 471
  $entry->{object}->part_type($part_type);
472
  $entry->{object}->classification_id( $classification_id );
446 473

  
447 474
  return 1;
448 475
}
......
699 726

  
700 727
  $self->add_displayable_columns({ name => 'bin_id',             description => $::locale->text('Bin (database ID)')                                    },
701 728
                                 { name => 'bin',                description => $::locale->text('Bin (name)')                                           },
702
                                 { name => 'buchungsgruppen_id', description => $::locale->text('Booking group (database ID)')                         },
703
                                 { name => 'buchungsgruppe',     description => $::locale->text('Booking group (name)')                                },
729
                                 { name => 'buchungsgruppen_id', description => $::locale->text('Booking group (database ID)')                          },
730
                                 { name => 'buchungsgruppe',     description => $::locale->text('Booking group (name)')                                 },
704 731
                                 { name => 'description',        description => $::locale->text('Description')                                          },
705 732
                                 { name => 'drawing',            description => $::locale->text('Drawing')                                              },
706 733
                                 { name => 'ean',                description => $::locale->text('EAN')                                                  },
......
721 748
                                 { name => 'partnumber',         description => $::locale->text('Part Number')                                          },
722 749
                                 { name => 'partsgroup_id',      description => $::locale->text('Partsgroup (database ID)')                             },
723 750
                                 { name => 'partsgroup',         description => $::locale->text('Partsgroup (name)')                                    },
751
                                 { name => 'part_classification',description => $::locale->text('Article classification')  . ' [3]'                     },
724 752
                                 { name => 'payment_id',         description => $::locale->text('Payment terms (database ID)')                          },
725 753
                                 { name => 'payment',            description => $::locale->text('Payment terms (name)')                                 },
726 754
                                 { name => 'price_factor_id',    description => $::locale->text('Price factor (database ID)')                           },
727 755
                                 { name => 'price_factor',       description => $::locale->text('Price factor (name)')                                  },
728 756
                                 { name => 'rop',                description => $::locale->text('ROP')                                                  },
729 757
                                 { name => 'sellprice',          description => $::locale->text('Sellprice')                                            },
730
                                 { name => 'shop',               description => $::locale->text('Shop article')                                          },
731
                                 { name => 'type',               description => $::locale->text('Article type')  . ' [3]'                             },
758
                                 { name => 'shop',               description => $::locale->text('Shop article')                                         },
759
                                 { name => 'type',               description => $::locale->text('Article type')  . ' [3]'                               },
732 760
                                 { name => 'unit',               description => $::locale->text('Unit (if missing or empty default unit will be used)') },
733 761
                                 { name => 've',                 description => $::locale->text('Verrechnungseinheit')                                  },
734 762
                                 { name => 'warehouse_id',       description => $::locale->text('Warehouse (database ID)')                              },
735
                                 { name => 'warehouse',          description => $::locale->text('Warehouse (name)')                              },
763
                                 { name => 'warehouse',          description => $::locale->text('Warehouse (name)')                                     },
736 764
                                 { name => 'weight',             description => $::locale->text('Weight')                                               },
737 765
                                );
738 766

  
SL/Controller/Inventory.pm
59 59
  $self->render('inventory/warehouse_usage',
60 60
                title => $::form->{title},
61 61
                year => DateTime->today->year,
62
  #              PARTSCLASSIFICATIONS => SL::DB:Manager::PartsClassification->get_all_classifications_by_name() ,
63 62
                WAREHOUSES => $::form->{WAREHOUSES},
64 63
                WAREHOUSE_FILTER => 1,
65 64
                warehouse_id => 0,
SL/Controller/PartClassification.pm
1
package SL::Controller::PartClassification;
2

  
3
use strict;
4

  
5
use parent qw(SL::Controller::Base);
6

  
7
use SL::DB::PartClassification;
8
use SL::Helper::Flash;
9

  
10
use Rose::Object::MakeMethods::Generic
11
(
12
 scalar => [ qw(part_classification) ],
13
);
14

  
15
__PACKAGE__->run_before('check_auth');
16
__PACKAGE__->run_before('load_part_classification', only => [ qw(edit update destroy) ]);
17

  
18
#
19
# This Controller is responsible for creating,editing or deleting
20
# Part Classifications.
21
#
22
# The use of Part Classifications is described in SL::DB::PartClassification
23
#
24
#
25

  
26
# List all available part classifications
27
#
28

  
29
sub action_list {
30
  my ($self) = @_;
31

  
32
  $self->render('part_classification/list',
33
                title                => $::locale->text('Parts Classifications'),
34
                PART_CLASSIFICATIONS => SL::DB::Manager::PartClassification->get_all_sorted);
35
}
36

  
37
# A Form for a new creatable part classifications is generated
38
#
39
sub action_new {
40
  my ($self) = @_;
41

  
42
  $self->{part_classification} = SL::DB::PartClassification->new;
43
  $self->render('part_classification/form', title => $::locale->text('Create a new parts classification'));
44
}
45

  
46
# Edit an existing part classifications
47
#
48
sub action_edit {
49
  my ($self) = @_;
50
  $self->render('part_classification/form', title => $::locale->text('Edit parts classification'));
51
}
52

  
53
# A new part classification is saved
54
#
55
sub action_create {
56
  my ($self) = @_;
57

  
58
  $self->{part_classification} = SL::DB::PartClassification->new;
59
  $self->create_or_update;
60
}
61

  
62
# An existing part classification is saved
63
#
64
sub action_update {
65
  my ($self) = @_;
66
  $self->create_or_update;
67
}
68

  
69
# An existing part classification is deleted
70
#
71
# The basic classifications cannot be deleted, also classifications which are in use
72
#
73
sub action_destroy {
74
  my ($self) = @_;
75

  
76
  if ( $self->{part_classification}->id < 5 ) {
77
    flash_later('error', $::locale->text('The basic parts classification cannot be deleted.'));
78
  }
79
  elsif (eval { $self->{part_classification}->delete; 1; }) {
80
    flash_later('info',  $::locale->text('The parts classification has been deleted.'));
81
  } else {
82
    flash_later('error', $::locale->text('The parts classification is in use and cannot be deleted.'));
83
  }
84

  
85
  $self->redirect_to(action => 'list');
86
}
87
# reordering the lines
88
#
89
sub action_reorder {
90
  my ($self) = @_;
91

  
92
  SL::DB::PartClassification->reorder_list(@{ $::form->{part_classification_id} || [] });
93

  
94
  $self->render(\'', { type => 'json' });
95
}
96

  
97
#
98
# filters
99
#
100

  
101
# check authentication, only "config" is allowed
102
#
103
sub check_auth {
104
  $::auth->assert('config');
105
}
106

  
107
#
108
# helpers
109
#
110

  
111
# submethod for update the database
112
#
113
sub create_or_update {
114
  my $self   = shift;
115
  my $is_new = !$self->{part_classification}->id;
116

  
117
  $::form->{part_classification}->{used_for_purchase} = 0 if ! $::form->{part_classification}->{used_for_purchase};
118
  $::form->{part_classification}->{used_for_sale}     = 0 if ! $::form->{part_classification}->{used_for_sale};
119

  
120
  my $params = delete($::form->{part_classification}) || { };
121

  
122
  $self->{part_classification}->assign_attributes(%{ $params });
123

  
124
  my @errors = $self->{part_classification}->validate;
125

  
126
  if (@errors) {
127
    flash('error', @errors);
128
    $self->render('part_classification/form', title => $is_new ? $::locale->text('Create a new parts classification') : $::locale->text('Edit parts classification'));
129
    return;
130
  }
131

  
132
  $self->{part_classification}->save;
133

  
134
  flash_later('info', $is_new ? $::locale->text('The parts classification has been created.') : $::locale->text('The parts classification has been saved.'));
135
  $self->redirect_to(action => 'list');
136
}
137

  
138
# submethod for loading one item from the database
139
#
140
sub load_part_classification {
141
  my ($self) = @_;
142
  $self->{part_classification} = SL::DB::PartClassification->new(id => $::form->{id})->load;
143
}
144

  
145
1;
146

  
147

  
148

  
149
__END__
150

  
151
=encoding utf-8
152

  
153
=head1 NAME
154

  
155
SL::Controller::PartClassification
156

  
157
=head1 SYNOPSIS
158

  
159
This Controller is responsible for creating,editing or deleting
160
Part Classifications.
161

  
162
=head1 DESCRIPTION
163

  
164
The use of Part Classifications is described in L<SL::DB::PartClassification>
165

  
166
=head1 METHODS
167

  
168
=head2 action_create
169

  
170
 $self->action_create();
171

  
172
A new part classification is saved
173

  
174

  
175

  
176
=head2 action_destroy
177

  
178
 $self->action_destroy();
179

  
180
An existing part classification is deleted
181

  
182
The basic classifications cannot be deleted, also classifications which are in use
183

  
184

  
185

  
186
=head2 action_edit
187

  
188
 $self->action_edit();
189

  
190
Edit an existing part classifications
191

  
192

  
193

  
194
=head2 action_list
195

  
196
 $self->action_list();
197

  
198
List all available part classifications
199

  
200

  
201

  
202
=head2 action_new
203

  
204
 $self->action_new();
205

  
206
A Form for a new creatable part classifications is generated
207

  
208

  
209

  
210
=head2 action_reorder
211

  
212
 $self->action_reorder();
213

  
214
reordering the lines
215

  
216

  
217

  
218
=head2 action_update
219

  
220
 $self->action_update();
221

  
222
An existing part classification is saved
223

  
224

  
225
=head1 AUTHOR
226

  
227
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>
228

  
229
=cut
SL/DB/Helper/ALL.pm
71 71
use SL::DB::Order;
72 72
use SL::DB::OrderItem;
73 73
use SL::DB::Part;
74
use SL::DB::PartClassification;
74 75
use SL::DB::PartsGroup;
75 76
use SL::DB::PartsPriceHistory;
76 77
use SL::DB::PaymentTerm;
SL/DB/Helper/Mappings.pm
153 153
  oe                             => 'order',
154 154
  parts                          => 'part',
155 155
  partsgroup                     => 'parts_group',
156
  part_classifications           => 'PartClassification',
156 157
  parts_price_history            => 'PartsPriceHistory',
157 158
  payment_terms                  => 'payment_term',
158 159
  periodic_invoices              => 'periodic_invoice',
SL/DB/Manager/PartClassification.pm
1
package SL::DB::Manager::PartClassification;
2

  
3
use strict;
4

  
5
use parent qw(SL::DB::Helper::Manager);
6
use SL::DB::Helper::Sorted;
7

  
8
sub object_class { 'SL::DB::PartClassification' }
9

  
10
__PACKAGE__->make_manager_methods;
11

  
12
#
13
# get the one/two character shortcut of the parts classification
14
#
15
sub get_abbreviation {
16
  my ($class,$id) = @_;
17
  my $obj = $class->get_first(query => [ id => $id ]);
18
  return '' unless $obj;
19
  return $obj->abbreviation?$obj->abbreviation:'';
20
}
21

  
22
1;
23

  
24

  
25
__END__
26

  
27
=encoding utf-8
28

  
29
=head1 NAME
30

  
31
SL::DB::Manager::PartClassification
32

  
33

  
34
=head1 SYNOPSIS
35

  
36
This class has wrapper methodes to get the shortcuts
37

  
38
=head1 METHODS
39

  
40
=head2 get_abbreviation
41

  
42
 $class->get_abbreviation($classification_id);
43

  
44
get the one/two character shortcut of the parts classification
45

  
46
=head2 get_separate_abbreviation
47

  
48
 $class->get_separate_abbreviation($classification_id);
49

  
50
get the one/two character shortcut of the parts classification if it is a separate article
51

  
52
=head1 AUTHOR
53

  
54
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>
55

  
56
=cut
SL/DB/MetaSetup/Part.pm
12 12
  bin_id             => { type => 'integer' },
13 13
  bom                => { type => 'boolean', default => 'false' },
14 14
  buchungsgruppen_id => { type => 'integer' },
15
  classification_id  => { type => 'integer', default => '0' },
15 16
  description        => { type => 'text' },
16 17
  drawing            => { type => 'text' },
17 18
  ean                => { type => 'text' },
......
63 64
    key_columns => { buchungsgruppen_id => 'id' },
64 65
  },
65 66

  
67
  classification => {
68
    class       => 'SL::DB::PartClassification',
69
    key_columns => { classification_id => 'id' },
70
  },
71

  
66 72
  partsgroup => {
67 73
    class       => 'SL::DB::PartsGroup',
68 74
    key_columns => { partsgroup_id => 'id' },
SL/DB/MetaSetup/PartClassification.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::PartClassification;
4

  
5
use strict;
6

  
7
use parent qw(SL::DB::Object);
8

  
9
__PACKAGE__->meta->table('part_classifications');
10

  
11
__PACKAGE__->meta->columns(
12
  abbreviation      => { type => 'text' },
13
  description       => { type => 'text' },
14
  id                => { type => 'serial', not_null => 1 },
15
  used_for_purchase => { type => 'boolean', default => 'true' },
16
  used_for_sale     => { type => 'boolean', default => 'true' },
17
);
18

  
19
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
20

  
21
1;
22
;
SL/DB/PartClassification.pm
1

  
2
package SL::DB::PartClassification;
3

  
4
use strict;
5

  
6
use SL::DB::MetaSetup::PartClassification;
7
use SL::DB::Manager::PartClassification;
8

  
9
__PACKAGE__->meta->initialize;
10

  
11
# check if the description and abbreviation is present
12
#
13
sub validate {
14
  my ($self) = @_;
15

  
16
  my @errors;
17
  push @errors, $::locale->text('The description is missing.')  if !$self->description;
18
  push @errors, $::locale->text('The abbreviation is missing.') if !$self->abbreviation;
19

  
20
  return @errors;
21
}
22

  
23

  
24

  
25
1;
26

  
27
__END__
28

  
29
=encoding utf-8
30

  
31
=head1 NAME
32

  
33
SL::DB::PartClassification
34

  
35
=head1 SYNOPSIS
36

  
37
Additional to the article types "part", "assembly", "service" and "assortement"
38
the parts classification specifies other ortogonal attributes
39

  
40
=head1 DESCRIPTION
41

  
42
The primary attributes are the rule
43
of the article as "used_for_sales" or "used_for_purchase".
44

  
45
Additional other attributes may follow
46

  
47
To see this attributes in a short way there are shortcuts of one (or two characters, if needed for compare )
48
which may be translated in the specified language
49

  
50
The type of the article is also as shortcut available, so this combined type and classification shortcut
51
is used short as "Type"
52

  
53
English type shortcuts are 'P','A','S'
54
German  type shortcuts are 'W','E','D'
55
The can set in the language-files
56

  
57
To get the localized abbreviations you can use L<SL::Presenter::Part> .
58

  
59
=head1 METHODS
60

  
61
=head2 validate
62

  
63
 $self->validate();
64

  
65
check if the description and abbreviation is present
66

  
67

  
68
=head1 AUTHOR
69

  
70
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>
71

  
72

  
73
=cut
SL/IC.pm
92 92
  $main::lxdebug->leave_sub();
93 93
}
94 94

  
95

  
95 96
sub assembly_item {
96 97
  $main::lxdebug->enter_sub();
97 98

  
......
129 130

  
130 131
  my $query =
131 132
    qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
133
       p.classification_id,
132 134
       p.weight, p.onhand, p.unit, pg.partsgroup, p.lastcost,
133 135
       p.price_factor_id, pfac.factor AS price_factor, p.notes as longdescription
134 136
       FROM parts p
......
210 212
#  my @other_flags          = qw(onhand); # ToDO: implement these
211 213
#  my @inactive_flags       = qw(l_subtotal short l_linetotal);
212 214

  
213
  my @select_tokens = qw(id factor);
215
  my @select_tokens = qw(id factor part_type classification_id);
214 216
  my @where_tokens  = qw(1=1);
215 217
  my @group_tokens  = ();
216 218
  my @bind_vars     = ();
......
287 289
    insertdate         => 'itime::DATE',
288 290
  );
289 291

  
290
  if (($form->{searchitems} eq 'assembly') && $form->{l_lastcost}) {
292
  if ($form->{l_assembly} && $form->{l_lastcost}) {
291 293
    @simple_l_switches = grep { $_ ne 'lastcost' } @simple_l_switches;
292 294
  }
293 295

  
......
378 380
  }
379 381

  
380 382
  for ($form->{searchitems}) {
381
    push @where_tokens, "p.part_type = 'part'"     if /part/;
382
    push @where_tokens, "p.part_type = 'service'"  if /service/;
383
    push @where_tokens, "p.part_type = 'assembly'" if /assembly/;
383
    push @where_tokens, "p.part_type = 'part'"       if /part/;
384
    push @where_tokens, "p.part_type = 'service'"    if /service/;
385
    push @where_tokens, "p.part_type = 'assembly'"   if /assembly/;
386
    push @where_tokens, "p.part_type = 'assortment'" if /assortment/;
387
  }
388
  if ( $form->{classification_id} > 0 ) {
389
    push @where_tokens, "p.classification_id = ?";
390
    push @bind_vars, $form->{classification_id};
384 391
  }
385 392

  
386 393
  for ($form->{itemstatus}) {
......
438 445

  
439 446
  push @select_tokens, @qsooqr_flags, 'quotation', 'cv', 'ioi.id', 'ioi.ioi'  if $bsooqr;
440 447
  push @select_tokens, @deliverydate_flags                                    if $bsooqr && $form->{l_deliverydate};
441
  push @select_tokens, $q_assembly_lastcost                                   if ($form->{searchitems} eq 'assembly') && $form->{l_lastcost};
448
  push @select_tokens, $q_assembly_lastcost                                   if $form->{l_assembly} && $form->{l_lastcost};
442 449
  push @bsooqr_tokens, q|module = 'ir' AND NOT ioi.assemblyitem|              if $form->{bought};
443 450
  push @bsooqr_tokens, q|module = 'is' AND NOT ioi.assemblyitem|              if $form->{sold};
444 451
  push @bsooqr_tokens, q|module = 'oe' AND NOT quotation AND cv = 'customer'| if $form->{ordered};
......
536 543
  # post processing for assembly parts lists (bom)
537 544
  # for each part get the assembly parts and add them into the partlist.
538 545
  my @assemblies;
539
  if ($form->{searchitems} eq 'assembly' && $form->{bom}) {
546
  if ($form->{l_assembly} && $form->{bom}) {
540 547
    $query =
541 548
      qq|SELECT p.id, p.partnumber, p.description, a.qty AS onhand,
542 549
           p.unit, p.notes, p.itime::DATE as insertdate,
......
583 590
      }
584 591
      $sth->finish;
585 592
    }
586
  };
587

  
593
  }
588 594

  
589 595
  $main::lxdebug->leave_sub();
590 596

  
......
815 821
  }
816 822

  
817 823
  my $query =
818
    qq|SELECT id, partnumber, description, unit, sellprice
824
    qq|SELECT id, partnumber, description, unit, sellprice,
825
       classification_id
819 826
       FROM parts
820 827
       WHERE $where ORDER BY $order|;
821 828

  
......
828 835
    }
829 836

  
830 837
    $j++;
838
    $form->{"type_and_classific_$j"} = $::request->presenter->type_abbreviation($ref->{part_type}).
839
                                       $::request->presenter->classification_abbreviation($ref->{classification_id});
831 840
    $form->{"id_$j"}          = $ref->{id};
832 841
    $form->{"partnumber_$j"}  = $ref->{partnumber};
833 842
    $form->{"description_$j"} = $ref->{description};
......
1122 1131
  for my $i (1..$rowcount) {
1123 1132
    my $id = $form->{"${prefix}${i}"};
1124 1133
    next unless $id;
1125

  
1126
    push @{ $template_arrays{part_type} },  $parts_by_id{$id}->type;
1134
    my $prt = $parts_by_id{$id};
1135
    my $type_abbr = $::request->presenter->type_abbreviation($prt->part_type);
1136
    push @{ $template_arrays{part_type} }, $type_abbr;
1137
    push @{ $template_arrays{type_and_classific}},  $type_abbr.$::request->presenter->classification_abbreviation($prt->classification_id);
1127 1138
  }
1128 1139

  
1129
  return %template_arrays;
1130 1140
  $main::lxdebug->leave_sub();
1141
  return %template_arrays;
1131 1142
}
1132 1143

  
1133 1144
sub normalize_text_blocks {
SL/IR.pm
52 52
use List::Util qw(min);
53 53

  
54 54
use strict;
55
use constant PCLASS_OK             =>   0;
56
use constant PCLASS_NOTFORSALE     =>   1;
57
use constant PCLASS_NOTFORPURCHASE =>   2;
55 58

  
56 59
sub post_invoice {
57 60
  my ($self, $myconfig, $form, $provided_dbh, $payments_only) = @_;
......
1021 1024
        i.description, i.longdescription, i.qty, i.fxsellprice AS sellprice, i.parts_id AS id, i.unit, i.deliverydate, i.project_id, i.serialnumber,
1022 1025
        i.price_factor_id, i.price_factor, i.marge_price_factor, i.discount, i.active_price_source, i.active_discount_source,
1023 1026
        p.partnumber, p.part_type, pr.projectnumber, pg.partsgroup
1027
        ,p.classification_id
1024 1028

  
1025 1029
        FROM invoice i
1026 1030
        JOIN parts p ON (i.parts_id = p.id)
......
1280 1284
         p.notes AS partnotes, p.notes AS longdescription, p.not_discountable,
1281 1285
         p.price_factor_id,
1282 1286
         p.ean,
1287
         p.classification_id,
1283 1288

  
1284 1289
         pfac.factor AS price_factor,
1285 1290

  
......
1295 1300
         c3.new_chart_id                  AS expense_new_chart,
1296 1301
         date($transdate) - c3.valid_from AS expense_valid,
1297 1302

  
1303
         pt.used_for_purchase AS used_for_purchase,
1298 1304
         pg.partsgroup
1299 1305

  
1300 1306
       FROM parts p
......
1311 1317
           FROM taxzone_charts tc
1312 1318
           WHERE tc.taxzone_id = '$taxzone_id' and tc.buchungsgruppen_id = p.buchungsgruppen_id) = c3.id)
1313 1319
       LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
1320
       LEFT JOIN part_classifications pt ON (pt.id = p.classification_id)
1314 1321
       LEFT JOIN price_factors pfac ON (pfac.id = p.price_factor_id)
1315 1322
       WHERE $where|;
1316 1323
  my $sth = prepare_execute_query($form, $dbh, $query, @values);
......
1329 1336
  map { push @{ $_ }, prepare_query($form, $dbh, $_->[0]) } @translation_queries;
1330 1337

  
1331 1338
  $form->{item_list} = [];
1339
  my $has_wrong_pclass = PCLASS_OK;
1332 1340
  while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
1333 1341

  
1334 1342
    if ($mm_by_id{$ref->{id}}) {
......
1339 1347
    if (($::form->{"partnumber_$i"} ne '') && ($ref->{ean} eq $::form->{"partnumber_$i"})) {
1340 1348
      push @{ $ref->{matches} ||= [] }, $::locale->text('EAN') . ': ' . $ref->{ean};
1341 1349
    }
1350
    $ref->{type_and_classific} = $::request->presenter->type_abbreviation($ref->{part_type}).
1351
                                 $::request->presenter->classification_abbreviation($ref->{classification_id});
1342 1352

  
1353
    if (! $ref->{used_for_purchase} ) {
1354
       $has_wrong_pclass = PCLASS_NOTFORPURCHASE;
1355
       next;
1356
    }
1343 1357
    # In der Buchungsgruppe ist immer ein Bestandskonto verknuepft, auch wenn
1344 1358
    # es sich um eine Dienstleistung handelt. Bei Dienstleistungen muss das
1345 1359
    # Buchungskonto also aus dem Ergebnis rausgenommen werden.
......
1409 1423
  $sth->finish();
1410 1424
  $_->[1]->finish for @translation_queries;
1411 1425

  
1426
  $form->{is_wrong_pclass} = $has_wrong_pclass;
1427
  $form->{NOTFORSALE}      = PCLASS_NOTFORSALE;
1428
  $form->{NOTFORPURCHASE}  = PCLASS_NOTFORPURCHASE;
1412 1429
  foreach my $item (@{ $form->{item_list} }) {
1413 1430
    my $custom_variables = CVar->get_custom_variables(module   => 'IC',
1414 1431
                                                      trans_id => $item->{id},
1415 1432
                                                      dbh      => $dbh,
1416 1433
                                                     );
1417

  
1434
    $form->{is_wrong_pclass} = PCLASS_OK; # one correct type
1418 1435
    map { $item->{"ic_cvar_" . $_->{name} } = $_->{value} } @{ $custom_variables };
1419 1436
  }
1420 1437

  
SL/IS.pm
59 59
use Data::Dumper;
60 60

  
61 61
use strict;
62
use constant PCLASS_OK             =>   0;
63
use constant PCLASS_NOTFORSALE     =>   1;
64
use constant PCLASS_NOTFORPURCHASE =>   2;
62 65

  
63 66
sub invoice_details {
64 67
  $main::lxdebug->enter_sub();
......
2003 2006
           i.project_id, i.serialnumber, i.pricegroup_id, i.ordnumber, i.donumber, i.transdate, i.cusordnumber, i.subtotal, i.lastcost,
2004 2007
           i.price_factor_id, i.price_factor, i.marge_price_factor, i.active_price_source, i.active_discount_source,
2005 2008
           p.partnumber, p.part_type, p.notes AS partnotes, p.formel, p.listprice,
2009
           p.classification_id,
2006 2010
           pr.projectnumber, pg.partsgroup, prg.pricegroup
2007 2011

  
2008 2012
         FROM invoice i
......
2300 2304
         p.id, p.partnumber, p.description, p.sellprice,
2301 2305
         p.listprice, p.part_type, p.lastcost,
2302 2306
         p.ean, p.notes,
2307
         p.classification_id,
2303 2308

  
2304 2309
         c1.accno AS inventory_accno,
2305 2310
         c1.new_chart_id AS inventory_new_chart,
......
2319 2324
         p.price_factor_id, p.weight,
2320 2325

  
2321 2326
         pfac.factor AS price_factor,
2322

  
2327
         pt.used_for_sale AS used_for_sale,
2323 2328
         pg.partsgroup
2324 2329

  
2325 2330
       FROM parts p
......
2336 2341
           FROM taxzone_charts tc
2337 2342
           WHERE tc.buchungsgruppen_id = p.buchungsgruppen_id and tc.taxzone_id = ${taxzone_id}) = c3.id)
2338 2343
       LEFT JOIN partsgroup pg ON (pg.id = p.partsgroup_id)
2344
       LEFT JOIN part_classifications pt ON (pt.id = p.classification_id)
2339 2345
       LEFT JOIN price_factors pfac ON (pfac.id = p.price_factor_id)
2340 2346
       WHERE $where|;
2341 2347
  my $sth = prepare_execute_query($form, $dbh, $query, @values);
......
2353 2359
                                   LIMIT 1| ] );
2354 2360
  map { push @{ $_ }, prepare_query($form, $dbh, $_->[0]) } @translation_queries;
2355 2361

  
2362
  my $has_wrong_pclass = PCLASS_OK;
2356 2363
  while (my $ref = $sth->fetchrow_hashref('NAME_lc')) {
2357 2364

  
2358 2365
    if ($mm_by_id{$ref->{id}}) {
......
2364 2371
      push @{ $ref->{matches} ||= [] }, $::locale->text('EAN') . ': ' . $ref->{ean};
2365 2372
    }
2366 2373

  
2374
    $ref->{type_and_classific} = $::request->presenter->type_abbreviation($ref->{part_type}).
2375
                                 $::request->presenter->classification_abbreviation($ref->{classification_id});
2376
    if (! $ref->{used_for_sale} ) {
2377
      $has_wrong_pclass = PCLASS_NOTFORSALE ;
2378
      next;
2379
    }
2367 2380
    # In der Buchungsgruppe ist immer ein Bestandskonto verknuepft, auch wenn
2368 2381
    # es sich um eine Dienstleistung handelt. Bei Dienstleistungen muss das
2369 2382
    # Buchungskonto also aus dem Ergebnis rausgenommen werden.
......
2447 2460
  $sth->finish;
2448 2461
  $_->[1]->finish for @translation_queries;
2449 2462

  
2463
  $form->{is_wrong_pclass} = $has_wrong_pclass;
2464
  $form->{NOTFORSALE}      = PCLASS_NOTFORSALE;
2465
  $form->{NOTFORPURCHASE}  = PCLASS_NOTFORPURCHASE;
2450 2466
  foreach my $item (@{ $form->{item_list} }) {
2451 2467
    my $custom_variables = CVar->get_custom_variables(module   => 'IC',
2452 2468
                                                      trans_id => $item->{id},
2453 2469
                                                      dbh      => $dbh,
2454 2470
                                                     );
2455

  
2471
    $form->{is_wrong_pclass} = PCLASS_OK; # one correct type
2456 2472
    map { $item->{"ic_cvar_" . $_->{name} } = $_->{value} } @{ $custom_variables };
2457 2473
  }
2458

  
2459 2474
  $main::lxdebug->leave_sub();
2460 2475
}
2461 2476

  
SL/OE.pm
1090 1090
           c3.accno AS expense_accno,   c3.new_chart_id AS expense_new_chart,   date($transdate) - c3.valid_from as expense_valid,
1091 1091
           oe.ordnumber AS ordnumber_oe, oe.transdate AS transdate_oe, oe.cusordnumber AS cusordnumber_oe,
1092 1092
           p.partnumber, p.part_type, p.listprice, o.description, o.qty,
1093
           p.classification_id,
1093 1094
           o.sellprice, o.parts_id AS id, o.unit, o.discount, p.notes AS partnotes, p.part_type,
1094 1095
           o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
1095 1096
           o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
SL/Presenter/Part.pm
3 3
use strict;
4 4

  
5 5
use SL::DB::Part;
6
use SL::DB::PartClassification;
7
use SL::Locale::String qw(t8);
6 8

  
7 9
use Exporter qw(import);
8
our @EXPORT = qw(part_picker part);
10
our @EXPORT = qw(part_picker part select_classification classification_abbreviation type_abbreviation separate_abbreviation);
9 11

  
10 12
use Carp;
11 13

  
......
46 48
  $self->html_tag('span', $ret, class => 'part_picker');
47 49
}
48 50

  
51
#
52
# shortcut for article type
53
#
54
sub type_abbreviation {
55
  my ($self, $part_type) = @_;
56
  $main::lxdebug->message(LXDebug->DEBUG2(),"parttype=".$part_type);
57
  return $::locale->text('Assembly (typeabbreviation)')   if $part_type eq 'assembly';
58
  return $::locale->text('Part (typeabbreviation)')       if $part_type eq 'part';
59
  return $::locale->text('Assortment (typeabbreviation)') if $part_type eq 'assortment';
60
  return $::locale->text('Service (typeabbreviation)');
61
}
62

  
63
#
64
# Translations for Abbreviations:
65
#
66
# $::locale->text('None (typeabbreviation)')
67
# $::locale->text('Purchase (typeabbreviation)')
68
# $::locale->text('Sales (typeabbreviation)')
69
# $::locale->text('Merchandise (typeabbreviation)')
70
# $::locale->text('Production (typeabbreviation)')
71
#
72
# and for descriptions
73
# $::locale->text('Purchase')
74
# $::locale->text('Sales')
75
# $::locale->text('Merchandise')
76
# $::locale->text('Production')
77

  
78
#
79
# shortcut for article type
80
#
81
sub classification_abbreviation {
82
  my ($self, $id) = @_;
83
  SL::DB::Manager::PartClassification->cache_all();
84
  my $obj = SL::DB::PartClassification->load_cached($id);
85
  $obj && $obj->abbreviation ? t8($obj->abbreviation) : '';
86
}
87

  
88
#
89
# generate selection tag
90
#
91
sub select_classification {
92
  my ($self, $name, %attributes) = @_;
93
  $attributes{value_key} = 'id';
94
  $attributes{title_key} = 'description';
95
  my $collection = SL::DB::Manager::PartClassification->get_all_sorted();
96
  $_->description($::locale->text($_->description)) for @{ $collection };
97
  return $self->select_tag( $name, $collection, %attributes );
98
}
99

  
49 100
1;
50 101

  
51 102
__END__
......
93 144

  
94 145
=over 2
95 146

  
147
=item C<classification_abbreviation $classification_id>
148

  
149
Returns the shortcut of the classification
150

  
151
=back
152

  
153
=over 2
154

  
155
=item C<select_classification $name,%params>
156

  
157
Returns a HTML Select Tag with all available Classifications
158

  
159
C<%params> can include:
160

  
161
=over 4
162

  
163
=item * default
164

  
165
The Id of the selected item .
166

  
167
=back
168

  
169
=back
170

  
171
=over 2
172

  
96 173
=item C<part_picker $name, $value, %params>
97 174

  
98 175
All-in-one picker widget for parts. The name will be both id and name
......
214 291

  
215 292
Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
216 293

  
294
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>
295

  
217 296
=cut
SL/WH.pm
369 369
    push @filter_vars, like($filter{description});
370 370
  }
371 371

  
372
  if ($filter{classification_id}) {
373
    push @filter_ary, "p.classification_id = ?";
374
    push @filter_vars, $filter{classification_id};
375
  }
376

  
372 377
  if ($filter{chargenumber}) {
373 378
    push @filter_ary, "i1.chargenumber ILIKE ?";
374 379
    push @filter_vars, like($filter{chargenumber});
......
427 432
     "qty"                  => "ABS(SUM(i1.qty))",
428 433
     "partnumber"           => "p.partnumber",
429 434
     "partdescription"      => "p.description",
435
     "classification_id"    => "p.classification_id",
436
     "part_type"            => "p.part_type",
430 437
     "bindescription"       => "b.description",
431 438
     "chargenumber"         => "i1.chargenumber",
432 439
     "bestbefore"           => "i1.bestbefore",
......
458 465
     "warehouse_from"       => "'$filter{na}'",
459 466
     };
460 467

  
468
  $form->{l_classification_id}  = 'Y';
461 469
  $form->{l_invoice_id} = $form->{l_oe_id} if $form->{l_oe_id};
462 470

  
463 471
  # build the select clauses.
......
615 623
#  - warehouse_id - will return matches with this warehouse_id only
616 624
#  - partnumber   - will return only matches where the given string is a substring of the partnumber
617 625
#  - partsid      - will return matches with this parts_id only
626
#  - classification_id - will return matches with this parts with this classification only
618 627
#  - description  - will return only matches where the given string is a substring of the description
619 628
#  - chargenumber - will return only matches where the given string is a substring of the chargenumber
620 629
#  - bestbefore   - will return only matches with this bestbefore date
......
666 675
    push @filter_vars, like($filter{partnumber});
667 676
  }
668 677

  
678
  if ($filter{classification_id}) {
679
    push @filter_ary, "p.classification_id = ?";
680
    push @filter_vars, $filter{classification_id};
681
  }
682

  
669 683
  if ($filter{description}) {
670 684
    push @filter_ary,  "p.description ILIKE ?";
671 685
    push @filter_vars, like($filter{description});
......
738 752
     "warehouseid"          => "i.warehouse_id",
739 753
     "partnumber"           => "p.partnumber",
740 754
     "partdescription"      => "p.description",
755
     "classification_id"    => "p.classification_id",
756
     "part_type"            => "p.part_type",
741 757
     "bindescription"       => "b.description",
742 758
     "binid"                => "b.id",
743 759
     "chargenumber"         => "i.chargenumber",
......
748 764
     "partunit"             => "p.unit",
749 765
     "stock_value"          => "p.lastcost / COALESCE(pfac.factor, 1)",
750 766
  );
767
  $form->{l_classification_id}  = 'Y';
768
  $form->{l_part_type}          = 'Y';
769

  
751 770
  my $select_clause = join ', ', map { +/^l_/; "$select_tokens{$'} AS $'" }
752 771
        ( grep( { !/qty/ and /^l_/ and $form->{$_} eq 'Y' } keys %$form),
753 772
          qw(l_parts_id l_qty l_partunit) );
bin/mozilla/ic.pl
84 84
  $form->{lastsort}     = ""; # memory for which table was sort at last time
85 85
  $form->{ndxs_counter} = 0;  # counter for added entries to top100
86 86

  
87
  my %is_xyz     = map { +"is_$_" => ($form->{searchitems} eq $_) } qw(part service assembly);
87
  my %is_xyz     = map { +"is_$_" => ($form->{searchitems} eq $_) } qw(part service assembly assortment);
88 88

  
89 89
  $form->{title} = (ucfirst $form->{searchitems}) . "s";
90
  $form->{title} =~ s/ys$/ies/;
90 91
  $form->{title} = $locale->text($form->{title});
91 92
  $form->{title} = $locale->text('Assemblies') if ($is_xyz{is_assembly});
92 93

  
......
217 218
#  searchitems=part revers=0 lastsort=''
218 219
#
219 220
# filter:
220
# partnumber ean description partsgroup serialnumber make model drawing microfiche
221
# partnumber ean description partsgroup classification serialnumber make model drawing microfiche
221 222
# transdatefrom transdateto
222 223
#
223 224
# radio:
......
284 285
    'unit'               => { 'text' => $locale->text('Unit'), },
285 286
    'weight'             => { 'text' => $locale->text('Weight'), },
286 287
    'shop'               => { 'text' => $locale->text('Shop article'), },
288
    'type_and_classific' => { 'text' => $locale->text('Type'), },
287 289
    'projectnumber'      => { 'text' => $locale->text('Project Number'), },
288 290
    'projectdescription' => { 'text' => $locale->text('Project Description'), },
289 291
  );
......
408 410
    $form->{l_linetotallastcost}  = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if  $form->{l_lastcost};
409 411
    $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
410 412
  }
413
  $form->{"l_type_and_classific"} = "Y";
411 414

  
412 415
  if ($form->{searchitems} eq 'service') {
413 416

  
......
456 459
  IC->all_parts(\%myconfig, \%$form);
457 460

  
458 461
  my @columns = qw(
459
    partnumber description notes partsgroup bin onhand rop soldtotal unit listprice
462
    partnumber type_and_classific description notes partsgroup bin onhand rop soldtotal unit listprice
460 463
    linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
461 464
    priceupdate weight image drawing microfiche invnumber ordnumber quonumber
462 465
    transdate name serialnumber deliverydate ean projectnumber projectdescription
......
489 492

  
490 493
  my @hidden_variables = (
491 494
    qw(l_subtotal l_linetotal searchitems itemstatus bom l_pricegroups insertdatefrom insertdateto),
495
    qw(l_type_and_classific classification_id),
492 496
    @itemstatus_keys,
493 497
    @callback_keys,
494 498
    map({ "cvar_$_->{name}" } @searchable_custom_variables),
......
515 519
    'part'     => $locale->text('part_list'),
516 520
    'service'  => $locale->text('service_list'),
517 521
    'assembly' => $locale->text('assembly_list'),
522
    'article'  => $locale->text('article_list'),
518 523
  );
519 524

  
520 525
  $report->set_options('raw_top_info_text'     => $form->parse_html_template('ic/generate_report_top', { options => \@options }),
521
                       'raw_bottom_info_text'  => $form->parse_html_template('ic/generate_report_bottom'),
526
                       'raw_bottom_info_text'  => $form->parse_html_template('ic/generate_report_bottom' ,
527
                                                  { PART_CLASSIFICATIONS => SL::DB::Manager::PartClassification->get_all_sorted }),
522 528
                       'output_format'         => 'HTML',
523 529
                       'title'                 => $form->{title},
524 530
                       'attachment_basename'   => $attachment_basenames{$form->{searchitems}} . strftime('_%Y%m%d', localtime time),
......
631 637
    map { $row->{$_}{link} = $ref->{$_} } qw(drawing microfiche);
632 638

  
633 639
    $row->{notes}{data} = SL::HTML::Util->strip($ref->{notes});
640
    $row->{type_and_classific}{data} = $::request->presenter->type_abbreviation($ref->{part_type}).
641
                                       $::request->presenter->classification_abbreviation($ref->{classification_id});
634 642

  
635 643
    $report->add_data($row);
636 644

  
bin/mozilla/io.pl
159 159

  
160 160
  # column_index
161 161
  my @header_sort = qw(
162
    runningnumber partnumber description ship ship_missing qty price_factor
162
    runningnumber partnumber type_and_classific description ship ship_missing qty price_factor
163 163
    unit weight price_source sellprice discount linetotal
164 164
    bin stock_in_out
165 165
  );
......
169 169
  my %column_def = (
170 170
    runningnumber => { width => 5,     value => $locale->text('No.'),                  display => 1, },
171 171
    partnumber    => { width => 8,     value => $locale->text('Number'),               display => 1, },
172
    type_and_classific
173
                  => { width => 2,     value => $locale->text('Type'),                 display => 1, },
172 174
    description   => { width => 30,    value => $locale->text('Part Description'),     display => 1, },
173 175
    ship          => { width => 5,     value => $locale->text('Delivered'),            display => $is_s_p_order, },
174 176
    ship_missing  => { width => 5,     value => $locale->text('Not delivered'),        display => $show_ship_missing, },
......
295 297
    my $rows            = $form->numtextrows($form->{"description_$i"}, 30, 6);
296 298

  
297 299
    # quick delete single row
298
    $column_data{runningnumber} .= q|<a onclick= "$('#partnumber_| . $i . q|').val(''); $('#update_button').click();">| .
300
    $column_data{runningnumber}  = q|<a onclick= "$('#partnumber_| . $i . q|').val(''); $('#update_button').click();">| .
299 301
                                   q|<img height="10px" width="10px" src="image/cross.png" alt="| . $locale->text('Remove') . q|"></a> |;
300 302
    $column_data{runningnumber} .= $cgi->textfield(-name => "runningnumber_$i", -id => "runningnumber_$i", -size => 5,  -value => $i);    # HuT
301 303

  
302 304

  
303 305
    $column_data{partnumber}    = $cgi->textfield(-name => "partnumber_$i",    -id => "partnumber_$i",    -size => 12, -value => $form->{"partnumber_$i"});
306
    $column_data{type_and_classific} = $::request->presenter->type_abbreviation($form->{"part_type_$i"}).
307
                                       $::request->presenter->classification_abbreviation($form->{"classification_id_$i"}) if $form->{"id_$i"};
304 308
    $column_data{description} = (($rows > 1) # if description is too large, use a textbox instead
305 309
                                ? $cgi->textarea( -name => "description_$i", -id => "description_$i", -default => $form->{"description_$i"}, -rows => $rows, -columns => 30)
306 310
                                : $cgi->textfield(-name => "description_$i", -id => "description_$i",   -value => $form->{"description_$i"}, -size => 30))
......
665 669
    map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{"taxaccounts_$i"} if !$form->{taxincluded};
666 670

  
667 671
    $form->{creditremaining} -= $amount;
668

  
669 672
    $form->{"runningnumber_$i"} = $i;
670 673

  
671 674
    # format amounts
......
1759 1762
  foreach my $i (1..$form->{rowcount}) {
1760 1763
    next unless ($form->{"id_${i}"});
1761 1764

  
1762
    my $info                 = $form->{PART_INFORMATION}->{$form->{"id_${i}"}} || { };
1763
    $form->{"partunit_${i}"} = $info->{unit};
1764
    $form->{"weight_$i"}     = $info->{weight};
1765
    my $info                        = $form->{PART_INFORMATION}->{$form->{"id_${i}"}} || { };
1766
    $form->{"partunit_${i}"}        = $info->{unit};
1767
    $form->{"weight_$i"}            = $info->{weight};
1768
    $form->{"part_type_$i"}         = $info->{part_type};
1769
    $form->{"classification_id_$i"} = $info->{classification_id};
1765 1770
  }
1766 1771

  
1767 1772
  $main::lxdebug->leave_sub();
bin/mozilla/wh.pl
678 678
  $form->{report_generator_output_format} = 'HTML' if !$form->{report_generator_output_format};
679 679

  
680 680
  my %filter;
681
  my @columns = qw(trans_id date warehouse_from bin_from warehouse_to bin_to partnumber partdescription chargenumber bestbefore trans_type comment qty employee oe_id projectnumber);
681
  my @columns = qw(trans_id date warehouse_from bin_from warehouse_to bin_to partnumber type_and_classific partdescription chargenumber bestbefore trans_type comment qty unit partunit employee oe_id projectnumber);
682 682

  
683 683
  # filter stuff
684
  map { $filter{$_} = $form->{$_} if ($form->{$_}) } qw(warehouse_id bin_id partnumber description chargenumber bestbefore);
684
  map { $filter{$_} = $form->{$_} if ($form->{$_}) } qw(warehouse_id bin_id classification_id partnumber description chargenumber bestbefore);
685 685

  
686 686
  $filter{qty_op} = WH->convert_qty_op($form->{qty_op});
687 687
  if ($filter{qty_op}) {
......
697 697

  
698 698
  my @hidden_variables = map { "l_${_}" } @columns;
699 699
  push @hidden_variables, qw(warehouse_id bin_id partnumber description chargenumber bestbefore qty_op qty qty_unit fromdate todate);
700
  push @hidden_variables, qw(classification_id);
700 701

  
701 702
  my %column_defs = (
702 703
    'date'            => { 'text' => $locale->text('Date'), },
......
708 709
    'bin_from'        => { 'text' => $locale->text('Bin From'), },
709 710
    'bin_to'          => { 'text' => $locale->text('Bin To'), },
710 711
    'partnumber'      => { 'text' => $locale->text('Part Number'), },
712
    'type_and_classific'
713
                      => { 'text' => $locale->text('Type'), },
711 714
    'partdescription' => { 'text' => $locale->text('Part Description'), },
712 715
    'chargenumber'    => { 'text' => $locale->text('Charge Number'), },
713 716
    'bestbefore'      => { 'text' => $locale->text('Best Before'), },
......
726 729
  my %column_alignment = map { $_ => 'right' } qw(qty);
727 730

  
728 731
  map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
732
  $column_defs{type_and_classific}->{visible} = 1;
733
  $column_defs{type_and_classific}->{link} ='';
729 734

  
730 735
  $report->set_columns(%column_defs);
731 736
  $report->set_column_order(@columns);
......
753 758
                    'purchase_invoice'        => { script => 'ir', title => $locale->text('Purchase Invoice') },
754 759
                  );
755 760

  
756
   my $allrows = 0;
757
   $allrows = 1 if $form->{report_generator_output_format} ne 'HTML' ;
761
  my $allrows = 0;
762
  $allrows = 1 if $form->{report_generator_output_format} ne 'HTML' ;
758 763

  
759
   # manual paginating
760
   my $pages = {};
761
   $pages->{per_page}        = $::form->{per_page} || 15;
762
   my $first_nr = ($page - 1) * $pages->{per_page};
763
   my $last_nr  = $first_nr + $pages->{per_page};
764
   my $idx       = 0;
764
  # manual paginating
765
  my $pages = {};
766
  $pages->{per_page}        = $::form->{per_page} || 15;
767
  my $first_nr = ($page - 1) * $pages->{per_page};
768
  my $last_nr  = $first_nr + $pages->{per_page};
769
  my $idx       = 0;
765 770

  
766 771
  foreach my $entry (@contents) {
772
    $entry->{type_and_classific} = $::request->presenter->type_abbreviation($entry->{part_type}).
773
                                   $::request->presenter->classification_abbreviation($entry->{classification_id});
767 774
    $entry->{qty}        = $form->format_amount_units('amount'     => $entry->{qty},
768 775
                                                      'part_unit'  => $entry->{partunit},
769 776
                                                      'conv_units' => 'convertible');
......
853 860
  my $sort_col     = $form->{sort};
854 861

  
855 862
  my %filter;
856
  my @columns = qw(warehousedescription bindescription partnumber partdescription chargenumber bestbefore qty stock_value);
863
  my @columns = qw(warehousedescription bindescription partnumber type_and_classific partdescription chargenumber bestbefore comment qty partunit stock_value);
857 864

  
858 865
  # filter stuff
859
  map { $filter{$_} = $form->{$_} if ($form->{$_}) } qw(warehouse_id bin_id partstypes_id partnumber description chargenumber bestbefore date include_invalid_warehouses);
866
  map { $filter{$_} = $form->{$_} if ($form->{$_}) } qw(warehouse_id bin_id classification_id partnumber description chargenumber bestbefore date include_invalid_warehouses);
860 867

  
861 868
  # show filter stuff also in report
862 869
  my @options;
870
  my $currentdate = $form->current_date(\%myconfig);
871
  push @options, $locale->text('Printdate') . " : ".$locale->date(\%myconfig, $currentdate, 1);
872

  
863 873
  # dispatch all options
864 874
  my $dispatch_options = {
865 875
   warehouse_id   => sub { push @options, $locale->text('Warehouse') . " : " .
......
867 877
   bin_id         => sub { push @options, $locale->text('Bin') . " : " .
868 878
                                            SL::DB::Manager::Bin->find_by(id => $form->{bin_id})->description},
869 879
   partnumber     => sub { push @options, $locale->text('Partnumber')     . " : $form->{partnumber}"},
880
   classification_id => sub { push @options, $locale->text('Parts Classification'). " : ".
881
                                               SL::DB::Manager::PartClassification->get_first(where => [ id => $form->{classification_id} ] )->description; },
870 882
   description    => sub { push @options, $locale->text('Description')    . " : $form->{description}"},
871 883
   chargenumber   => sub { push @options, $locale->text('Charge Number')  . " : $form->{chargenumber}"},
872 884
   bestbefore     => sub { push @options, $locale->text('Best Before')    . " : $form->{bestbefore}"},
873
   date           => sub { push @options, $locale->text('Date')           . " : $form->{date}"},
874 885
   include_invalid_warehouses    => sub { push @options, $locale->text('Include invalid warehouses ')},
875 886
  };
876 887
  foreach (keys %filter) {
877 888
   $dispatch_options->{$_}->() if $dispatch_options->{$_};
878 889
  }
890
  push @options, $locale->text('Stock Qty for Date') . " " . $locale->date(\%myconfig, $form->{date}?$form->{date}:$currentdate, 1);
891

  
879 892
  # / end show filter stuff also in report
880 893

  
881 894
  $filter{qty_op} = WH->convert_qty_op($form->{qty_op});
......
896 909
  my @hidden_variables = map { "l_${_}" } @columns;
897 910
  push @hidden_variables, qw(warehouse_id bin_id partnumber partstypes_id description chargenumber bestbefore qty_op qty qty_unit partunit l_warehousedescription l_bindescription);
898 911
  push @hidden_variables, qw(include_empty_bins subtotal include_invalid_warehouses date);
912
  push @hidden_variables, qw(classification_id);
899 913

  
900 914
  my %column_defs = (
901 915
    'warehousedescription' => { 'text' => $locale->text('Warehouse'), },
902 916
    'bindescription'       => { 'text' => $locale->text('Bin'), },
903 917
    'partnumber'           => { 'text' => $locale->text('Part Number'), },
918
    'type_and_classific'   => { 'text' => $locale->text('Type'), },
904 919
    'partdescription'      => { 'text' => $locale->text('Part Description'), },
905 920
    'chargenumber'         => { 'text' => $locale->text('Charge Number'), },
906 921
    'bestbefore'           => { 'text' => $locale->text('Best Before'), },
......
917 932

  
918 933
  map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns;
919 934

  
935
  $column_defs{type_and_classific}->{visible} = 1;
936
  $column_defs{type_and_classific}->{link} ='';
937

  
920 938
  $report->set_columns(%column_defs);
921 939
  $report->set_column_order(@columns);
922 940

  
......
951 969
  my $last_nr  = $first_nr + $pages->{per_page};
952 970

  
953 971
  foreach my $entry (@contents) {
972

  
973
    $entry->{type_and_classific} = $::request->presenter->type_abbreviation($entry->{part_type}).
974
                                   $::request->presenter->classification_abbreviation($entry->{classification_id});
954 975
    map { $subtotals{$_} += $entry->{$_} } @subtotals_columns;
955 976
    $total_stock_value   += $entry->{stock_value} * 1;
956 977
    $entry->{qty}         = $form->format_amount(\%myconfig, $entry->{qty});
js/locale/en.js
1
namespace("kivi").setupLocale({
2
"A transaction description is required.":"",
3
"Add function block":"",
4
"Add linked record":"",
5
"Add multiple items":"",
6
"Add picture":"",
7
"Add picture to text block":"",
8
"Add section":"",
9
"Add sub function block":"",
10
"Add text block":"",
11
"Additional articles actions":"",
12
"Are you sure?":"",
13
"Assign invoice":"",
14
"Basic settings actions":"",
15
"Cancel":"",
16
"Chart picker":"",
17
"Copy":"",
18
"Copy requirement spec":"",
19
"Copy template":"",
20
"Create":"",
21
"Create HTML":"",
22
"Create PDF":"",
23
"Create a new version":"",
24
"Create and print all invoices":"",
25
"Create invoice":"",
26
"Create new quotation/order":"",
27
"Create new qutoation/order":"",
28
"Create new version":"",
29
"Database Connection Test":"",
30
"Delete":"",
31
"Delete picture":"",
32
"Delete quotation/order":"",
33
"Delete requirement spec":"",
34
"Delete template":"",
35
"Delete text block":"",
36
"Do you really want do continue?":"",
37
"Do you really want to cancel?":"",
38
"Do you really want to delete this draft?":"",
39
"Do you really want to revert to this version?":"",
40
"Do you really want to save?":"",
41
"Do you want to set the account number \"#1\" to \"#2\" and the name \"#3\" to \"#4\"?":"",
42
"Download picture":"",
43
"Edit":"",
44
"Edit article/section assignments":"",
45
"Edit picture":"",
46
"Edit project link":"",
47
"Edit text block":"",
48
"Enter longdescription":"",
49
"Function block actions":"",
50
"Hide all details":"",
51
"Hide details":"",
52
"History":"",
53
"If you switch to a different tab without saving you will lose the data you've entered in the current tab.":"",
54
"Map":"",
55
"No":"",
56
"No delivery orders have been selected.":"",
57
"No invoices have been selected.":"",
58
"Part picker":"",
59
"Paste":"",
60
"Paste template":"",
61
"Please select a customer.":"",
62
"Please select a vendor.":"",
63
"Price Types":"",
64
"Print options":"",
65
"Project link actions":"",
66
"Quotations/Orders actions":"",
67
"Re-numbering all sections and function blocks in the order they are currently shown cannot be undone.":"",
68
"Remove article":"",
69
"Renumber sections and function blocks":"",
70
"Requirement spec actions":"",
71
"Requirement spec template actions":"",
72
"Revert to version":"",
73
"Save":"",
74
"Save and keep open":"",
75
"Section/Function block actions":"",
76
"Select template to paste":"",
77
"Show all details":"",
78
"Show details":"",
79
"Subject":"",
80
"Text block actions":"",
81
"Text block picture actions":"",
82
"The IBAN is missing.":"",
83
"The description is missing.":"",
84
"The name is missing.":"",
85
"The name must only consist of letters, numbers and underscores and start with a letter.":"",
86
"The option field is empty.":"",
87
"The recipient, subject or body is missing.":"",
88
"The selected database is still configured for client \"#1\". If you delete the database that client will stop working until you re-configure it. Do you still want to delete the database?":"",
89
"There are duplicate parts at positions":"",
90
"There are still transfers not matching the qty of the delivery order. Stock operations can not be changed later. Do you really want to proceed?":"",
91
"There is no connected chart.":"",
92
"There is one or more sections for which no part has been assigned yet; therefore creating the new record is not possible yet.":"",
93
"This sales order has an active configuration for periodic invoices. If you save then all subsequently created invoices will contain those changes as well, but not those that have already been created. Do you want to continue?":"",
94
"Time/cost estimate actions":"",
95
"Title":"",
96
"Toggle marker":"",
... Dieser Diff wurde abgeschnitten, weil er die maximale Anzahl anzuzeigender Zeilen überschreitet.

Auch abrufbar als: Unified diff