Merge branch 'f-project-search-custom-variables'
[kivitendo-erp.git] / SL / Controller / Part.pm
index 7b4a2bc..e427cab 100644 (file)
@@ -6,6 +6,7 @@ use parent qw(SL::Controller::Base);
 use Clone qw(clone);
 use SL::DB::Part;
 use SL::DB::PartsGroup;
+use SL::DB::PriceRuleItem;
 use SL::DB::Shop;
 use SL::Controller::Helper::GetModels;
 use SL::Locale::String qw(t8);
@@ -20,6 +21,7 @@ use SL::CVar;
 use SL::MoreCommon qw(save_form);
 use Carp;
 use SL::Presenter::EscapedText qw(escape is_escaped);
+use SL::Presenter::Tag qw(select_tag);
 
 use Rose::Object::MakeMethods::Generic (
   'scalar --get_set_init' => [ qw(parts models part p warehouses multi_items_models
@@ -227,6 +229,7 @@ sub render_form {
   %assembly_vars   = %{ $self->prepare_assembly_render_vars   } if $self->part->is_assembly;
 
   $params{CUSTOM_VARIABLES}  = CVar->get_custom_variables(module => 'IC', trans_id => $self->part->id);
+  $_->{valid}                = 1 for @{ $params{CUSTOM_VARIABLES} };
 
   CVar->render_inputs('variables' => $params{CUSTOM_VARIABLES}, show_disabled_message => 1, partsgroup_id => $self->part->partsgroup_id)
     if (scalar @{ $params{CUSTOM_VARIABLES} });
@@ -641,6 +644,8 @@ sub prepare_assortment_render_vars {
 sub prepare_assembly_render_vars {
   my ($self) = @_;
 
+  croak("Need assembly item(s) to create a 'save as new' assembly.") unless $self->part->items;
+
   my %vars = ( items_sellprice_sum => $self->part->items_sellprice_sum,
                items_lastcost_sum  => $self->part->items_lastcost_sum,
                assembly_html       => $self->render_assembly_items_to_html( \@{ $self->part->items } ),
@@ -728,6 +733,8 @@ sub parse_form {
   $self->part->assign_attributes(%{ $params});
   $self->part->bin_id(undef) unless $self->part->warehouse_id;
 
+  $self->normalize_text_blocks;
+
   # Only reset items ([]) and rewrite from form if $::form->{assortment_items} isn't empty. This
   # will be the case for used assortments when saving, or when a used assortment
   # is "used as new"
@@ -794,8 +801,9 @@ sub parse_form_makemodels {
     $position++;
     my $vendor = SL::DB::Manager::Vendor->find_by(id => $makemodel->{make}) || die "Can't find vendor from make";
 
+    my $id = $makemodels_map->{$makemodel->{id}} ? $makemodels_map->{$makemodel->{id}}->id : undef;
     my $mm = SL::DB::MakeModel->new( # parts_id   => $self->part->id, # will be assigned by row add_makemodels
-                                     id         => $makemodel->{id},
+                                     id         => $id,
                                      make       => $makemodel->{make},
                                      model      => $makemodel->{model} || '',
                                      lastcost   => $::form->parse_amount(\%::myconfig, $makemodel->{lastcost_as_number}),
@@ -834,8 +842,9 @@ sub parse_form_customerprices {
     $position++;
     my $customer = SL::DB::Manager::Customer->find_by(id => $customerprice->{customer_id}) || die "Can't find customer from id";
 
+    my $id = $customerprices_map->{$customerprice->{id}} ? $customerprices_map->{$customerprice->{id}}->id : undef;
     my $cu = SL::DB::PartCustomerPrice->new( # parts_id   => $self->part->id, # will be assigned by row add_customerprices
-                                     id                   => $customerprice->{id},
+                                     id                   => $id,
                                      customer_id          => $customerprice->{customer_id},
                                      customer_partnumber  => $customerprice->{customer_partnumber} || '',
                                      price                => $::form->parse_amount(\%::myconfig, $customerprice->{price_as_number}),
@@ -857,12 +866,13 @@ sub parse_form_customerprices {
 }
 
 sub build_bin_select {
-  $_[0]->p->select_tag('part.bin_id', [ $_[0]->warehouse->bins ],
+  select_tag('part.bin_id', [ $_[0]->warehouse->bins ],
     title_key => 'description',
     default   => $_[0]->bin->id,
   );
 }
 
+
 # get_set_inits for partpicker
 
 sub init_parts {
@@ -1020,7 +1030,7 @@ sub init_all_buchungsgruppen {
   if ( $self->part->orphaned ) {
     return SL::DB::Manager::Buchungsgruppe->get_all_sorted;
   } else {
-    return SL::DB::Manager::Buchungsgruppe->get_all(where => [ id => $self->part->buchungsgruppen_id ]);
+    return SL::DB::Manager::Buchungsgruppe->get_all_sorted(where => [ id => $self->part->buchungsgruppen_id ]);
   }
 }
 
@@ -1187,6 +1197,25 @@ sub check_has_valid_part_type {
   die "invalid part_type" unless $_[0] =~ /^(part|service|assembly|assortment)$/;
 }
 
+
+sub normalize_text_blocks {
+  my ($self) = @_;
+
+  # check if feature is enabled (select normalize_part_descriptions from defaults)
+  return unless ($::instance_conf->get_normalize_part_descriptions);
+
+  # text block
+  foreach (qw(description)) {
+    $self->part->{$_} =~ s/\s+$//s;
+    $self->part->{$_} =~ s/^\s+//s;
+    $self->part->{$_} =~ s/ {2,}/ /g;
+  }
+  # html block (caveat: can be circumvented by using bold or italics)
+  $self->part->{notes} =~ s/^<p>(&nbsp;)+\s+/<p>/s;
+  $self->part->{notes} =~ s/(&nbsp;)+<\/p>$/<\/p>/s;
+
+}
+
 sub render_assortment_items_to_html {
   my ($self, $assortment_items, $number_of_items) = @_;
 
@@ -1261,7 +1290,8 @@ sub parse_add_items_to_objects {
 sub _setup_form_action_bar {
   my ($self) = @_;
 
-  my $may_edit = $::auth->assert('part_service_assembly_edit', 'may fail');
+  my $may_edit           = $::auth->assert('part_service_assembly_edit', 'may fail');
+  my $used_in_pricerules = !!SL::DB::Manager::PriceRuleItem->get_all_count(where => [type => 'part', value_int => $self->part->id]);
 
   for my $bar ($::request->layout->get('actionbar')) {
     $bar->add(
@@ -1270,7 +1300,6 @@ sub _setup_form_action_bar {
           t8('Save'),
           call      => [ 'kivi.Part.save' ],
           disabled  => !$may_edit ? t8('You do not have the permissions to access this function.') : undef,
-          accesskey => 'enter',
         ],
         action => [
           t8('Use as new'),
@@ -1288,6 +1317,7 @@ sub _setup_form_action_bar {
         disabled => !$self->part->id       ? t8('This object has not been saved yet.')
                   : !$may_edit             ? t8('You do not have the permissions to access this function.')
                   : !$self->part->orphaned ? t8('This object has already been used.')
+                  : $used_in_pricerules    ? t8('This object is used in price rules.')
                   :                          undef,
       ],