Merge branch 'dpt_trans_entfernen'
[kivitendo-erp.git] / bin / mozilla / oe.pl
index 5b1bc51..f7f3375 100644 (file)
@@ -31,6 +31,8 @@
 # Quotation module
 #======================================================================
 
+
+use Carp;
 use POSIX qw(strftime);
 
 use SL::DO;
@@ -42,7 +44,7 @@ use SL::MoreCommon qw(ary_diff);
 use SL::PE;
 use SL::ReportGenerator;
 use List::MoreUtils qw(any none);
-use List::Util qw(max reduce sum);
+use List::Util qw(min max reduce sum);
 use Data::Dumper;
 
 require "bin/mozilla/io.pl";
@@ -153,6 +155,8 @@ sub edit {
 
   check_oe_access();
 
+  $form->{taxincluded_changed_by_user} = 1;
+
   # show history button
   $form->{javascript} = qq|<script type="text/javascript" src="js/show_history.js"></script>|;
   #/show hhistory button
@@ -181,7 +185,8 @@ sub edit {
 
   my ($language_id, $printer_id);
   if ($form->{print_and_save}) {
-    $form->{action}   = "print";
+    $form->{action}   = "dispatcher";
+    $form->{action_print}   = "1";
     $form->{resubmit} = 1;
     $language_id = $form->{language_id};
     $printer_id = $form->{printer_id};
@@ -238,14 +243,15 @@ sub order_links {
 
   $form->{"$form->{vc}_id"} ||= $form->{"all_$form->{vc}"}->[0]->{id} if $form->{"all_$form->{vc}"};
 
-  $form->backup_vars(qw(payment_id language_id taxzone_id salesman_id taxincluded cp_id intnotes shipto_id));
-  $form->{shipto} = 1 if $form->{id};
+  $form->backup_vars(qw(payment_id language_id taxzone_id salesman_id taxincluded cp_id intnotes shipto_id currency));
+  $form->{shipto} = 1 if $form->{id} || $form->{convert_from_oe_ids};
 
   # get customer / vendor
   IR->get_vendor(\%myconfig, \%$form)   if $form->{type} =~ /(purchase_order|request_quotation)/;
   IS->get_customer(\%myconfig, \%$form) if $form->{type} =~ /sales_(order|quotation)/;
 
   $form->restore_vars(qw(payment_id language_id taxzone_id intnotes cp_id shipto_id));
+  $form->restore_vars(qw(currency))    if $form->{id};
   $form->restore_vars(qw(taxincluded)) if $form->{id};
   $form->restore_vars(qw(salesman_id)) if $editing;
   $form->{forex}       = $form->{exchangerate};
@@ -297,7 +303,7 @@ sub form_header {
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
   my $locale   = $main::locale;
-  my $cgi      = $main::cgi;
+  my $cgi      = $::request->{cgi};
 
   check_oe_access();
 
@@ -316,7 +322,7 @@ sub form_header {
   # openclosed checkboxes
   my @tmp;
   push @tmp, sprintf qq|<input name="delivered" id="delivered" type="checkbox" class="checkbox" value="1" %s><label for="delivered">%s</label>|,
-                        $form->{"delivered"} ? "checked" : "",  $locale->text('Delivered') if $form->{"type"} =~ /_order$/;
+                        $form->{"delivered"} ? "checked" : "",  $locale->text('Delivery Order created') if $form->{"type"} =~ /_order$/;
   push @tmp, sprintf qq|<input name="closed" id="closed" type="checkbox" class="checkbox" value="1" %s><label for="closed">%s</label>|,
                         $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;
@@ -325,13 +331,9 @@ sub form_header {
   my @old_project_ids = ($form->{"globalproject_id"}, grep { $_ } map { $form->{"project_id_$_"} } 1..$form->{"rowcount"});
 
   my $vc = $form->{vc} eq "customer" ? "customers" : "vendors";
-  $form->get_lists("contacts"      => "ALL_CONTACTS",
-                   "shipto"        => "ALL_SHIPTO",
-                   "projects"      => { "key"      => "ALL_PROJECTS",
+  $form->get_lists("projects"      => { "key"      => "ALL_PROJECTS",
                                         "all"      => 0,
                                         "old_id"   => \@old_project_ids },
-                   "employees"     => "ALL_EMPLOYEES",
-                   "salesmen"      => "ALL_SALESMEN",
                    "taxzones"      => "ALL_TAXZONES",
                    "payments"      => "ALL_PAYMENTS",
                    "currencies"    => "ALL_CURRENCIES",
@@ -341,9 +343,22 @@ sub form_header {
                    "price_factors" => "ALL_PRICE_FACTORS");
 
   # label subs
+  my $employee_list_query_gen      = sub { $::form->{$_[0]} ? [ or => [ id => $::form->{$_[0]}, deleted => 0 ] ] : [ deleted => 0 ] };
+  $TMPL_VAR{ALL_EMPLOYEES}         = SL::DB::Manager::Employee->get_all(query => $employee_list_query_gen->('employee_id'));
+  $TMPL_VAR{ALL_SALESMEN}          = SL::DB::Manager::Employee->get_all(query => $employee_list_query_gen->('salesman_id'));
+  $TMPL_VAR{ALL_SHIPTO}            = SL::DB::Manager::Shipto->get_all(query => [
+    or => [ trans_id  => $::form->{"$::form->{vc}_id"} * 1, and => [ shipto_id => $::form->{shipto_id} * 1, trans_id => undef ] ]
+  ]);
+  $TMPL_VAR{ALL_CONTACTS}          = SL::DB::Manager::Contact->get_all(query => [
+    or => [
+      cp_cv_id => $::form->{"$::form->{vc}_id"} * 1,
+      and      => [
+        cp_cv_id => undef,
+        cp_id    => $::form->{cp_id} * 1
+      ]
+    ]
+  ]);
   $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
@@ -360,7 +375,9 @@ sub form_header {
   $form->{currency}            = $form->{defaultcurrency} unless $form->{currency};
   $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;
+                                                      '-values' => \@values, '-labels' => \%labels,
+                                                      '-onchange' => "document.getElementById('update_button').click();"
+                                     )) if scalar @values;
   push @custom_hiddens, "forex";
   push @custom_hiddens, "exchangerate" if $form->{forex};
 
@@ -388,11 +405,18 @@ sub form_header {
     }
   }
 
-  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')"
-          :                                                      "";
+  my $dispatch_to_popup = '';
+  if ($form->{resubmit} && ($form->{format} eq "html")) {
+      $dispatch_to_popup  = "window.open('about:blank','Beleg'); document.oe.target = 'Beleg';";
+      $dispatch_to_popup .= "document.do.submit();";
+  } elsif ($form->{resubmit}) {
+    # emulate click for resubmitting actions
+    $dispatch_to_popup  = "document.oe.${_}.click(); " for grep { /^action_/ } keys %$form;
+  } elsif ($creditwarning) {
+    $::request->{layout}->add_javascripts_inline("alert('$credittext');");
+  }
 
+  $::request->{layout}->add_javascripts_inline("\$(function(){$dispatch_to_popup})");
   $TMPL_VAR{dateformat}          = $myconfig{dateformat};
   $TMPL_VAR{numberformat}        = $myconfig{numberformat};
 
@@ -410,6 +434,8 @@ sub form_header {
   $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>|;
 
+  $::request->layout->use_stylesheet('presenter/record/record_list.css');
+
   $form->header;
 
   $TMPL_VAR{HIDDENS} = [ map { name => $_, value => $form->{$_} },
@@ -417,7 +443,7 @@ sub form_header {
         title creditlimit creditremaining tradediscount business
         max_dunning_level dunning_amount shiptoname shiptostreet shiptozipcode
         shiptocity shiptocountry shiptocontact shiptophone shiptofax
-        shiptodepartment_1 shiptodepartment_2 shiptoemail
+        shiptodepartment_1 shiptodepartment_2 shiptoemail shiptocp_gender
         message email subject cc bcc taxpart taxservice taxaccounts cursor_fokus),
         @custom_hiddens,
         map { $_.'_rate', $_.'_description' } split / /, $form->{taxaccounts} ];  # deleted: discount
@@ -452,8 +478,16 @@ sub form_footer {
   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>| . H($form->{notes}) . qq|</textarea>|;
-  $TMPL_VAR{intnotes} = qq|<textarea name=intnotes rows=$introws cols=35 wrap=soft>| . H($form->{intnotes}) . qq|</textarea>|;
+  $TMPL_VAR{notes}    = qq|<textarea name=notes rows="$rows" cols="25">| . H($form->{notes}) . qq|</textarea>|;
+  $TMPL_VAR{intnotes} = qq|<textarea name=intnotes rows="$introws" cols="35">| . H($form->{intnotes}) . qq|</textarea>|;
+
+  my $paymet_id = $::form->{payment_id};
+  IS->get_customer(\%myconfig, $::form) if $form->{type} =~ /sales_(order|quotation)/;
+  $::form->{payment_id} = $paymet_id;
+
+  if ( $form->{vc} eq 'customer' && !$form->{taxincluded_changed_by_user} ) {
+    $form->{taxincluded} = defined($form->{taxincluded_checked}) ? $form->{taxincluded_checked} : $myconfig{taxincluded_checked};
+  }
 
   if (!$form->{taxincluded}) {
 
@@ -522,15 +556,15 @@ sub update {
 
   check_oe_access();
 
-#  $main::lxdebug->message(0, Dumper($form));
-
   set_headings($form->{"id"} ? "edit" : "add");
 
-  map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) } qw(exchangerate) unless $recursive_call;
   $form->{update} = 1;
 
   &check_name($form->{vc});
 
+  if (!$form->{forex}) {        # read exchangerate from input field (not hidden)
+    map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) } qw(exchangerate) unless $recursive_call;
+  }
   my $buysell           = 'buy';
   $buysell              = 'sell' if ($form->{vc} eq 'vendor');
   $form->{forex}        = $form->check_exchangerate(\%myconfig, $form->{currency}, $form->{transdate}, $buysell);
@@ -550,10 +584,13 @@ sub update {
     &check_form;
   } else {
 
+    my $mode;
     if ($form->{type} =~ /^sales/) {
       IS->retrieve_item(\%myconfig, \%$form);
+      $mode = 'IS';
     } else {
       IR->retrieve_item(\%myconfig, \%$form);
+      $mode = 'IR';
     }
 
     my $rows = scalar @{ $form->{item_list} };
@@ -571,7 +608,7 @@ sub update {
 
       if ($rows > 1) {
 
-        &select_item;
+        select_item(mode => $mode);
         ::end_of_request();
 
       } else {
@@ -686,16 +723,13 @@ sub search {
   # 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");
+  $form->{ALL_EMPLOYEES} = SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]);
 
   # 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};
 
   $form->header();
 
@@ -734,7 +768,7 @@ sub orders {
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
   my $locale   = $main::locale;
-  my $cgi      = $main::cgi;
+  my $cgi      = $::request->{cgi};
 
   check_oe_access();
 
@@ -751,6 +785,7 @@ sub orders {
   my @columns = (
     "transdate",               "reqdate",
     "id",                      $ordnumber,
+    "customernumber",
     "name",                    "netamount",
     "tax",                     "amount",
     "curr",                    "employee",
@@ -810,6 +845,7 @@ sub orders {
     'ordnumber'               => { 'text' => $locale->text('Order'), },
     'quonumber'               => { 'text' => $form->{type} eq "request_quotation" ? $locale->text('RFQ') : $locale->text('Quotation'), },
     'name'                    => { 'text' => $form->{vc} eq 'customer' ? $locale->text('Customer') : $locale->text('Vendor'), },
+    'customernumber'          => { 'text' => $locale->text('Customer Number'), },
     'netamount'               => { 'text' => $locale->text('Amount'), },
     'tax'                     => { 'text' => $locale->text('Tax'), },
     'amount'                  => { 'text' => $locale->text('Total'), },
@@ -820,7 +856,7 @@ sub orders {
     'globalprojectnumber'     => { 'text' => $locale->text('Project Number'), },
     'transaction_description' => { 'text' => $locale->text('Transaction description'), },
     'open'                    => { 'text' => $locale->text('Open'), },
-    'delivered'               => { 'text' => $locale->text('Delivered'), },
+    'delivered'               => { 'text' => $locale->text('Delivery Order created'), },
     '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'), },
@@ -866,7 +902,7 @@ sub orders {
   };
   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('Delivery Order created')                                                               if $form->{delivered};
   push @options, $locale->text('Not delivered')                                                           if $form->{notdelivered};
   push @options, $locale->text('Periodic invoices active')                                                if $form->{periodic_invoices_actibe};
 
@@ -891,7 +927,7 @@ sub orders {
   my %totals    = map { $_ => 0 } @subtotal_columns;
   my %subtotals = map { $_ => 0 } @subtotal_columns;
 
-  my $idx = 0;
+  my $idx = 1;
 
   my $edit_url = build_std_url('action=edit', 'type', 'vc');
 
@@ -933,8 +969,8 @@ sub orders {
     my $row_set = [ $row ];
 
     if (($form->{l_subtotal} eq 'Y')
-        && (($idx == (scalar @{ $form->{OE} } - 1))
-            || ($oe->{ $form->{sort} } ne $form->{OE}->[$idx + 1]->{ $form->{sort} }))) {
+        && (($idx == (scalar @{ $form->{OE} }))
+            || ($oe->{ $form->{sort} } ne $form->{OE}->[$idx]->{ $form->{sort} }))) {
       push @{ $row_set }, create_subtotal_row(\%subtotals, \@columns, \%column_alignment, \@subtotal_columns, 'listsubtotal');
     }
 
@@ -1193,7 +1229,7 @@ sub save {
 
   $form->{simple_save} = 1;
   if(!$form->{print_and_save}) {
-    delete @{$form}{ary_diff([keys %{ $form }], [qw(login stylesheet id script type cursor_fokus)])};
+    delete @{$form}{ary_diff([keys %{ $form }], [qw(login id script type cursor_fokus)])};
     edit();
     ::end_of_request();
   }
@@ -1201,56 +1237,28 @@ sub save {
 }
 
 sub delete {
-  $main::lxdebug->enter_sub();
-
-  my $form     = $main::form;
-  my $locale   = $main::locale;
+  $::lxdebug->enter_sub;
 
   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';
-  } else {
-    $msg = $locale->text('Are you sure you want to delete Quotation Number');
-    $ordnumber = 'quonumber';
-  }
-
-  print qq|
-<body>
-
-<form method=post action=$form->{script}>
-|;
+  $::form->header;
 
   # delete action variable
-  map { delete $form->{$_} } qw(action header);
+  delete $::form->{$_} for qw(action header);
 
-  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|;
+  my @hiddens;
+  for my $key (keys %$::form) {
+    next if $key eq 'login' || $key eq 'password' || '' ne ref $::form->{$key};
+    push @hiddens, { key => $key, value => $::form->{$key} };
   }
 
-  print qq|
-<h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
-
-<h4>$msg $form->{$ordnumber}</h4>
-<p>
-<input type="hidden" name="yes_nextsub" value="delete_order_quotation">
-<input name=action class=submit type=submit value="|
-    . $locale->text('Yes') . qq|">
-<button class=submit type=button onclick="history.back()">|
-    . $locale->text('No') . qq|</button>
-</form>
+  print $::form->parse_html_template('oe/delete', {
+    hiddens => \@hiddens,
+    is_order => scalar($::form->{type} =~ /_order$/),
+  });
 
-</body>
-</html>
-|;
 
-  $main::lxdebug->leave_sub();
+  $::lxdebug->leave_sub;
 }
 
 sub delete_order_quotation {
@@ -1319,7 +1327,10 @@ sub invoice {
     $form->{quodate}      = $form->{transdate};
   }
 
-  my $payment_id = $form->{payment_id} 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})) {
@@ -1328,6 +1339,8 @@ sub invoice {
     ::end_of_request();
   }
 
+  _oe_remove_delivered_or_billed_rows(id => $form->{id}, type => 'billed');
+
   $form->{cp_id} *= 1;
 
   for my $i (1 .. $form->{rowcount}) {
@@ -1428,10 +1441,6 @@ sub invoice {
     $dec_qty = length $dec_qty;
     $form->{"qty_$i"} =
       $form->format_amount(\%myconfig, $form->{"qty_$i"}, $dec_qty);
-
-    map { $form->{"${_}_$i"} =~ s/\"/&quot;/g }
-      qw(partnumber description unit);
-
   }
 
   #  show pricegroup in newly loaded invoice when creating invoice from quotation/order
@@ -1456,8 +1465,6 @@ sub backorder_exchangerate {
   $form->header;
 
   print qq|
-<body>
-
 <form method=post action=$form->{script}>
 |;
 
@@ -1509,9 +1516,6 @@ sub backorder_exchangerate {
     . $locale->text('Continue') . qq|">
 
 </form>
-
-</body>
-</html>
 |;
 
   $main::lxdebug->leave_sub();
@@ -1616,7 +1620,7 @@ sub save_as_new {
   $form->{saveasnew} = 1;
   map { delete $form->{$_} } qw(printed emailed queued delivered closed);
 
-  # Let Lx-Office assign a new order number if the user hasn't changed the
+  # Let kivitendo 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.
   my $idx = $form->{type} =~ /_quotation$/ ? "quonumber" : "ordnumber";
   $form->{$idx} =~ s/^\s*//g;
@@ -1626,11 +1630,25 @@ sub save_as_new {
     delete($form->{$idx});
   }
 
-  # clear reqdate unless changed
-  if ($form->{reqdate} && $form->{id}) {
+  # clear reqdate and transdate 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};
+    if ( $saved_order && $saved_order->{reqdate} eq $form->{reqdate} && $saved_order->{transdate} eq $form->{transdate} ) {
+
+      my $dbh = $form->get_standard_dbh;
+
+      my $wday         = (localtime(time))[6];
+      my $next_workday = $wday == 5 ? 3 : $wday == 6 ? 2 : 1;
+
+      my $query = 'SELECT
+                     date(current_date + interval \''. $next_workday .' days\') AS reqdate,
+                     date(current_date) AS transdate';
+      my $ref = selectfirst_hashref_query($form, $dbh, $query);
+
+      map(
+        { $form->{$_} = $ref->{$_} }
+        keys %{$ref}
+      );
     }
   }
 
@@ -1724,13 +1742,14 @@ sub purchase_order {
 
   $form->{cp_id} *= 1;
 
+  my $source_type = $form->{type};
   $form->{title} = $locale->text('Add Purchase Order');
   $form->{vc}    = "vendor";
   $form->{type}  = "purchase_order";
 
   $form->get_employee();
 
-  &poso;
+  poso(source_type => $form->{type});
 
   delete $form->{sales_order_to_purchase_order};
 
@@ -1752,13 +1771,14 @@ sub sales_order {
 
   $form->{cp_id} *= 1;
 
+  my $source_type = $form->{type};
   $form->{title}  = $locale->text('Add Sales Order');
   $form->{vc}     = "customer";
   $form->{type}   = "sales_order";
 
   $form->get_employee();
 
-  &poso;
+  poso(source_type => $source_type);
 
   $main::lxdebug->leave_sub();
 }
@@ -1766,6 +1786,7 @@ sub sales_order {
 sub poso {
   $main::lxdebug->enter_sub();
 
+  my %param    = @_;
   my $form     = $main::form;
   my %myconfig = %main::myconfig;
 
@@ -1775,6 +1796,11 @@ sub poso {
   $form->{transdate} = $form->current_date(\%myconfig);
   delete $form->{duedate};
 
+  # "reqdate" is the validity date for a quotation and the delivery
+  # date for an order. Therefore it makes no sense to keep the value
+  # when converting from one into the other.
+  delete $form->{reqdate} if ($param{source_type} =~ /_quotation$/) == ($form->{type} =~ /_quotation$/);
+
   $form->{convert_from_oe_ids} = $form->{id};
   $form->{closed}              = 0;
 
@@ -1785,9 +1811,11 @@ sub poso {
   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
+  # also reset discounts
   if ( $form->{sales_order_to_purchase_order} ) {
     for my $i (1 .. $form->{rowcount}) {
       $form->{"sellprice_${i}"} = $form->format_amount(\%myconfig,$form->{"lastcost_${i}"});
+      $form->{"discount_${i}"}  = 0;
     };
   };
 
@@ -1848,6 +1876,8 @@ sub delivery_order {
   $form->{old_employee_id}  = $form->{employee_id};
   $form->{old_salesman_id}  = $form->{salesman_id};
 
+  _oe_remove_delivered_or_billed_rows(id => $form->{id}, type => 'delivered');
+
   # reset
   delete @{$form}{qw(id subject message cc bcc printed emailed queued creditlimit creditremaining discount tradediscount oldinvtotal closed delivered)};
 
@@ -1863,6 +1893,9 @@ sub delivery_order {
 
   map { $form->{$_} = $old_values{$_} if ($old_values{$_}) } keys %old_values;
 
+  for my $i (1 .. $form->{rowcount}) {
+    (my $dummy, $form->{"pricegroup_id_$i"}) = split /--/, $form->{"sellprice_pg_$i"};
+  }
   update();
 
   $main::lxdebug->leave_sub();
@@ -1982,7 +2015,7 @@ sub edit_periodic_invoices_config {
   $::form->{AR}    = [ grep { $_->{link} =~ m/(?:^|:)AR(?::|$)/ } @{ $::form->{ALL_CHARTS} } ];
   $::form->{title} = $::locale->text('Edit the configuration for periodic invoices');
 
-  $::form->header();
+  $::form->header(no_layout => 1);
   print $::form->parse_html_template('oe/edit_periodic_invoices_config', $config);
 
   $::lxdebug->leave_sub();
@@ -2018,11 +2051,36 @@ sub save_periodic_invoices_config {
   $::lxdebug->leave_sub();
 }
 
+sub _oe_remove_delivered_or_billed_rows {
+  my (%params) = @_;
+
+  return if !$params{id} || !$params{type};
+
+  my $ord_quot = SL::DB::Order->new(id => $params{id})->load;
+  return if !$ord_quot;
+
+  my %args    = (
+    direction => 'to',
+    to        =>   $params{type} eq 'delivered' ? 'DeliveryOrder' : 'Invoice',
+    via       => [ $params{type} eq 'delivered' ? qw(Order)       : qw(Order DeliveryOrder) ],
+  );
+
+  my %handled_base_qtys;
+  foreach my $record (@{ $ord_quot->linked_records(%args) }) {
+    next if $ord_quot->is_sales != $record->is_sales;
+
+    foreach my $item (@{ $record->items }) {
+      $handled_base_qtys{ $item->parts_id } += $item->qty * $item->unit_obj->base_factor;
+    }
+  }
+
+  _remove_billed_or_delivered_rows(quantities => \%handled_base_qtys);
+}
+
 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;
     }