Merge branch 'after-262'
[kivitendo-erp.git] / bin / mozilla / oe.pl
index b515be1..97cc388 100644 (file)
 
 use POSIX qw(strftime);
 
+use SL::DO;
+use SL::FU;
 use SL::OE;
 use SL::IR;
 use SL::IS;
+use SL::MoreCommon qw(ary_diff);
 use SL::PE;
 use SL::ReportGenerator;
-use List::Util qw(max reduce);
+use List::MoreUtils qw(any none);
+use List::Util qw(max reduce sum);
+use Data::Dumper;
 
 require "bin/mozilla/io.pl";
 require "bin/mozilla/arap.pl";
 require "bin/mozilla/reportgenerator.pl";
 
+use strict;
+
+our %TMPL_VAR;
+
 1;
 
 # end of main
@@ -59,8 +68,29 @@ require "bin/mozilla/reportgenerator.pl";
 # $locale->text('Workflow request_quotation');
 # $locale->text('Workflow sales_quotation');
 
+my $oe_access_map = {
+  'sales_order'       => 'sales_order_edit',
+  'purchase_order'    => 'purchase_order_edit',
+  'request_quotation' => 'request_quotation_edit',
+  'sales_quotation'   => 'sales_quotation_edit',
+};
+
+sub check_oe_access {
+  my $form     = $main::form;
+
+  my $right   = $oe_access_map->{$form->{type}};
+  $right    ||= 'DOES_NOT_EXIST';
+
+  $main::auth->assert($right);
+}
+
 sub set_headings {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my $locale   = $main::locale;
+
+  check_oe_access();
 
   my ($action) = @_;
 
@@ -93,27 +123,36 @@ sub set_headings {
     $form->{vc}      = 'customer';
   }
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub add {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+
+  check_oe_access();
 
   set_headings("add");
 
   $form->{callback} =
-    "$form->{script}?action=add&type=$form->{type}&vc=$form->{vc}&login=$form->{login}&password=$form->{password}"
+    "$form->{script}?action=add&type=$form->{type}&vc=$form->{vc}"
     unless $form->{callback};
 
   &order_links;
   &prepare_order;
   &display_form;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub edit {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+
+  check_oe_access();
+
   # show history button
   $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
   #/show hhistory button
@@ -124,21 +163,23 @@ sub edit {
 
   # editing without stuff to edit? try adding it first
   if ($form->{rowcount} && !$form->{print_and_save}) {
+    my $id;
     map { $id++ if $form->{"multi_id_$_"} } (1 .. $form->{rowcount});
     if (!$id) {
 
       # reset rowcount
       undef $form->{rowcount};
       &add;
-      $lxdebug->leave_sub();
+      $main::lxdebug->leave_sub();
       return;
     }
   } elsif (!$form->{id}) {
     &add;
-    $lxdebug->leave_sub();
+    $main::lxdebug->leave_sub();
     return;
   }
 
+  my ($language_id, $printer_id);
   if ($form->{print_and_save}) {
     $form->{action}   = "print";
     $form->{resubmit} = 1;
@@ -149,186 +190,128 @@ sub edit {
   set_headings("edit");
 
   &order_links;
+
+  $form->{rowcount} = 0;
+  foreach my $ref (@{ $form->{form_details} }) {
+    $form->{rowcount}++;
+    map { $form->{"${_}_$form->{rowcount}"} = $ref->{$_} } keys %{$ref};
+  }
+
   &prepare_order;
+
   if ($form->{print_and_save}) {
     $form->{language_id} = $language_id;
     $form->{printer_id} = $printer_id;
   }
+
   &display_form;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub order_links {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+
+  check_oe_access();
+
   # get customer/vendor
   $form->all_vc(\%myconfig, $form->{vc}, ($form->{vc} eq 'customer') ? "AR" : "AP");
 
   # retrieve order/quotation
-  $form->{webdav}   = $webdav;
+  $form->{webdav}   = $::lx_office_conf{system}->{webdav};
   $form->{jsscript} = 1;
 
   my $editing = $form->{id};
 
   OE->retrieve(\%myconfig, \%$form);
 
-  if ($form->{payment_id}) {
-    $payment_id = $form->{payment_id};
-  }
-  if ($form->{language_id}) {
-    $language_id = $form->{language_id};
-  }
-  if ($form->{taxzone_id}) {
-    $taxzone_id = $form->{taxzone_id};
-  }
-
-  $salesman_id = $form->{salesman_id} if ($editing);
-
-
   # if multiple rowcounts (== collective order) then check if the
   # there were more than one customer (in that case OE::retrieve removes
   # the content from the field)
-  if (   $form->{rowcount}
-      && $form->{type} eq 'sales_order'
-      && defined $form->{customer}
-      && $form->{customer} eq '') {
-
-    #    $main::lxdebug->message(0, "Detected Edit order with concurrent customers");
-    $form->error(
-                 $locale->text(
-                   'Collective Orders only work for orders from one customer!')
-    );
-  }
+  $form->error($locale->text('Collective Orders only work for orders from one customer!'))
+    if          $form->{rowcount}  && $form->{type}     eq 'sales_order'
+     && defined $form->{customer}  && $form->{customer} eq '';
 
-  $taxincluded = $form->{taxincluded};
-  $form->{shipto} = 1 if $form->{id};
+  $form->{"$form->{vc}_id"} ||= $form->{"all_$form->{vc}"}->[0]->{id} if $form->{"all_$form->{vc}"};
 
-  if ($form->{"all_$form->{vc}"}) {
-    unless ($form->{"$form->{vc}_id"}) {
-      $form->{"$form->{vc}_id"} = $form->{"all_$form->{vc}"}->[0]->{id};
-    }
-  }
-
-  $cp_id    = $form->{cp_id};
-  $intnotes = $form->{intnotes};
+  $form->backup_vars(qw(payment_id language_id taxzone_id salesman_id taxincluded cp_id intnotes));
+  $form->{shipto} = 1 if $form->{id};
 
   # get customer / vendor
-  if ($form->{type} =~ /(purchase_order|request_quotation)/) {
-    IR->get_vendor(\%myconfig, \%$form);
+  IR->get_vendor(\%myconfig, \%$form)   if $form->{type} =~ /(purchase_order|request_quotation)/;
+  IS->get_customer(\%myconfig, \%$form) if $form->{type} =~ /sales_(order|quotation)/;
 
-    #quote all_vendor Bug 133
-    foreach $ref (@{ $form->{all_vendor} }) {
-      $ref->{name} = $form->quote($ref->{name});
-    }
+  $form->restore_vars(qw(payment_id language_id taxzone_id intnotes cp_id));
+  $form->restore_vars(qw(taxincluded)) if $form->{id};
+  $form->restore_vars(qw(salesman_id)) if $editing;
+  $form->{forex}       = $form->{exchangerate};
+  $form->{employee}    = "$form->{employee}--$form->{employee_id}";
 
+  # build vendor/customer drop down comatibility... don't ask
+  if (@{ $form->{"all_$form->{vc}"} || [] }) {
+    $form->{"select$form->{vc}"} = 1;
+    $form->{$form->{vc}}         = qq|$form->{$form->{vc}}--$form->{"$form->{vc}_id"}|;
   }
-  if ($form->{type} =~ /sales_(order|quotation)/) {
-    IS->get_customer(\%myconfig, \%$form);
 
-    #quote all_vendor Bug 133
-    foreach $ref (@{ $form->{all_customer} }) {
-      $ref->{name} = $form->quote($ref->{name});
-    }
+  $form->{"old$form->{vc}"}  = $form->{$form->{vc}};
 
+  if ($form->{"old$form->{vc}"} !~ m/--\d+$/ && $form->{"$form->{vc}_id"}) {
+    $form->{"old$form->{vc}"} .= qq|--$form->{"$form->{vc}_id"}|
   }
-  $form->{cp_id} = $cp_id;
 
-  if ($payment_id) {
-    $form->{payment_id} = $payment_id;
-  }
-  if ($language_id) {
-    $form->{language_id} = $language_id;
-  }
-  if ($taxzone_id) {
-    $form->{taxzone_id} = $taxzone_id;
-  }
-  $form->{intnotes} = $intnotes if $intnotes;
-  ($form->{ $form->{vc} }) = split /--/, $form->{ $form->{vc} };
-  $form->{"old$form->{vc}"} = qq|$form->{$form->{vc}}--$form->{"$form->{vc}_id"}|;
-
-  # build the popup menus
-  if (@{ $form->{"all_$form->{vc}"} }) {
-    $form->{ $form->{vc} } =
-      qq|$form->{$form->{vc}}--$form->{"$form->{vc}_id"}|;
-    map { $form->{"select$form->{vc}"} .=
-"<option>$_->{name}--$_->{id}</option>\n" }
-      (@{ $form->{"all_$form->{vc}"} });
-  }
-
-  $form->{taxincluded} = $taxincluded if ($form->{id});
-
-  # departments
-  if (@{ $form->{all_departments} }) {
-    $form->{selectdepartment} = "<option>\n";
-    $form->{department}       = "$form->{department}--$form->{department_id}";
+  $main::lxdebug->leave_sub();
+}
 
-    map {
-      $form->{selectdepartment} .= "<option>$_->{description}--$_->{id}</option>\n"
-    } @{ $form->{all_departments} };
-  }
+sub prepare_order {
+  $main::lxdebug->enter_sub();
 
-  $form->{employee} = "$form->{employee}--$form->{employee_id}";
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
-  # forex
-  $form->{forex} = $form->{exchangerate};
+  check_oe_access();
 
-  $form->{salesman_id} = $salesman_id if ($editing);
+  $form->{formname} ||= $form->{type};
 
-  $lxdebug->leave_sub();
-}
+  # format discounts if values come from db. either as single id, or as a collective order
+  my $format_discounts = $form->{id} || $form->{convert_from_oe_ids};
 
-sub prepare_order {
-  $lxdebug->enter_sub();
-  $form->{formname} = $form->{type} unless $form->{formname};
-
-  my $i = 0;
-  foreach $ref (@{ $form->{form_details} }) {
-    $form->{rowcount} = ++$i;
-    map { $form->{"${_}_$i"} = $ref->{$_} } keys %{$ref};
-  }
   for my $i (1 .. $form->{rowcount}) {
-    $form->{"reqdate_$i"}   = $form->{"deliverydate_$i"} unless $form->{"reqdate_$i"};
-    $form->{"discount_$i"}  = $form->format_amount(\%myconfig, $form->{"discount_$i"} * ($form->{id} ? 100 : 1));
+    $form->{"reqdate_$i"} ||= $form->{"deliverydate_$i"};
+    $form->{"discount_$i"}  = $form->format_amount(\%myconfig, $form->{"discount_$i"} * ($format_discounts ? 100 : 1));
     $form->{"sellprice_$i"} = $form->format_amount(\%myconfig, $form->{"sellprice_$i"});
+    $form->{"lastcost_$i"}  = $form->format_amount(\%myconfig, $form->{"lastcost_$i"});
     $form->{"qty_$i"}       = $form->format_amount(\%myconfig, $form->{"qty_$i"});
-    map { $form->{"${_}_$i"} =~ s/\"/&quot;/g } qw(partnumber description unit);
   }
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub form_header {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
   my @custom_hiddens;
 
-  # Container for template variables. Unfortunately this has to be visible in form_footer too, so not my.
-  our %TMPL_VAR = ();
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+  my $cgi      = $main::cgi;
 
-  $form->{employee_id} = $form->{old_employee_id} if $form->{old_employee_id};
-  $form->{salesman_id} = $form->{old_salesman_id} if $form->{old_salesman_id};
+  check_oe_access();
+
+  # Container for template variables. Unfortunately this has to be
+  # visible in form_footer too, so package local level and not my here.
+  %TMPL_VAR = ();
 
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
   $form->{employee_id} = $form->{old_employee_id} if $form->{old_employee_id};
   $form->{salesman_id} = $form->{old_salesman_id} if $form->{old_salesman_id};
 
-  map { $form->{$_} = H($form->{$_}) }
-    qw(shippingpoint shipvia notes intnotes shiptoname
-       shiptostreet shiptozipcode shiptocity shiptocountry shiptocontact
-       shiptophone shiptofax shiptodepartment_1 shiptodepartment_2);
   # use JavaScript Calendar or not
   $form->{jsscript} = 1;
-  $TMPL_VAR{button1} = qq|
-     <td nowrap><input name=transdate id=transdate size=11 title="$myconfig{dateformat}" value="$form->{transdate}" onBlur=\"check_right_date_format(this)\">
-      <input type=button name=transdate id="trigger1" value=| . $locale->text('button') . qq|></td>
-    |;
-  $TMPL_VAR{button2} = qq|
-     <td nowrap width="13"><input name=reqdate id=reqdate size=11 title="$myconfig{dateformat}" value="$form->{reqdate}" onBlur=\"check_right_date_format(this)\">
-      <input type=button name=reqdate name=reqdate id="trigger2" value=| . $locale->text('button') . qq|></td>
-   |;
-  #write Trigger
-  $TMPL_VAR{jsscript} = Form->write_trigger(\%myconfig, "2", "transdate", "BL", "trigger1", "reqdate", "BL", "trigger2");
 
   # openclosed checkboxes
   my @tmp;
@@ -338,18 +321,7 @@ sub form_header {
                         $form->{"closed"}    ? "checked" : "",  $locale->text('Closed')    if $form->{id};
   $TMPL_VAR{openclosed} = sprintf qq|<tr><td colspan=%d align=center>%s</td></tr>\n|, 2 * scalar @tmp, join "\n", @tmp if @tmp;
 
-  # set option selected
-  foreach $item ($form->{vc}, 'currency', 'department', ($form->{vc} eq "customer" ? 'customer' : 'vendor')) {
-    $form->{"select$item"} =~ s/ selected//;
-    $form->{"select$item"} =~ s/option>\Q$form->{$item}\E/option selected>$form->{$item}/;
-  }
-
-  #quote select[customer|vendor] Bug 133
-  $form->{"select$form->{vc}"} = $form->quote($form->{"select$form->{vc}"});
-
-  #substitute \n and \r to \s (bug 543)
-  $form->{"select$form->{vc}"} =~ s/[\n\r]/&nbsp;/g;
-  
+  # project ids
   my @old_project_ids = ($form->{"globalproject_id"}, grep { $_ } map { $form->{"project_id_$_"} } 1..$form->{"rowcount"});
 
   my $vc = $form->{vc} eq "customer" ? "customers" : "vendors";
@@ -363,101 +335,78 @@ sub form_header {
                    "taxzones"      => "ALL_TAXZONES",
                    "payments"      => "ALL_PAYMENTS",
                    "currencies"    => "ALL_CURRENCIES",
+                   "departments"   => "ALL_DEPARTMENTS",
                    $vc             => { key   => "ALL_" . uc($vc),
                                         limit => $myconfig{vclimit} + 1 },
                    "price_factors" => "ALL_PRICE_FACTORS");
 
-  # contacts
-  @values = ("", map { $_->{cp_id} } @{ $form->{ALL_CONTACTS} });
-  %labels = map { $_->{cp_id} => $_->{"cp_name"} . ($_->{cp_abteilung} ? " ($_->{cp_abteilung})" : "") } @{ $form->{ALL_CONTACTS} };
-  $TMPL_VAR{contact} = NTI($cgi->popup_menu('-name' => 'cp_id', '-values' => \@values, '-style' => 'width: 250px',
-                                            '-labels' => \%labels, '-default' => $form->{"cp_id"})) if scalar @values > 1;
+  # label subs
+  $TMPL_VAR{sales_employee_labels} = sub { $_[0]->{name} || $_[0]->{login} };
+  $TMPL_VAR{shipto_labels}         = sub { join "; ", grep { $_ } map { $_[0]->{"shipto${_}" } } qw(name department_1 street city) };
+  $TMPL_VAR{contact_labels}        = sub { join(', ', $_[0]->{"cp_name"}, $_[0]->{"cp_givenname"}) . ($_[0]->{cp_abteilung} ? " ($_[0]->{cp_abteilung})" : "") };
+  $TMPL_VAR{department_labels}     = sub { "$_[0]->{description}--$_[0]->{id}" };
 
   # vendor/customer
-  @values = map { "$_->{name}--$_->{id}" } @{ $form->{uc "all_$form->{vc}s" } };
-  %labels = map { +"$_->{name}--$_->{id}" => $_->{name} } @{ $form->{uc "all_$form->{vc}s" } };
+  $TMPL_VAR{vc_keys} = sub { "$_[0]->{name}--$_[0]->{id}" };
+  $TMPL_VAR{vclimit} = $myconfig{vclimit};
+  $TMPL_VAR{vc_select} = "customer_or_vendor_selection_window('$form->{vc}', '', @{[ $form->{vc} eq 'vendor' ? 1 : 0 ]}, 0)";
   push @custom_hiddens, "$form->{vc}_id";
   push @custom_hiddens, "old$form->{vc}";
   push @custom_hiddens, "select$form->{vc}";
-  $TMPL_VAR{vc} = sprintf qq|<th align="right">%s</th><td>%s<input type="button" value="?" onclick="show_vc_details('$form->{vc}')"></td>|,
-       $locale->text(ucfirst $form->{vc}), 
-       ($myconfig{vclimit} <=  scalar(@values)) 
-        ? $cgi->textfield(-value => H($form->{"old$form->{vc}"} =~ /^(.*)\-\-.*$/), -name => $form->{vc}) 
-        : NTI($cgi->popup_menu('-name' => "$form->{vc}", '-default' => $form->{"old$form->{vc}"}, 
-                               '-onChange' => "document.getElementById('update_button').click();",
-                               '-values' => \@values, '-labels' => \%labels, '-style' => 'width: 250px'));
-
-  # payments (for footer)
-  @values = ("", map { $_->{id} } @{ $form->{ALL_PAYMENTS} });
-  %labels = map { $_->{id} => $_->{description} } @{ $form->{ALL_PAYMENTS} };
-  $TMPL_VAR{payments} = NTI($cgi->popup_menu('-name' => 'payment_id', '-values' => \@values, '-style' => 'width: 250px',
-                                             '-labels' => \%labels, '-default' => $form->{payment_id}));
-
-  # shipto
-  @values = ("", map { $_->{shipto_id} } @{ $form->{ALL_SHIPTO} });
-  $TMPL_VAR{ALL_SHIPTO} = $form->{ALL_SHIPTO};
-  for my $item ( @{ $TMPL_VAR{ALL_SHIPTO} }) {
-     $item->{label} = join "; ", grep { $_ } map { $item->{"shipto${_}" } } qw(name department_1 street city);
-  }
-  %labels = map { my $item=$_; $_->{shipto_id} => join "; ", grep { $_ } map { $item->{"shipto${_}" } } qw(name department_1 street city) } @{ $form->{ALL_SHIPTO} };
-  $TMPL_VAR{shipto} = NTI($cgi->popup_menu('-name' => 'shipto_id', '-values' => \@values, '-style' => 'width: 250px',
-                                           '-labels' => \%labels, '-default' => $form->{"shipto_id"})) if scalar @values > 1;
-
-  # projects
-  @values = ("", map { $_->{id} } @{ $form->{ALL_PROJECTS} });
-  %labels = map { $_->{id} => $_->{projectnumber} } @{ $form->{ALL_PROJECTS} };
-  $TMPL_VAR{globalprojectnumber} = NTI($cgi->popup_menu('-name' => 'globalproject_id', '-values' => \@values,
-                                                        '-labels' => \%labels, '-default' => $form->{"globalproject_id"}));
-  
-  # salesmen
-  @values = map { $_->{id} } @{ $form->{ALL_SALESMEN} };
-  %labels = map { $_->{id} => ($_->{name} || $_->{login}) } @{ $form->{ALL_SALESMEN} };
-  $TMPL_VAR{salesmen} = NTI($cgi->popup_menu('-name' => 'salesman_id', '-default' => $form->{"salesman_id"} ? $form->{"salesman_id"} : $form->{"employee_id"},
-                                             '-values' => \@values, '-labels' => \%labels)) if $form->{type} =~ /^sales_/ && scalar @values;
-
-  # employees
-  @values = map { $_->{id} } @{ $form->{ALL_EMPLOYEES} };
-  %labels = map { $_->{id} => $_->{name} || $_->{login} } @{ $form->{ALL_EMPLOYEES} };
-  $TMPL_VAR{employee} = NTI($cgi->popup_menu('-name' => 'employee_id', '-default' => $form->{"employee_id"},
-                                             '-values' => \@values, '-labels' => \%labels));
-
-  # taxzone
-  @values = map { $_->{id} } @{ $form->{ALL_TAXZONES} };
-  %labels = map { $_->{id} => $_->{description} } @{ $form->{ALL_TAXZONES} };
-  $TMPL_VAR{taxzone} = NTI($cgi->popup_menu('-name' => 'taxzone_id', '-default' => $form->{"taxzone_id"},
-                                            '-values' => \@values, '-labels' => \%labels, '-style' => 'width: 250px'));
 
   # currencies and exchangerate
-  @values = map { $_ } @{ $form->{ALL_CURRENCIES} };
-  %labels = map { $_ => $_ } @{ $form->{ALL_CURRENCIES} };
+  my @values = map { $_ } @{ $form->{ALL_CURRENCIES} };
+  my %labels = map { $_ => $_ } @{ $form->{ALL_CURRENCIES} };
   $form->{currency}            = $form->{defaultcurrency} unless $form->{currency};
-  $TMPL_VAR{show_exchangerate} = $form->{currency} ne $form->{defaultcurrency} && $form->{exchangerate};
+  $TMPL_VAR{show_exchangerate} = $form->{currency} ne $form->{defaultcurrency};
   $TMPL_VAR{currencies}        = NTI($cgi->popup_menu('-name' => 'currency', '-default' => $form->{"currency"},
                                                       '-values' => \@values, '-labels' => \%labels)) if scalar @values;
   push @custom_hiddens, "forex";
   push @custom_hiddens, "exchangerate" if $form->{forex};
 
   # credit remaining
-  $creditwarning = (($form->{creditlimit} != 0) && ($form->{creditremaining} < 0) && !$form->{update}) ? 1 : 0;
+  my $creditwarning = (($form->{creditlimit} != 0) && ($form->{creditremaining} < 0) && !$form->{update}) ? 1 : 0;
   $TMPL_VAR{is_credit_remaining_negativ} = ($form->{creditremaining} =~ /-/) ? "0" : "1";
-  
+
   # business
   $TMPL_VAR{business_label} = ($form->{vc} eq "customer" ? $locale->text('Customer type') : $locale->text('Vendor type'));
 
-  push @custom_hiddens, "ordnumber"      if $form->{type} =~ /_quotation$/;
   push @custom_hiddens, "customer_klass" if $form->{vc} eq 'customer';
 
-  $credittext = $locale->text('Credit Limit exceeded!!!');
+  my $credittext = $locale->text('Credit Limit exceeded!!!');
+
+  my $follow_up_vc                =  $form->{ $form->{vc} eq 'customer' ? 'customer' : 'vendor' };
+  $follow_up_vc                   =~ s/--\d*\s*$//;
+  $TMPL_VAR{follow_up_trans_info} =  ($form->{type} =~ /_quotation$/ ? $form->{quonumber} : $form->{ordnumber}) . " ($follow_up_vc)";
 
-  $onload = ($form->{resubmit} && ($form->{format} eq "html")) ? "window.open('about:blank','Beleg'); document.oe.target = 'Beleg';document.oe.submit()"
+  if ($form->{id}) {
+    my $follow_ups = FU->follow_ups('trans_id' => $form->{id});
+
+    if (scalar @{ $follow_ups }) {
+      $TMPL_VAR{num_follow_ups}     = scalar                    @{ $follow_ups };
+      $TMPL_VAR{num_due_follow_ups} = sum map { $_->{due} * 1 } @{ $follow_ups };
+    }
+  }
+
+  my $onload = ($form->{resubmit} && ($form->{format} eq "html")) ? "window.open('about:blank','Beleg'); document.oe.target = 'Beleg';document.oe.submit()"
           : ($form->{resubmit})                                ? "document.oe.submit()"
           : ($creditwarning)                                   ? "alert('$credittext')"
-          :                                                      "focus()";
+          :                                                      "";
 
   $onload .= qq|;setupDateFormat('|. $myconfig{dateformat} .qq|', '|. $locale->text("Falsches Datumsformat!") .qq|')|;
   $onload .= qq|;setupPoints('|.   $myconfig{numberformat} .qq|', '|. $locale->text("wrongformat") .qq|')|;
   $TMPL_VAR{onload} = $onload;
-  
+
+  if ($form->{type} eq 'sales_order') {
+    if (!$form->{periodic_invoices_config}) {
+      $form->{periodic_invoices_status} = $locale->text('not configured');
+
+    } else {
+      my $config                        = YAML::Load($form->{periodic_invoices_config});
+      $form->{periodic_invoices_status} = $config->{active} ? $locale->text('active') : $locale->text('inactive');
+    }
+  }
+
   $form->{javascript} .= qq|<script type="text/javascript" src="js/show_form_details.js"></script>|;
   $form->{javascript} .= qq|<script type="text/javascript" src="js/show_history.js"></script>|;
   $form->{javascript} .= qq|<script type="text/javascript" src="js/show_vc_details.js"></script>|;
@@ -470,7 +419,7 @@ sub form_header {
         max_dunning_level dunning_amount shiptoname shiptostreet shiptozipcode
         shiptocity shiptocountry shiptocontact shiptophone shiptofax
         shiptodepartment_1 shiptodepartment_2 shiptoemail
-        message email subject cc bcc taxpart taxservice taxaccounts),
+        message email subject cc bcc taxpart taxservice taxaccounts cursor_fokus),
         @custom_hiddens,
         map { $_.'_rate', $_.'_description' } split / /, $form->{taxaccounts} ];  # deleted: discount
 
@@ -484,42 +433,48 @@ sub form_header {
      is_pur_ord      => scalar ($form->{type} =~ /purchase_order$/),
   );
 
-  print $form->parse_html_template("oe/orders_header", { %TMPL_VAR });
+  print $form->parse_html_template("oe/form_header", { %TMPL_VAR });
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub form_footer {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+
+  check_oe_access();
 
   $form->{invtotal} = $form->{invsubtotal};
 
-  $rows    = max 2, $form->numtextrows($form->{notes}, 25, 8);
-  $introws = max 2, $form->numtextrows($form->{intnotes}, 35, 8);
+  my $rows    = max 2, $form->numtextrows($form->{notes}, 25, 8);
+  my $introws = max 2, $form->numtextrows($form->{intnotes}, 35, 8);
   $rows    = max $rows, $introws;
 
-  $TMPL_VAR{notes} = qq|<textarea name=notes rows=$rows cols=25 wrap=soft>$form->{notes}</textarea>|;
-  $TMPL_VAR{intnotes} = qq|<textarea name=intnotes rows=$rows cols=35 wrap=soft>$form->{intnotes}</textarea>|;
+  $TMPL_VAR{notes}    = qq|<textarea name=notes rows=$rows cols=25 wrap=soft>| . H($form->{notes}) . qq|</textarea>|;
+  $TMPL_VAR{intnotes} = qq|<textarea name=intnotes rows=$introws cols=35 wrap=soft>| . H($form->{intnotes}) . qq|</textarea>|;
 
   if (!$form->{taxincluded}) {
 
-    foreach $item (split / /, $form->{taxaccounts}) {
+    foreach my $item (split / /, $form->{taxaccounts}) {
       if ($form->{"${item}_base"}) {
         $form->{invtotal} += $form->{"${item}_total"} = $form->round_amount( $form->{"${item}_base"} * $form->{"${item}_rate"}, 2);
         $form->{"${item}_total"} = $form->format_amount(\%myconfig, $form->{"${item}_total"}, 2);
 
         $TMPL_VAR{tax} .= qq|
-             <tr>
-               <th align=right>$form->{"${item}_description"}&nbsp;| . $form->{"${item}_rate"} * 100 .qq|%</th>
-               <td align=right>$form->{"${item}_total"}</td>
-             </tr> |;
+              <tr>
+                <th align=right>$form->{"${item}_description"}&nbsp;| . $form->{"${item}_rate"} * 100 .qq|%</th>
+                <td align=right>$form->{"${item}_total"}</td>
+              </tr> |;
       }
     }
 
-    $form->{invsubtotal} = $form->format_amount(\%myconfig, $form->{invsubtotal}, 2, 0);
+#    $form->{invsubtotal} = $form->format_amount(\%myconfig, $form->{invsubtotal}, 2, 0); # template does this
 
   } else {
-    foreach $item (split / /, $form->{taxaccounts}) {
+    foreach my $item (split / /, $form->{taxaccounts}) {
       if ($form->{"${item}_base"}) {
         $form->{"${item}_total"} = $form->round_amount( ($form->{"${item}_base"} * $form->{"${item}_rate"} / (1 + $form->{"${item}_rate"})), 2);
         $form->{"${item}_netto"} = $form->round_amount( ($form->{"${item}_base"} - $form->{"${item}_total"}), 2);
@@ -527,64 +482,73 @@ sub form_footer {
         $form->{"${item}_netto"} = $form->format_amount(\%myconfig, $form->{"${item}_netto"}, 2);
 
         $TMPL_VAR{tax} .= qq|
-             <tr>
-               <th align=right>Enthaltene $form->{"${item}_description"}&nbsp;| . $form->{"${item}_rate"} * 100 .qq|%</th>
-               <td align=right>$form->{"${item}_total"}</td>
-             </tr>
-             <tr>
-               <th align=right>Nettobetrag</th>
-               <td align=right>$form->{"${item}_netto"}</td>
-             </tr> |;
+              <tr>
+                <th align=right>Enthaltene $form->{"${item}_description"}&nbsp;| . $form->{"${item}_rate"} * 100 .qq|%</th>
+                <td align=right>$form->{"${item}_total"}</td>
+              </tr>
+              <tr>
+                <th align=right>Nettobetrag</th>
+                <td align=right>$form->{"${item}_netto"}</td>
+              </tr> |;
       }
     }
   }
 
   $form->{oldinvtotal} = $form->{invtotal};
 
-  print $form->parse_html_template("oe/orders_footer", {
+  print $form->parse_html_template("oe/form_footer", {
      %TMPL_VAR,
-     webdav          => $webdav,
+     webdav          => $::lx_office_conf{system}->{webdav},
      print_options   => print_options(inline => 1),
      label_edit      => $locale->text("Edit the $form->{type}"),
      label_workflow  => $locale->text("Workflow $form->{type}"),
+     is_sales        => scalar ($form->{type} =~ /^sales_/),              # these vars are exported, so that the template
+     is_order        => scalar ($form->{type} =~ /_order$/),              # may determine what to show
+     is_sales_quo    => scalar ($form->{type} =~ /sales_quotation$/),
+     is_req_quo      => scalar ($form->{type} =~ /request_quotation$/),
+     is_sales_ord    => scalar ($form->{type} =~ /sales_order$/),
+     is_pur_ord      => scalar ($form->{type} =~ /purchase_order$/),
   });
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub update {
-  $lxdebug->enter_sub();
-  
+  $main::lxdebug->enter_sub();
+
   my ($recursive_call) = shift;
 
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  check_oe_access();
+
+#  $main::lxdebug->message(0, Dumper($form));
+
   set_headings($form->{"id"} ? "edit" : "add");
 
-  map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) } qw(exchangerate creditlimit creditremaining) unless $recursive_call;
+  map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) } qw(exchangerate) unless $recursive_call;
   $form->{update} = 1;
-      
-  $payment_id = $form->{payment_id} if $form->{payment_id};
-  
+
   &check_name($form->{vc});
-  
-  $form->{payment_id} = $payment_id if $form->{payment_id} eq "";
-  
-  $buysell              = 'buy';
+
+  my $buysell           = 'buy';
   $buysell              = 'sell' if ($form->{vc} eq 'vendor');
-  $form->{exchangerate} = $exchangerate if 
-    $form->{forex} = $exchangerate = $form->check_exchangerate(\%myconfig, $form->{currency}, $form->{transdate}, $buysell);
+  $form->{forex}        = $form->check_exchangerate(\%myconfig, $form->{currency}, $form->{transdate}, $buysell);
+  $form->{exchangerate} = $form->{forex} if $form->{forex};
 
-  $exchangerate = $form->{exchangerate} || 1;
+  my $exchangerate = $form->{exchangerate} || 1;
 
 ##################### process items ######################################
   # for pricegroups
-  $i = $form->{rowcount};
+  my $i = $form->{rowcount};
   if (   ($form->{"partnumber_$i"} eq "")
       && ($form->{"description_$i"} eq "")
       && ($form->{"partsgroup_$i"}  eq "")) {
 
     $form->{creditremaining} += ($form->{oldinvtotal} - $form->{oldtotalpaid});
-    &check_form;
 
+    &check_form;
   } else {
 
     if ($form->{type} =~ /^sales/) {
@@ -595,28 +559,43 @@ sub update {
 
     my $rows = scalar @{ $form->{item_list} };
 
-    $form->{"discount_$i"} = $form->format_amount(\%myconfig, $form->{discount} * 100);
+    # hier ist das problem fuer bug 817 $form->{discount} wird nicht durchgeschliffen
+    # ferner fallunterscheidung fuer verkauf oder einkauf s.a. bug 736 jb 04.05.2009
+    # select discount as vendor_discount from vendor ||
+    # select discount as customer_discount from customer
+    $form->{"discount_$i"} = $form->format_amount(\%myconfig, $form->{"$form->{vc}_discount"} * 100);
+
+    $form->{"lastcost_$i"} = $form->parse_amount(\%myconfig, $form->{"lastcost_$i"});
 
     if ($rows) {
-      $form->{"qty_$i"} = 1 unless ($form->{"qty_$i"});
+      $form->{"qty_$i"} = 1 unless ($form->parse_amount(\%myconfig, $form->{"qty_$i"}));
 
       if ($rows > 1) {
 
         &select_item;
-        exit;
+        ::end_of_request();
 
       } else {
 
-        $sellprice             = $form->parse_amount(\%myconfig, $form->{"sellprice_$i"});
-        $form->{"discount_$i"} = 0 if $form->{"not_discountable_$i"};
+        my $sellprice             = $form->parse_amount(\%myconfig, $form->{"sellprice_$i"});
+        # hier werden parts (Artikeleigenschaften) aus item_list (retrieve_item aus IS.pm)
+        # (item wahrscheinlich synonym für parts) entsprechend in die form geschrieben ...
+
+        # Wäre dieses Mapping nicht besser in retrieve_items aufgehoben?
+        #(Eine Funktion bekommt Daten -> ARBEIT -> Rückgabe DATEN)
+        #  Das quot sieht doch auch nach Überarbeitung aus ... (hmm retrieve_items gibt es in IS und IR)
         map { $form->{item_list}[$i]{$_} =~ s/\"/&quot;/g }    qw(partnumber description unit);
         map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} } keys %{ $form->{item_list}[0] };
+
+        # ... deswegen muss die prüfung, ob es sich um einen nicht rabattierfähigen artikel handelt später erfolgen (Bug 1136)
+        $form->{"discount_$i"} = 0 if $form->{"not_discountable_$i"};
         $form->{payment_id} = $form->{"part_payment_id_$i"} if $form->{"part_payment_id_$i"} ne "";
 
         $form->{"marge_price_factor_$i"} = $form->{item_list}->[0]->{price_factor};
 
         ($sellprice || $form->{"sellprice_$i"}) =~ /\.(\d+)/;
-        $decimalplaces = max 2, length $1;
+        my $dec_qty       = length $1;
+        my $decimalplaces = max 2, $dec_qty;
 
         if ($sellprice) {
           $form->{"sellprice_$i"} = $sellprice;
@@ -625,7 +604,7 @@ sub update {
           $form->{"sellprice_$i"} /= $exchangerate;   # if there is an exchange rate adjust sellprice
         }
 
-        $amount = $form->{"sellprice_$i"} * $form->{"qty_$i"} * (1 - $form->{"discount_$i"} / 100);
+        my $amount = $form->{"sellprice_$i"} * $form->{"qty_$i"} * (1 - $form->{"discount_$i"} / 100);
         map { $form->{"${_}_base"} = 0 }                                 split / /, $form->{taxaccounts};
         map { $form->{"${_}_base"} += $amount }                          split / /, $form->{"taxaccounts_$i"};
         map { $amount += ($form->{"${_}_base"} * $form->{"${_}_rate"}) } split / /, $form->{taxaccounts} if !$form->{taxincluded};
@@ -633,6 +612,7 @@ sub update {
         $form->{creditremaining} -= $amount;
 
         $form->{"sellprice_$i"} = $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
+        $form->{"lastcost_$i"}  = $form->format_amount(\%myconfig, $form->{"lastcost_$i"}, $decimalplaces);
         $form->{"qty_$i"}       = $form->format_amount(\%myconfig, $form->{"qty_$i"}, $dec_qty);
 
         # get pricegroups for parts
@@ -664,274 +644,78 @@ sub update {
 ##################### process items ######################################
 
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub search {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
-  if ($form->{type} eq 'purchase_order') {
-    $form->{title} = $locale->text('Purchase Orders');
-    $form->{vc}    = 'vendor';
-    $ordlabel      = $locale->text('Order Number');
-    $ordnumber     = 'ordnumber';
-    $employee      = $locale->text('Employee');
-  }
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
-  if ($form->{type} eq 'request_quotation') {
-    $form->{title} = $locale->text('Request for Quotations');
-    $form->{vc}    = 'vendor';
-    $ordlabel      = $locale->text('RFQ Number');
-    $ordnumber     = 'quonumber';
-    $employee      = $locale->text('Employee');
-  }
+  check_oe_access();
 
-  if ($form->{type} eq 'sales_order') {
-    $form->{title} = $locale->text('Sales Orders');
-    $form->{vc}    = 'customer';
-    $ordlabel      = $locale->text('Order Number');
-    $ordnumber     = 'ordnumber';
-    $employee      = $locale->text('Employee');
-  }
-
-  if ($form->{type} eq 'sales_quotation') {
-    $form->{title} = $locale->text('Quotations');
-    $form->{vc}    = 'customer';
-    $ordlabel      = $locale->text('Quotation Number');
-    $ordnumber     = 'quonumber';
-    $employee      = $locale->text('Employee');
-  }
-
-  # setup vendor / customer selection
-  $form->all_vc(\%myconfig, $form->{vc},
-                ($form->{vc} eq 'customer') ? "AR" : "AP");
-
-  # departments
-  if (@{ $form->{all_departments} }) {
-    $form->{selectdepartment} = "<option>\n";
-
-    map {
-      $form->{selectdepartment} .=
-        "<option>$_->{description}--$_->{id}</option>\n"
-    } (@{ $form->{all_departments} });
-  }
+  if ($form->{type} eq 'purchase_order') {
+    $form->{vc}        = 'vendor';
+    $form->{ordnrname} = 'ordnumber';
+    $form->{title}     = $locale->text('Purchase Orders');
+    $form->{ordlabel}  = $locale->text('Order Number');
+
+  } elsif ($form->{type} eq 'request_quotation') {
+    $form->{vc}        = 'vendor';
+    $form->{ordnrname} = 'quonumber';
+    $form->{title}     = $locale->text('Request for Quotations');
+    $form->{ordlabel}  = $locale->text('RFQ Number');
+
+  } elsif ($form->{type} eq 'sales_order') {
+    $form->{vc}        = 'customer';
+    $form->{ordnrname} = 'ordnumber';
+    $form->{title}     = $locale->text('Sales Orders');
+    $form->{ordlabel}  = $locale->text('Order Number');
+
+  } elsif ($form->{type} eq 'sales_quotation') {
+    $form->{vc}        = 'customer';
+    $form->{ordnrname} = 'quonumber';
+    $form->{title}     = $locale->text('Quotations');
+    $form->{ordlabel}  = $locale->text('Quotation Number');
 
-  $department = qq|
-        <tr>
-         <th align=right nowrap>| . $locale->text('Department') . qq|</th>
-         <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
-       </tr>
-| if $form->{selectdepartment};
-
-  my $delivered;
-  if (($form->{"type"} eq "sales_order") ||
-      ($form->{"type"} eq "purchase_order")) {
-    $delivered = qq|
-        <tr>
-          <td><input name="notdelivered" id="notdelivered" class="checkbox" type="checkbox" value="1" checked>
-            <label for="notdelivered">|. $locale->text('Not delivered') . qq|</label></td>
-          <td><input name="delivered" id="delivered" class="checkbox" type="checkbox" value="1" checked>
-            <label for="delivered">| . $locale->text('Delivered') . qq|</label></td>
-        </tr>
-|;
+  } else {
+    $form->show_generic_error($locale->text('oe.pl::search called with unknown type'), back_button => 1);
   }
 
-  # use JavaScript Calendar or not
-  $form->{jsscript} = 1;
-  $jsscript = "";
-
-  $button1 = qq|
-     <td><input name=transdatefrom id=transdatefrom size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\">
-     <input type=button name=transdatefrom id="trigger3" value=|
-    . $locale->text('button') . qq|></td>
-    |;
-  $button2 = qq|
-     <td><input name=transdateto id=transdateto size=11 title="$myconfig{dateformat}" onBlur=\"check_right_date_format(this)\">
-     <input type=button name=transdateto name=transdateto id="trigger4" value=|
-    . $locale->text('button') . qq|></td>
-   |;
-
-  #write Trigger
-  $jsscript =
-    Form->write_trigger(\%myconfig, "2", "transdatefrom", "BR", "trigger3",
-                        "transdateto", "BL", "trigger4");
-
-  my $vc = $form->{vc} eq "customer" ? "customers" : "vendors";
-
-  $form->get_lists("projects"  => { "key" => "ALL_PROJECTS",
-                                    "all" => 1 },
-                   "employees" => "ALL_EMPLOYEES",
-                   "salesmen"  => "ALL_SALESMEN",
-                   $vc         => "ALL_" . uc($vc)
-                  );
-
-  my %labels = ();
-  my @values = ("");
-  foreach my $item (@{ $form->{"ALL_PROJECTS"} }) {
-    push(@values, $item->{"id"});
-    $labels{$item->{"id"}} = $item->{"projectnumber"};
-  }
-  my $projectnumber =
-    NTI($cgi->popup_menu('-name' => 'project_id', '-values' => \@values,
-                         '-labels' => \%labels));
-
-  #employees
-  %labels = ();
-  @values = ("");
-  foreach my $item (@{ $form->{"ALL_EMPLOYEES"} }) {
-    push(@values, $item->{"id"});
-    $labels{$item->{"id"}} = $item->{"name"} ne "" ? $item->{"name"} : $item->{"login"};
-  }
-  
-  #salesmen
-  my %labels_salesmen = ();
-  my @values_salesmen = ('');
-  foreach my $item (@{ $form->{"ALL_SALESMEN"} }) {
-    push(@values_salesmen, $item->{"id"});
-    $labels_salesmen{$item->{"id"}} = $item->{"name"} ne "" ? $item->{"name"} : $item->{"login"};
-  }
-
-  my $employee_block = qq|
-    <tr>
-      <th align="right">| . $locale->text('Employee') . qq|</th>
-      <td>| .  NTI($cgi->popup_menu('-name'   => 'employee_id', '-values' => \@values, '-labels' => \%labels)) . qq|</td>
-    </tr>
-    <tr>
-      <th align="right">| . $locale->text('Salesman') . qq|</th>
-      <td>| .
-        NTI($cgi->popup_menu('-name'   => 'salesman_id',
-                             '-values' => \@values_salesmen,
-                             '-labels' => \%labels_salesmen)) . qq|
-      </td>
-    </tr>|;
-
-  %labels = ();
-  @values = ("");
-
-  foreach my $item (@{ $form->{($form->{vc} eq "customer" ? "ALL_CUSTOMERS" : "ALL_VENDORS")}}) {
-    push(@values, $item->{name}.qq|--|.$item->{"id"});
-    $labels{$item->{name}.qq|--|.$item->{"id"}} = $item->{"name"};
-  }
-
-  my $vc_label = $form->{vc} eq "customer" ? $locale->text('Customer') : $locale->text('Vendor');
-  $vc =
-    $myconfig{vclimit} <=  scalar(@values)
-    ? qq|<input type="text" value="| . H(($form->{"old$form->{vc}"} =~ /^(.*)\-\-.*$/)) . qq|" name="$form->{vc}">| 
-    : NTI($cgi->popup_menu('-name' => "$form->{vc}",
-                           '-default' => $form->{"old$form->{vc}"},
-                           '-onChange' => 'document.getElementById(\'update_button\').click();',
-                           '-values' => \@values,
-                           '-labels' => \%labels));
-  $form->header;
-
-  print qq|
-<body>
-
-<form method=post action=$form->{script}>
-
-<table width=100%>
-  <tr>
-    <th class=listtop>$form->{title}</th>
-  </tr>
-  <tr height="5"></tr>
-  <tr>
-    <td>
-      <table>
-        <tr>
-          <th align=right>$vc_label</th>
-          <td colspan=3>$vc</td>
-        </tr>
-$department
-        <tr>
-          <th align=right>$ordlabel</th>
-          <td colspan=3><input name="$ordnumber" size=20></td>
-        </tr>
-$employee_block
-        <tr>
-          <th align="right">| . $locale->text('Transaction description') . qq|</th>
-          <td colspan="3"><input name="transaction_description" size=20></td>
-        </tr>
-        <tr>
-          <th align="right">| . $locale->text("Project Number") . qq|</th>
-          <td colspan="3">$projectnumber</td>
-        </tr>
-        <tr>
-          <th align=right>| . $locale->text('From') . qq|</th> $button1
-          <th align=right>| . $locale->text('Bis') . qq|</th> $button2
-        </tr>
-        <input type=hidden name=sort value=transdate>
-        <tr>
-          <th align=right>| . $locale->text('Include in Report') . qq|</th>
-          <td colspan=5>
-           <table>
-        <tr>
-          <td><input type="checkbox" name="open" value="1" id="open" checked> <label for="open">| . $locale->text("Open") . qq|</td>
-          <td><input type="checkbox" name="closed" value="1" id="closed"> <label for="closed">| . $locale->text("Closed") . qq|</td>
-        </tr>
-        $delivered
-             <tr>
-               <td><input name="l_id" class=checkbox type=checkbox value=Y> | . $locale->text('ID') . qq|</td>
-               <td><input name="l_$ordnumber" class=checkbox type=checkbox value=Y checked> $ordlabel</td>
-               <td><input name="l_transdate" class=checkbox type=checkbox value=Y checked> | . $locale->text('Date') . qq|</td>
-               <td><input name="l_reqdate" class=checkbox type=checkbox value=Y checked> | . $locale->text('Required by') . qq|</td>
-             </tr>
-             <tr>
-               <td><input name="l_name" class=checkbox type=checkbox value=Y checked> $vc_label</td>
-               <td><input name="l_employee" class=checkbox type=checkbox value=Y checked> $employee</td>
-               
-               <td><input name="l_shipvia" class=checkbox type=checkbox value=Y> | . $locale->text('Ship via') . qq|</td>
-             </tr>
-             <tr>
-               <td><input name="l_netamount" class=checkbox type=checkbox value=Y> | . $locale->text('Amount') . qq|</td>
-               <td><input name="l_tax" class=checkbox type=checkbox value=Y> | . $locale->text('Tax') . qq|</td>
-               <td><input name="l_amount" class=checkbox type=checkbox value=Y checked> | . $locale->text('Total') . qq|</td>
-             </tr>
-             <tr>
-               <td><input name="l_marge_total" class=checkbox type=checkbox value=Y> | .             $locale->text('Ertrag') . qq|</td>
-               <td><input name="l_marge_percent" class=checkbox type=checkbox value=Y> | .             $locale->text('Ertrag prozentual') . qq|</td>
-             </tr>
-             <tr>
-          <td><input name="l_globalprojectnumber" class=checkbox type=checkbox value=Y> | . $locale->text('Project Number') . qq|</td>
-          <td><input name="l_transaction_description" class=checkbox type=checkbox value=Y> | . $locale->text('Transaction description') . qq|</td>
-             </tr>
-             <tr>
-               <td><input name="l_subtotal" class=checkbox type=checkbox value=Y> | . $locale->text('Subtotal') . qq|</td>
-                <td><input name="l_salesman" class="checkbox" type="checkbox" value="Y"> | . $locale->text('Salesman') . qq|</td>
-             </tr>
-           </table>
-          </td>
-        </tr>
-      </table>
-    </td>
-  </tr>
-  <tr><td colspan=4><hr size=3 noshade></td></tr>
-</table>
-
-$jsscript
-
-<br>
-<input type=hidden name=nextsub value=orders>
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
-<input type=hidden name=vc value=$form->{vc}>
-<input type=hidden name=type value=$form->{type}>
+  # setup vendor / customer data
+  $form->all_vc(\%myconfig, $form->{vc}, ($form->{vc} eq 'customer') ? "AR" : "AP");
+  $form->get_lists("projects"     => { "key" => "ALL_PROJECTS", "all" => 1 },
+                   "employees"    => "ALL_EMPLOYEES",
+                   "salesmen"     => "ALL_SALESMEN",
+                   "departments"  => "ALL_DEPARTMENTS",
+                   "$form->{vc}s" => "ALL_VC");
+
+  # constants and subs for template
+  $form->{jsscript}        = 1;
+  $form->{employee_labels} = sub { $_[0]->{"name"} || $_[0]->{"login"} };
+  $form->{vc_keys}         = sub { "$_[0]->{name}--$_[0]->{id}" };
+  $form->{salesman_labels} = $form->{employee_labels};
 
-<input class=submit type=submit name=action value="|
-    . $locale->text('Continue') . qq|">
-</form>
+  $form->header();
 
-</body>
-</html>
-|;
+  print $form->parse_html_template('oe/search', {
+    %myconfig,
+    is_order => $form->{type} =~ /_order/,
+  });
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub create_subtotal_row {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
   my ($totals, $columns, $column_alignment, $subtotal_columns, $class) = @_;
 
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
   my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } };
 
   map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } @{ $subtotal_columns };
@@ -940,19 +724,26 @@ sub create_subtotal_row {
 
   map { $totals->{$_} = 0 } @{ $subtotal_columns };
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
   return $row;
 }
 
 sub orders {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
-  $ordnumber = ($form->{type} =~ /_order$/) ? "ordnumber" : "quonumber";
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+  my $cgi      = $main::cgi;
 
-  ($form->{ $form->{vc} }, $form->{"${form->{vc}}_id"}) = split(/--/, $form->{ $form->{vc} });
+  check_oe_access();
 
-  $form->{sort} ||= 'transdate';
+  my $ordnumber = ($form->{type} =~ /_order$/) ? "ordnumber" : "quonumber";
+
+  ($form->{ $form->{vc} }, $form->{"$form->{vc}_id"}) = split(/--/, $form->{ $form->{vc} });
+
+  report_generator_set_default_sort('transdate', 1);
 
   OE->transactions(\%myconfig, \%$form);
 
@@ -967,7 +758,10 @@ sub orders {
     "salesman",
     "shipvia",                 "globalprojectnumber",
     "transaction_description", "open",
-    "delivered", "marge_total", "marge_percent"
+    "delivered",               "periodic_invoices",
+    "marge_total",             "marge_percent",
+    "vcnumber",                "ustid",
+    "country",
   );
 
   # only show checkboxes if gotten here via sales_order form.
@@ -976,8 +770,9 @@ sub orders {
     unshift @columns, "ids";
   }
 
-  $form->{l_open}      = $form->{l_closed} = "Y" if ($form->{open}      && $form->{closed});
-  $form->{l_delivered} = "Y"                     if ($form->{delivered} && $form->{notdelivered});
+  $form->{l_open}              = $form->{l_closed} = "Y" if ($form->{open}      && $form->{closed});
+  $form->{l_delivered}         = "Y"                     if ($form->{delivered} && $form->{notdelivered});
+  $form->{l_periodic_invoices} = "Y"                     if ($form->{periodic_invoices_active} && $form->{periodic_invoices_inactive});
 
   my $attachment_basename;
   if ($form->{vc} eq 'vendor') {
@@ -1003,14 +798,15 @@ sub orders {
 
   my @hidden_variables = map { "l_${_}" } @columns;
   push @hidden_variables, "l_subtotal", $form->{vc}, qw(l_closed l_notdelivered open closed delivered notdelivered ordnumber quonumber
-                                                        transaction_description transdatefrom transdateto type vc employee_id salesman_id);
+                                                        transaction_description transdatefrom transdateto type vc employee_id salesman_id
+                                                        reqdatefrom reqdateto projectnumber project_id periodic_invoices_active periodic_invoices_inactive);
 
   my $href = build_std_url('action=orders', grep { $form->{$_} } @hidden_variables);
 
   my %column_defs = (
     'ids'                     => { 'text' => '', },
     'transdate'               => { 'text' => $locale->text('Date'), },
-    'reqdate'                 => { 'text' => $locale->text('Required by'), },
+    'reqdate'                 => { 'text' => $form->{type} =~ /_order/ ? $locale->text('Required by') : $locale->text('Valid until') },
     'id'                      => { 'text' => $locale->text('ID'), },
     'ordnumber'               => { 'text' => $locale->text('Order'), },
     'quonumber'               => { 'text' => $form->{type} eq "request_quotation" ? $locale->text('RFQ') : $locale->text('Quotation'), },
@@ -1026,12 +822,17 @@ sub orders {
     'transaction_description' => { 'text' => $locale->text('Transaction description'), },
     'open'                    => { 'text' => $locale->text('Open'), },
     'delivered'               => { 'text' => $locale->text('Delivered'), },
-    'marge_total'                   => { 'text' => $locale->text('Ertrag'), },
-    'marge_percent'           => { 'text' => $locale->text('Ertrag prozentual'), }
+    'marge_total'             => { 'text' => $locale->text('Ertrag'), },
+    'marge_percent'           => { 'text' => $locale->text('Ertrag prozentual'), },
+    'vcnumber'                => { 'text' => $form->{vc} eq 'customer' ? $locale->text('Customer Number') : $locale->text('Vendor Number'), },
+    'country'                 => { 'text' => $locale->text('Country'), },
+    'ustid'                   => { 'text' => $locale->text('USt-IdNr.'), },
+    'periodic_invoices'       => { 'text' => $locale->text('Per. Inv.'), },
   );
 
-  foreach my $name (qw(id transdate reqdate quonumber ordnumber name employee salesman shipvia)) {
-    $column_defs{$name}->{link} = $href . "&sort=$name";
+  foreach my $name (qw(id transdate reqdate quonumber ordnumber name employee salesman shipvia transaction_description)) {
+    my $sortdir                 = $form->{sort} eq $name ? 1 - $form->{sortdir} : $form->{sortdir};
+    $column_defs{$name}->{link} = $href . "&sort=$name&sortdir=$sortdir";
   }
 
   my %column_alignment = map { $_ => 'right' } qw(netamount tax amount curr);
@@ -1042,49 +843,33 @@ sub orders {
 
   $report->set_columns(%column_defs);
   $report->set_column_order(@columns);
-
-  $report->set_export_options('orders', @hidden_variables);
-
-  $report->set_sort_indicator($form->{sort}, 1);
+  $report->set_export_options('orders', @hidden_variables, qw(sort sortdir));
+  $report->set_sort_indicator($form->{sort}, $form->{sortdir});
 
   my @options;
-  if ($form->{customer}) {
-    push @options, $locale->text('Customer') . " : $form->{customer}";
-  }
-  if ($form->{vendor}) {
-    push @options, $locale->text('Vendor') . " : $form->{vendor}";
-  }
-  if ($form->{department}) {
-    ($department) = split /--/, $form->{department};
-    push @options, $locale->text('Department') . " : $department";
-  }
-  if ($form->{ordnumber}) {
-    push @options, $locale->text('Order Number') . " : $form->{ordnumber}";
-  }
-  if ($form->{notes}) {
-    push @options, $locale->text('Notes') . " : $form->{notes}";
-  }
-  if ($form->{transaction_description}) {
-    push @options, $locale->text('Transaction description') . " : $form->{transaction_description}";
-  }
-  if ($form->{transdatefrom}) {
-    push @options, $locale->text('From') . "&nbsp;" . $locale->date(\%myconfig, $form->{transdatefrom}, 1);
-  }
-  if ($form->{transdateto}) {
-    push @options, $locale->text('Bis') . "&nbsp;" . $locale->date(\%myconfig, $form->{transdateto}, 1);
-  }
-  if ($form->{open}) {
-    push @options, $locale->text('Open');
-  }
-  if ($form->{closed}) {
-    push @options, $locale->text('Closed');
-  }
-  if ($form->{delivered}) {
-    push @options, $locale->text('Delivered');
-  }
-  if ($form->{notdelivered}) {
-    push @options, $locale->text('Not delivered');
-  }
+  my ($department) = split m/--/, $form->{department};
+
+  push @options, $locale->text('Customer')                . " : $form->{customer}"                        if $form->{customer};
+  push @options, $locale->text('Vendor')                  . " : $form->{vendor}"                          if $form->{vendor};
+  push @options, $locale->text('Department')              . " : $department"                              if $form->{department};
+  push @options, $locale->text('Order Number')            . " : $form->{ordnumber}"                       if $form->{ordnumber};
+  push @options, $locale->text('Notes')                   . " : $form->{notes}"                           if $form->{notes};
+  push @options, $locale->text('Transaction description') . " : $form->{transaction_description}"         if $form->{transaction_description};
+  if ( $form->{transdatefrom} or $form->{transdateto} ) {
+    push @options, $locale->text('Order Date');
+    push @options, $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1)     if $form->{transdatefrom};
+    push @options, $locale->text('Bis')  . " " . $locale->date(\%myconfig, $form->{transdateto},   1)     if $form->{transdateto};
+  };
+  if ( $form->{reqdatefrom} or $form->{reqdateto} ) {
+    push @options, $locale->text('Delivery Date');
+    push @options, $locale->text('From') . " " . $locale->date(\%myconfig, $form->{reqdatefrom}, 1)       if $form->{reqdatefrom};
+    push @options, $locale->text('Bis')  . " " . $locale->date(\%myconfig, $form->{reqdateto},   1)       if $form->{reqdateto};
+  };
+  push @options, $locale->text('Open')                                                                    if $form->{open};
+  push @options, $locale->text('Closed')                                                                  if $form->{closed};
+  push @options, $locale->text('Delivered')                                                               if $form->{delivered};
+  push @options, $locale->text('Not delivered')                                                           if $form->{notdelivered};
+  push @options, $locale->text('Periodic invoices active')                                                if $form->{periodic_invoices_actibe};
 
   $report->set_options('top_info_text'        => join("\n", @options),
                        'raw_top_info_text'    => $form->parse_html_template('oe/orders_top'),
@@ -1094,12 +879,13 @@ sub orders {
                        'attachment_basename'  => $attachment_basename . strftime('_%Y%m%d', localtime time),
     );
   $report->set_options_from_form();
+  $locale->set_numberformat_wo_thousands_separator(\%myconfig) if lc($report->{options}->{output_format}) eq 'csv';
 
   # add sort and escape callback, this one we use for the add sub
   $form->{callback} = $href .= "&sort=$form->{sort}";
 
   # escape callback for href
-  $callback = $form->escape($href);
+  my $callback = $form->escape($href);
 
   my @subtotal_columns = qw(netamount amount marge_total marge_percent);
 
@@ -1110,12 +896,13 @@ sub orders {
 
   my $edit_url = build_std_url('action=edit', 'type', 'vc');
 
-  foreach $oe (@{ $form->{OE} }) {
+  foreach my $oe (@{ $form->{OE} }) {
     map { $oe->{$_} *= $oe->{exchangerate} } @subtotal_columns;
 
-    $oe->{tax}       = $oe->{amount} - $oe->{netamount};
-    $oe->{open}      = $oe->{closed}    ? $locale->text('No')  : $locale->text('Yes');
-    $oe->{delivered} = $oe->{delivered} ? $locale->text('Yes') : $locale->text('No');
+    $oe->{tax}               = $oe->{amount} - $oe->{netamount};
+    $oe->{open}              = $oe->{closed}            ? $locale->text('No')  : $locale->text('Yes');
+    $oe->{delivered}         = $oe->{delivered}         ? $locale->text('Yes') : $locale->text('No');
+    $oe->{periodic_invoices} = $oe->{periodic_invoices} ? $locale->text('On')  : $locale->text('Off');
 
     map { $subtotals{$_} += $oe->{$_};
           $totals{$_}    += $oe->{$_} } @subtotal_columns;
@@ -1162,14 +949,19 @@ sub orders {
 
   $report->generate_with_headers();
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub check_delivered_flag {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  check_oe_access();
 
   if (($form->{type} ne 'sales_order') && ($form->{type} ne 'purchase_order')) {
-    return $lxdebug->leave_sub();
+    return $main::lxdebug->leave_sub();
   }
 
   my $all_delivered = 0;
@@ -1188,11 +980,17 @@ sub check_delivered_flag {
 
   $form->{delivered} = 1 if $all_delivered;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub save_and_close {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+
+  check_oe_access();
 
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
@@ -1206,7 +1004,7 @@ sub save_and_close {
   $form->{$idx} =~ s/^\s*//g;
   $form->{$idx} =~ s/\s*$//g;
 
-  $msg = ucfirst $form->{vc};
+  my $msg = ucfirst $form->{vc};
   $form->isblank($form->{vc}, $locale->text($msg . " missing!"));
 
   # $locale->text('Customer missing!');
@@ -1216,22 +1014,24 @@ sub save_and_close {
     if ($form->{currency} ne $form->{defaultcurrency});
 
   &validate_items;
-  
-  if($form->{payment_id}) { 
+
+  my $payment_id;
+  if($form->{payment_id}) {
     $payment_id = $form->{payment_id};
   }
-  
+
   # if the name changed get new values
   if (&check_name($form->{vc})) {
-    if($form->{payment_id} eq "") { 
+    if($form->{payment_id} eq "") {
       $form->{payment_id} = $payment_id;
     }
     &update;
-    exit;
+    ::end_of_request();
   }
 
   $form->{id} = 0 if $form->{saveasnew};
 
+  my ($numberfld, $ordnumber, $err);
   # this is for the internal notes section for the [email] Subject
   if ($form->{type} =~ /_order$/) {
     if ($form->{type} eq 'sales_order') {
@@ -1279,19 +1079,25 @@ sub save_and_close {
   # saving the history
   if(!exists $form->{addition}) {
     $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
-       $form->{addition} = "SAVED";
-       $form->save_history($form->dbconnect(\%myconfig));
+    $form->{addition} = "SAVED";
+    $form->save_history;
   }
   # /saving the history
 
   $form->redirect($form->{label} . " $form->{$ordnumber} " .
                   $locale->text('saved!'));
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub save {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+
+  check_oe_access();
 
   $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
@@ -1306,7 +1112,7 @@ sub save {
   $form->{$idx} =~ s/^\s*//g;
   $form->{$idx} =~ s/\s*$//g;
 
-  $msg = ucfirst $form->{vc};
+  my $msg = ucfirst $form->{vc};
   $form->isblank($form->{vc}, $locale->text($msg . " missing!"));
 
   # $locale->text('Customer missing!');
@@ -1315,23 +1121,27 @@ sub save {
   $form->isblank("exchangerate", $locale->text('Exchangerate missing!'))
     if ($form->{currency} ne $form->{defaultcurrency});
 
+  remove_emptied_rows();
   &validate_items;
-  
-  if($form->{payment_id}) { 
+
+  my $payment_id;
+  if($form->{payment_id}) {
     $payment_id = $form->{payment_id};
   }
-  
+
   # if the name changed get new values
   if (&check_name($form->{vc})) {
-    if($form->{payment_id} eq "") { 
+    if($form->{payment_id} eq "") {
       $form->{payment_id} = $payment_id;
     }
     &update;
-    exit;
+    ::end_of_request();
   }
 
   $form->{id} = 0 if $form->{saveasnew};
 
+  my ($numberfld, $ordnumber, $err);
+
   # this is for the internal notes section for the [email] Subject
   if ($form->{type} =~ /_order$/) {
     if ($form->{type} eq 'sales_order') {
@@ -1377,25 +1187,31 @@ sub save {
   # saving the history
   if(!exists $form->{addition}) {
     $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
-       $form->{addition} = "SAVED";
-       $form->save_history($form->dbconnect(\%myconfig));
+    $form->{addition} = "SAVED";
+    $form->save_history;
   }
-  # /saving the history 
+  # /saving the history
 
   $form->{simple_save} = 1;
   if(!$form->{print_and_save}) {
-    set_headings("edit");
-    &update;
-    exit;
+    delete @{$form}{ary_diff([keys %{ $form }], [qw(login stylesheet id script type cursor_fokus)])};
+    edit();
+    ::end_of_request();
   }
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub delete {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my $locale   = $main::locale;
+
+  check_oe_access();
 
   $form->header;
 
+  my ($msg, $ordnumber);
   if ($form->{type} =~ /_order$/) {
     $msg       = $locale->text('Are you sure you want to delete Order Number');
     $ordnumber = 'ordnumber';
@@ -1413,7 +1229,8 @@ sub delete {
   # delete action variable
   map { delete $form->{$_} } qw(action header);
 
-  foreach $key (keys %$form) {
+  foreach my $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|;
   }
@@ -1434,12 +1251,19 @@ sub delete {
 </html>
 |;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub delete_order_quotation {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
+  check_oe_access();
+
+  my ($msg, $err);
   if ($form->{type} =~ /_order$/) {
     $msg = $locale->text('Order deleted!');
     $err = $locale->text('Cannot delete order!');
@@ -1447,27 +1271,35 @@ sub delete_order_quotation {
     $msg = $locale->text('Quotation deleted!');
     $err = $locale->text('Cannot delete quotation!');
   }
-  if (OE->delete(\%myconfig, \%$form, $spool)){
+  if (OE->delete(\%myconfig, \%$form)){
     # saving the history
     if(!exists $form->{addition}) {
       $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber};
-         $form->{addition} = "DELETED";
-         $form->save_history($form->dbconnect(\%myconfig));
+      $form->{addition} = "DELETED";
+      $form->save_history;
     }
-    # /saving the history 
+    # /saving the history
     $form->info($msg);
-    exit();
+    ::end_of_request();
   }
   $form->error($err);
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub invoice {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
+
+  check_oe_access();
+  $main::auth->assert($form->{type} eq 'purchase_order' || $form->{type} eq 'request_quotation' ? 'vendor_invoice_edit' : 'invoice_edit');
 
-  $form->{old_employee_id} = $form->{employee_id};
   $form->{old_salesman_id} = $form->{salesman_id};
+  $form->get_employee();
+
 
   if ($form->{type} =~ /_order$/) {
 
@@ -1487,24 +1319,25 @@ sub invoice {
     $form->{ordnumber}    = "";
     $form->{quodate}      = $form->{transdate};
   }
-  
-  $payment_id = $form->{payment_id} if $form->{payment_id};
-  
+
+  my $payment_id = $form->{payment_id} if $form->{payment_id};
+
   # if the name changed get new values
   if (&check_name($form->{vc})) {
     $form->{payment_id} = $payment_id if $form->{payment_id} eq "";
     &update;
-    exit;
+    ::end_of_request();
   }
 
   $form->{cp_id} *= 1;
 
-  for $i (1 .. $form->{rowcount}) {
+  for my $i (1 .. $form->{rowcount}) {
     for (qw(ship qty sellprice listprice basefactor)) {
       $form->{"${_}_${i}"} = $form->parse_amount(\%myconfig, $form->{"${_}_${i}"}) if $form->{"${_}_${i}"};
     }
   }
 
+  my ($buysell, $orddate, $exchangerate);
   if (   $form->{type} =~ /_order/
       && $form->{currency} ne $form->{defaultcurrency}) {
 
@@ -1516,37 +1349,25 @@ sub invoice {
 
     if (!$exchangerate) {
       &backorder_exchangerate($orddate, $buysell);
-      exit;
+      ::end_of_request();
     }
   }
 
-  # close orders/quotations
-  $form->{closed} = 1;
+  $form->{convert_from_oe_ids} = $form->{id};
+  $form->{transdate}           = $form->{invdate} = $form->current_date(\%myconfig);
+  $form->{duedate}             = $form->current_date(\%myconfig, $form->{invdate}, $form->{terms} * 1);
+  $form->{shipto}              = 1;
+  $form->{defaultcurrency}     = $form->get_default_currency(\%myconfig);
 
-  # save order if one ordnumber has been given
-  # if not it's most likely a collective order, which can't be saved back
-  # so they just have to be closed
-  if (($form->{ordnumber} ne '') || ($form->{quonumber} ne '')) {
-    OE->close_order(\%myconfig, \%$form) if ($form->{id});
-  } else {
-    OE->close_orders(\%myconfig, \%$form);
-  }
-
-  $form->{transdate} = $form->{invdate} = $form->current_date(\%myconfig);
-  $form->{duedate}   = $form->current_date(\%myconfig, $form->{invdate}, $form->{terms} * 1);
-
-  $form->{id}     = '';
-  $form->{closed} = 0;
+  delete @{$form}{qw(id closed)};
   $form->{rowcount}--;
-  $form->{shipto} = 1;
-
-  $form->{defaultcurrency} = $form->get_default_currency(\%myconfig);
 
   if ($form->{type} =~ /_order$/) {
     $form->{exchangerate} = $exchangerate;
     &create_backorder;
   }
 
+  my ($script);
   if (   $form->{type} eq 'purchase_order'
       || $form->{type} eq 'request_quotation') {
     $form->{title}  = $locale->text('Add Vendor Invoice');
@@ -1555,7 +1376,7 @@ sub invoice {
     $buysell        = 'sell';
   }
 
-  if (   $form->{type} eq 'sales_order' 
+  if (   $form->{type} eq 'sales_order'
       || $form->{type} eq 'sales_quotation') {
     $form->{title}  = $locale->text('Add Sales Invoice');
     $form->{script} = 'is.pl';
@@ -1569,41 +1390,32 @@ sub invoice {
   $form->{type} = "invoice";
 
   # locale messages
-  $locale = new Locale "$myconfig{countrycode}", "$script";
+  $main::locale = new Locale "$myconfig{countrycode}", "$script";
+  $locale = $main::locale;
 
   require "bin/mozilla/$form->{script}";
 
-  map { $form->{"select$_"} = "" } ($form->{vc}, currency);
-
-  map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
-    qw(creditlimit creditremaining);
+  map { $form->{"select$_"} = "" } ($form->{vc}, "currency");
 
-  $currency = $form->{currency};
+  my $currency = $form->{currency};
   &invoice_links;
 
   $form->{currency}     = $currency;
-  $form->{exchangerate} = "";
-  $form->{forex}        = "";
-  $form->{exchangerate} = $exchangerate
-    if (
-        $form->{forex} = (
-                    $exchangerate =
-                      $form->check_exchangerate(
-                      \%myconfig, $form->{currency}, $form->{invdate}, $buysell
-                      )));
+  $form->{forex}        = $form->check_exchangerate( \%myconfig, $form->{currency}, $form->{invdate}, $buysell);
+  $form->{exchangerate} = $form->{forex} || '';
 
   $form->{creditremaining} -= ($form->{oldinvtotal} - $form->{ordtotal});
 
   &prepare_invoice;
 
   # format amounts
-  for $i (1 .. $form->{rowcount}) {
+  for my $i (1 .. $form->{rowcount}) {
     $form->{"discount_$i"} =
       $form->format_amount(\%myconfig, $form->{"discount_$i"});
 
-    ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
+    my ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
     $dec           = length $dec;
-    $decimalplaces = ($dec > 2) ? $dec : 2;
+    my $decimalplaces = ($dec > 2) ? $dec : 2;
 
     # copy delivery date from reqdate for order -> invoice conversion
     $form->{"deliverydate_$i"} = $form->{"reqdate_$i"}
@@ -1623,13 +1435,23 @@ sub invoice {
 
   }
 
+  #  show pricegroup in newly loaded invoice when creating invoice from quotation/order
+  IS->get_pricegroups_for_parts(\%myconfig, \%$form);
+  set_pricegroup($_) for 1 .. $form->{rowcount};
+
   &display_form;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub backorder_exchangerate {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my $locale   = $main::locale;
+
+  check_oe_access();
+
   my ($orddate, $buysell) = @_;
 
   $form->header;
@@ -1643,7 +1465,8 @@ sub backorder_exchangerate {
   # delete action variable
   map { delete $form->{$_} } qw(action header exchangerate);
 
-  foreach $key (keys %$form) {
+  foreach my $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|;
   }
@@ -1652,9 +1475,6 @@ sub backorder_exchangerate {
 
   print qq|
 
-<input type=hidden name=login value=$form->{login}>
-<input type=hidden name=password value=$form->{password}>
-
 <input type=hidden name=exchangeratedate value=$orddate>
 <input type=hidden name=buysell value=$buysell>
 
@@ -1665,16 +1485,16 @@ sub backorder_exchangerate {
     <td>
       <table>
         <tr>
-         <th align=right>| . $locale->text('Currency') . qq|</th>
-         <td>$form->{currency}</td>
-       </tr>
-       <tr>
-         <th align=right>| . $locale->text('Date') . qq|</th>
-         <td>$orddate</td>
-       </tr>
+          <th align=right>| . $locale->text('Currency') . qq|</th>
+          <td>$form->{currency}</td>
+        </tr>
+        <tr>
+          <th align=right>| . $locale->text('Date') . qq|</th>
+          <td>$orddate</td>
+        </tr>
         <tr>
-         <th align=right>| . $locale->text('Exchangerate') . qq|</th>
-         <td><input name=exchangerate size=11></td>
+          <th align=right>| . $locale->text('Exchangerate') . qq|</th>
+          <td><input name=exchangerate size=11></td>
         </tr>
       </table>
     </td>
@@ -1695,11 +1515,15 @@ sub backorder_exchangerate {
 </html>
 |;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub save_exchangerate {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+  my $locale   = $main::locale;
 
   $form->isblank("exchangerate", $locale->text('Exchangerate missing!'));
   $form->{exchangerate} =
@@ -1710,20 +1534,26 @@ sub save_exchangerate {
 
   &invoice;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub create_backorder {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
 
   $form->{shipped} = 1;
 
   # figure out if we need to create a backorder
   # items aren't saved if qty != 0
 
-  for $i (1 .. $form->{rowcount}) {
-    $totalqty  += $qty  = $form->{"qty_$i"};
-    $totalship += $ship = $form->{"ship_$i"};
+  my ($totalqty, $totalship);
+  for my $i (1 .. $form->{rowcount}) {
+    my $qty  = $form->{"qty_$i"};
+    my $ship = $form->{"ship_$i"};
+    $totalqty  += $qty;
+    $totalship += $ship;
 
     $form->{"qty_$i"} = $qty - $ship;
   }
@@ -1741,11 +1571,11 @@ sub create_backorder {
     return;
   }
 
-  @flds = (
+  my @flds = (
     qw(partnumber description qty ship unit sellprice discount id inventory_accno bin income_accno expense_accno listprice assembly taxaccounts partsgroup)
   );
 
-  for $i (1 .. $form->{rowcount}) {
+  for my $i (1 .. $form->{rowcount}) {
     map {
       $form->{"${_}_$i"} =
         $form->format_amount(\%myconfig, $form->{"${_}_$i"})
@@ -1757,15 +1587,15 @@ sub create_backorder {
   OE->save(\%myconfig, \%$form);
 
   # rebuild rows for invoice
-  @a     = ();
-  $count = 0;
+  my @a     = ();
+  my $count = 0;
 
-  for $i (1 .. $form->{rowcount}) {
+  for my $i (1 .. $form->{rowcount}) {
     $form->{"qty_$i"} = $form->{"ship_$i"};
 
     if ($form->{"qty_$i"}) {
       push @a, {};
-      $j = $#a;
+      my $j = $#a;
       map { $a[$j]->{$_} = $form->{"${_}_$i"} } @flds;
       $count++;
     }
@@ -1774,15 +1604,18 @@ sub create_backorder {
   $form->redo_rows(\@flds, \@a, $count, $form->{rowcount});
   $form->{rowcount} = $count;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub save_as_new {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+
+  check_oe_access();
 
   $form->{saveasnew} = 1;
-  $form->{closed}    = 0;
-  map { delete $form->{$_} } qw(printed emailed queued);
+  map { delete $form->{$_} } qw(printed emailed queued delivered closed);
 
   # Let Lx-Office assign a new order number if the user hasn't changed the
   # previous one. If it has been changed manually then use it as-is.
@@ -1794,38 +1627,62 @@ sub save_as_new {
     delete($form->{$idx});
   }
 
+  # clear reqdate unless changed
+  if ($form->{reqdate} && $form->{id}) {
+    my $saved_order = OE->retrieve_simple(id => $form->{id});
+    if ($saved_order && $saved_order->{reqdate} eq $form->{reqdate}) {
+      delete $form->{reqdate};
+    }
+  }
+
+  # update employee
+  $form->get_employee();
+
   &save;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub check_for_direct_delivery_yes {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+
+  check_oe_access();
 
   $form->{direct_delivery_checked} = 1;
   delete @{$form}{grep /^shipto/, keys %{ $form }};
   map { s/^CFDD_//; $form->{$_} = $form->{"CFDD_${_}"} } grep /^CFDD_/, keys %{ $form };
   $form->{shipto} = 1;
   purchase_order();
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub check_for_direct_delivery_no {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+
+  check_oe_access();
 
   $form->{direct_delivery_checked} = 1;
   delete @{$form}{grep /^shipto/, keys %{ $form }};
   purchase_order();
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub check_for_direct_delivery {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  check_oe_access();
 
   if ($form->{direct_delivery_checked}
       || (!$form->{shiptoname} && !$form->{shiptostreet} && !$form->{shipto_id})) {
-    $lxdebug->leave_sub();
+    $main::lxdebug->leave_sub();
     return;
   }
 
@@ -1837,28 +1694,31 @@ sub check_for_direct_delivery {
   }
 
   delete $form->{action};
-  $form->{VARIABLES} = [ map { { "key" => $_, "value" => $form->{$_} } } grep { ref $_ eq "" } keys %{ $form } ];
+  $form->{VARIABLES} = [ map { { "key" => $_, "value" => $form->{$_} } } grep { ($_ ne 'login') && ($_ ne 'password') && (ref $_ eq "") } keys %{ $form } ];
 
   $form->header();
   print $form->parse_html_template("oe/check_for_direct_delivery");
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 
-  exit 0;
+  ::end_of_request();
 }
 
 sub purchase_order {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my $locale   = $main::locale;
+
+  check_oe_access();
+  $main::auth->assert('purchase_order_edit');
 
+  $form->{sales_order_to_purchase_order} = 0;
   if ($form->{type} eq 'sales_order') {
+    $form->{sales_order_to_purchase_order} = 1;
     check_for_direct_delivery();
   }
 
-  if (   $form->{type} eq 'sales_quotation'
-      || $form->{type} eq 'request_quotation') {
-    OE->close_order(\%myconfig, \%$form);
-  }
-
   if ($form->{type} =~ /^sales_/) {
     delete($form->{ordnumber});
   }
@@ -1869,18 +1729,23 @@ sub purchase_order {
   $form->{vc}    = "vendor";
   $form->{type}  = "purchase_order";
 
+  $form->get_employee();
+
   &poso;
 
-  $lxdebug->leave_sub();
+  delete $form->{sales_order_to_purchase_order};
+
+  $main::lxdebug->leave_sub();
 }
 
 sub sales_order {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
-  if (   $form->{type} eq 'sales_quotation'
-      || $form->{type} eq 'request_quotation') {
-    OE->close_order(\%myconfig, $form);
-  }
+  my $form     = $main::form;
+  my $locale   = $main::locale;
+
+  check_oe_access();
+  $main::auth->assert('sales_order_edit');
 
   if ($form->{type} eq "purchase_order") {
     delete($form->{ordnumber});
@@ -1888,89 +1753,162 @@ sub sales_order {
 
   $form->{cp_id} *= 1;
 
-  $form->{title} = $locale->text('Add Sales Order');
-  $form->{vc}    = "customer";
-  $form->{type}  = "sales_order";
+  $form->{title}  = $locale->text('Add Sales Order');
+  $form->{vc}     = "customer";
+  $form->{type}   = "sales_order";
+
+  $form->get_employee();
 
   &poso;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub poso {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  check_oe_access();
+  $main::auth->assert('purchase_order_edit | sales_order_edit');
 
   $form->{transdate} = $form->current_date(\%myconfig);
   delete $form->{duedate};
 
-  $form->{closed} = 0;
+  $form->{convert_from_oe_ids} = $form->{id};
+  $form->{closed}              = 0;
 
-  $form->{old_employee_id} = $form->{employee_id};
-  $form->{old_salesman_id} = $form->{salesman_id};
+  $form->{old_employee_id}     = $form->{employee_id};
+  $form->{old_salesman_id}     = $form->{salesman_id};
 
   # reset
-  map { delete $form->{$_} }
-    qw(id subject message cc bcc printed emailed queued customer vendor creditlimit creditremaining discount tradediscount oldinvtotal);
+  map { delete $form->{$_} } qw(id subject message cc bcc printed emailed queued customer vendor creditlimit creditremaining discount tradediscount oldinvtotal delivered ordnumber);
+
+  # if purchase_order was generated from sales_order, use  lastcost_$i as sellprice_$i
+  if ( $form->{sales_order_to_purchase_order} ) {
+    for my $i (1 .. $form->{rowcount}) {
+      $form->{"sellprice_${i}"} = $form->format_amount(\%myconfig,$form->{"lastcost_${i}"});
+    };
+  };
 
-  for $i (1 .. $form->{rowcount}) {
-    map({ $form->{"${_}_${i}"} = $form->parse_amount(\%myconfig,
-                                                     $form->{"${_}_${i}"})
-            if ($form->{"${_}_${i}"}) }
-        qw(ship qty sellprice listprice basefactor));
+  for my $i (1 .. $form->{rowcount}) {
+    map { $form->{"${_}_${i}"} = $form->parse_amount(\%myconfig, $form->{"${_}_${i}"}) if ($form->{"${_}_${i}"}) } qw(ship qty sellprice listprice basefactor discount);
   }
 
+  my %saved_vars = map { $_ => $form->{$_} } grep { $form->{$_} } qw(currency);
+
   &order_links;
 
+  map { $form->{$_} = $saved_vars{$_} } keys %saved_vars;
+
+  # prepare_order assumes that the discount is in db-notation (0.05) and not user-notation (5)
+  # and therefore multiplies the values by 100 in the case of reading from db or making an order
+  # from several quotation, so we convert this back into percent-notation for the user interface by multiplying with 0.01
+  # ergänzung 03.10.2010 muss vor prepare_order passieren (s.a. Svens Kommentar zu Bug 1017)
+  # das parse_amount wird oben schon ausgeführt, deswegen an dieser stelle raus (wichtig: kommawerte bei discount testen)
+  for my $i (1 .. $form->{rowcount}) {
+    $form->{"discount_$i"} /=100;
+  };
+
   &prepare_order;
+  &update;
 
-  # format amounts
-  for $i (1 .. $form->{rowcount} - 1) {
-    map { $form->{"${_}_$i"} =~ s/\"/&quot;/g }
-      qw(partnumber description unit);
+  $main::lxdebug->leave_sub();
+}
+
+sub delivery_order {
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  if ($form->{type} =~ /^sales/) {
+    $main::auth->assert('sales_delivery_order_edit');
+
+    $form->{vc}    = 'customer';
+    $form->{type}  = 'sales_delivery_order';
+
+  } else {
+    $main::auth->assert('purchase_delivery_order_edit');
+
+    $form->{vc}    = 'vendor';
+    $form->{type}  = 'purchase_delivery_order';
   }
 
-  map { $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 0, "0") }
-    qw(creditlimit creditremaining);
+  $form->get_employee();
 
-  &update;
+  require "bin/mozilla/do.pl";
+
+  $form->{script}               = 'do.pl';
+  $form->{cp_id}               *= 1;
+  $form->{convert_from_oe_ids}  = $form->{id};
+  $form->{transdate}            = $form->current_date(\%myconfig);
+  delete $form->{duedate};
+
+  $form->{old_employee_id}  = $form->{employee_id};
+  $form->{old_salesman_id}  = $form->{salesman_id};
+
+  # reset
+  delete @{$form}{qw(id subject message cc bcc printed emailed queued creditlimit creditremaining discount tradediscount oldinvtotal closed delivered)};
+
+  for my $i (1 .. $form->{rowcount}) {
+    map { $form->{"${_}_${i}"} = $form->parse_amount(\%myconfig, $form->{"${_}_${i}"}) if ($form->{"${_}_${i}"}) } qw(ship qty sellprice listprice lastcost basefactor discount);
+  }
+
+  my %old_values = map { $_ => $form->{$_} } qw(customer_id oldcustomer customer vendor_id oldvendor vendor shipto_id);
+
+  order_links();
+
+  prepare_order();
+
+  map { $form->{$_} = $old_values{$_} if ($old_values{$_}) } keys %old_values;
 
-  $lxdebug->leave_sub();
+  update();
+
+  $main::lxdebug->leave_sub();
 }
 
 sub e_mail {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
 
-  $form->{print_and_save} = 1;
+  my $form     = $main::form;
+
+  check_oe_access();
 
-  $print_post = 1;
+  $form->{print_and_save} = 1;
 
   my $saved_form = save_form();
 
   save();
 
-  my %saved_vars;
-  map({ $saved_vars{$_} = $form->{$_}; } qw(id ordnumber quonumber));
-  restore_form($saved_form);
-  map({ $form->{$_} = $saved_vars{$_}; } qw(id ordnumber quonumber));
+  restore_form($saved_form, 0, qw(id ordnumber quonumber));
 
   edit_e_mail();
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
 sub yes {
-  call_sub($form->{yes_nextsub});
+  call_sub($main::form->{yes_nextsub});
 }
 
 sub no {
-  call_sub($form->{no_nextsub});
+  call_sub($main::form->{no_nextsub});
 }
 
 ######################################################################################################
 # IO ENTKOPPLUNG
 # ###############################################################################################
 sub display_form {
-  $lxdebug->enter_sub();
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %myconfig = %main::myconfig;
+
+  check_oe_access();
+
+  retrieve_partunits() if ($form->{type} =~ /_delivery_order$/);
 
   $form->{"taxaccounts"} =~ s/\s*$//;
   $form->{"taxaccounts"} =~ s/^\s*//;
@@ -1979,16 +1917,14 @@ sub display_form {
   }
   $form->{"taxaccounts"} = "";
 
-  for my $i (1 .. $form->{"rowcount"}) {
-    IC->retrieve_accounts(\%myconfig, $form, $form->{"id_$i"}, $i, 1) if $form->{"id_$i"};
-  }
+  IC->retrieve_accounts(\%myconfig, $form, map { $_ => $form->{"id_$_"} } 1 .. $form->{rowcount});
 
   $form->{rowcount}++;
   $form->{"project_id_$form->{rowcount}"} = $form->{globalproject_id};
 
   $form->language_payment(\%myconfig);
 
-  Common::webdav_folder($form) if ($webdav);
+  Common::webdav_folder($form);
 
   &form_header;
 
@@ -1997,215 +1933,101 @@ sub display_form {
 
   &form_footer;
 
-  $lxdebug->leave_sub();
+  $main::lxdebug->leave_sub();
 }
 
-sub display_row {
-  $lxdebug->enter_sub();
-  my $numrows = shift;
-
-  # 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 => '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 => 1, },
-    {  id => 'sellprice_pg',  width => 15,    value => $locale->text('Pricegroup'),           display => $form->{type} =~ /^sales_/,  },
-    {  id => 'discount',      width => 5,     value => $locale->text('Discount'),             display => $form->{vc} eq 'customer', },
-    {  id => 'linetotal',     width => 10,    value => $locale->text('Extended'),             display => 1, },
-    {  id => 'bin',           width => 10,    value => $locale->text('Bin'),                  display => 0, },
-  ); 
-  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 $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);
-
-  $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";
-
-    $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;
-
-    $discount  = $form->round_amount($form->{"sellprice_$i"} * $form->{"discount_$i"} / 100, $decimalplaces);
-    $linetotal = $form->round_amount($form->{"sellprice_$i"} - $discount, $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 => H($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"};
-
-    my @ROW1 = map { value => $column_data{$_}, align => $align{$_} }, @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;
-
-    $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"}) * 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}));
-    }
+sub report_for_todo_list {
+  $main::lxdebug->enter_sub();
 
-    my $marge_adjust_credit_note = $form->{type} eq 'credit_note' ? -1 : 1;
-    $form->{"marge_absolut_$i"}  = ($real_sellprice - $form->{"lastcost_$i"}) * $form->{"qty_$i"} * $marge_adjust_credit_note;
-    $form->{"marge_total"}      += $form->{"marge_absolut_$i"};
-    $form->{"lastcost_total"}   += $form->{"lastcost_$i"} * $form->{"qty_$i"};
-    $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_/;
-# / marge calculations ending
-
-    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 lastcost)
-    );
+  my $form     = $main::form;
 
-    map { $form->{"${_}_base"} += $linetotal } (split(/ /, $form->{"taxaccounts_$i"}));
+  my $quotations = OE->transactions_for_todo_list();
+  my $content;
 
-    $form->{invsubtotal} += $linetotal;
+  if (@{ $quotations }) {
+    my $edit_url = build_std_url('script=oe.pl', 'action=edit');
 
-    push @ROWS, { ROW1 => \@ROW1, ROW2 => \@ROW2, HIDDENS => \@HIDDENS, colspan => $colspan, };
+    $content     = $form->parse_html_template('oe/report_for_todo_list', { 'QUOTATIONS' => $quotations,
+                                                                           'edit_url'   => $edit_url });
   }
 
-  print $form->parse_html_template('oe/sales_order', { ROWS   => \@ROWS,
-                                                       HEADER => \@HEADER,
-                                                     });
+  $main::lxdebug->leave_sub();
+
+  return $content;
+}
+
+sub edit_periodic_invoices_config {
+  $::lxdebug->enter_sub();
+
+  $::form->{type} = 'sales_order';
+
+  check_oe_access();
 
-  if (0 != ($form->{sellprice_total} * 1)) {
-    $form->{marge_percent} = ($form->{sellprice_total} - $form->{lastcost_total}) / $form->{sellprice_total} * 100;
+  my $config;
+  $config = YAML::Load($::form->{periodic_invoices_config}) if $::form->{periodic_invoices_config};
+
+  if ('HASH' ne ref $config) {
+    $config =  { periodicity             => 'y',
+                 start_date_as_date      => $::form->{transdate},
+                 extend_automatically_by => 12,
+                 active                  => 1,
+               };
+  }
+
+  $config->{periodicity} = 'm' if none { $_ eq $config->{periodicity} } qw(m q y);
+
+  $::form->get_lists(printers => "ALL_PRINTERS",
+                     charts   => { key       => 'ALL_CHARTS',
+                                   transdate => 'current_date' });
+
+  $::form->{AR}    = [ grep { $_->{link} =~ m/(?:^|:)AR(?::|$)/ } @{ $::form->{ALL_CHARTS} } ];
+  $::form->{title} = $::locale->text('Edit the configuration for periodic invoices');
+
+  $::form->header();
+  print $::form->parse_html_template('oe/edit_periodic_invoices_config', $config);
+
+  $::lxdebug->leave_sub();
+}
+
+sub save_periodic_invoices_config {
+  $::lxdebug->enter_sub();
+
+  $::form->{type} = 'sales_order';
+
+  check_oe_access();
+
+  $::form->isblank('start_date_as_date', $::locale->text('The start date is missing.'));
+
+  my $config = { active                  => $::form->{active}     ? 1 : 0,
+                 terminated              => $::form->{terminated} ? 1 : 0,
+                 periodicity             => (any { $_ eq $::form->{periodicity} } qw(m q y)) ? $::form->{periodicity} : 'm',
+                 start_date_as_date      => $::form->{start_date_as_date},
+                 end_date_as_date        => $::form->{end_date_as_date},
+                 print                   => $::form->{print} ? 1 : 0,
+                 printer_id              => $::form->{print} ? $::form->{printer_id} * 1 : undef,
+                 copies                  => $::form->{copies} * 1 ? $::form->{copies} : 1,
+                 extend_automatically_by => $::form->{extend_automatically_by} * 1 || undef,
+                 ar_chart_id             => $::form->{ar_chart_id} * 1,
+               };
+
+  $::form->{periodic_invoices_config} = YAML::Dump($config);
+
+  $::form->{title} = $::locale->text('Edit the configuration for periodic invoices');
+  $::form->header;
+  print $::form->parse_html_template('oe/save_periodic_invoices_config', $config);
+
+  $::lxdebug->leave_sub();
+}
+
+sub dispatcher {
+  foreach my $action (qw(delete delivery_order e_mail invoice print purchase_order purchase_order quotation
+                         request_for_quotation sales_order sales_order save save_and_close save_as_new ship_to update)) {
+    if ($::form->{"action_${action}"}) {
+      $::form->{dispatched_action} = $action;
+      call_sub($action);
+      return;
+    }
   }
 
-  $lxdebug->leave_sub();
+  $::form->error($::locale->text('No action defined.'));
 }