Entitaeten fuer die Umlaute hinzugefuegt
[kivitendo-erp.git] / bin / mozilla / io.pl
index ca50587..aa5c248 100644 (file)
 
 use CGI;
 use CGI::Ajax;
-use List::Util qw(max);
+use List::Util qw(max first);
 
+use SL::CVar;
 use SL::Common;
 use SL::CT;
 use SL::IC;
+use SL::IO;
 
 require "bin/mozilla/common.pl";
 
@@ -86,16 +88,291 @@ use SL::IS;
 use SL::PE;
 use SL::AM;
 use Data::Dumper;
+
+sub _check_io_auth {
+  $auth->assert('part_service_assembly_edit   | vendor_invoice_edit       | sales_order_edit    | invoice_edit |' .
+                'request_quotation_edit       | sales_quotation_edit      | purchase_order_edit | ' .
+                'purchase_delivery_order_edit | sales_delivery_order_edit');
+}
+
 ########################################
 # Eintrag fuer Version 2.2.0 geaendert #
 # neue Optik im Rechnungsformular      #
 ########################################
+sub display_row {
+  $lxdebug->enter_sub();
+
+  _check_io_auth();
+
+  my $numrows = shift;
+
+  my ($readonly, $stock_in_out, $stock_in_out_title);
+
+  my $is_purchase        = (first { $_ eq $form->{type} } qw(request_quotation purchase_order purchase_delivery_order)) || ($form->{script} eq 'ir.pl');
+  my $show_min_order_qty =  first { $_ eq $form->{type} } qw(request_quotation purchase_order);
+  my $is_delivery_order  = $form->{type} =~ /_delivery_order$/;
+
+  if ($is_delivery_order) {
+    $readonly             = ' readonly' if ($form->{closed});
+
+    if ($form->{type} eq 'sales_delivery_order') {
+      $stock_in_out_title = $locale->text('Release From Stock');
+      $stock_in_out       = 'out';
+    } else {
+      $stock_in_out_title = $locale->text('Transfer To Stock');
+      $stock_in_out       = 'in';
+    }
+  }
+
+  # column_index
+  my @header_sort = qw(runningnumber partnumber description ship qty unit sellprice_pg sellprice discount linetotal);
+  my @HEADER = (
+    {  id => 'runningnumber', width => 5,     value => $locale->text('No.'),                  display => 1, },
+    {  id => 'partnumber',    width => 12,    value => $locale->text('Number'),               display => 1, },
+    {  id => 'description',   width => 30,    value => $locale->text('Part Description'),     display => 1, },
+    {  id => 'ship',          width => 5,     value => ($form->{type} eq 'purchase_order' ? $locale->text('Ship rcvd') : $locale->text('Ship')),                 
+       display => $form->{type} =~ /sales_order/ || ($form->{type} =~ /purchase_order/ && !($lizenzen && $form->{vc} eq "customer")) , },
+    {  id => 'qty',           width => 5,     value => $locale->text('Qty'),                  display => 1, },
+    {  id => 'price_factor',  width => 5,     value => $locale->text('Price Factor'),         display => !$is_delivery_order, },
+    {  id => 'unit',          width => 5,     value => $locale->text('Unit'),                 display => 1, },
+    {  id => 'license',       width => 10,    value => $locale->text('License'),              display => 0, },
+    {  id => 'serialnr',      width => 10,    value => $locale->text('Serial No.'),           display => 0, },
+    {  id => 'projectnr',     width => 10,    value => $locale->text('Project'),              display => 0, },
+    {  id => 'sellprice',     width => 15,    value => $locale->text('Price'),                display => !$is_delivery_order, },
+    {  id => 'sellprice_pg',  width => 15,    value => $locale->text('Pricegroup'),           display => ($form->{type} =~ /^sales_/) && !$is_delivery_order,  },
+    {  id => 'discount',      width => 5,     value => $locale->text('Discount'),             display => ($form->{vc} eq 'customer') && !$is_delivery_order, },
+    {  id => 'linetotal',     width => 10,    value => $locale->text('Extended'),             display => !$is_delivery_order, },
+    {  id => 'bin',           width => 10,    value => $locale->text('Bin'),                  display => 0, },
+    {  id => 'stock_in_out',  width => 10,    value => $stock_in_out_title,                   display => $is_delivery_order, },
+  ); 
+  my @column_index = map { $_->{id} } grep { $_->{display} } @HEADER;
+
+  # cache units
+  my $dimension_units = AM->retrieve_units(\%myconfig, $form, "dimension");
+  my $service_units   = AM->retrieve_units(\%myconfig, $form, "service");
+  my $all_units       = AM->retrieve_units(\%myconfig, $form);
+
+  my %price_factors   = map { $_->{id} => $_->{factor} } @{ $form->{ALL_PRICE_FACTORS} };
+
+  my $colspan = scalar @column_index;
+
+  $form->{invsubtotal} = 0;
+  map { $form->{"${_}_base"} = 0 } (split(/ /, $form->{taxaccounts}));
+
+  # about details 
+  $myconfig{show_form_details} = 1                            unless (defined($myconfig{show_form_details}));
+  $form->{show_details}        = $myconfig{show_form_details} unless (defined($form->{show_details}));
+  # /about details
+
+  # translations, unused commented out
+#  $runningnumber = $locale->text('No.');
+  $deliverydate  = $locale->text('Delivery Date');
+  $serialnumber  = $locale->text('Serial No.');
+  $projectnumber = $locale->text('Project');
+#  $partsgroup    = $locale->text('Group');
+  $reqdate       = $locale->text('Reqdate');
+  $deliverydate  = $locale->text('Required by');
+
+  # special alignings
+  my %align  = map { $_ => 'right' } qw(qty ship right sellprice_pg discount linetotal stock_in_out);
+  my %nowrap = map { $_ => 1 }       qw(description unit);
+
+  $form->{marge_total}           = 0;
+  $form->{sellprice_total}       = 0;
+  $form->{lastcost_total}        = 0;
+  my %projectnumber_labels = ();
+  my @projectnumber_values = ("");
+
+  foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
+    push(@projectnumber_values, $item->{"id"});
+    $projectnumber_labels{$item->{"id"}} = $item->{"projectnumber"};
+  }
+
+  # rows
+  for $i (1 .. $numrows) {
+
+    # undo formatting
+    map { $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"}) } qw(qty ship discount sellprice price_new price_old) unless ($form->{simple_save});
+
+# unit begin
+    $form->{"unit_old_$i"}      ||= $form->{"unit_$i"};
+    $form->{"selected_unit_$i"} ||= $form->{"unit_$i"};
+
+    my $local_units = $form->{"inventory_accno_$i"} || $form->{"assembly_$i"} ? $dimension_units 
+                    : $form->{"id_$i"}                                        ? $service_units 
+                    :                                                           $all_units;
+    if (   !$local_units->{$form->{"selected_unit_$i"}}                                          # Die ausgewaehlte Einheit ist fuer diesen Artikel nicht gueltig
+        || !AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units)) { # (z.B. Dimensionseinheit war ausgewaehlt, es handelt sich aber
+      $form->{"unit_old_$i"} = $form->{"selected_unit_$i"} = $form->{"unit_$i"};                 # um eine Dienstleistung). Dann keinerlei Umrechnung vornehmen.
+    }
+    # adjust prices by unit, ignore if pricegroup changed
+    if ((!$form->{"prices_$i"}) || ($form->{"new_pricegroup_$i"} == $form->{"old_pricegroup_$i"})) {
+        $form->{"sellprice_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
+        $form->{"unit_old_$i"}   = $form->{"selected_unit_$i"};
+    }
+    my $this_unit = $form->{"unit_$i"};
+    $this_unit    = $form->{"selected_unit_$i"} if AM->convert_unit($this_unit, $form->{"selected_unit_$i"}, $all_units);
+    $this_unit  ||= "kg";
+
+    if (0 < scalar @{ $form->{ALL_PRICE_FACTORS} }) {
+      my @values = ('', map { $_->{id}                      } @{ $form->{ALL_PRICE_FACTORS} });
+      my %labels =      map { $_->{id} => $_->{description} } @{ $form->{ALL_PRICE_FACTORS} };
+
+      $column_data{price_factor} =
+        NTI($cgi->popup_menu('-name'    => "price_factor_id_$i",
+                             '-default' => $form->{"price_factor_id_$i"},
+                             '-values'  => \@values,
+                             '-labels'  => \%labels,
+                             '-style'   => 'width:90px'));
+    } else {
+      $column_data{price_factor} = '&nbsp;';
+    }
+
+    $column_data{"unit"} = AM->unit_select_html($local_units, "unit_$i", $this_unit, $form->{"id_$i"} ? $form->{"unit_$i"} : undef);
+# / unit ending
+
+    $form->{"sellprice_$i"} =~ /\.(\d+)/;
+    $decimalplaces = max 2, length $1;
+
+    $price_factor   = $price_factors{$form->{"price_factor_id_$i"}} || 1;
+    $discount       = $form->round_amount($form->{"sellprice_$i"} * $form->{"discount_$i"} / 100, $decimalplaces);
+    $linetotal      = $form->round_amount(($form->{"sellprice_$i"} - $discount) / $price_factor, $decimalplaces);
+    $linetotal      = $form->round_amount($linetotal * $form->{"qty_$i"}, 2);
+
+    # convert " to &quot;
+    map { $form->{"${_}_$i"} =~ s/\"/&quot;/g } qw(partnumber description unit unit_old);
+
+    $column_data{runningnumber} = $cgi->textfield(-name => "runningnumber_$i", -size => 5,  -value => $i);    # HuT
+    $column_data{partnumber}    = $cgi->textfield(-name => "partnumber_$i",    -size => 12, -value => $form->{"partnumber_$i"});
+    $column_data{description} = ((($rows = $form->numtextrows($form->{"description_$i"}, 30, 6)) > 1) # if description is too large, use a textbox instead
+                                ? $cgi->textarea( -name => "description_$i", -default => $form->{"description_$i"}, -rows => $rows, -columns => 30)
+                                : $cgi->textfield(-name => "description_$i",   -size => 30, -value => $form->quote($form->{"description_$i"})))
+                                . $cgi->button(-value => $locale->text('L'), -onClick => "set_longdescription_window('longdescription_$i')");
+
+    $form->{"qty_$i"} =~ /\.(\d+)/;
+    my $qty_dec = length $1;
+
+    $column_data{qty}  = $cgi->textfield(-name => "qty_$i", -size => 5, -value => $form->format_amount(\%myconfig, $form->{"qty_$i"}, $qty_dec));
+    $column_data{qty} .= $cgi->button(-onclick => "calculate_qty_selection_window('qty_$i','alu_$i', 'formel_$i', $i)", -value => $locale->text('*/'))
+                       . $cgi->hidden(-name => "formel_$i", -value => $form->{"formel_$i"}) . $cgi->hidden("-name" => "alu_$i", "-value" => $form->{"alu_$i"})
+      if $form->{"formel_$i"};
+    $column_data{ship} = $cgi->textfield(-name => "ship_$i", -size => 5, -value => $form->format_amount(\%myconfig, $form->{"ship_$i"}));
+
+    # build in drop down list for pricesgroups
+    if ($form->{"prices_$i"}) {
+      $column_data{sellprice_pg} = qq|<select name="sellprice_pg_$i">$form->{"prices_$i"}</select>|;
+      $column_data{sellprice}    = $cgi->textfield(-name => "sellprice_$i", -size => 10, -onBlur => 'check_right_number_format(this)', -value =>
+                                   (($form->{"new_pricegroup_$i"} != $form->{"old_pricegroup_$i"})
+                                      ? $form->format_amount(\%myconfig, $form->{"price_new_$i"}, $decimalplaces)
+                                      : $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces)));
+    } else {
+      # for last row and report
+      # set pricegroup drop down list from report menu
+      if ($form->{"sellprice_$i"} != 0) {
+        $form->{"pricegroup_old_$i"} = $form->{"pricegroup_id_$i"};
+        my $default_option           = $form->{"sellprice_$i"}.'--'.$form->{"pricegroup_id_$i"};
+        $column_data{sellprice_pg}   = NTI($cgi->popup_menu("sellpricepg_$i", [ $default_option ], $default_option, { $default_option => $form->{"pricegroup_$i"} || '' }));
+      } else {
+        $column_data{sellprice_pg} = qq|&nbsp;|;
+      }
+      $column_data{sellprice} = $cgi->textfield(-name => "sellprice_$i", -size => 10, -onBlur => "check_right_number_format(this)", -value =>
+                                                $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces));
+    }
+    $column_data{discount}    = $cgi->textfield(-name => "discount_$i", -size => 3, -value => $form->format_amount(\%myconfig, $form->{"discount_$i"}));
+    $column_data{linetotal}   = $form->format_amount(\%myconfig, $linetotal, 2);
+    $column_data{bin}         = $form->{"bin_$i"};
+
+    if ($is_delivery_order) {
+      $column_data{stock_in_out} = (!$form->{"assembly_$i"} && $form->{"inventory_accno_$i"}) ? calculate_stock_in_out($i) : '&nbsp;';
+    }
+
+    my @ROW1 = map { value => $column_data{$_}, align => $align{$_}, nowrap => $nowrap{$_} }, @column_index;
+
+    # second row
+    my @ROW2 = ();
+    push @ROW2, { value => qq|<b>$serialnumber</b> <input name="serialnumber_$i" size="15" value="$form->{"serialnumber_$i"}">| } 
+      if $form->{type} !~ /_quotation/;
+    push @ROW2, { value => qq|<b>$projectnumber</b> | . NTI($cgi->popup_menu('-name'  => "project_id_$i",        '-values'  => \@projectnumber_values,
+                                                                             '-labels' => \%projectnumber_labels, '-default' => $form->{"project_id_$i"})) };
+    push @ROW2, { value => qq|<b>$reqdate</b> <input name="reqdate_$i" size="11" onBlur="check_right_date_format(this)" value="$form->{"reqdate_$i"}">| }
+      if $form->{type} =~ /order/;
+    push @ROW2, { value => sprintf qq|<b>%s</b>&nbsp;<input type="checkbox" name="subtotal_$i" value="1" %s>|, 
+                   $locale->text('Subtotal'), $form->{"subtotal_$i"} ? 'checked' : '' };
+
+# begin marge calculations
+    my $marge_color;
+    my $real_sellprice     = ($form->{"sellprice_$i"} - $discount) / $price_factor;
+    my $marge_price_factor = $form->{"marge_price_factor_$i"} * 1 || 1;
+
+    $form->{"lastcost_$i"} *= 1;
+    $form->{"marge_percent_$i"} = 0;
+
+    if ($real_sellprice && ($form->{"qty_$i"} * 1)) {
+      $form->{"marge_percent_$i"}     = ($real_sellprice - $form->{"lastcost_$i"} / $marge_price_factor) * 100 / $real_sellprice;
+      $myconfig{marge_percent_warn} ||= 15;
+      $marge_color                    = 'color="#ff0000"' if $form->{"id_$i"} && ($form->{"marge_percent_$i"} < (1 * $myconfig{marge_percent_warn}));
+    }
+
+    my $marge_adjust_credit_note = $form->{type} eq 'credit_note' ? -1 : 1;
+    $form->{"marge_absolut_$i"}  = ($real_sellprice - $form->{"lastcost_$i"} / $marge_price_factor) * $form->{"qty_$i"} * $marge_adjust_credit_note;
+    $form->{"marge_total"}      += $form->{"marge_absolut_$i"};
+    $form->{"lastcost_total"}   += $form->{"lastcost_$i"} * $form->{"qty_$i"} / $marge_price_factor;
+    $form->{"sellprice_total"}  += $real_sellprice * $form->{"qty_$i"};
+
+    map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}, 2) } qw(marge_absolut marge_percent);
+
+    push @ROW2, { value => sprintf qq|<font %s><b>%s</b> %s &nbsp;%s%% </font> &nbsp;<b>%s</b> %s &nbsp;<b>%s</b> %s|,
+                   $marge_color, $locale->text('Ertrag'),$form->{"marge_absolut_$i"}, $form->{"marge_percent_$i"},
+                   $locale->text('LP'), $form->format_amount(\%myconfig, $form->{"listprice_$i"}, 2),
+                   $locale->text('EK'), $form->format_amount(\%myconfig, $form->{"lastcost_$i"}, 2) }
+      if $form->{"id_$i"} && $form->{type} =~ /^sales_/ && !$is_delivery_order;
+# / marge calculations ending
+
+    my @hidden_vars;
+
+    if ($is_delivery_order) {
+      map { $form->{"${_}_${i}"} = $form->format_amount(\%myconfig, $form->{"${_}_${i}"}) } qw(sellprice discount);
+      push @hidden_vars, qw(sellprice discount price_factor_id);
+      push @hidden_vars, "stock_${stock_in_out}_sum_qty", "stock_${stock_in_out}";
+    }
+
+    push @hidden_vars, qw(partunit) if ($is_purchase);
+
+    my @HIDDENS = map { value => $_}, (
+          $cgi->hidden("-name" => "unit_old_$i", "-value" => $form->{"selected_unit_$i"}),
+          $cgi->hidden("-name" => "price_new_$i", "-value" => $form->format_amount(\%myconfig, $form->{"price_new_$i"})),
+          map { ($cgi->hidden("-name" => $_, "-value" => $form->{$_})); } map { $_."_$i" } 
+            (qw(orderitems_id bo pricegroup_old price_old id inventory_accno bin partsgroup partnotes
+                income_accno expense_accno listprice assembly taxaccounts ordnumber transdate cusordnumber
+                longdescription basefactor marge_absolut marge_percent marge_price_factor lastcost), @hidden_vars)
+    );
+
+    map { $form->{"${_}_base"} += $linetotal } (split(/ /, $form->{"taxaccounts_$i"}));
+
+    $form->{invsubtotal} += $linetotal;
+
+    push @ROWS, { ROW1 => \@ROW1, ROW2 => \@ROW2, HIDDENS => \@HIDDENS, colspan => $colspan, error => $form->{"row_error_$i"}, };
+  }
+
+  print $form->parse_html_template('oe/sales_order', { ROWS   => \@ROWS,
+                                                       HEADER => \@HEADER,
+                                                     });
+
+  if (0 != ($form->{sellprice_total} * 1)) {
+    $form->{marge_percent} = ($form->{sellprice_total} - $form->{lastcost_total}) / $form->{sellprice_total} * 100;
+  }
+
+  $lxdebug->leave_sub();
+}
 
 ##################################################
 # build html-code for pricegroups in variable $form->{prices_$j}
 
 sub set_pricegroup {
   $lxdebug->enter_sub();
+
+  _check_io_auth();
+
   my $rowcount = shift;
   for $j (1 .. $rowcount) {
     next unless $form->{PRICES}{$j};
@@ -116,6 +393,9 @@ sub set_pricegroup {
 
 sub select_item {
   $lxdebug->enter_sub();
+
+  _check_io_auth();
+
   @column_index = qw(ndx partnumber description onhand unit sellprice);
 
   $column_data{ndx}        = qq|<th>&nbsp;</th>|;
@@ -221,6 +501,7 @@ sub select_item {
 
   # save all other form variables
   foreach $key (keys %${form}) {
+    next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
     $form->{$key} =~ s/\"/&quot;/g;
     print qq|<input name="$key" type="hidden" value="$form->{$key}">\n|;
   }
@@ -243,6 +524,8 @@ sub select_item {
 sub item_selected {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   # replace the last row with the checked row
   $i = $form->{rowcount};
   $i = $form->{assembly_rows} if ($form->{item} eq 'assembly');
@@ -341,6 +624,8 @@ sub item_selected {
 sub new_item {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   # change callback
   $form->{old_callback} = $form->escape($form->{callback}, 1);
   $form->{callback}     = $form->escape("$form->{script}?action=display_form", 1);
@@ -348,45 +633,40 @@ sub new_item {
   # save all form variables except action in a previousform variable
   my $previousform = join '&', map { $form->{$_} =~ s/&/%26/; "$_=$form->{$_}" } grep { !/action/ } keys %$form;
 
-  map { $form->{"${_}_$form->{rowcount}"} =~ s/\"/&quot;/g } qw(partnumber description);
+  push @HIDDENS,      { 'name' => 'previousform', 'value' => $form->escape($previousform, 1) };
+  push @HIDDENS, map +{ 'name' => $_,             'value' => $form->{$_} },                       qw(rowcount vc);
+  push @HIDDENS, map +{ 'name' => $_,             'value' => $form->{"${_}_$form->{rowcount}"} }, qw(partnumber description unit sellprice);
+  push @HIDDENS,      { 'name' => 'taxaccount2',  'value' => $form->{taxaccounts} };
 
-  $form->header;
-
-  push @HIDDENS, { value => $cgi->hidden("-name" => "previousform", "-value" => $form->escape($previousform, 1)) };
-  push @HIDDENS, map +{ value => $cgi->hidden("-name" => $_, "-value" => $form->{$_}) },                       qw(rowcount vc login password);
-  push @HIDDENS, map +{ value => $cgi->hidden("-name" => $_, "-value" => $form->{"${_}_$form->{rowcount}"}) }, qw(partnumber description unit sellprice);
-  push @HIDDENS, { value => $cgi->hidden("-name" => "taxaccount2", "-value" => $form->{taxaccounts}) };
-
-  print $form->parse_html_template("generic/new_item", { HIDDENS => \@HIDDENS} );
+  $form->header();
+  print $form->parse_html_template("generic/new_item", { HIDDENS => [ sort { $a->{name} cmp $b->{name} } @HIDDENS ] } );
 
   $lxdebug->leave_sub();
 }
 
 sub check_form {
   $lxdebug->enter_sub();
+
+  _check_io_auth();
+
   my @a     = ();
   my $count = 0;
-  my @flds  = (qw(id partnumber description qty ship sellprice unit discount inventory_accno income_accno expense_accno listprice taxaccounts bin assembly weight projectnumber project_id oldprojectnumber runningnumber serialnumber partsgroup payment_id not_discountable shop ve gv buchungsgruppen_id language_values sellprice_pg pricegroup_old price_old price_new unit_old ordnumber transdate longdescription basefactor marge_total marge_percent marge_price_factor lastcost price_factor_id));
+
+  my @flds = qw(id partnumber description qty ship sellprice unit
+                discount inventory_accno income_accno expense_accno listprice
+                taxaccounts bin assembly weight projectnumber project_id
+                oldprojectnumber runningnumber serialnumber partsgroup payment_id
+                not_discountable shop ve gv buchungsgruppen_id language_values
+                sellprice_pg pricegroup_old price_old price_new unit_old ordnumber
+                transdate longdescription basefactor marge_total marge_percent
+                marge_price_factor lastcost price_factor_id
+                stock_out stock_in);
 
   # remove any makes or model rows
   if ($form->{item} eq 'part') {
     map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
       qw(listprice sellprice lastcost weight rop);
 
-    @flds = (make, model);
-    for my $i (1 .. ($form->{makemodel_rows})) {
-      if (($form->{"make_$i"} ne "") || ($form->{"model_$i"} ne "")) {
-        push @a, {};
-        my $j = $#a;
-
-        map { $a[$j]->{$_} = $form->{"${_}_$i"} } @flds;
-        $count++;
-      }
-    }
-
-    $form->redo_rows(\@flds, \@a, $count, $form->{makemodel_rows});
-    $form->{makemodel_rows} = $count;
-
   } elsif ($form->{item} eq 'assembly') {
 
     $form->{sellprice} = 0;
@@ -419,23 +699,6 @@ sub check_form {
     $form->redo_rows(\@flds, \@a, $count, $form->{assembly_rows});
     $form->{assembly_rows} = $count;
 
-    $count = 0;
-    @flds  = qw(make model);
-    @a     = ();
-
-    for my $i (1 .. ($form->{makemodel_rows})) {
-      if (($form->{"make_$i"} ne "") || ($form->{"model_$i"} ne "")) {
-        push @a, {};
-        my $j = $#a;
-
-        map { $a[$j]->{$_} = $form->{"${_}_$i"} } @flds;
-        $count++;
-      }
-    }
-
-    $form->redo_rows(\@flds, \@a, $count, $form->{makemodel_rows});
-    $form->{makemodel_rows} = $count;
-
   } elsif ($form->{item} eq 'service') {
     map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) } qw(listprice sellprice lastcost);
 
@@ -491,6 +754,8 @@ sub check_form {
 sub invoicetotal {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   $form->{oldinvtotal} = 0;
 
   # add all parts and deduct paid
@@ -529,6 +794,8 @@ sub invoicetotal {
 sub validate_items {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   # check if items are valid
   if ($form->{rowcount} == 1) {
     &update;
@@ -545,6 +812,9 @@ sub validate_items {
 
 sub order {
   $lxdebug->enter_sub();
+
+  _check_io_auth();
+
   if ($form->{second_run}) {
     $form->{print_and_post} = 0;
   }
@@ -612,6 +882,9 @@ sub order {
 
 sub quotation {
   $lxdebug->enter_sub();
+
+  _check_io_auth();
+
   if ($form->{second_run}) {
     $form->{print_and_post} = 0;
   }
@@ -677,6 +950,8 @@ sub request_for_quotation {
 sub edit_e_mail {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   if ($form->{second_run}) {
     $form->{print_and_post} = 0;
     $form->{resubmit}       = 0;
@@ -700,16 +975,16 @@ sub edit_e_mail {
   $form->header;
 
   my (@dont_hide_key_list, %dont_hide_key, @hidden_keys);
-  @dont_hide_key_list = qw(action email cc bcc subject message sendmode format header override);
+  @dont_hide_key_list = qw(action email cc bcc subject message sendmode format header override login password);
   @dont_hide_key{@dont_hide_key_list} = (1) x @dont_hide_key_list;
   @hidden_keys = sort grep { !$dont_hide_key{$_} } grep { !ref $form->{$_} } keys %$form;
 
-  print $form->parse_html_template2('generic/edit_email',
-                                    { title           => $title,
-                                      a_filename      => $attachment_filename,
-                                      _print_options_ => print_options('inline' => 1),
-                                      HIDDEN          => [ map +{ name => $_, value => $form->{$_} }, @hidden_keys ],
-                                      SHOW_BCC        => $myconfig{role} eq 'admin' });
+  print $form->parse_html_template('generic/edit_email',
+                                   { title           => $title,
+                                     a_filename      => $attachment_filename,
+                                     _print_options_ => print_options('inline' => 1),
+                                     HIDDEN          => [ map +{ name => $_, value => $form->{$_} }, @hidden_keys ],
+                                     SHOW_BCC        => $myconfig{role} eq 'admin' });
 
   $lxdebug->leave_sub();
 }
@@ -717,9 +992,10 @@ sub edit_e_mail {
 sub send_email {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   my $callback = $form->{script} . "?action=edit";
-  map({ $callback .= "\&${_}=" . E($form->{$_}); }
-      qw(login password type id));
+  map({ $callback .= "\&${_}=" . E($form->{$_}); } qw(type id));
 
   print_form("return");
 
@@ -743,6 +1019,8 @@ sub send_email {
 sub print_options {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   my %options = @_;
 
   # names 3 parameters and returns a hashref, for use in templates
@@ -772,20 +1050,23 @@ sub print_options {
     ($form->{type} eq 'sales_order') ? (
       opthash("sales_order",         $form->{PD}{sales_order},         $locale->text('Confirmation')),
       opthash("proforma",            $form->{PD}{proforma},            $locale->text('Proforma Invoice')),
-      opthash("pick_list",           $form->{PD}{pick_list},           $locale->text('Pick List')),
-      opthash("packing_list",        $form->{PD}{packing_list},        $locale->text('Packing List')) 
     ) : undef,
-    ($form->{type} =~ /_quotation$/) ?
-      opthash("$`_quotation",        $form->{PD}{"$`_quotation"},      $locale->text('Quotation')) : undef,
+    ($form->{type} =~ /sales_quotation$/) ?
+      opthash('sales_quotation',     $form->{PD}{sales_quotation},     $locale->text('Quotation')) : undef,
+    ($form->{type} =~ /request_quotation$/) ?
+      opthash('request_quotation',   $form->{PD}{request_quotation},   $locale->text('Request for Quotation')) : undef,
     ($form->{type} eq 'invoice') ? (
       opthash("invoice",             $form->{PD}{invoice},             $locale->text('Invoice')),
       opthash("proforma",            $form->{PD}{proforma},            $locale->text('Proforma Invoice')),
-      opthash("packing_list",        $form->{PD}{packing_list},        $locale->text('Packing List'))
     ) : undef,
     ($form->{type} eq 'invoice' && $form->{storno}) ? (
       opthash("storno_invoice",      $form->{PD}{storno_invoice},      $locale->text('Storno Invoice')),
       opthash("storno_packing_list", $form->{PD}{storno_packing_list}, $locale->text('Storno Packing List')) 
     ) : undef,
+    ($form->{type} =~ /_delivery_order$/) ? (
+      opthash($form->{type},         $form->{PD}{$form->{type}},       $locale->text('Delivery Order')),
+      opthash('pick_list',           $form->{PD}{pick_list},           $locale->text('Pick List')),
+    ) : undef;
     ($form->{type} eq 'credit_note') ?
       opthash("credit_note",         $form->{PD}{credit_note},         $locale->text('Credit Note')) : undef;
 
@@ -798,21 +1079,21 @@ sub print_options {
       opthash("screen",              $form->{OP}{screen},              $locale->text('Screen')),
     (scalar @{ $form->{printers} } && $latex_templates) ?
       opthash("printer",             $form->{OP}{printer},             $locale->text('Printer')) : undef,
-    ($latex_templates && !$options->{no_queue}) ?
+    ($latex_templates && !$options{no_queue}) ?
       opthash("queue",               $form->{OP}{queue},               $locale->text('Queue')) : undef
         if ($form->{media} ne 'email');
 
   push @FORMAT, grep $_,
     ($opendocument_templates && $openofficeorg_writer_bin && $xvfb_bin && (-x $openofficeorg_writer_bin) && (-x $xvfb_bin)
-     && !$options->{no_opendocument_pdf}) ?
+     && !$options{no_opendocument_pdf}) ?
       opthash("opendocument_pdf",    $form->{DF}{"opendocument_pdf"},  $locale->text("PDF (OpenDocument/OASIS)")) : undef,
     ($latex_templates) ?
       opthash("pdf",                 $form->{DF}{pdf},                 $locale->text('PDF')) : undef,
-    ($latex_templates && !$options->{no_postscript}) ?
+    ($latex_templates && !$options{no_postscript}) ?
       opthash("postscript",          $form->{DF}{postscript},          $locale->text('Postscript')) : undef,
-    (!$options->{no_html}) ?
+    (!$options{no_html}) ?
       opthash("html", $form->{DF}{html}, "HTML") : undef,
-    ($opendocument_templates && !$options->{no_opendocument}) ?
+    ($opendocument_templates && !$options{no_opendocument}) ?
       opthash("opendocument",        $form->{DF}{opendocument},        $locale->text("OpenDocument/OASIS")) : undef;
 
   push @LANGUAGE_ID, 
@@ -840,15 +1121,20 @@ sub print_options {
   my $print_options = $form->parse_html_template("generic/print_options", { SELECTS  => \@SELECTS, %template_vars } );
 
   if ($options{inline}) {
-    $lxdebug->leave_sub() and return $print_options;
-  } else {
-    print $print_options; $lxdebug->leave_sub();
+    $lxdebug->leave_sub();
+    return $print_options;
   }
+
+  print $print_options;
+
+  $lxdebug->leave_sub();
 }
 
 sub print {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   if ($form->{print_nextsub}) {
     call_sub($form->{print_nextsub});
     $lxdebug->leave_sub();
@@ -883,6 +1169,9 @@ sub print {
 
 sub print_form {
   $lxdebug->enter_sub();
+
+  _check_io_auth();
+
   my ($old_form) = @_;
 
   $inv       = "inv";
@@ -943,14 +1232,6 @@ sub print_form {
     # set invnumber for template packing_list 
     $form->{invnumber}   = $form->{ordnumber};
   }
-  if ($form->{formname} eq 'pick_list') {
-    $inv                  = "ord";
-    $due                  = "req";
-    $form->{"${inv}date"} =
-      ($form->{transdate}) ? $form->{transdate} : $form->{invdate};
-    $form->{label} = $locale->text('Pick List');
-    $order = 1 unless $form->{type} eq 'invoice';
-  }
   if ($form->{formname} eq 'purchase_order') {
     $inv                  = "ord";
     $due                  = "req";
@@ -994,6 +1275,14 @@ sub print_form {
     $order                = 1;
   }
 
+  if ($form->{type} =~ /_delivery_order$/) {
+    undef $due;
+    $inv                  = "do";
+    $form->{"${inv}date"} = $form->{transdate};
+    $numberfld            = $form->{type} =~ /^sales/ ? 'sdonumber' : 'pdonumber';
+    $form->{label}        = $form->{formname} eq 'pick_list' ? $locale->text('Pick List') : $locale->text('Delivery Order');
+  }
+
   $form->isblank("email", $locale->text('E-mail address missing!'))
     if ($form->{media} eq 'email');
   $form->isblank("${inv}date",
@@ -1047,7 +1336,7 @@ sub print_form {
   $salesman_id_saved = $form->{salesman_id};
   $cp_id_saved = $form->{cp_id};
 
-  call_sub("$form->{vc}_details");
+  call_sub("$form->{vc}_details") if ($form->{vc});
 
   $form->{language_id} = $language_saved;
   $form->{payment_id} = $payment_id_saved;
@@ -1076,7 +1365,9 @@ sub print_form {
   ($form->{employee}) = split /--/, $form->{employee};
 
   # create the form variables
-  if ($order) {
+  if ($form->{type} =~ /_delivery_order$/) {
+    DO->order_details();
+  } elsif ($order) {
     OE->order_details(\%myconfig, \%$form);
   } else {
     IS->invoice_details(\%myconfig, \%$form, $locale);
@@ -1170,6 +1461,16 @@ sub print_form {
                    grep({ /^qty_\d+$/
                         } keys(%{$form})));
 
+  my ($cvar_date_fields, $cvar_number_fields) = CVar->get_field_format_list('module' => 'CT', 'prefix' => 'vc_');
+
+  if (scalar @{ $cvar_date_fields }) {
+    format_dates($output_dateformat, $output_longdates, @{ $cvar_date_fields });
+  }
+
+  while (my ($precision, $field_list) = each %{ $cvar_number_fields }) {
+    reformat_numbers($output_numberformat, $precision, @{ $field_list });
+  }
+
   $form->{IN} = "$form->{formname}$form->{language}${printer_code}.html";
   if ($form->{format} eq 'postscript') {
     $form->{postscript} = 1;
@@ -1305,7 +1606,9 @@ sub print_form {
 
 sub customer_details {
   $lxdebug->enter_sub();
+
   IS->customer_details(\%myconfig, \%$form, @_);
+
   $lxdebug->leave_sub();
 }
 
@@ -1320,6 +1623,8 @@ sub vendor_details {
 sub post_as_new {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   $form->{postasnew} = 1;
   map { delete $form->{$_} } qw(printed emailed queued);
 
@@ -1330,6 +1635,9 @@ sub post_as_new {
 
 sub ship_to {
   $lxdebug->enter_sub();
+
+  _check_io_auth();
+
   if ($form->{second_run}) {
     $form->{print_and_post} = 0;
   }
@@ -1458,6 +1766,7 @@ sub ship_to {
   $form->{title} = $title;
 
   foreach $key (keys %$form) {
+    next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
     $form->{$key} =~ s/\"/&quot;/g;
     print qq|<input type="hidden" name="$key" value="$form->{$key}">\n|;
   }
@@ -1481,6 +1790,8 @@ sub ship_to {
 sub new_license {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   my $row = shift;
 
   # change callback
@@ -1496,6 +1807,7 @@ sub new_license {
   # save all other form variables in a previousform variable
   $form->{row} = $row;
   foreach $key (keys %$form) {
+    next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key}));
 
     # escape ampersands
     $form->{$key} =~ s/&/%26/g;
@@ -1510,7 +1822,7 @@ sub new_license {
   map { $form->{$_} = $form->escape($form->{$_}, 1) }
     qw(partnumber description);
   $form->{callback} =
-    qq|$form->{script}?login=$form->{login}&password=$form->{password}&action=add&vc=$form->{db}&$form->{db}_id=$form->{id}&$form->{db}=$name&type=$form->{type}&customer=$customer&partnumber=$form->{partnumber}&description=$form->{description}&previousform="$previousform"&initial=1|;
+    qq|$form->{script}?action=add&vc=$form->{db}&$form->{db}_id=$form->{id}&$form->{db}=$name&type=$form->{type}&customer=$customer&partnumber=$form->{partnumber}&description=$form->{description}&previousform="$previousform"&initial=1|;
   $form->redirect;
 
   $lxdebug->leave_sub();
@@ -1519,6 +1831,8 @@ sub new_license {
 sub relink_accounts {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   $form->{"taxaccounts"} =~ s/\s*$//;
   $form->{"taxaccounts"} =~ s/^\s*//;
   foreach my $accno (split(/\s*/, $form->{"taxaccounts"})) {
@@ -1538,13 +1852,12 @@ sub relink_accounts {
 sub set_duedate {
   $lxdebug->enter_sub();
 
+  _check_io_auth();
+
   $form->get_duedate(\%myconfig);
 
-  my $q = new CGI;
-  $result = "$form->{duedate}";
-  print $q->header();
-  print $result;
-  $lxdebug->leave_sub();
+  print $cgi->header() . $form->{duedate};
 
+  $lxdebug->leave_sub();
 }