Revision 706e28ed
Von Tamino Steinert vor etwa 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