Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 56da9bba

Von Tamino Steinert vor 6 Tagen hinzugefügt

  • ID 56da9bba662605b6a59c2fa444f11bf5465c61c1
  • Vorgänger 1095df47
  • Nachfolger 65c0626e

Varianten: Stammartikel anlegen und Varianten erstellen

Unterschiede anzeigen:

SL/Controller/Part.pm
87 87
  $self->add;
88 88
};
89 89

  
90
sub action_add_parent_variant {
91
  my ($self, %params) = @_;
92

  
93
  $self->part( SL::DB::Part->new_parent_variant );
94
  $self->add;
95
}
96

  
90 97
sub action_add_from_record {
91 98
  my ($self) = @_;
92 99

  
......
104 111

  
105 112
  check_has_valid_part_type($::form->{part_type});
106 113

  
107
  $self->action_add_part       if $::form->{part_type} eq 'part';
108
  $self->action_add_service    if $::form->{part_type} eq 'service';
109
  $self->action_add_assembly   if $::form->{part_type} eq 'assembly';
110
  $self->action_add_assortment if $::form->{part_type} eq 'assortment';
114
  $self->action_add_part           if $::form->{part_type} eq 'part';
115
  $self->action_add_service        if $::form->{part_type} eq 'service';
116
  $self->action_add_assembly       if $::form->{part_type} eq 'assembly';
117
  $self->action_add_assortment     if $::form->{part_type} eq 'assortment';
118
  $self->action_add_parent_variant if $::form->{part_type} eq 'parent_variant';
119
  $self->action_add_variant        if $::form->{part_type} eq 'variant';
111 120
};
112 121

  
113 122
sub action_save {
......
213 222
  }
214 223
}
215 224

  
225
sub action_create_variants {
226
  my ($self) = @_;
227
  my @variant_property_ids = sort keys %{$::form->{variant_properties}};
228

  
229
  my $part = $self->part;
230
  my $variant_properties = $part->variant_properties();
231
  my @needed_variant_property_ids = sort map {$_->id} @$variant_properties;
232

  
233
  if (@variant_property_ids != @needed_variant_property_ids) {
234
    return $self->js->error(
235
      t8('No property value selected for variant properties: #1.',
236
        join(", ",
237
          map {$_->name_translated}
238
          grep {!defined $::form->{variant_properties}->{$_->id}->{selected_property_values}}
239
          @$variant_properties
240
        )
241
      )
242
    )->render();
243
  }
244

  
245
  my @grouped_variant_property_values = ();
246
  push @grouped_variant_property_values,
247
    SL::DB::Manager::VariantPropertyValue->get_all(
248
      where => [ id => $::form->{variant_properties}->{$_}->{selected_property_values} ]
249
    )
250
    for @variant_property_ids;
251

  
252

  
253
  my @variant_property_values_lists = ();
254
  foreach my $variant_property_values (@grouped_variant_property_values) {
255
    my @new_lists = ();
256
    foreach my $variant_property_value (@$variant_property_values) {
257
      unless (scalar @variant_property_values_lists) {
258
        push @new_lists, [$variant_property_value];
259
      }
260
      foreach my $variant_property_values_list (@variant_property_values_lists) {
261
        push @new_lists, [@$variant_property_values_list, $variant_property_value];
262
      }
263
    }
264
    @variant_property_values_lists = @new_lists;
265
  }
266

  
267
  my @new_variants = ();
268
  SL::DB->client->with_transaction(sub {
269
    push @new_variants, $part->create_new_variant($_)
270
      for @variant_property_values_lists;
271
    1;
272
  }) or do {
273
    return $self->js->error(t8('Error while creating variants: ' . @_))->render();
274
  };
275

  
276
  $self->redirect_to(
277
    controller => 'Part',
278
    action     => 'edit',
279
    'part.id'  => $self->part->id
280
  );
281
}
282

  
216 283
sub action_delete {
217 284
  my ($self) = @_;
218 285

  
......
314 381
    @{ $params{CUSTOM_VARIABLES_FIRST_TAB} }  = extract_by { $_->{first_tab} == 1 } @{ $params{CUSTOM_VARIABLES} };
315 382
  }
316 383

  
317
  my %title_hash = ( part       => t8('Edit Part'),
318
                     assembly   => t8('Edit Assembly'),
319
                     service    => t8('Edit Service'),
320
                     assortment => t8('Edit Assortment'),
384
  my %title_hash = ( part           => t8('Edit Part'),
385
                     assembly       => t8('Edit Assembly'),
386
                     service        => t8('Edit Service'),
387
                     assortment     => t8('Edit Assortment'),
388
                     parent_variant => t8('Edit Parent Variant'),
389
                     variant        => t8('Edit Variant'),
321 390
                   );
322 391

  
323 392
  $self->part->prices([])       unless $self->part->prices;
......
964 1033
  $self->_set_javascript;
965 1034
  $self->_setup_form_action_bar;
966 1035

  
967
  my %title_hash = ( part       => t8('Add Part'),
968
                     assembly   => t8('Add Assembly'),
969
                     service    => t8('Add Service'),
970
                     assortment => t8('Add Assortment'),
1036
  my %title_hash = ( part           => t8('Add Part'),
1037
                     assembly       => t8('Add Assembly'),
1038
                     service        => t8('Add Service'),
1039
                     assortment     => t8('Add Assortment'),
1040
                     parent_variant => t8('Add Parent Variant'),
1041
                     variant        => t8('Add Variant'),
971 1042
                   );
972 1043

  
973 1044
  $self->render(
......
979 1050

  
980 1051
sub _set_javascript {
981 1052
  my ($self) = @_;
982
  $::request->layout->use_javascript("${_}.js")  for qw(kivi.Part kivi.File kivi.PriceRule kivi.ShopPart kivi.Validator);
1053
  $::request->layout->use_javascript("${_}.js")  for qw(kivi.Part kivi.File kivi.PriceRule kivi.ShopPart kivi.Validator jquery.selectboxes jquery.multiselect2side);
983 1054
  $::request->layout->add_javascripts_inline("\$(function(){kivi.PriceRule.load_price_rules_for_part(@{[ $self->part->id ]})});") if $self->part->id;
984 1055
}
985 1056

  
......
1619 1690
}
1620 1691

  
1621 1692
sub check_has_valid_part_type {
1622
  die "invalid part_type" unless $_[0] =~ /^(part|service|assembly|assortment)$/;
1693
  die "invalid part_type" unless $_[0] =~ /^(part|service|assembly|assortment|parent_variant|variant)$/;
1623 1694
}
1624 1695

  
1625 1696

  
SL/DB/Part.pm
242 242
  $class->new(%params, part_type => 'parent_variant');
243 243
}
244 244

  
245
sub new_variant {
246
  my ($class, %params) = @_;
247
  $class->new(%params, part_type => 'variant');
248
}
249

  
250 245
sub last_modification {
251 246
  my ($self) = @_;
252 247
  return $self->mtime // $self->itime;
......
504 499
  return \@sorted;
505 500
}
506 501

  
502
sub create_new_variant {
503
  my ($self, $variant_property_values) = @_;
504
  die "only callable on parts of type parent_variant" unless $self->is_parent_variant;
505
  die "only callable on saved objects"                unless $self->id;
506

  
507
  my @selected_variant_property_ids = sort map {$_->variant_property_id} @$variant_property_values;
508
  my @variant_property_ids = sort map {$_->id} @{$self->variant_properties};
509
  if (@variant_property_ids != @selected_variant_property_ids) {
510
    die "Given variant_property_values dosn't match the variant_properties of parent_variant part";
511
  }
512

  
513
  my $new_variant = $self->clone_and_reset;
514
  # TODO set partnumber
515
  $new_variant->part_type('variant');
516
  $new_variant->save;
517
  SL::DB::VariantPropertyValuePart->new(
518
    part_id                   => $new_variant->id,
519
    variant_property_value_id => $_->id,
520
  )->save for @$variant_property_values;
521
  SL::DB::PartParentVariantPartVariant->new(
522
    variant_id        => $new_variant->id,
523
    parent_variant_id => $self->id,
524
  )->save;
525

  
526
  return $new_variant;
527
}
528

  
507 529
sub clone_and_reset_deep {
508 530
  my ($self) = @_;
509 531

  
SL/DB/VariantProperty.pm
15 15
    map_to    => 'part',
16 16
    type      => 'many to many',
17 17
  },
18
  property_values => {
19
    class => 'SL::DB::VariantPropertyValue',
20
    column_map => { id => 'variant_property_id' },
21
    type => 'one to many',
22
  }
18 23
);
19 24

  
20 25
__PACKAGE__->meta->initialize;
......
30 35
  return @errors;
31 36
}
32 37

  
38
sub name_translated {goto &name} # TODO
39

  
33 40
1;
SL/DB/VariantPropertyValue.pm
19 19

  
20 20
__PACKAGE__->meta->initialize;
21 21

  
22
sub value_translated {goto &value} # TODO
23

  
22 24
1;
js/kivi.Part.js
331 331
    $.post("controller.pl", { action: 'Part/warehouse_changed', warehouse_id: function(){ return $('#part_warehouse_id').val(); } },   kivi.eval_json_result);
332 332
  };
333 333

  
334
  ns.create_variants = function() {
335
    var data = $('#ic').serializeArray();
336
    data.push({ name: 'action', value: 'Part/create_variants' });
337
    $.post("controller.pl", data, kivi.eval_json_result);
338
  };
339

  
334 340
  var KEY = {
335 341
    TAB:       9,
336 342
    ENTER:     13,
locale/de/all
203 203
  'Add Invoice'                 => 'Rechnung erfassen',
204 204
  'Add Invoice for Advance Payment' => 'Anzahlungsrechnung erfassen',
205 205
  'Add Letter'                  => 'Brief hinzufügen',
206
  'Add Parent Variant'          => 'Stammartikel erfassen',
206 207
  'Add Part'                    => 'Ware erfassen',
207 208
  'Add Parts here!'             => 'Artikel hier hinzufügen!',
208 209
  'Add Price Factor'            => 'Preisfaktor erfassen',
......
235 236
  'Add Transaction'             => 'Dialogbuchen',
236 237
  'Add User'                    => 'Neuer Benutzer',
237 238
  'Add User Group'              => 'Neue Benutzergruppe',
239
  'Add Variant'                 => 'Variante erfassen',
238 240
  'Add Vendor'                  => 'Lieferant erfassen',
239 241
  'Add Vendor Invoice'          => 'Einkaufsrechnung erfassen',
240 242
  'Add Warehouse'               => 'Lager erfassen',
......
315 317
  'All'                         => 'Alle',
316 318
  'All Accounts'                => 'Alle Konten',
317 319
  'All Data'                    => 'Alle Daten',
320
  'All Property Values'         => 'Alle Ausprägunen',
318 321
  'All as list'                 => 'Alle als Liste',
319 322
  'All changes in that file have been reverted.' => 'Alle Änderungen in dieser Datei wurden rückgängig gemacht.',
320 323
  'All clients'                 => 'Alle Mandanten',
......
884 887
  'Create PDF'                  => 'PDF erzeugen',
885 888
  'Create Reclamation'          => 'Reklamation erstellen',
886 889
  'Create Sub-Version'          => 'Unterversion erzeugen',
890
  'Create Variants with selected Values' => 'Varianten mit ausgewählten Ausprägungen erstellen',
887 891
  'Create a new background job' => 'Einen neuen Hintergrund-Job anlegen',
888 892
  'Create a new client'         => 'Einen neuen Mandanten anlegen',
889 893
  'Create a new delivery term'  => 'Neue Lieferbedingungen anlegen',
......
935 939
  'Create invoice'              => 'Buchung erstellen',
936 940
  'Create invoice?'             => 'Rechnung erstellen?',
937 941
  'Create new'                  => 'Neu erfassen',
942
  'Create new Variants'         => 'Neue Varianten erstellen',
938 943
  'Create new client #1'        => 'Neuen Mandanten #1 anlegen',
939 944
  'Create new quotation or order' => 'Neues Angebot oder neuen Auftrag anlegen',
940 945
  'Create new quotation/order'  => 'Neues Angebot/neuen Auftrag anlegen',
......
1425 1430
  'Edit Invoice'                => 'Rechnung bearbeiten',
1426 1431
  'Edit Invoice for Advance Payment' => 'Anzahlungsrechnung bearbeiten',
1427 1432
  'Edit Letter'                 => 'Brief bearbeiten',
1433
  'Edit Parent Variant'         => 'Stammartikel bearbeiten',
1428 1434
  'Edit Part'                   => 'Ware bearbeiten',
1429 1435
  'Edit Preferences for #1'     => 'Einstellungen von #1 bearbeiten',
1430 1436
  'Edit Price Factor'           => 'Preisfaktor bearbeiten',
......
1452 1458
  'Edit Supplier Delivery Order' => 'Beistell-Lieferschein bearbeiten',
1453 1459
  'Edit User'                   => 'Benutzerdaten bearbeiten',
1454 1460
  'Edit User Group'             => 'Benutzergruppe bearbeiten',
1461
  'Edit Variant'                => 'Variante bearbeiten',
1455 1462
  'Edit Vendor'                 => 'Lieferant editieren',
1456 1463
  'Edit Vendor Invoice'         => 'Einkaufsrechnung bearbeiten',
1457 1464
  'Edit Warehouse'              => 'Lager bearbeiten',
......
2224 2231
  'Last Dunning'                => 'Letzte Mahnung',
2225 2232
  'Last Invoice Number'         => 'Letzte Rechnungsnummer',
2226 2233
  'Last Numbers / Prefixes'     => 'Letzte Nummern / Präfixe',
2234
  'Last Parent Variant Number'  => 'Letzte Stammartikelnummer',
2227 2235
  'Last Purchase Delivery Order Number' => 'Letzte Lieferscheinnummer (Einkauf)',
2228 2236
  'Last Purchase Order Confirmation Number' => 'Letzte Lieferantenauftragsbestätigungs-Nummer',
2229 2237
  'Last Purchase Order Number'  => 'Letzte Lieferantenauftragsnummer',
......
2239 2247
  'Last Service Number'         => 'Letzte Dienstleistungsnr.',
2240 2248
  'Last Supplier Delivery Order Number' => 'Letzte Beistell-Lieferscheinnummer',
2241 2249
  'Last Transaction'            => 'Letzte Buchung',
2250
  'Last Variant Number'         => 'Letzte Variantennummer',
2242 2251
  'Last Vendor Number'          => 'Letzte Lieferantennummer',
2243 2252
  'Last command output'         => 'Ausgabe des letzten Befehls',
2244 2253
  'Last modification'           => 'Letzte Änderung',
......
2799 2808
  'Paid'                        => 'bezahlt',
2800 2809
  'Paid amount'                 => 'Bezahlter Betrag',
2801 2810
  'Parameter module must be given.' => 'Der Parameter "module" miss angegeben werden.',
2811
  'Parent Variant'              => 'Stammartikel',
2802 2812
  'Parsing the XML data failed: #1' => 'Parsen der XML-Daten fehlgeschlagen: #1',
2803 2813
  'Parsing the XMP metadata failed.' => 'Parsen der XMP-Metadaten schlug fehl.',
2804 2814
  'Part'                        => 'Ware',
......
3553 3563
  'Select/Deselect'             => 'Aus-/Abwählen',
3554 3564
  'Select/Deselect all'         => 'Alle Aus-/Abwählen',
3555 3565
  'Selected'                    => 'Ausgewählt',
3566
  'Selected Property Values'    => 'Ausgewählte Ausprägunen',
3556 3567
  'Selected items deleted'      => 'Ausgewählte Positionen gelöscht',
3557 3568
  'Selection'                   => 'Auswahlbox',
3558 3569
  'Selection fields: The option field must contain the available options for the selection. Options are separated by \'##\', for example \'Early##Normal##Late\'.' => 'Auswahlboxen: Das Optionenfeld muss die für die Auswahl verfügbaren Einträge enthalten. Die Einträge werden mit \'##\' voneinander getrennt. Beispiel: \'Früh##Normal##Spät\'.',
......
4784 4795
  'Variable'                    => 'Variable',
4785 4796
  'Variable Description'        => 'Datenfeldbezeichnung',
4786 4797
  'Variable Name'               => 'Datenfeldname (intern)',
4798
  'Variant'                     => 'Variante',
4799
  'Variants'                    => 'Varianten',
4787 4800
  'Vendor'                      => 'Lieferant',
4788 4801
  'Vendor & Order'              => 'Lieferant & Bestellung',
4789 4802
  'Vendor & Transaction'        => 'Lieferant & Buchung',
locale/en/all
203 203
  'Add Invoice'                 => '',
204 204
  'Add Invoice for Advance Payment' => '',
205 205
  'Add Letter'                  => '',
206
  'Add Parent Variant'          => '',
206 207
  'Add Part'                    => '',
207 208
  'Add Parts here!'             => '',
208 209
  'Add Price Factor'            => '',
......
235 236
  'Add Transaction'             => '',
236 237
  'Add User'                    => '',
237 238
  'Add User Group'              => '',
239
  'Add Variant'                 => '',
238 240
  'Add Vendor'                  => '',
239 241
  'Add Vendor Invoice'          => '',
240 242
  'Add Warehouse'               => '',
......
315 317
  'All'                         => '',
316 318
  'All Accounts'                => '',
317 319
  'All Data'                    => '',
320
  'All Property Values'         => '',
318 321
  'All as list'                 => '',
319 322
  'All changes in that file have been reverted.' => '',
320 323
  'All clients'                 => '',
......
884 887
  'Create PDF'                  => '',
885 888
  'Create Reclamation'          => '',
886 889
  'Create Sub-Version'          => '',
890
  'Create Variants with selected Values' => '',
887 891
  'Create a new background job' => '',
888 892
  'Create a new client'         => '',
889 893
  'Create a new delivery term'  => '',
......
935 939
  'Create invoice'              => '',
936 940
  'Create invoice?'             => '',
937 941
  'Create new'                  => '',
942
  'Create new Variants'         => '',
938 943
  'Create new client #1'        => '',
939 944
  'Create new quotation or order' => '',
940 945
  'Create new quotation/order'  => '',
......
1425 1430
  'Edit Invoice'                => '',
1426 1431
  'Edit Invoice for Advance Payment' => '',
1427 1432
  'Edit Letter'                 => '',
1433
  'Edit Parent Variant'         => '',
1428 1434
  'Edit Part'                   => '',
1429 1435
  'Edit Preferences for #1'     => '',
1430 1436
  'Edit Price Factor'           => '',
......
1452 1458
  'Edit Supplier Delivery Order' => '',
1453 1459
  'Edit User'                   => '',
1454 1460
  'Edit User Group'             => '',
1461
  'Edit Variant'                => '',
1455 1462
  'Edit Vendor'                 => '',
1456 1463
  'Edit Vendor Invoice'         => '',
1457 1464
  'Edit Warehouse'              => '',
......
2223 2230
  'Last Dunning'                => '',
2224 2231
  'Last Invoice Number'         => '',
2225 2232
  'Last Numbers / Prefixes'     => '',
2233
  'Last Parent Variant Number'  => '',
2226 2234
  'Last Purchase Delivery Order Number' => '',
2227 2235
  'Last Purchase Order Confirmation Number' => '',
2228 2236
  'Last Purchase Order Number'  => '',
......
2238 2246
  'Last Service Number'         => '',
2239 2247
  'Last Supplier Delivery Order Number' => '',
2240 2248
  'Last Transaction'            => '',
2249
  'Last Variant Number'         => '',
2241 2250
  'Last Vendor Number'          => '',
2242 2251
  'Last command output'         => '',
2243 2252
  'Last modification'           => '',
......
2798 2807
  'Paid'                        => '',
2799 2808
  'Paid amount'                 => '',
2800 2809
  'Parameter module must be given.' => '',
2810
  'Parent Variant'              => '',
2801 2811
  'Parsing the XML data failed: #1' => '',
2802 2812
  'Parsing the XMP metadata failed.' => '',
2803 2813
  'Part'                        => '',
......
3552 3562
  'Select/Deselect'             => '',
3553 3563
  'Select/Deselect all'         => '',
3554 3564
  'Selected'                    => '',
3565
  'Selected Property Values'    => '',
3555 3566
  'Selected items deleted'      => '',
3556 3567
  'Selection'                   => '',
3557 3568
  'Selection fields: The option field must contain the available options for the selection. Options are separated by \'##\', for example \'Early##Normal##Late\'.' => '',
......
4782 4793
  'Variable'                    => '',
4783 4794
  'Variable Description'        => '',
4784 4795
  'Variable Name'               => '',
4796
  'Variant'                     => '',
4797
  'Variants'                    => '',
4785 4798
  'Vendor'                      => '',
4786 4799
  'Vendor & Order'              => '',
4787 4800
  'Vendor & Transaction'        => '',
menus/user/00-erp.yaml
79 79
  access: part_service_assembly_edit & client/feature_experimental_assortment
80 80
  params:
81 81
    action: Part/add_assortment
82
- parent: master_data
83
  id: master_data_add_parent_variant
84
  name: Add Parent Variant
85
  order: 575
86
  access: part_service_assembly_edit
87
  params:
88
    action: Part/add_parent_variant
82 89
- parent: master_data
83 90
  id: master_data_add_project
84 91
  name: Add Project
templates/design40_webpages/part/_variants.html
1
[% USE T8 %]
2
[% USE HTML %]
3
[% USE LxERP %]
4
[% USE L %]
5
[% USE P %]
6

  
7
<div class="wrapper input-panel">
8
  <h3> [% LxERP.t8("Create new Variants") %] </h3>
9
  <div class="wrapper">
10
  [% FOREACH variant_property = SELF.part.variant_properties %]
11
    <div class="col input-panel" style="min-width:fit-content;">
12
      <h4>[% variant_property.name_translated | html %]</h4>
13
      [% L.select_tag("variant_properties." _ variant_property.id _ ".selected_property_values[]",
14
        variant_property.property_values,
15
        title_key='value_translated', value_key='id',
16
        id="selected_property_values_" _ variant_property.id,
17
        multiple=1,
18
      ) %]
19
      [% L.multiselect2side(
20
        "selected_property_values_" _ variant_property.id,
21
        labelsx=LxERP.t8("All Property Values"),
22
        labeldx=LxERP.t8("Selected Property Values")
23
      ) %]
24
    </div>
25
  [% END %]
26
  </div>
27
  [% L.button_tag('kivi.Part.create_variants();', LxERP.t8("Create Variants with selected Values")) %]
28
</div>
29

  
30
<br>
31

  
32
variants:
33
[% FOREACH variant = SELF.part.variants %]
34
  [% variant.partnumber %]:[% variant.description %]
35
[% END %]
36

  
37

  
templates/design40_webpages/part/form.html
19 19

  
20 20
  <ul class="ui-tabs">
21 21
    <li><a href="#basic_data">[% 'Basic Data' | $T8 %]</a></li>
22
    [% IF SELF.part.is_parent_variant && SELF.part.id %]
23
      <li><a href="#variants_tab">[% 'Variants' | $T8 %]</a></li>
24
    [% END %]
22 25
    [% IF SELF.part.is_assortment %]
23 26
      <li><a href="#assortment_tab">[% 'Assortment items' | $T8 %]</a></li>
24 27
    [% END %]
......
55 58
    [% PROCESS 'part/_basic_data.html' %]
56 59
  </div>
57 60

  
61
  [% IF SELF.part.is_parent_variant && SELF.part.id %]
62
    <div id="variants_tab" class="ui-tabs-panel">
63
      [% PROCESS 'part/_variants.html' id=part.id %]
64
    </div>
65
  [% END %]
66

  
58 67
  [% IF SELF.part.is_assortment %]
59 68
    <div id="assortment_tab" class="ui-tabs-panel">
60 69
      [% PROCESS 'part/_assortment.html' id=part.id assortment_id=SELF.part.id %]

Auch abrufbar als: Unified diff