commit 540867317f60c7344f3e99bf77ea723d33e71dee
Author: Jan Büren <jan@kivitendo-premium.de>
Date:   Tue Sep 22 10:22:36 2015 +0200

    Implementiert FB0017 Position nach Art.Nummer in Lieferschein sortieren
    
    Ab dem Status Verkaufs-Lieferschein können die Positionen nach Artikelnummern sortiert werden,
     sodass diese Sortierreihenfolge in die Rechnung übernommen wird.
    Implementierung mit Natural Sort, d.h. Buchstaben und Zahlen können gemischt sein.
    
    Aktion kann entweder über einen Knopf ausgelöst werden oder wird standardmässig bei jedem Speichern ausgeführt.
    Aktuell heißt der Knopf: Sortieren und Speichern und erscheint sobald, der Lieferschein persisitente
    Positionen in der DB hat.

diff --git a/bin/mozilla/do.pl b/bin/mozilla/do.pl
index 1f9419b39..4b8ead658 100644
--- a/bin/mozilla/do.pl
+++ b/bin/mozilla/do.pl
@@ -42,6 +42,7 @@ use SL::IS;
 use SL::MoreCommon qw(ary_diff);
 use SL::ReportGenerator;
 use SL::WH;
+use Sort::Naturally;
 require "bin/mozilla/arap.pl";
 require "bin/mozilla/common.pl";
 require "bin/mozilla/invoice_io.pl";
@@ -1542,7 +1543,7 @@ sub dispatcher {
   my $form     = $main::form;
   my $locale   = $main::locale;
 
-  foreach my $action (qw(update ship_to print e_mail save transfer_out transfer_out_default
+  foreach my $action (qw(update ship_to print e_mail save transfer_out transfer_out_default sort
                          transfer_in transfer_in_default mark_closed save_as_new invoice delete)) {
     if ($form->{"action_${action}"}) {
       call_sub($action);
@@ -1724,3 +1725,36 @@ sub transfer_in_out_default {
   $form->redirect;
 
 }
+sub sort {
+  $main::lxdebug->enter_sub();
+
+  my $form     = $main::form;
+  my %temp_hash;
+
+  croak ("Delivery Order needs to be saved") unless $form->{id};
+
+  # hashify partnumbers, positions. key is delivery_order_items_id
+  for my $i (1 .. ($form->{rowcount}) ) {
+    $temp_hash{$form->{"delivery_order_items_id_$i"}} = { runningnumber => $form->{"runningnumber_$i"}, partnumber => $form->{"partnumber_$i"} };
+  }
+  # naturally sort partnumbers and get a sorted array of doi_ids
+  my @sorted_doi_ids =  sort { ncmp($temp_hash{$a}->{"partnumber"}, $temp_hash{$b}->{"partnumber"}) }  keys %temp_hash;
+
+  #$main::lxdebug->message(0, 'sortiert, vorher :' . Dumper(%temp_hash));
+  #$main::lxdebug->message(0, 'sortiert, nachher:' . Dumper(@sorted_doi_ids));
+
+  my $new_number = 1;
+  for (@sorted_doi_ids) {
+    # reposition old runningnumber with the new order 1 .. n
+    $form->{"runningnumber_$temp_hash{$_}->{runningnumber}"} = $new_number;
+
+    #$main::lxdebug->message(0, 'hier jetzt:' . 'ferner' . $temp_hash{$_}->{runningnumber} .
+    # 'mit' . $form->{"runningnumber_{$temp_hash{$_}->{runningnumber}}"}); #" = $new_number;
+
+    $new_number++;
+  }
+    # update or save directly
+    # update_delivery_order;
+    $main::lxdebug->leave_sub();
+    save();
+}
diff --git a/locale/de/all b/locale/de/all
index 59c92b9bd..f07e20967 100755
--- a/locale/de/all
+++ b/locale/de/all
@@ -2471,6 +2471,7 @@ $self->{texts} = {
   'Soldtotal does not make sense without any bsooqr options' => 'Option "Menge in gewählten Belegen" ohne gewählte Belege wird ignoriert.',
   'Solution'                    => 'Lösung',
   'Sort By'                     => 'Sortiert nach',
+  'Sort and Save'               => 'Sortieren und Speichern',
   'Source'                      => 'Beleg',
   'Source BIC'                  => 'Quell-BIC',
   'Source IBAN'                 => 'Quell-IBAN',
diff --git a/templates/webpages/do/form_footer.html b/templates/webpages/do/form_footer.html
index 6c8e0c62e..67f631e4f 100644
--- a/templates/webpages/do/form_footer.html
+++ b/templates/webpages/do/form_footer.html
@@ -92,6 +92,7 @@
    [%- END %]
    [%- END %]
    [%- IF id %]
+    <input class="submit" type="submit" name="action_sort" id="sort_button" value="[% 'Sort and Save' | $T8 %]">
      <input type="button" class="submit" onclick="follow_up_window()" value="[% 'Follow-Up' | $T8 %]">
    [%- UNLESS closed %]
    <input class="submit" type="submit" name="action_mark_closed" value="[% 'Mark closed' | $T8 %]" data-require-transaction-description="[% INSTANCE_CONF.get_require_transaction_description_ps %]">
