Revision a279fb60
Von Tamino Steinert vor 12 Monaten hinzugefügt
SL/Controller/Part.pm | ||
---|---|---|
$self->add;
|
||
};
|
||
|
||
sub action_add_parent_variant {
|
||
my ($self, %params) = @_;
|
||
|
||
$self->part( SL::DB::Part->new_parent_variant );
|
||
$self->add;
|
||
}
|
||
|
||
sub action_add_from_record {
|
||
my ($self) = @_;
|
||
|
||
... | ... | |
|
||
check_has_valid_part_type($::form->{part_type});
|
||
|
||
$self->action_add_part if $::form->{part_type} eq 'part';
|
||
$self->action_add_service if $::form->{part_type} eq 'service';
|
||
$self->action_add_assembly if $::form->{part_type} eq 'assembly';
|
||
$self->action_add_assortment if $::form->{part_type} eq 'assortment';
|
||
$self->action_add_part if $::form->{part_type} eq 'part';
|
||
$self->action_add_service if $::form->{part_type} eq 'service';
|
||
$self->action_add_assembly if $::form->{part_type} eq 'assembly';
|
||
$self->action_add_assortment if $::form->{part_type} eq 'assortment';
|
||
$self->action_add_parent_variant if $::form->{part_type} eq 'parent_variant';
|
||
$self->action_add_variant if $::form->{part_type} eq 'variant';
|
||
};
|
||
|
||
sub action_save {
|
||
... | ... | |
}
|
||
}
|
||
|
||
sub action_create_variants {
|
||
my ($self) = @_;
|
||
my @variant_property_ids = sort keys %{$::form->{variant_properties}};
|
||
|
||
my $part = $self->part;
|
||
my $variant_properties = $part->variant_properties();
|
||
my @needed_variant_property_ids = sort map {$_->id} @$variant_properties;
|
||
|
||
if (@variant_property_ids != @needed_variant_property_ids) {
|
||
return $self->js->error(
|
||
t8('No property value selected for variant properties: #1.',
|
||
join(", ",
|
||
map {$_->name_translated}
|
||
grep {!defined $::form->{variant_properties}->{$_->id}->{selected_property_values}}
|
||
@$variant_properties
|
||
)
|
||
)
|
||
)->render();
|
||
}
|
||
|
||
my @grouped_variant_property_values = ();
|
||
push @grouped_variant_property_values,
|
||
SL::DB::Manager::VariantPropertyValue->get_all(
|
||
where => [ id => $::form->{variant_properties}->{$_}->{selected_property_values} ]
|
||
)
|
||
for @variant_property_ids;
|
||
|
||
|
||
my @variant_property_values_lists = ();
|
||
foreach my $variant_property_values (@grouped_variant_property_values) {
|
||
my @new_lists = ();
|
||
foreach my $variant_property_value (@$variant_property_values) {
|
||
unless (scalar @variant_property_values_lists) {
|
||
push @new_lists, [$variant_property_value];
|
||
}
|
||
foreach my $variant_property_values_list (@variant_property_values_lists) {
|
||
push @new_lists, [@$variant_property_values_list, $variant_property_value];
|
||
}
|
||
}
|
||
@variant_property_values_lists = @new_lists;
|
||
}
|
||
|
||
my @new_variants = ();
|
||
SL::DB->client->with_transaction(sub {
|
||
push @new_variants, $part->create_new_variant($_)
|
||
for @variant_property_values_lists;
|
||
1;
|
||
}) or do {
|
||
return $self->js->error(t8('Error while creating variants: ' . @_))->render();
|
||
};
|
||
|
||
$self->redirect_to(
|
||
controller => 'Part',
|
||
action => 'edit',
|
||
'part.id' => $self->part->id
|
||
);
|
||
}
|
||
|
||
sub action_delete {
|
||
my ($self) = @_;
|
||
|
||
... | ... | |
@{ $params{CUSTOM_VARIABLES_FIRST_TAB} } = extract_by { $_->{first_tab} == 1 } @{ $params{CUSTOM_VARIABLES} };
|
||
}
|
||
|
||
my %title_hash = ( part => t8('Edit Part'),
|
||
assembly => t8('Edit Assembly'),
|
||
service => t8('Edit Service'),
|
||
assortment => t8('Edit Assortment'),
|
||
my %title_hash = ( part => t8('Edit Part'),
|
||
assembly => t8('Edit Assembly'),
|
||
service => t8('Edit Service'),
|
||
assortment => t8('Edit Assortment'),
|
||
parent_variant => t8('Edit Parent Variant'),
|
||
variant => t8('Edit Variant'),
|
||
);
|
||
|
||
$self->part->prices([]) unless $self->part->prices;
|
||
... | ... | |
$self->_set_javascript;
|
||
$self->_setup_form_action_bar;
|
||
|
||
my %title_hash = ( part => t8('Add Part'),
|
||
assembly => t8('Add Assembly'),
|
||
service => t8('Add Service'),
|
||
assortment => t8('Add Assortment'),
|
||
my %title_hash = ( part => t8('Add Part'),
|
||
assembly => t8('Add Assembly'),
|
||
service => t8('Add Service'),
|
||
assortment => t8('Add Assortment'),
|
||
parent_variant => t8('Add Parent Variant'),
|
||
variant => t8('Add Variant'),
|
||
);
|
||
|
||
$self->render(
|
||
... | ... | |
|
||
sub _set_javascript {
|
||
my ($self) = @_;
|
||
$::request->layout->use_javascript("${_}.js") for qw(kivi.Part kivi.File kivi.PriceRule kivi.ShopPart kivi.Validator);
|
||
$::request->layout->use_javascript("${_}.js") for qw(kivi.Part kivi.File kivi.PriceRule kivi.ShopPart kivi.Validator jquery.selectboxes jquery.multiselect2side);
|
||
$::request->layout->add_javascripts_inline("\$(function(){kivi.PriceRule.load_price_rules_for_part(@{[ $self->part->id ]})});") if $self->part->id;
|
||
}
|
||
|
||
... | ... | |
}
|
||
|
||
sub check_has_valid_part_type {
|
||
die "invalid part_type" unless $_[0] =~ /^(part|service|assembly|assortment)$/;
|
||
die "invalid part_type" unless $_[0] =~ /^(part|service|assembly|assortment|parent_variant|variant)$/;
|
||
}
|
||
|
||
|
SL/DB/Part.pm | ||
---|---|---|
$class->new(%params, part_type => 'parent_variant');
|
||
}
|
||
|
||
sub new_variant {
|
||
my ($class, %params) = @_;
|
||
$class->new(%params, part_type => 'variant');
|
||
}
|
||
|
||
sub last_modification {
|
||
my ($self) = @_;
|
||
return $self->mtime // $self->itime;
|
||
... | ... | |
return \@sorted;
|
||
}
|
||
|
||
sub create_new_variant {
|
||
my ($self, $variant_property_values) = @_;
|
||
die "only callable on parts of type parent_variant" unless $self->is_parent_variant;
|
||
die "only callable on saved objects" unless $self->id;
|
||
|
||
my @selected_variant_property_ids = sort map {$_->variant_property_id} @$variant_property_values;
|
||
my @variant_property_ids = sort map {$_->id} @{$self->variant_properties};
|
||
if (@variant_property_ids != @selected_variant_property_ids) {
|
||
die "Given variant_property_values dosn't match the variant_properties of parent_variant part";
|
||
}
|
||
|
||
my $new_variant = $self->clone_and_reset;
|
||
# TODO set partnumber
|
||
$new_variant->part_type('variant');
|
||
$new_variant->save;
|
||
SL::DB::VariantPropertyValuePart->new(
|
||
part_id => $new_variant->id,
|
||
variant_property_value_id => $_->id,
|
||
)->save for @$variant_property_values;
|
||
SL::DB::PartParentVariantPartVariant->new(
|
||
variant_id => $new_variant->id,
|
||
parent_variant_id => $self->id,
|
||
)->save;
|
||
|
||
return $new_variant;
|
||
}
|
||
|
||
sub clone_and_reset_deep {
|
||
my ($self) = @_;
|
||
|
SL/DB/VariantProperty.pm | ||
---|---|---|
map_to => 'part',
|
||
type => 'many to many',
|
||
},
|
||
property_values => {
|
||
class => 'SL::DB::VariantPropertyValue',
|
||
column_map => { id => 'variant_property_id' },
|
||
type => 'one to many',
|
||
}
|
||
);
|
||
|
||
__PACKAGE__->meta->initialize;
|
||
... | ... | |
return @errors;
|
||
}
|
||
|
||
sub name_translated {goto &name} # TODO
|
||
|
||
1;
|
SL/DB/VariantPropertyValue.pm | ||
---|---|---|
|
||
__PACKAGE__->meta->initialize;
|
||
|
||
sub value_translated {goto &value} # TODO
|
||
|
||
1;
|
js/kivi.Part.js | ||
---|---|---|
$.post("controller.pl", { action: 'Part/warehouse_changed', warehouse_id: function(){ return $('#part_warehouse_id').val(); } }, kivi.eval_json_result);
|
||
};
|
||
|
||
ns.create_variants = function() {
|
||
var data = $('#ic').serializeArray();
|
||
data.push({ name: 'action', value: 'Part/create_variants' });
|
||
$.post("controller.pl", data, kivi.eval_json_result);
|
||
};
|
||
|
||
var KEY = {
|
||
TAB: 9,
|
||
ENTER: 13,
|
locale/de/all | ||
---|---|---|
'Add Invoice' => 'Rechnung erfassen',
|
||
'Add Invoice for Advance Payment' => 'Anzahlungsrechnung erfassen',
|
||
'Add Letter' => 'Brief hinzufügen',
|
||
'Add Parent Variant' => 'Stammartikel erfassen',
|
||
'Add Part' => 'Ware erfassen',
|
||
'Add Parts here!' => 'Artikel hier hinzufügen!',
|
||
'Add Price Factor' => 'Preisfaktor erfassen',
|
||
... | ... | |
'Add Transaction' => 'Dialogbuchen',
|
||
'Add User' => 'Neuer Benutzer',
|
||
'Add User Group' => 'Neue Benutzergruppe',
|
||
'Add Variant' => 'Variante erfassen',
|
||
'Add Vendor' => 'Lieferant erfassen',
|
||
'Add Vendor Invoice' => 'Einkaufsrechnung erfassen',
|
||
'Add Warehouse' => 'Lager erfassen',
|
||
... | ... | |
'All' => 'Alle',
|
||
'All Accounts' => 'Alle Konten',
|
||
'All Data' => 'Alle Daten',
|
||
'All Property Values' => 'Alle Ausprägunen',
|
||
'All as list' => 'Alle als Liste',
|
||
'All changes in that file have been reverted.' => 'Alle Änderungen in dieser Datei wurden rückgängig gemacht.',
|
||
'All clients' => 'Alle Mandanten',
|
||
... | ... | |
'Create PDF' => 'PDF erzeugen',
|
||
'Create Reclamation' => 'Reklamation erstellen',
|
||
'Create Sub-Version' => 'Unterversion erzeugen',
|
||
'Create Variants with selected Values' => 'Varianten mit ausgewählten Ausprägungen erstellen',
|
||
'Create a new background job' => 'Einen neuen Hintergrund-Job anlegen',
|
||
'Create a new client' => 'Einen neuen Mandanten anlegen',
|
||
'Create a new delivery term' => 'Neue Lieferbedingungen anlegen',
|
||
... | ... | |
'Create invoice' => 'Buchung erstellen',
|
||
'Create invoice?' => 'Rechnung erstellen?',
|
||
'Create new' => 'Neu erfassen',
|
||
'Create new Variants' => 'Neue Varianten erstellen',
|
||
'Create new client #1' => 'Neuen Mandanten #1 anlegen',
|
||
'Create new quotation or order' => 'Neues Angebot oder neuen Auftrag anlegen',
|
||
'Create new quotation/order' => 'Neues Angebot/neuen Auftrag anlegen',
|
||
... | ... | |
'Edit Invoice' => 'Rechnung bearbeiten',
|
||
'Edit Invoice for Advance Payment' => 'Anzahlungsrechnung bearbeiten',
|
||
'Edit Letter' => 'Brief bearbeiten',
|
||
'Edit Parent Variant' => 'Stammartikel bearbeiten',
|
||
'Edit Part' => 'Ware bearbeiten',
|
||
'Edit Preferences for #1' => 'Einstellungen von #1 bearbeiten',
|
||
'Edit Price Factor' => 'Preisfaktor bearbeiten',
|
||
... | ... | |
'Edit Supplier Delivery Order' => 'Beistell-Lieferschein bearbeiten',
|
||
'Edit User' => 'Benutzerdaten bearbeiten',
|
||
'Edit User Group' => 'Benutzergruppe bearbeiten',
|
||
'Edit Variant' => 'Variante bearbeiten',
|
||
'Edit Vendor' => 'Lieferant editieren',
|
||
'Edit Vendor Invoice' => 'Einkaufsrechnung bearbeiten',
|
||
'Edit Warehouse' => 'Lager bearbeiten',
|
||
... | ... | |
'Last Dunning' => 'Letzte Mahnung',
|
||
'Last Invoice Number' => 'Letzte Rechnungsnummer',
|
||
'Last Numbers / Prefixes' => 'Letzte Nummern / Präfixe',
|
||
'Last Parent Variant Number' => 'Letzte Stammartikelnummer',
|
||
'Last Purchase Delivery Order Number' => 'Letzte Lieferscheinnummer (Einkauf)',
|
||
'Last Purchase Order Confirmation Number' => 'Letzte Lieferantenauftragsbestätigungs-Nummer',
|
||
'Last Purchase Order Number' => 'Letzte Lieferantenauftragsnummer',
|
||
... | ... | |
'Last Service Number' => 'Letzte Dienstleistungsnr.',
|
||
'Last Supplier Delivery Order Number' => 'Letzte Beistell-Lieferscheinnummer',
|
||
'Last Transaction' => 'Letzte Buchung',
|
||
'Last Variant Number' => 'Letzte Variantennummer',
|
||
'Last Vendor Number' => 'Letzte Lieferantennummer',
|
||
'Last command output' => 'Ausgabe des letzten Befehls',
|
||
'Last modification' => 'Letzte Änderung',
|
||
... | ... | |
'Paid' => 'bezahlt',
|
||
'Paid amount' => 'Bezahlter Betrag',
|
||
'Parameter module must be given.' => 'Der Parameter "module" miss angegeben werden.',
|
||
'Parent Variant' => 'Stammartikel',
|
||
'Parsing the XML data failed: #1' => 'Parsen der XML-Daten fehlgeschlagen: #1',
|
||
'Parsing the XMP metadata failed.' => 'Parsen der XMP-Metadaten schlug fehl.',
|
||
'Part' => 'Ware',
|
||
... | ... | |
'Select/Deselect' => 'Aus-/Abwählen',
|
||
'Select/Deselect all' => 'Alle Aus-/Abwählen',
|
||
'Selected' => 'Ausgewählt',
|
||
'Selected Property Values' => 'Ausgewählte Ausprägunen',
|
||
'Selected items deleted' => 'Ausgewählte Positionen gelöscht',
|
||
'Selection' => 'Auswahlbox',
|
||
'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\'.',
|
||
... | ... | |
'Variable' => 'Variable',
|
||
'Variable Description' => 'Datenfeldbezeichnung',
|
||
'Variable Name' => 'Datenfeldname (intern)',
|
||
'Variant' => 'Variante',
|
||
'Variants' => 'Varianten',
|
||
'Vendor' => 'Lieferant',
|
||
'Vendor & Order' => 'Lieferant & Bestellung',
|
||
'Vendor & Transaction' => 'Lieferant & Buchung',
|
locale/en/all | ||
---|---|---|
'Add Invoice' => '',
|
||
'Add Invoice for Advance Payment' => '',
|
||
'Add Letter' => '',
|
||
'Add Parent Variant' => '',
|
||
'Add Part' => '',
|
||
'Add Parts here!' => '',
|
||
'Add Price Factor' => '',
|
||
... | ... | |
'Add Transaction' => '',
|
||
'Add User' => '',
|
||
'Add User Group' => '',
|
||
'Add Variant' => '',
|
||
'Add Vendor' => '',
|
||
'Add Vendor Invoice' => '',
|
||
'Add Warehouse' => '',
|
||
... | ... | |
'All' => '',
|
||
'All Accounts' => '',
|
||
'All Data' => '',
|
||
'All Property Values' => '',
|
||
'All as list' => '',
|
||
'All changes in that file have been reverted.' => '',
|
||
'All clients' => '',
|
||
... | ... | |
'Create PDF' => '',
|
||
'Create Reclamation' => '',
|
||
'Create Sub-Version' => '',
|
||
'Create Variants with selected Values' => '',
|
||
'Create a new background job' => '',
|
||
'Create a new client' => '',
|
||
'Create a new delivery term' => '',
|
||
... | ... | |
'Create invoice' => '',
|
||
'Create invoice?' => '',
|
||
'Create new' => '',
|
||
'Create new Variants' => '',
|
||
'Create new client #1' => '',
|
||
'Create new quotation or order' => '',
|
||
'Create new quotation/order' => '',
|
||
... | ... | |
'Edit Invoice' => '',
|
||
'Edit Invoice for Advance Payment' => '',
|
||
'Edit Letter' => '',
|
||
'Edit Parent Variant' => '',
|
||
'Edit Part' => '',
|
||
'Edit Preferences for #1' => '',
|
||
'Edit Price Factor' => '',
|
||
... | ... | |
'Edit Supplier Delivery Order' => '',
|
||
'Edit User' => '',
|
||
'Edit User Group' => '',
|
||
'Edit Variant' => '',
|
||
'Edit Vendor' => '',
|
||
'Edit Vendor Invoice' => '',
|
||
'Edit Warehouse' => '',
|
||
... | ... | |
'Last Dunning' => '',
|
||
'Last Invoice Number' => '',
|
||
'Last Numbers / Prefixes' => '',
|
||
'Last Parent Variant Number' => '',
|
||
'Last Purchase Delivery Order Number' => '',
|
||
'Last Purchase Order Confirmation Number' => '',
|
||
'Last Purchase Order Number' => '',
|
||
... | ... | |
'Last Service Number' => '',
|
||
'Last Supplier Delivery Order Number' => '',
|
||
'Last Transaction' => '',
|
||
'Last Variant Number' => '',
|
||
'Last Vendor Number' => '',
|
||
'Last command output' => '',
|
||
'Last modification' => '',
|
||
... | ... | |
'Paid' => '',
|
||
'Paid amount' => '',
|
||
'Parameter module must be given.' => '',
|
||
'Parent Variant' => '',
|
||
'Parsing the XML data failed: #1' => '',
|
||
'Parsing the XMP metadata failed.' => '',
|
||
'Part' => '',
|
||
... | ... | |
'Select/Deselect' => '',
|
||
'Select/Deselect all' => '',
|
||
'Selected' => '',
|
||
'Selected Property Values' => '',
|
||
'Selected items deleted' => '',
|
||
'Selection' => '',
|
||
'Selection fields: The option field must contain the available options for the selection. Options are separated by \'##\', for example \'Early##Normal##Late\'.' => '',
|
||
... | ... | |
'Variable' => '',
|
||
'Variable Description' => '',
|
||
'Variable Name' => '',
|
||
'Variant' => '',
|
||
'Variants' => '',
|
||
'Vendor' => '',
|
||
'Vendor & Order' => '',
|
||
'Vendor & Transaction' => '',
|
menus/user/00-erp.yaml | ||
---|---|---|
access: part_service_assembly_edit & client/feature_experimental_assortment
|
||
params:
|
||
action: Part/add_assortment
|
||
- parent: master_data
|
||
id: master_data_add_parent_variant
|
||
name: Add Parent Variant
|
||
order: 575
|
||
access: part_service_assembly_edit
|
||
params:
|
||
action: Part/add_parent_variant
|
||
- parent: master_data
|
||
id: master_data_add_project
|
||
name: Add Project
|
templates/design40_webpages/part/_variants.html | ||
---|---|---|
[% USE T8 %]
|
||
[% USE HTML %]
|
||
[% USE LxERP %]
|
||
[% USE L %]
|
||
[% USE P %]
|
||
|
||
<div class="wrapper input-panel">
|
||
<h3> [% LxERP.t8("Create new Variants") %] </h3>
|
||
<div class="wrapper">
|
||
[% FOREACH variant_property = SELF.part.variant_properties %]
|
||
<div class="col input-panel" style="min-width:fit-content;">
|
||
<h4>[% variant_property.name_translated | html %]</h4>
|
||
[% L.select_tag("variant_properties." _ variant_property.id _ ".selected_property_values[]",
|
||
variant_property.property_values,
|
||
title_key='value_translated', value_key='id',
|
||
id="selected_property_values_" _ variant_property.id,
|
||
multiple=1,
|
||
) %]
|
||
[% L.multiselect2side(
|
||
"selected_property_values_" _ variant_property.id,
|
||
labelsx=LxERP.t8("All Property Values"),
|
||
labeldx=LxERP.t8("Selected Property Values")
|
||
) %]
|
||
</div>
|
||
[% END %]
|
||
</div>
|
||
[% L.button_tag('kivi.Part.create_variants();', LxERP.t8("Create Variants with selected Values")) %]
|
||
</div>
|
||
|
||
<br>
|
||
|
||
variants:
|
||
[% FOREACH variant = SELF.part.variants %]
|
||
[% variant.partnumber %]:[% variant.description %]
|
||
[% END %]
|
||
|
||
|
templates/design40_webpages/part/form.html | ||
---|---|---|
|
||
<ul class="ui-tabs">
|
||
<li><a href="#basic_data">[% 'Basic Data' | $T8 %]</a></li>
|
||
[% IF SELF.part.is_parent_variant && SELF.part.id %]
|
||
<li><a href="#variants_tab">[% 'Variants' | $T8 %]</a></li>
|
||
[% END %]
|
||
[% IF SELF.part.is_assortment %]
|
||
<li><a href="#assortment_tab">[% 'Assortment items' | $T8 %]</a></li>
|
||
[% END %]
|
||
... | ... | |
[% PROCESS 'part/_basic_data.html' %]
|
||
</div>
|
||
|
||
[% IF SELF.part.is_parent_variant && SELF.part.id %]
|
||
<div id="variants_tab" class="ui-tabs-panel">
|
||
[% PROCESS 'part/_variants.html' id=part.id %]
|
||
</div>
|
||
[% END %]
|
||
|
||
[% IF SELF.part.is_assortment %]
|
||
<div id="assortment_tab" class="ui-tabs-panel">
|
||
[% PROCESS 'part/_assortment.html' id=part.id assortment_id=SELF.part.id %]
|
Auch abrufbar als: Unified diff
Varianten: Stammartikel anlegen und Varianten erstellen