Revision 8a0d2996
Von Tamino Steinert vor mehr als 1 Jahr hinzugefügt
SL/Controller/Part.pm | ||
---|---|---|
use File::Temp;
|
||
use List::Util qw(sum);
|
||
use List::UtilsBy qw(extract_by);
|
||
use List::MoreUtils qw(any pairwise);
|
||
use POSIX qw(strftime);
|
||
use Text::CSV_XS;
|
||
|
||
... | ... | |
|
||
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) {
|
||
if (any {$_} grep {
|
||
!defined $::form->{variant_properties}->{$_->id}->{selected_property_value_ids}
|
||
} @$variant_properties
|
||
) {
|
||
return $self->js->error(
|
||
t8('No property value selected for variant properties: #1.',
|
||
join(", ",
|
||
map {$_->displayable_name}
|
||
grep {!defined $::form->{variant_properties}->{$_->id}->{selected_property_values}}
|
||
grep {!defined $::form->{variant_properties}->{$_->id}->{selected_property_value_ids}}
|
||
@$variant_properties
|
||
)
|
||
)
|
||
... | ... | |
my @grouped_variant_property_values = ();
|
||
push @grouped_variant_property_values,
|
||
SL::DB::Manager::VariantPropertyValue->get_all(
|
||
where => [ id => $::form->{variant_properties}->{$_}->{selected_property_values} ]
|
||
where => [ id => $::form->{variant_properties}->{$_}->{selected_property_value_ids} ]
|
||
)
|
||
for @variant_property_ids;
|
||
|
||
|
||
my @variant_property_values_lists = ();
|
||
my @variant_property_value_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) {
|
||
unless (scalar @variant_property_value_lists) {
|
||
push @new_lists, [$variant_property_value];
|
||
}
|
||
foreach my $variant_property_values_list (@variant_property_values_lists) {
|
||
foreach my $variant_property_values_list (@variant_property_value_lists) {
|
||
push @new_lists, [@$variant_property_values_list, $variant_property_value];
|
||
}
|
||
}
|
||
@variant_property_values_lists = @new_lists;
|
||
@variant_property_value_lists = @new_lists;
|
||
}
|
||
|
||
my @new_variants = ();
|
||
_check_variant_property_values_not_taken($part, \@variant_property_value_lists);
|
||
SL::DB->client->with_transaction(sub {
|
||
push @new_variants, $part->create_new_variant($_)
|
||
for @variant_property_values_lists;
|
||
$part->create_new_variant($_) for @variant_property_value_lists;
|
||
1;
|
||
}) or do {
|
||
die t8('Error while creating variants: '), $@;
|
||
die t8('Error while creating variants: '), SL::DB->client->error;
|
||
};
|
||
|
||
$self->redirect_to(
|
||
controller => 'Part',
|
||
action => 'edit',
|
||
'part.id' => $self->part->id
|
||
);
|
||
}
|
||
|
||
sub action_convert_part_to_variant {
|
||
my ($self) = @_;
|
||
|
||
my $convert_part_id = $::form->{convert_part}->{id};
|
||
die t8("Please select a part to convert.") unless $convert_part_id;
|
||
|
||
my @variant_property_ids = sort keys %{$::form->{convert_part}->{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 {$_->displayable_name}
|
||
grep {!defined $::form->{convert_part}->{variant_properties}->{$_->id}->{selected_property_value_id}}
|
||
@$variant_properties
|
||
)
|
||
)
|
||
)->render();
|
||
}
|
||
|
||
my @variant_property_values = map {
|
||
SL::DB::VariantPropertyValue->new(
|
||
id => $::form->{convert_part}->{variant_properties}->{$_}->{selected_property_value_id}
|
||
)->load()
|
||
} @variant_property_ids;
|
||
|
||
_check_variant_property_values_not_taken($part, [\@variant_property_values]);
|
||
SL::DB->client->with_transaction(sub {
|
||
my $part_to_convert = SL::DB::Part->new(id => $convert_part_id)->load;
|
||
$part_to_convert->variant_type('variant');
|
||
$part_to_convert->variant_property_values(\@variant_property_values);
|
||
$part_to_convert->parent_variant($part);
|
||
$part_to_convert->save;
|
||
1;
|
||
}) or do {
|
||
die t8('Error while converting part to variant: '), SL::DB->Client->error;
|
||
};
|
||
|
||
$self->redirect_to(
|
||
... | ... | |
Carp::confess "invalid part_type" unless $_[0] =~ /^(part|service|assembly|assortment)$/;
|
||
}
|
||
|
||
sub _check_variant_property_values_not_taken {
|
||
my ($parent_variant, $variant_property_value_lists) = @_;
|
||
|
||
my @double_lists;
|
||
my $variants = $parent_variant->variants;
|
||
foreach my $variant (@$variants) {
|
||
my @property_value_ids = sort map {$_->id} $variant->variant_property_values;
|
||
foreach my $test_property_values (@$variant_property_value_lists) {
|
||
my @test_property_value_ids = sort map {$_->id} @$test_property_values;
|
||
if (@test_property_value_ids == @property_value_ids
|
||
&& not any {$_} pairwise {$a != $b} @test_property_value_ids, @property_value_ids
|
||
) {
|
||
push @double_lists, join(', ', map {$_->displayable_name} @$test_property_values);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (@double_lists) {
|
||
die t8("There is already a variant with the property values: #1.", join("; ", @double_lists));
|
||
}
|
||
}
|
||
|
||
sub normalize_text_blocks {
|
||
my ($self) = @_;
|
SL/DB/Part.pm | ||
---|---|---|
use strict;
|
||
|
||
use Carp;
|
||
use List::MoreUtils qw(any uniq);
|
||
use List::MoreUtils qw(any uniq pairwise);
|
||
use List::Util qw(sum max);
|
||
use Rose::DB::Object::Helpers qw(as_tree);
|
||
|
||
... | ... | |
|
||
__PACKAGE__->before_save('_before_save_set_partnumber');
|
||
__PACKAGE__->before_save('_before_save_set_assembly_weight');
|
||
__PACKAGE__->before_save('_before_check_variant_property_values');
|
||
|
||
sub _before_save_set_partnumber {
|
||
my ($self) = @_;
|
||
... | ... | |
return 1;
|
||
}
|
||
|
||
sub _before_check_variant_property_values {
|
||
my ($self) = @_;
|
||
if ($self->is_variant) {
|
||
my @property_value_ids = sort map {$_->id} $self->variant_property_values;
|
||
my ($parent_variant) = $self->parent_variant;
|
||
my $other_variants = $parent_variant->variants;
|
||
foreach my $variant (@$other_variants) {
|
||
next if $variant->id == $self->id;
|
||
my @other_property_value_ids = sort map {$_->id} $variant->variant_property_values;
|
||
if (@other_property_value_ids == @property_value_ids
|
||
&& not any {$_} pairwise {$a != $b} @other_property_value_ids, @property_value_ids
|
||
) {
|
||
die t8("There is already a variant with the property values: "),
|
||
join(' ,', map {$_->displayable_name} $self->variant_property_values);
|
||
}
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
sub items {
|
||
my ($self) = @_;
|
||
|
||
... | ... | |
die "Given variant_property_values dosn't match the variant_properties of parent_variant part";
|
||
}
|
||
|
||
my $separator = '.'; # TODO: make configurable
|
||
my $new_variant = $self->clone_and_reset;
|
||
$new_variant->partnumber($self->_next_variant_partnumber);
|
||
$new_variant->variant_type('variant');
|
||
$new_variant->add_assemblies(map {$_->clone_and_reset} $self->assemblies) if ($self->is_assembly);
|
||
$new_variant->add_variant_property_values(@$variant_property_values);
|
||
$new_variant->parent_variant($self);
|
||
$new_variant->save;
|
||
|
||
$self->add_variants($new_variant);
|
||
return $new_variant;
|
||
}
|
||
|
||
sub _next_variant_partnumber {
|
||
my ($self) = @_;
|
||
die "only callable on parts of type parent_variant" unless $self->is_parent_variant;
|
||
|
||
my $separator = '.'; # TODO: make configurable
|
||
my $last_variant_number =
|
||
max
|
||
map {
|
||
... | ... | |
}
|
||
$self->variants;
|
||
|
||
my $new_variant = $self->clone_and_reset;
|
||
$new_variant->partnumber($self->partnumber . $separator . ($last_variant_number + 1));
|
||
$new_variant->variant_type('variant');
|
||
$new_variant->add_assemblies(map {$_->clone_and_reset} $self->assemblies) if ($self->is_assembly);
|
||
$new_variant->add_variant_property_values(@$variant_property_values);
|
||
|
||
$self->add_variants($new_variant);
|
||
$self->save;
|
||
return $new_variant;
|
||
return $self->partnumber . $separator . ($last_variant_number + 1);
|
||
}
|
||
|
||
sub clone_and_reset_deep {
|
SL/Presenter/Part.pm | ||
---|---|---|
for autocompletion. You may comma separate multiple types as in
|
||
C<part,assembly>.
|
||
|
||
If C<%params> contains C<variant_type> only parts of this variant type will be
|
||
used for autocompletion. You may comma separate multiple variant types as in
|
||
C<single,variant>.
|
||
|
||
If C<%params> contains C<status> only parts of this status will be used
|
||
for autocompletion. C<status> can be one of the following strings:
|
||
C<active>, C<obsolete> or C<all>. C<active> is the default if C<status> is
|
js/kivi.Part.js | ||
---|---|---|
$.post("controller.pl", data, kivi.eval_json_result);
|
||
};
|
||
|
||
ns.convert_part_to_variant = function() {
|
||
var data = $('#ic').serializeArray();
|
||
data.push({ name: 'action', value: 'Part/convert_part_to_variant' });
|
||
$.post("controller.pl", data, kivi.eval_json_result);
|
||
};
|
||
|
||
ns.update_variant_property_value_options = function() {
|
||
var data = $('#ic').serializeArray();
|
||
data.push({ name: 'action', value: 'Part/update_variant_property_value_options' });
|
||
... | ... | |
if (this.o.part_type)
|
||
data['filter.part_type'] = this.o.part_type.split(',');
|
||
|
||
if (this.o.variant_type)
|
||
data['filter.variant_type'] = this.o.variant_type.split(',');
|
||
|
||
if (this.o.status) {
|
||
if (this.o.status == 'active') data['filter.obsolete'] = 0;
|
||
if (this.o.status == 'obsolete') data['filter.obsolete'] = 1;
|
templates/design40_webpages/part/_parent_variant.html | ||
---|---|---|
<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[]",
|
||
<h4>[% variant_property.displayable_name | html %]</h4>
|
||
[% L.select_tag("variant_properties." _ variant_property.id _ ".selected_property_value_ids[]",
|
||
variant_property.property_values,
|
||
title_key='displayable_name', value_key='id',
|
||
id="selected_property_values_" _ variant_property.id,
|
||
id="selected_property_value_ids_" _ variant_property.id,
|
||
multiple=1,
|
||
) %]
|
||
[% L.multiselect2side(
|
||
"selected_property_values_" _ variant_property.id,
|
||
"selected_property_value_ids_" _ variant_property.id,
|
||
labelsx=LxERP.t8("All Property Values"),
|
||
labeldx=LxERP.t8("Selected Property Values")
|
||
) %]
|
||
... | ... | |
</div>
|
||
[% L.button_tag('kivi.Part.create_variants();', LxERP.t8("Create Variants with selected Values")) %]
|
||
</div>
|
||
|
||
<div class="wrapper input-panel">
|
||
<h3> [% LxERP.t8("Convert part to Variant") %] </h3>
|
||
<table class="tbl-list">
|
||
<caption>
|
||
[% 'Variant Properties' | $T8 %]
|
||
</caption>
|
||
<thead>
|
||
<tr>
|
||
<th>[% 'Name' | $T8 %]</th>
|
||
<th>[% 'Value' | $T8 %]</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
[% FOREACH variant_property = SELF.part.variant_properties %]
|
||
<tr>
|
||
<td>[% variant_property.displayable_name | html %]</td>
|
||
<td>
|
||
[% L.select_tag("convert_part.variant_properties." _ variant_property.id _ ".selected_property_value_id",
|
||
variant_property.property_values,
|
||
title_key='displayable_name', value_key='id',
|
||
size=variant_property.property_values.size,
|
||
) %]
|
||
</tr>
|
||
[% END %]
|
||
</tbody>
|
||
</table>
|
||
<label for="convert_part.id">[% 'Part to convert:' | $T8 %]</label>
|
||
[% P.part.picker('convert_part.id', undef,
|
||
part_type=SELF.part.part_type, variant_type='single',
|
||
placeholder=(LxERP.t8('Type:') _ ' ' _ LxERP.t8(SELF.part.part_type)),
|
||
class="wi-wide"
|
||
) %]
|
||
<br>
|
||
<br>
|
||
[% L.button_tag('kivi.Part.convert_part_to_variant();', LxERP.t8("Convert")) %]
|
||
</div>
|
||
</div>
|
||
|
||
|
Auch abrufbar als: Unified diff
Varianten: einfachen Artikel in Variante umwandeln