commit be5cf70d9ddb91a1e96b8f61fa9f518431b16091
Author: Werner Hahn <wh@futureworldsearch.net>
Date:   Wed Mar 29 15:56:57 2017 +0200

    Shopmodul: Fehlermeldung beim Übernehmen; Kunde nicht gefunden, Shopbestellung nicht gefunden, Artikel nicht gefunden, DB fehler beim Einfügen

diff --git a/SL/BackgroundJob/ShopOrderMassTransfer.pm b/SL/BackgroundJob/ShopOrderMassTransfer.pm
index dd2988a4c..7c8d85761 100644
--- a/SL/BackgroundJob/ShopOrderMassTransfer.pm
+++ b/SL/BackgroundJob/ShopOrderMassTransfer.pm
@@ -17,10 +17,10 @@ use SL::DB::History;
 use SL::DB::DeliveryOrder;
 use SL::DB::Inventory;
 use Sort::Naturally ();
+use SL::Locale::String qw(t8);
 
 use constant WAITING_FOR_EXECUTION        => 0;
-#use constant CONVERTING_TO_ORDER          => 1;
-use constant CONVERTING_TO_DELIVERY_ORDER => 1;
+use constant CONVERTING_TO_ORDER          => 1;
 use constant DONE                         => 2;
 
 # Data format:
@@ -28,7 +28,7 @@ use constant DONE                         => 2;
 #     shop_order_record_ids       => [ 603, 604, 605],
 #     num_order_created           => 0,
 #     orders_ids                  => [1,2,3]
-#     conversation_errors         => [ { id => 603 , item => 2, message => "Out of stock"}, ],
+#     conversion_errors         => [ { id => 603 , item => 2, message => "Out of stock"}, ],
 # };
 #
 
@@ -36,42 +36,60 @@ sub create_order {
   my ( $self ) = @_;
   my $job_obj = $self->{job_obj};
   my $db      = $job_obj->db;
-  my %error_report;
-  $job_obj->set_data(CONVERTING_TO_DELIVERY_ORDER())->save;
+  $job_obj->set_data(CONVERTING_TO_ORDER())->save;
 
-  foreach my $shop_order_id (@{ $job_obj->data_as_hash->{shop_order_record_ids} }) {
-    my $data = $job_obj->data_as_hash;
+  my $data = $job_obj->data_as_hash;
+  foreach my $shop_order_id (@{ $data->{shop_order_record_ids} }) {
     my $shop_order = SL::DB::ShopOrder->new(id => $shop_order_id)->load;
     unless($shop_order){
-      push @{ $error_report{$shop_order_id} }, 'Shoporder not found';
+      push @{ $data->{conversion_errors} }, { id => $shop_order->id, number => $shop_order->shop_ordernumber, message => t8('Shoporder not found') };
+      $job_obj->update_attributes(data_as_hash => $data);
     }
     my $customer = SL::DB::Manager::Customer->find_by(id => $shop_order->{kivi_customer_id});
-    die "Can't find customer" unless $customer;
+    unless($customer){
+      push @{ $data->{conversion_errors} }, { id => $shop_order->id, number => $shop_order->shop_ordernumber, message => t8('Customer not found') };
+      $job_obj->update_attributes(data_as_hash => $data);
+    }
     my $employee = SL::DB::Manager::Employee->current;
-    my $items = SL::DB::Manager::ShopOrderItem->get_all( where => [shop_order_id => $shop_order_id],
-                                                          sort_by => 'partnumber::int' );
+    my $items = SL::DB::Manager::ShopOrderItem->get_all( where => [shop_order_id => $shop_order_id], );
+
     if ($customer->{order_lock} == 0) {
       $shop_order->{shop_order_items} = $items;
 
-      my $order = $shop_order->convert_to_sales_order(customer => $customer, employee => $employee);
-      $order->save;
-      my $snumbers = "ordernumber_" . $order->ordnumber;
-      SL::DB::History->new(
-                        trans_id    => $order->id,
-                        snumbers    => $snumbers,
-                        employee_id => SL::DB::Manager::Employee->current->id,
-                        addition    => 'SAVED',
-                        what_done   => 'Shopimport->Order(MassTransfer)',
-                      )->save();
-      $shop_order->transferred(1);
-      $shop_order->transfer_date(DateTime->now_local);
-      $shop_order->oe_transid($order->id);
-      $shop_order->save;
-      $shop_order->link_to_record($order);
-      $data->{num_order_created} ++;
-      push @{ $data->{orders_ids} }, $order->id;
-      push @{ $data->{shop_orders_ids} }, $shop_order->id;
+      $db->with_transaction( sub {
+        my $order = $shop_order->convert_to_sales_order(customer => $customer, employee => $employee);
+
+        if ($order->{error}){
+          push @{ $data->{conversion_errors} }, { id => $shop_order->id, number => $shop_order->shop_ordernumber, message => \@{$order->{errors}} };
+          $job_obj->update_attributes(data_as_hash => $data);
+        }else{
+          $order->save;
+          my $snumbers = "ordernumber_" . $order->ordnumber;
+          SL::DB::History->new(
+                            trans_id    => $order->id,
+                            snumbers    => $snumbers,
+                            employee_id => SL::DB::Manager::Employee->current->id,
+                            addition    => 'SAVED',
+                            what_done   => 'Shopimport->Order(MassTransfer)',
+                          )->save();
+          $shop_order->transferred(1);
+          $shop_order->transfer_date(DateTime->now_local);
+          $shop_order->oe_transid($order->id);
+          $shop_order->save;
+          $shop_order->link_to_record($order);
+          $data->{num_order_created} ++;
+          push @{ $data->{orders_ids} }, $order->id;
+          push @{ $data->{shop_orders_ids} }, $shop_order->id;
 
+          $job_obj->update_attributes(data_as_hash => $data);
+        }
+        1;
+      })or do {
+        push @{ $data->{conversion_errors} }, { id => $shop_order->id, number => $shop_order->shop_ordernumber, message => $@ };
+        $job_obj->update_attributes(data_as_hash => $data);
+      }
+    }else{
+      push @{ $data->{conversion_errors} }, { id => $shop_order->id, number => $shop_order->shop_ordernumber, message => t8('Customerorderlock') };
       $job_obj->update_attributes(data_as_hash => $data);
     }
   }
diff --git a/SL/Controller/ShopOrder.pm b/SL/Controller/ShopOrder.pm
index a6af062b0..e8e638ac1 100644
--- a/SL/Controller/ShopOrder.pm
+++ b/SL/Controller/ShopOrder.pm
@@ -153,28 +153,35 @@ sub action_transfer {
   die "Can't load shop_order form form->import_id" unless $self->shop_order;
 
   my $order = $self->shop_order->convert_to_sales_order(customer => $customer, employee => $employee);
-  $order->save;
+  $main::lxdebug->dump(0, 'WH:OOO ',$order);
 
-  my $snumbers = "ordernumber_" . $order->ordnumber;
-  SL::DB::History->new(
-                    trans_id    => $order->id,
-                    snumbers    => $snumbers,
-                    employee_id => SL::DB::Manager::Employee->current->id,
-                    addition    => 'SAVED',
-                    what_done   => 'Shopimport -> Order',
-                  )->save();
-  foreach my $item(@{ $order->orderitems }){
-    $item->parse_custom_variable_values->save;
-    $item->{custom_variables} = \@{ $item->cvars_by_config };
-    $item->save;
+  if ($order->{error}){
+    flash_later('error',@{$order->{errors}});
+  $self->redirect_to(controller => "ShopOrder", action => 'show', id => $self->shop_order->id);
+  }else{
+    $order->save;
+
+    my $snumbers = "ordernumber_" . $order->ordnumber;
+    SL::DB::History->new(
+                      trans_id    => $order->id,
+                      snumbers    => $snumbers,
+                      employee_id => SL::DB::Manager::Employee->current->id,
+                      addition    => 'SAVED',
+                      what_done   => 'Shopimport -> Order',
+                    )->save();
+    foreach my $item(@{ $order->orderitems }){
+      $item->parse_custom_variable_values->save;
+      $item->{custom_variables} = \@{ $item->cvars_by_config };
+      $item->save;
+    }
+
+    $self->shop_order->transferred(1);
+    $self->shop_order->transfer_date(DateTime->now_local);
+    $self->shop_order->oe_transid($order->id);
+    $self->shop_order->save;
+    $self->shop_order->link_to_record($order);
+    $self->redirect_to(controller => "oe.pl", action => 'edit', type => 'sales_order', vc => 'customer', id => $order->id);
   }
-
-  $self->shop_order->transferred(1);
-  $self->shop_order->transfer_date(DateTime->now_local);
-  $self->shop_order->oe_transid($order->id);
-  $self->shop_order->save;
-  $self->shop_order->link_to_record($order);
-  $self->redirect_to(controller => "oe.pl", action => 'edit', type => 'sales_order', vc => 'customer', id => $order->id);
 }
 
 sub action_mass_transfer {
@@ -190,7 +197,7 @@ sub action_mass_transfer {
      num_order_created           => 0,
      num_delivery_order_created  => 0,
      status                      => SL::BackgroundJob::ShopOrderMassTransfer->WAITING_FOR_EXECUTION(),
-     conversation_errors         => [ ],
+     conversion_errors         => [ ],
    )->update_next_run_at;
 
    SL::System::TaskServer->new->wake_up;
diff --git a/SL/DB/ShopOrder.pm b/SL/DB/ShopOrder.pm
index d40cf22e5..e0a79f548 100644
--- a/SL/DB/ShopOrder.pm
+++ b/SL/DB/ShopOrder.pm
@@ -8,6 +8,7 @@ use strict;
 use SL::DB::MetaSetup::ShopOrder;
 use SL::DB::Manager::ShopOrder;
 use SL::DB::Helper::LinkedRecords;
+use SL::Locale::String qw(t8);
 
 __PACKAGE__->meta->add_relationships(
   shop_order_items => {
@@ -41,68 +42,83 @@ sub convert_to_sales_order {
   require SL::DB::OrderItem;
   require SL::DB::Part;
   require SL::DB::Shipto;
+  my @error_report;
 
   my @items = map{
+
   # TODO Flash and exit if part not found
-    my $part = SL::DB::Part->new( partnumber => $_->partnumber )->load;
-    my $shop_part = SL::DB::Manager::ShopPart->get_all( where => [ shop_id => $self->shop_id, part_id => $part->id] )->[0];
-
-    my @cvars = map { ($_->config->name => { value => $_->value_as_text, is_valid => $_->is_valid }) } @{ $part->cvars_by_config } ;
-    my $current_order_item =
-      SL::DB::OrderItem->new(parts_id               => $part->id,
-                             description            => $part->description,
-                             qty                    => $_->quantity,
-                             sellprice              => $_->price,
-                             unit                   => $part->unit,
-                             position               => $_->position,
-                             active_price_source    => $shop_part->active_price_source,
-                           );
+    my $part = SL::DB::Manager::Part->get_first( query => [ partnumber => $_->partnumber, ], );
+
+    unless($part){
+      push @error_report, t8('Part with Partnumber: ') . $_->partnumber . t8(' not found');
+    }else{
+      my $shop_part = SL::DB::Manager::ShopPart->get_all( where => [ shop_id => $self->shop_id, part_id => $part->id] )->[0];
+
+      my @cvars = map { ($_->config->name => { value => $_->value_as_text, is_valid => $_->is_valid }) } @{ $part->cvars_by_config } ;
+      my $current_order_item =
+        SL::DB::OrderItem->new(parts_id               => $part->id,
+                               description            => $part->description,
+                               qty                    => $_->quantity,
+                               sellprice              => $_->price,
+                               unit                   => $part->unit,
+                               position               => $_->position,
+                               active_price_source    => $shop_part->active_price_source,
+                             );
+    }
   }@{ $self->shop_order_items };
 
-  my $shipto_id;
-  if ($self->{billing_firstname} ne $self->{delivery_firstname} || $self->{billing_lastname} ne $self->{delivery_lastname} || $self->{billing_city} ne $self->{delivery_city} || $self->{billing_street} ne $self->{delivery_street}) {
-    if(my $address = SL::DB::Manager::Shipto->find_by( shiptoname          => $self->{delivery_firstname} . " " . $self->{delivery_lastname},
-                                                        shiptostreet        => $self->{delivery_street},
-                                                        shiptocity          => $self->{delivery_city},
-                                                      )) {
-      $shipto_id = $address->{shipto_id};
-    } else {
-      my $gender = $self->{delivery_greeting} eq "Frau" ? 'f' : 'm';
-      my $deliveryaddress = SL::DB::Shipto->new;
-      $deliveryaddress->assign_attributes(
-        shiptoname          => $self->{delivery_firstname} . " " . $self->{delivery_lastname},
-        shiptodepartment_1  => $self->{delivery_company},
-        shiptodepartment_2  => $self->{delivery_department},
-        shiptocp_gender     => $gender,
-        shiptostreet        => $self->{delivery_street},
-        shiptozipcode       => $self->{delivery_zipcode},
-        shiptocity          => $self->{delivery_city},
-        shiptocountry       => $self->{delivery_country},
-        trans_id            => $customer->id,
-        module              => "CT",
-      );
-      $deliveryaddress->save;
-      $shipto_id = $deliveryaddress->{shipto_id};
+  if(!scalar(@error_report)){
+
+    my $shipto_id;
+    if ($self->{billing_firstname} ne $self->{delivery_firstname} || $self->{billing_lastname} ne $self->{delivery_lastname} || $self->{billing_city} ne $self->{delivery_city} || $self->{billing_street} ne $self->{delivery_street}) {
+      if(my $address = SL::DB::Manager::Shipto->find_by( shiptoname          => $self->{delivery_firstname} . " " . $self->{delivery_lastname},
+                                                          shiptostreet        => $self->{delivery_street},
+                                                          shiptocity          => $self->{delivery_city},
+                                                        )) {
+        $shipto_id = $address->{shipto_id};
+      } else {
+        my $gender = $self->{delivery_greeting} eq "Frau" ? 'f' : 'm';
+        my $deliveryaddress = SL::DB::Shipto->new;
+        $deliveryaddress->assign_attributes(
+          shiptoname          => $self->{delivery_firstname} . " " . $self->{delivery_lastname},
+          shiptodepartment_1  => $self->{delivery_company},
+          shiptodepartment_2  => $self->{delivery_department},
+          shiptocp_gender     => $gender,
+          shiptostreet        => $self->{delivery_street},
+          shiptozipcode       => $self->{delivery_zipcode},
+          shiptocity          => $self->{delivery_city},
+          shiptocountry       => $self->{delivery_country},
+          trans_id            => $customer->id,
+          module              => "CT",
+        );
+        $deliveryaddress->save;
+        $shipto_id = $deliveryaddress->{shipto_id};
+      }
     }
-  }
-
-  my $order = SL::DB::Order->new(
-                  amount                  => $self->amount,
-                  cusordnumber            => $self->shop_ordernumber,
-                  customer_id             => $customer->id,
-                  shipto_id               => $shipto_id,
-                  orderitems              => [ @items ],
-                  employee_id             => $employee->id,
-                  intnotes                => ($customer->notes ne "" ? "\n[Kundestammdaten]\n" . $customer->notes : ""),
-                  salesman_id             => $employee->id,
-                  taxincluded             => $self->tax_included,
-                  payment_id              => $customer->payment_id,
-                  taxzone_id              => $customer->taxzone_id,
-                  currency_id             => $customer->currency_id,
-                  transaction_description => 'Shop Import',
-                  transdate               => DateTime->today_local
+
+    my $order = SL::DB::Order->new(
+                    amount                  => $self->amount,
+                    cusordnumber            => $self->shop_ordernumber,
+                    customer_id             => $customer->id,
+                    shipto_id               => $shipto_id,
+                    orderitems              => [ @items ],
+                    employee_id             => $employee->id,
+                    intnotes                => ($customer->notes ne "" ? "\n[Kundestammdaten]\n" . $customer->notes : ""),
+                    salesman_id             => $employee->id,
+                    taxincluded             => $self->tax_included,
+                    payment_id              => $customer->payment_id,
+                    taxzone_id              => $customer->taxzone_id,
+                    currency_id             => $customer->currency_id,
+                    transaction_description => 'Shop Import',
+                    transdate               => DateTime->today_local
+                  );
+     return $order;
+   }else{
+     my %error_order = (error   => 1,
+                        errors  => [ @error_report ],
                 );
-   return $order;
+     return \%error_order;
+   }
 };
 
 sub compare_to {
diff --git a/templates/webpages/shop_order/_transfer_status.html b/templates/webpages/shop_order/_transfer_status.html
index 2e6f12719..81255664d 100644
--- a/templates/webpages/shop_order/_transfer_status.html
+++ b/templates/webpages/shop_order/_transfer_status.html
@@ -11,7 +11,7 @@ JOBID: [% job.id %] <p>
  [% LxERP.t8("This status output will be refreshed every five seconds.") %]
 </p>
 <p>
-[% # Dumper.dump_html(data) %]
+[%  Dumper.dump_html(data) %]
 </p>
 <p>
  [% L.link("#", LxERP.t8("Close window"), onclick="kivi.ShopOrder.processClose();") %]
@@ -44,14 +44,14 @@ JOBID: [% job.id %] <p>
 [% ELSE %]
     <table>
      <tr class="listheader">
-      <th>[% LxERP.t8("Delivery Order") %]</th>
+      <th>[% LxERP.t8("Shoporder") %]</th>
       <th>[% LxERP.t8("Error") %]</th>
      </tr>
 
  [% FOREACH error = data.conversion_errors %]
      <tr>
-      <td valign="top">[% IF error.id %][% L.link(SELF.url_for(controller='do.pl', action='edit', type='sales_delivery_order', id=error.id), HTML.escape(error.number), target="_blank") %][% ELSE %]–[% END %]</td>
-      <td valign="top">[% HTML.escape(error.message) %]</td>
+      <td valign="top">[% HTML.escape(error.number) %]</td>
+      <td valign="top">[% FOREACH message = error.message %][% HTML.escape(message) %]<br>[% END %]</td>
      </tr>
  [% END %]
     </table>
diff --git a/templates/webpages/shop_order/show.html b/templates/webpages/shop_order/show.html
index 6d74648aa..396cc7fa2 100644
--- a/templates/webpages/shop_order/show.html
+++ b/templates/webpages/shop_order/show.html
@@ -1,6 +1,6 @@
 [%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%]
 [% L.stylesheet_tag('webshop') %]
-
+[%- INCLUDE 'common/flash.html' %]
 <h1>[% title %]</h1>
 
   <div class="shop_table shop_main">
