Merge branch 'master' of vc.linet-services.de:public/lx-office-erp
[kivitendo-erp.git] / bin / mozilla / ic.pl
index 2976a49..2cbad4f 100644 (file)
@@ -32,7 +32,7 @@
 #======================================================================
 
 use POSIX qw(strftime);
 #======================================================================
 
 use POSIX qw(strftime);
-use List::Util qw(max);
+use List::Util qw(first max);
 use List::MoreUtils qw(any);
 
 use SL::AM;
 use List::MoreUtils qw(any);
 
 use SL::AM;
@@ -115,8 +115,10 @@ sub search {
 
   $form->header;
 
 
   $form->header;
 
+  $form->get_lists('partsgroup'    => 'ALL_PARTSGROUPS');
   print $form->parse_html_template('ic/search', { %is_xyz,
   print $form->parse_html_template('ic/search', { %is_xyz,
-                                                  dateformat => $myconfig{dateformat}, });
+                                                  dateformat => $myconfig{dateformat},
+                                                  limit => $myconfig{vclimit}, });
 
   $lxdebug->leave_sub();
 }    #end search()
 
   $lxdebug->leave_sub();
 }    #end search()
@@ -286,7 +288,6 @@ sub update_prices {
 #  $form->header;
 #
 #  print qq|
 #  $form->header;
 #
 #  print qq|
-#<body>
 #  <form method=post action=ic.pl>
 #    <table width=100%>
 #     <tr>
 #  <form method=post action=ic.pl>
 #    <table width=100%>
 #     <tr>
@@ -386,8 +387,6 @@ sub update_prices {
 #    . $locale->text('TOP100') . qq|">
 #
 #</form>
 #    . $locale->text('TOP100') . qq|">
 #
 #</form>
-#</body>
-#</html>
 #|;
 #  $lxdebug->leave_sub();
 #}    #end list()
 #|;
 #  $lxdebug->leave_sub();
 #}    #end list()
@@ -723,8 +722,6 @@ sub addtop100 {
   my $colspan = $#column_index + 1;
 
   print qq|
   my $colspan = $#column_index + 1;
 
   print qq|
-<body>
-
 <table width=100%>
   <tr>
     <th class=listtop colspan=$colspan>$form->{title}</th>
 <table width=100%>
   <tr>
     <th class=listtop colspan=$colspan>$form->{title}</th>
@@ -979,9 +976,6 @@ sub addtop100 {
     . $locale->text('choice') . qq|">
 
   </form>
     . $locale->text('choice') . qq|">
 
   </form>
-
-</body>
-</html>
 |;
 
   $lxdebug->leave_sub();
 |;
 
   $lxdebug->leave_sub();
@@ -1008,7 +1002,7 @@ sub addtop100 {
 #  bought sold onorder ordered rfq quoted
 #  l_partnumber l_description l_serialnumber l_unit l_listprice l_sellprice l_lastcost
 #  l_linetotal l_priceupdate l_bin l_rop l_weight l_image l_drawing l_microfiche
 #  bought sold onorder ordered rfq quoted
 #  l_partnumber l_description l_serialnumber l_unit l_listprice l_sellprice l_lastcost
 #  l_linetotal l_priceupdate l_bin l_rop l_weight l_image l_drawing l_microfiche
-#  l_partsgroup l_subtotal l_soldtotal l_deliverydate
+#  l_partsgroup l_subtotal l_soldtotal l_deliverydate l_pricegroups
 #
 # hiddens:
 #  nextsub revers lastsort sort ndxs_counter
 #
 # hiddens:
 #  nextsub revers lastsort sort ndxs_counter
@@ -1030,6 +1024,7 @@ sub generate_report {
     'bin'                => { 'text' => $locale->text('Bin'), },
     'deliverydate'       => { 'text' => $locale->text('deliverydate'), },
     'description'        => { 'text' => $locale->text('Part Description'), },
     'bin'                => { 'text' => $locale->text('Bin'), },
     'deliverydate'       => { 'text' => $locale->text('deliverydate'), },
     'description'        => { 'text' => $locale->text('Part Description'), },
+    'notes'              => { 'text' => $locale->text('Notes'), },
     'drawing'            => { 'text' => $locale->text('Drawing'), },
     'ean'                => { 'text' => $locale->text('EAN'), },
     'image'              => { 'text' => $locale->text('Image'), },
     'drawing'            => { 'text' => $locale->text('Drawing'), },
     'ean'                => { 'text' => $locale->text('EAN'), },
     'image'              => { 'text' => $locale->text('Image'), },
@@ -1041,7 +1036,7 @@ sub generate_report {
     'listprice'          => { 'text' => $locale->text('List Price'), },
     'microfiche'         => { 'text' => $locale->text('Microfiche'), },
     'name'               => { 'text' => $locale->text('Name'), },
     'listprice'          => { 'text' => $locale->text('List Price'), },
     'microfiche'         => { 'text' => $locale->text('Microfiche'), },
     'name'               => { 'text' => $locale->text('Name'), },
-    'onhand'             => { 'text' => $locale->text('Qty'), },
+    'onhand'             => { 'text' => $locale->text('Stocked Qty'), },
     'ordnumber'          => { 'text' => $locale->text('Order Number'), },
     'partnumber'         => { 'text' => $locale->text('Part Number'), },
     'partsgroup'         => { 'text' => $locale->text('Group'), },
     'ordnumber'          => { 'text' => $locale->text('Order Number'), },
     'partnumber'         => { 'text' => $locale->text('Part Number'), },
     'partsgroup'         => { 'text' => $locale->text('Group'), },
@@ -1050,10 +1045,12 @@ sub generate_report {
     'rop'                => { 'text' => $locale->text('ROP'), },
     'sellprice'          => { 'text' => $locale->text('Sell Price'), },
     'serialnumber'       => { 'text' => $locale->text('Serial Number'), },
     'rop'                => { 'text' => $locale->text('ROP'), },
     'sellprice'          => { 'text' => $locale->text('Sell Price'), },
     'serialnumber'       => { 'text' => $locale->text('Serial Number'), },
-    'soldtotal'          => { 'text' => $locale->text('soldtotal'), },
+    'soldtotal'          => { 'text' => $locale->text('Qty in Selected Records'), },
     'transdate'          => { 'text' => $locale->text('Transdate'), },
     'unit'               => { 'text' => $locale->text('Unit'), },
     'weight'             => { 'text' => $locale->text('Weight'), },
     'transdate'          => { 'text' => $locale->text('Transdate'), },
     'unit'               => { 'text' => $locale->text('Unit'), },
     'weight'             => { 'text' => $locale->text('Weight'), },
+    'projectnumber'      => { 'text' => $locale->text('Project Number'), },
+    'projectdescription' => { 'text' => $locale->text('Project Description'), },
   );
 
   $revers     = $form->{revers};
   );
 
   $revers     = $form->{revers};
@@ -1103,6 +1100,13 @@ sub generate_report {
     no_sn_joins  => [ qw(bought sold) ],
   );
 
     no_sn_joins  => [ qw(bought sold) ],
   );
 
+  # get name of partsgroup if id is given
+  my $pg_name;
+  if ($form->{partsgroup_id}) {
+    my $pg = SL::DB::PartsGroup->new(id => $form->{partsgroup_id})->load;
+    $pg_name = $pg->{'partsgroup'};
+  }
+
   # these strings get displayed at the top of the results to indicate the user which switches were used
   my %optiontexts = (
     active        => $locale->text('Active'),
   # these strings get displayed at the top of the results to indicate the user which switches were used
   my %optiontexts = (
     active        => $locale->text('Active'),
@@ -1120,18 +1124,19 @@ sub generate_report {
     transdateto   => $locale->text('To (time)')  . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
     partnumber    => $locale->text('Part Number')      . ": '$form->{partnumber}'",
     partsgroup    => $locale->text('Group')            . ": '$form->{partsgroup}'",
     transdateto   => $locale->text('To (time)')  . " " . $locale->date(\%myconfig, $form->{transdateto}, 1),
     partnumber    => $locale->text('Part Number')      . ": '$form->{partnumber}'",
     partsgroup    => $locale->text('Group')            . ": '$form->{partsgroup}'",
+    partsgroup_id => $locale->text('Group')            . ": '$pg_name'",
     serialnumber  => $locale->text('Serial Number')    . ": '$form->{serialnumber}'",
     description   => $locale->text('Part Description') . ": '$form->{description}'",
     make          => $locale->text('Make')             . ": '$form->{make}'",
     model         => $locale->text('Model')            . ": '$form->{model}'",
     drawing       => $locale->text('Drawing')          . ": '$form->{drawing}'",
     microfiche    => $locale->text('Microfiche')       . ": '$form->{microfiche}'",
     serialnumber  => $locale->text('Serial Number')    . ": '$form->{serialnumber}'",
     description   => $locale->text('Part Description') . ": '$form->{description}'",
     make          => $locale->text('Make')             . ": '$form->{make}'",
     model         => $locale->text('Model')            . ": '$form->{model}'",
     drawing       => $locale->text('Drawing')          . ": '$form->{drawing}'",
     microfiche    => $locale->text('Microfiche')       . ": '$form->{microfiche}'",
-    l_soldtotal   => $locale->text('soldtotal'),
+    l_soldtotal   => $locale->text('Qty in Selected Records'),
     ean           => $locale->text('EAN')              . ": '$form->{ean}'",
   );
 
   my @itemstatus_keys = qw(active obsolete orphaned onhand short);
     ean           => $locale->text('EAN')              . ": '$form->{ean}'",
   );
 
   my @itemstatus_keys = qw(active obsolete orphaned onhand short);
-  my @callback_keys   = qw(onorder ordered rfq quoted bought sold partnumber partsgroup serialnumber description make model
+  my @callback_keys   = qw(onorder ordered rfq quoted bought sold partnumber partsgroup partsgroup_id serialnumber description make model
                            drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
 
   # calculate dependencies
                            drawing microfiche l_soldtotal l_deliverydate transdatefrom transdateto ean);
 
   # calculate dependencies
@@ -1161,7 +1166,7 @@ sub generate_report {
   }
 
   if ($form->{l_linetotal}) {
   }
 
   if ($form->{l_linetotal}) {
-    $form->{l_onhand} = "Y";
+    $form->{l_qty} = "Y";
     $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
     $form->{l_linetotallastcost}  = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if  $form->{l_lastcost};
     $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
     $form->{l_linetotalsellprice} = "Y" if $form->{l_sellprice};
     $form->{l_linetotallastcost}  = $form->{searchitems} eq 'assembly' && !$form->{bom} ? "" : 'Y' if  $form->{l_lastcost};
     $form->{l_linetotallistprice} = "Y" if $form->{l_listprice};
@@ -1181,34 +1186,60 @@ sub generate_report {
         || $form->{ordered}
         || $form->{rfq}
         || $form->{quoted}) {
         || $form->{ordered}
         || $form->{rfq}
         || $form->{quoted}) {
-      $form->{l_onhand} = "Y";
+#      $form->{l_onhand} = "Y";
     } else {
       $form->{l_linetotalsellprice} = "";
       $form->{l_linetotallastcost}  = "";
     }
   }
 
     } else {
       $form->{l_linetotalsellprice} = "";
       $form->{l_linetotallastcost}  = "";
     }
   }
 
+  # soldtotal doesn't make sense with more than one bsooqr option.
+  # so reset it to sold (the most common option), and issue a warning
+  my @bsooqr = qw(sold bought onorder ordered rfq quoted);
+  if ($form->{l_subtotal} && 1 < grep { $form->{$_} } @bsooqr) {
+    my $enabled       = first { $form->{$_} } @bsooqr;
+    $form->{$_}       = ''   for @bsooqr;
+    $form->{$enabled} = 'Y';
+
+    push @options, $::locale->text('Subtotal cannot distinguish betweens record types. Only one of the selected record types will be displayed: #1', $optiontexts{$enabled});
+  }
+
   IC->all_parts(\%myconfig, \%$form);
 
   my @columns = qw(
   IC->all_parts(\%myconfig, \%$form);
 
   my @columns = qw(
-    partnumber description partsgroup bin onhand rop unit listprice
+    partnumber description notes partsgroup bin onhand rop soldtotal unit listprice
     linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
     priceupdate weight image drawing microfiche invnumber ordnumber quonumber
     linetotallistprice sellprice linetotalsellprice lastcost linetotallastcost
     priceupdate weight image drawing microfiche invnumber ordnumber quonumber
-    transdate name serialnumber soldtotal deliverydate ean
+    transdate name serialnumber deliverydate ean projectnumber projectdescription
   );
 
   );
 
+  my $pricegroups = SL::DB::Manager::Pricegroup->get_all(sort => 'id');
+  my @pricegroup_columns;
+  my %column_defs_pricegroups;
+  if ($form->{l_pricegroups}) {
+    @pricegroup_columns      = map { "pricegroup_" . $_->id } @{ $pricegroups };
+    %column_defs_pricegroups = map {
+      "pricegroup_" . $_->id => {
+        text    => $::locale->text('Pricegroup') . ' ' . $_->pricegroup,
+        visible => 1,
+      },
+    }  @{ $pricegroups };
+  }
+  push @columns, @pricegroup_columns;
+
   my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
   my @searchable_custom_variables  = grep { $_->{searchable} }  @{ $cvar_configs };
   my %column_defs_cvars            = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
 
   push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
 
   my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
   my @searchable_custom_variables  = grep { $_->{searchable} }  @{ $cvar_configs };
   my %column_defs_cvars            = map { +"cvar_$_->{name}" => { 'text' => $_->{description} } } @includeable_custom_variables;
 
   push @columns, map { "cvar_$_->{name}" } @includeable_custom_variables;
 
-  %column_defs = (%column_defs,%column_defs_cvars); # nochmal die cvars als überschrift hinzufügen
-    map { $column_defs{$_}->{visible} = $form->{"l_$_"} ? 1 : 0 } @columns;
-  map { $column_defs{$_}->{align}   = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal);
+  %column_defs = (%column_defs, %column_defs_cvars, %column_defs_pricegroups);
+  map { $column_defs{$_}->{visible} ||= $form->{"l_$_"} ? 1 : 0 } @columns;
+  map { $column_defs{$_}->{align}   = 'right' } qw(onhand sellprice listprice lastcost linetotalsellprice linetotallastcost linetotallistprice rop weight soldtotal), @pricegroup_columns;
 
 
-  my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom), @itemstatus_keys, @callback_keys,
+  my @hidden_variables = (qw(l_subtotal l_linetotal searchitems itemstatus bom l_pricegroups), @itemstatus_keys, @callback_keys,
                               map({ "cvar_$_->{name}" } @searchable_custom_variables), map { "l_$_" } @columns);
                               map({ "cvar_$_->{name}" } @searchable_custom_variables), map { "l_$_" } @columns);
+
   my $callback         = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
 
   my @sort_full        = qw(partnumber description onhand soldtotal deliverydate);
   my $callback         = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables);
 
   my @sort_full        = qw(partnumber description onhand soldtotal deliverydate);
@@ -1263,7 +1294,7 @@ sub generate_report {
   my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
   my %totals    = map { $_ => 0 } @subtotal_columns;
   my $idx       = 0;
   my %subtotals = map { $_ => 0 } ('onhand', @subtotal_columns);
   my %totals    = map { $_ => 0 } @subtotal_columns;
   my $idx       = 0;
-  my $same_item = $form->{parts}[0]{ $form->{sort} } if (scalar @{ $form->{parts} });
+  my $same_item = @{ $form->{parts} } ? $form->{parts}[0]{ $form->{sort} } : undef;
 
   my $defaults  = AM->get_defaults();
 
 
   my $defaults  = AM->get_defaults();
 
@@ -1280,12 +1311,12 @@ sub generate_report {
     $ref->{lastcost}      *= $ref->{exchangerate} / $ref->{price_factor};
 
     # use this for assemblies
     $ref->{lastcost}      *= $ref->{exchangerate} / $ref->{price_factor};
 
     # use this for assemblies
-    my $onhand = $ref->{onhand};
+    my $soldtotal = $ref->{soldtotal};
 
     if ($ref->{assemblyitem}) {
       $row->{partnumber}{align}   = 'right';
 
     if ($ref->{assemblyitem}) {
       $row->{partnumber}{align}   = 'right';
-      $row->{onhand}{data}        = 0;
-      $onhand                     = 0 if ($form->{sold});
+      $row->{soldtotal}{data}     = 0;
+      $soldtotal                  = 0 if ($form->{sold});
     }
 
     my $edit_link               = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
     }
 
     my $edit_link               = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
@@ -1293,9 +1324,13 @@ sub generate_report {
     $row->{description}->{link} = $edit_link;
 
     foreach (qw(sellprice listprice lastcost)) {
     $row->{description}->{link} = $edit_link;
 
     foreach (qw(sellprice listprice lastcost)) {
-      $row->{$_}{data}            = $form->format_amount(\%myconfig, $ref->{$_}, -2);
+      $row->{$_}{data}            = $form->format_amount(\%myconfig, $ref->{$_}, 2);
       $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
     }
       $row->{"linetotal$_"}{data} = $form->format_amount(\%myconfig, $ref->{onhand} * $ref->{$_}, 2);
     }
+    foreach ( @pricegroup_columns ) {
+      $row->{$_}{data}            = $form->format_amount(\%myconfig, $ref->{"$_"}, 2);
+    };
+
 
     map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
 
 
     map { $row->{$_}{data} = $form->format_amount(\%myconfig, $ref->{$_}); } qw(onhand rop weight soldtotal);
 
@@ -1303,18 +1338,25 @@ sub generate_report {
 
     if (!$ref->{assemblyitem}) {
       foreach my $col (@subtotal_columns) {
 
     if (!$ref->{assemblyitem}) {
       foreach my $col (@subtotal_columns) {
-        $totals{$col}    += $onhand * $ref->{$col};
-        $subtotals{$col} += $onhand * $ref->{$col};
+        $totals{$col}    += $soldtotal * $ref->{$col};
+        $subtotals{$col} += $soldtotal * $ref->{$col};
       }
 
       }
 
-      $subtotals{onhand} += $onhand;
+      $subtotals{soldtotal} += $soldtotal;
     }
 
     # set module stuff
     if ($ref->{module} eq 'oe') {
     }
 
     # set module stuff
     if ($ref->{module} eq 'oe') {
-      my $edit_oe_link = build_std_url("script=oe.pl", 'action=edit', 'type=' . E($ref->{cv} eq 'vendor' ? 'purchase_order' : 'sales_order'), 'id=' . E($ref->{trans_id}), 'callback');
-      $row->{ordnumber}{link} = $edit_oe_link;
-      $row->{quonumber}{link} = $edit_oe_link if (!$ref->{ordnumber});
+      # für oe gibt es vier fälle, jeweils nach kunde oder lieferant unterschiedlich:
+      #
+      # | ist bestellt  | Vom Kunde bestellt |  -> edit_oe_ord_link
+      # | Anfrage       | Angebot            |  -> edit_oe_quo_link
+
+      my $edit_oe_ord_link = build_std_url("script=oe.pl", 'action=edit', 'type=' . E($ref->{cv} eq 'vendor' ? 'purchase_order' : 'sales_order'), 'id=' . E($ref->{trans_id}), 'callback');
+      my $edit_oe_quo_link = build_std_url("script=oe.pl", 'action=edit', 'type=' . E($ref->{cv} eq 'vendor' ? 'request_quotation' : 'sales_quotation'), 'id=' . E($ref->{trans_id}), 'callback');
+
+      $row->{ordnumber}{link} = $edit_oe_ord_link;
+      $row->{quonumber}{link} = $edit_oe_quo_link if (!$ref->{ordnumber});
 
     } else {
       $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
 
     } else {
       $row->{invnumber}{link} = build_std_url("script=$ref->{module}.pl", 'action=edit', 'type=invoice', 'id=' . E($ref->{trans_id}), 'callback');
@@ -1338,11 +1380,11 @@ sub generate_report {
       my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
 
       if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
       my $row = { map { $_ => { 'class' => 'listsubtotal', } } @columns };
 
       if (($form->{searchitems} ne 'assembly') || !$form->{bom}) {
-        $row->{onhand}->{data} = $form->format_amount(\%myconfig, $subtotals{onhand});
+        $row->{soldtotal}->{data} = $form->format_amount(\%myconfig, $subtotals{soldtotal});
       }
 
       map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
       }
 
       map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $subtotals{$_}, 2) } @subtotal_columns;
-      map { $subtotals{$_} = 0 } ('onhand', @subtotal_columns);
+      map { $subtotals{$_} = 0 } ('soldtotal', @subtotal_columns);
 
       $report->add_data($row);
 
 
       $report->add_data($row);
 
@@ -1352,7 +1394,7 @@ sub generate_report {
     $idx++;
   }
 
     $idx++;
   }
 
-  if ($form->{"l_linetotal"}) {
+  if ($form->{"l_linetotal"} && !$form->{report_generator_csv_options_for_import}) {
     my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
 
     map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
     my $row = { map { $_ => { 'class' => 'listtotal', } } @columns };
 
     map { $row->{"linetotal$_"}->{data} = $form->format_amount(\%myconfig, $totals{$_}, 2) } @subtotal_columns;
@@ -1528,7 +1570,6 @@ sub form_header {
 
   $auth->assert('part_service_assembly_edit');
 
 
   $auth->assert('part_service_assembly_edit');
 
-  $form->{eur}              = $::lx_office_conf{system}->{eur}; # config dumps into namespace - yuck
   $form->{pg_keys}          = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
   $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
   $form->{notes_rows}       =  max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
   $form->{pg_keys}          = sub { "$_[0]->{partsgroup}--$_[0]->{id}" };
   $form->{description_area} = ($form->{rows} = $form->numtextrows($form->{description}, 40)) > 1;
   $form->{notes_rows}       =  max 4, $form->numtextrows($form->{notes}, 40), $form->numtextrows($form->{formel}, 40);
@@ -1676,9 +1717,14 @@ sub assembly_row {
       }
       push @row_hiddens,        qw(unit description partnumber partsgroup);
       $row{unit}{data}        = $form->{"unit_$i"};
       }
       push @row_hiddens,        qw(unit description partnumber partsgroup);
       $row{unit}{data}        = $form->{"unit_$i"};
-      $row{description}{data} = $form->{"description_$i"};
-      $row{partsgroup}{data}  = $form->{"partsgroup_$i"};
-      $row{bom}{align}        = 'center';
+      #Bei der Artikelbeschreibung und Warengruppe können Sonderzeichen verwendet
+      #werden, die den HTML Code stören. Daher sollen diese im Template escaped werden
+      #dies geschieht, wenn die Variable escape gesetzt ist
+      $row{description}{data}   = $form->{"description_$i"};
+      $row{description}{escape} = 1;
+      $row{partsgroup}{data}    = $form->{"partsgroup_$i"};
+      $row{partsgroup}{escape}  = 1;
+      $row{bom}{align}          = 'center';
     }
 
     $row{lastcost}{data}      = $line_purchase_price;
     }
 
     $row{lastcost}{data}      = $line_purchase_price;
@@ -1704,8 +1750,11 @@ sub update {
   # parse pricegroups. and no, don't rely on check_form for this...
   map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
 
   # parse pricegroups. and no, don't rely on check_form for this...
   map { $form->{"price_$_"} = $form->parse_amount(\%myconfig, $form->{"price_$_"}) } 1 .. $form->{price_rows};
 
-  # same for lastcosts
-  map { $form->{"lastcost_$_"} = $form->parse_amount(\%myconfig, $form->{"lastcost_$_"}) } 1 .. $form->{"makemodel_rows"};
+  # same for makemodel lastcosts
+  # but parse_amount not necessary for assembly component lastcosts
+  unless ($form->{item} eq "assembly") {
+    map { $form->{"lastcost_$_"} = $form->parse_amount(\%myconfig, $form->{"lastcost_$_"}) } 1 .. $form->{"makemodel_rows"};
+  };
 
   if ($form->{item} eq "assembly") {
     my $i = $form->{assembly_rows};
 
   if ($form->{item} eq "assembly") {
     my $i = $form->{assembly_rows};
@@ -1728,7 +1777,7 @@ sub update {
 
         if ($rows > 1) {
           $form->{makemodel_rows}--;
 
         if ($rows > 1) {
           $form->{makemodel_rows}--;
-          &select_item;
+          select_item(mode => 'IC');
           ::end_of_request();
         } else {
           map { $form->{item_list}[$i]{$_} =~ s/\"/&quot;/g }
           ::end_of_request();
         } else {
           map { $form->{item_list}[$i]{$_} =~ s/\"/&quot;/g }
@@ -1785,7 +1834,6 @@ sub save {
   $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
 
   # save part
   $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
 
   # save part
-  $lxdebug->message($LXDebug::DEBUG1, "ic.pl: sellprice in save = $form->{sellprice}\n");
   if (IC->save(\%myconfig, \%$form) == 3) {
     $form->error($locale->text('Partnumber not unique!'));
   }
   if (IC->save(\%myconfig, \%$form) == 3) {
     $form->error($locale->text('Partnumber not unique!'));
   }
@@ -1822,7 +1870,7 @@ sub save {
         qw(weight listprice sellprice rop);
 
       $form->{assembly_rows}--;
         qw(weight listprice sellprice rop);
 
       $form->{assembly_rows}--;
-      $i = $newform{rowcount};
+      $i = $form->{assembly_rows};
       $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
 
       $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
       $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
 
       $form->{sellprice} -= $form->{"sellprice_$i"} * $form->{"qty_$i"};
@@ -1853,8 +1901,6 @@ sub save {
         $form->{"sellprice_$i"} /= $form->{exchangerate};
       }
 
         $form->{"sellprice_$i"} /= $form->{exchangerate};
       }
 
-      $lxdebug->message($LXDebug::DEBUG1, qq|sellprice_$i in previousform 2 = | . $form->{"sellprice_$i"} . qq|\n|);
-
       map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
       chop $form->{"taxaccounts_$i"};
       foreach my $item (qw(description rate taxnumber)) {
       map { $form->{"taxaccounts_$i"} .= "$_ " } split / /, $newform{taxaccount};
       chop $form->{"taxaccounts_$i"};
       foreach my $item (qw(description rate taxnumber)) {
@@ -1903,7 +1949,6 @@ sub save {
     }
     $form->{callback} = $callback;
   }
     }
     $form->{callback} = $callback;
   }
-  $lxdebug->message($LXDebug::DEBUG1, qq|ic.pl: sellprice_$i nach sub save = | . $form->{"sellprice_$i"} . qq|\n|);
 
   # redirect
   $form->redirect;
 
   # redirect
   $form->redirect;
@@ -1987,6 +2032,10 @@ sub parts_language_selection {
 
         $language->{translation}     = $translation;
         $language->{longdescription} = $longdescription;
 
         $language->{translation}     = $translation;
         $language->{longdescription} = $longdescription;
+
+        $language->{translation_area}     = ($language->{translation_rows} = $form->numtextrows($language->{translation}, 40)) > 1;
+        $language->{longdescription_rows} = max 4, $form->numtextrows($language->{longdescription}, 40);
+
         last;
       }
     }
         last;
       }
     }
@@ -2030,4 +2079,25 @@ sub ajax_autocomplete {
   $main::lxdebug->leave_sub();
 }
 
   $main::lxdebug->leave_sub();
 }
 
+sub back_to_record {
+  _check_io_auth();
+
+
+  delete @{$::form}{qw(action action_add action_back_to_record back_sub description item notes partnumber sellprice taxaccount2 unit vc)};
+
+  $::auth->restore_form_from_session($::form->{previousform}, clobber => 1);
+  $::form->{rowcount}--;
+  $::form->{action}   = 'display_form';
+  $::form->{callback} = $::form->{script} . '?' . join('&', map { $::form->escape($_) . '=' . $::form->escape($::form->{$_}) } sort keys %{ $::form });
+  $::form->redirect;
+}
+
 sub continue { call_sub($form->{"nextsub"}); }
 sub continue { call_sub($form->{"nextsub"}); }
+
+sub dispatcher {
+  my $action = first { $::form->{"action_${_}"} } qw(add back_to_record);
+  $::form->error($::locale->text('No action defined.')) unless $action;
+
+  $::form->{dispatched_action} = $action;
+  call_sub($action);
+}