ShopConnector get_part in WooCommerce implemented
authorTamino <tamino.steinert@web.de>
Thu, 31 Dec 2020 11:23:21 +0000 (12:23 +0100)
committerWerner Hahn <wh@futureworldsearch.net>
Thu, 24 Jun 2021 14:45:15 +0000 (16:45 +0200)
SL/Controller/ShopPart.pm
SL/ShopConnector/Shopware.pm
SL/ShopConnector/WooCommerce.pm
js/kivi.ShopPart.js
templates/webpages/shop_part/_filter.html
templates/webpages/shop_part/_get_one.html [new file with mode: 0644]
templates/webpages/shop_part/_list_articles.html

index fb2fe92..72ec923 100644 (file)
@@ -86,6 +86,50 @@ sub action_ajax_delete_file {
     ->render();
 }
 
+sub action_get_shop_parts {
+  my ( $self ) = @_;
+  $main::lxdebug->dump(0, "TST: ShopPart get_shop_parts form", $::form);
+  my $parts_fetched;
+  my $new_parts;
+
+  my $type = $::form->{type};
+  if ( $type eq "get_one" ) {
+    my $shop_id = $::form->{shop_id};
+    my $part_number = $::form->{part_number};
+
+    if ( $shop_id && $part_number ) {
+      my $shop_config = SL::DB::Manager::Shop->get_first(query => [ id => $shop_id, obsolete => 0 ]);
+      my $shop = SL::Shop->new( config => $shop_config );
+      unless ( SL::DB::Manager::Part->get_all_count( query => [ partnumber => $part_number ] )) {
+        $new_parts = $shop->connector->get_shop_parts($part_number);
+        push @{ $parts_fetched }, $new_parts ;
+      } else {
+        flash_later('error', t8('From shop "#1" :  Number: #2 #3 ', $shop->config->description, $part_number, t8('Partnumber is already exist')));
+      }
+    } else {
+        flash_later('error', t8('Shop or partnumber not selected.'));
+    }
+  } elsif ( $type eq "get_new" ) {
+    my $active_shops = SL::DB::Manager::Shop->get_all(query => [ obsolete => 0 ]);
+    foreach my $shop_config ( @{ $active_shops } ) {
+      my $shop = SL::Shop->new( config => $shop_config );
+
+      $new_parts = $shop->connector->get_shop_parts;
+      push @{ $parts_fetched }, $new_parts ;
+    }
+  }
+
+  foreach my $shop_fetched(@{ $parts_fetched }) {
+    if($shop_fetched->{error}){
+      flash_later('error', t8('From shop "#1" :  #2 ', $shop_fetched->{shop_description}, $shop_fetched->{message},));
+    }else{
+      flash_later('info', t8('From shop #1 :  #2 parts have been imported.', $shop_fetched->{description}, $shop_fetched->{number_of_parts},));
+    }
+  }
+
+  $self->redirect_to(controller => "ShopPart", action => 'list_articles');
+}
+
 sub action_get_categories {
   my ($self) = @_;
 
@@ -135,7 +179,7 @@ sub action_show_stock {
   my $shop = SL::Shop->new( config => $self->shop_part->shop );
 
   if($self->shop_part->last_update) {
-    my $shop_article = $shop->connector->get_article($self->shop_part->part->partnumber);
+    my $shop_article = $shop->connector->get_article_info($self->shop_part->part->partnumber);
     $stock_onlineshop = $shop_article->{data}->{mainDetail}->{inStock};
     $active_online = $shop_article->{data}->{active};
   }
@@ -156,7 +200,7 @@ sub action_get_n_write_categories {
     my $shop_part = SL::DB::Manager::ShopPart->get_all( where => [id => $part], with_objects => ['part', 'shop'])->[0];
     require SL::DB::Shop;
     my $shop = SL::Shop->new( config => $shop_part->shop );
-    my $online_article = $shop->connector->get_article($shop_part->part->partnumber);
+    my $online_article = $shop->connector->get_article_info($shop_part->part->partnumber);
     my $online_cat = $online_article->{data}->{categories};
     my @cat = ();
     for(keys %$online_cat){
@@ -224,6 +268,8 @@ sub action_list_articles {
     $article->{images} = $images;
   }
 
+  $self->_setup_list_action_bar;
+
   $self->render('shop_part/_list_articles', title => t8('Webshops articles'), SHOP_PARTS => $articles);
 }
 
@@ -355,6 +401,29 @@ sub get_price_n_pricesource {
   return($price,$price_src_str);
 }
 
+sub _setup_list_action_bar {
+  my ($self) = @_;
+
+  for my $bar ($::request->layout->get('actionbar')) {
+    $bar->add(
+        action => [
+          t8('Search'),
+          submit    => [ '#shop_part_filter', { action => "ShopPart/list_articles" } ],
+        ],
+        action => [
+          t8('Get one part'),
+          call    => [ 'kivi.ShopPart.get_shop_parts_one_setup' ],
+          tooltip => t8('Get one part by partnumber'),
+        ],
+        action => [
+          t8('Get new parts'),
+          call    => [ 'kivi.ShopPart.get_shop_parts_new' ],
+          tooltip => t8('Get all new parts'),
+        ],
+    );
+  }
+}
+
 sub check_auth {
   $::auth->assert('shop_part_edit');
 }
index d56f5e6..79f7cd6 100644 (file)
@@ -416,7 +416,7 @@ sub update_part {
   return $upload_content->{success};
 }
 
-sub get_article {
+sub get_parts_info {
   my ($self,$partnumber) = @_;
 
   my $url       = $self->url;
index f65570d..3ce4f41 100644 (file)
@@ -34,7 +34,7 @@ sub get_one_order {
     $dbh->with_transaction( sub{
         #update status on server
         $shoporder->{status} = "processing";
-        my $anser = $self->set_orderstatus($$shoporder->{id}, "fetched");
+        my $answer = $self->set_orderstatus($shoporder->{id}, "fetched");
         unless($answer){
           push @errors,($::locale->text('Saving failed. Error message from the server: #1', $answer->message));
           return 0;
@@ -151,6 +151,8 @@ sub import_data_to_shop_order {
                         shop_order_id        => $id,
                         active_price_source  => $active_price_source,
                       );
+    #$main::lxdebug->dump(0, "TST: WooCommerce save pos", $pos);
+    #$main::lxdebug->dump(0, "TST: WooCommerce save pos_columns", \%pos_columns);
     my $pos_insert = SL::DB::ShopOrderItem->new(%pos_columns);
     $pos_insert->save;
     $position++;
@@ -314,13 +316,15 @@ sub update_part {
   #};
 
   my @categories = ();
-  foreach my $row_cat ( @{ $shop_part->shop_category } ) {
-    my $temp = { ( id => @{$row_cat}[0], ) };
-    push ( @categories, $temp );
+  if ($shop_part->shop_category) {
+    foreach my $row_cat ( @{ $shop_part->shop_category } ) {
+      my $temp = { ( id => @{$row_cat}[0], ) };
+      push ( @categories, $temp );
+    }
   }
 
   #my @upload_img = $shop_part->get_images;
-  my $partnumber = $::form->escape($part->partnumber);#don't accept / in articlenumber
+  my $partnumber = $::form->escape($part->partnumber);#don't accept / in partnumber
   my $stock_status = ($part->onhand ? "instock" : "outofstock");
   my $status = ($shop_part->active ? "publish" : "private");
   my $tax_n_price = $shop_part->get_tax_and_price;
@@ -379,29 +383,178 @@ sub update_part {
 
   # don't know if this is needed
   #if(@upload_img) {
-  #  my $partnumber = $::form->escape($part->partnumber);#shopware don't accept / in articlenumber
-  #  my $imgup      = $self->connector->put($url . "api/generatearticleimages/$partnumber?useNumberAsId=true");
+  #  my $partnumber = $::form->escape($part->partnumber);#shopware don't accept / in partnumber
+  #  my $imgup      = $self->connector->put($url . "api/generatepartimages/$partnumber?useNumberAsId=true");
   #}
 
   return $answer->{success};
 }
 
-sub get_article {
+sub get_article_info {
   my ($self) = @_;
   my $partnumber = $_[1];
 
   $partnumber   = $::form->escape($partnumber);#don't accept / in partnumber
   my $answer = $self->send_request("products/", undef , "get" , "&sku=$partnumber");
 
+  $answer->{data} = $answer->{data}[0];
+  #$main::lxdebug->dump(0, "TST: WooCommerce get_part_info ", $answer);
+  return $answer;
+
   if($answer->{success} && scalar @{$answer->{data}}){
-    my $article = $answer->{data}[0];
-    return $article;
+    my $part = $self->map_data_to_part($answer->{data}[0]);
+    #$main::lxdebug->dump(0, "TST: WooCommerce get_part_info part", $part);
+    return $part;
   } else {
     #What shut be here?
     return $answer
   }
 }
 
+sub map_data_to_part {
+  my ($self, $part_data) = @_;
+
+  my %map_part_data =  (
+    #id                 => $part_data->{},
+    partnumber         => $part_data->{sku},
+    description        => $part_data->{name},
+    #listprice          => $part_data->{},
+    #sellprice          => $part_data->{},
+    #lastcost           => $part_data->{},
+    #priceupdate        => $part_data->{},
+    #weight             => $part_data->{},
+    notes              => $part_data->{description},
+    #makemodel          => $part_data->{},
+    #rop                => $part_data->{},
+    shop               => 1,
+    obsolete           => 0,
+    #bom                => $part_data->{},
+    #image              => $part_data->{},
+    #drawing            => $part_data->{},
+    #microfiche         => $part_data->{},
+    #partsgroup_id      => $part_data->{},
+    #ve                 => $part_data->{},
+    #gv                 => $part_data->{},
+    #itime              => $part_data->{},
+    #mtime              => $part_data->{},
+    #unit               => $part_data->{},
+    unit               => 'Stck',
+    #formel             => $part_data->{},
+    #not_discountable   => $part_data->{},
+    #buchungsgruppen_id => $part_data->{},
+    #payment_id         => $part_data->{},
+    #ean                => $part_data->{},
+    #price_factor_id    => $part_data->{},
+    #onhand             => $part_data->{},
+    #stockable          => $part_data->{},
+    #has_sernumber      => $part_data->{},
+    #warehouse_id       => $part_data->{},
+    #bin_id             => $part_data->{},
+    #df_status_aktuell  => $part_data->{},
+    #df_status_verlauf  => $part_data->{},
+    #active             => $part_data->{},
+    #classification_id  => $part_data->{},
+    part_type          => 'part',
+  );
+  return SL::DB::Part->new(%map_part_data);
+}
+
+sub map_data_to_shop_part {
+  my ($self, $part_data, $part) = @_;
+
+  my @categories = ();
+  foreach my $row_cat ( @{ $part_data->{categories} } ) {
+    my @tmp;
+    push( @tmp,$row_cat->{id} );
+    push( @tmp,$row_cat->{name} );
+    push( @categories,\@tmp );
+  }
+  my %map_shop_part_data =  (
+    #id                  => ,
+    shop_id             => $self->config->id,
+    part_id             => $part->id,
+    shop_description    => $part_data->{description},
+    #itime               => ,
+    #mtime               => ,
+    #last_update         => ,
+    #show_date           => ,
+    sortorder           => $part_data->{menu_order},
+    #front_page          => ,
+    active              => 1,
+    shop_category       => \@categories,
+    #active_price_source => ,
+    #metatag_keywords    => ,
+    #metatag_description => ,
+    #metatag_title       => ,
+    #shop_versandhinweis => ,
+  );
+  return SL::DB::ShopPart->new(%map_shop_part_data);
+}
+sub get_shop_parts {
+  my ($self, $partnumber) = @_;
+
+  my $dbh       = SL::DB::client;
+  my @errors;
+  my $number_of_parts = 0;
+  my %fetched_parts;
+  my $answer;
+
+  if ($partnumber) {
+    $partnumber   = $::form->escape($partnumber);#don't accept / in partnumber
+    $answer = $self->send_request("products/", undef , "get" , "&sku=$partnumber");
+  } else {
+    #TODO
+    $answer = $self->send_request("products/", undef , "get");
+    if ($answer->{total_pages} > 1) {
+      my $current_page = 2;
+      while ($current_page <= $answer->{total_pages}) {
+        my $tmp_answer = $self->send_request("products/", undef , "get", "&page=$current_page");
+        foreach my $part (@{$tmp_answer->{data}}) {
+          push @{$answer->{data}} , $part;
+        }
+        $current_page++;
+      }
+    }
+  }
+
+  if($answer->{success} && scalar @{$answer->{data}}){
+    $dbh->with_transaction( sub{
+      foreach my $part_data (@{$answer->{data}}) {
+      unless (!$part_data->{sku} || SL::DB::Manager::Part->get_all_count( query => [ partnumber => $part_data->{sku} ] )) {
+          my $part = $self->map_data_to_part($part_data);
+          #$main::lxdebug->dump(0, "TST: WooCommerce get_shop_parts part ", $part);
+          $part->save;
+          my $shop_part = $self->map_data_to_shop_part($part_data, $part);
+          #$main::lxdebug->dump(0, "TST: WooCommerce get_shop_parts shop_part ", $shop_part);
+          $shop_part->save;
+          $number_of_parts++;
+        }
+      }
+      return 1;
+    })or do {
+      push @errors,($::locale->text('Saving failed. Error message from the database: #1', $dbh->error));
+    };
+
+    if(@errors){
+      flash_later('error', $::locale->text('Errors: #1', @errors));
+    }
+    %fetched_parts = (
+      shop_id          => $self->config->id,
+      shop_description => $self->config->description,
+      number_of_parts => $number_of_parts,
+    );
+  } else {
+    my %error_msg  = (
+      shop_id          => $self->config->id,
+      shop_description => $self->config->description,
+      message          => $answer->{message},
+      error            => 1,
+    );
+    %fetched_parts = %error_msg;
+  }
+  return \%fetched_parts;
+}
+
 sub get_categories {
   my ($self) = @_;
 
@@ -495,10 +648,13 @@ sub send_request {
   my %return;
   if($answer->is_success && $type eq 'application/json'){
     my $data_json = $answer->content;
+    #$main::lxdebug->dump(0, "TST: WooCommerce send_request header ", $answer->header( 'Link'));
     my $json = SL::JSON::decode_json($data_json);
     %return = (
       success => 1,
       data    => $json,
+      total_pages => $answer->header( 'X-WP-TotalPages'),
+      total_elements => $answer->header( 'X-WP-Total'),
     );
   }else{
     %return = (
index 64a1e46..0d62fd6 100644 (file)
@@ -140,8 +140,34 @@ namespace('kivi.ShopPart', function(ns) {
                         id:     'files_upload',
                         dialog: { title: kivi.t8('File upload'), width: 650, height: 240 } });
     return true;
-  }
+  };
+
+  ns.get_shop_parts_one = function() {
+
+    var data = $('#get_one_shop_part_form').serializeArray();
+    data.push({ name: 'type', value: 'get_one'});
+    data.push({ name: 'action', value: 'ShopPart/get_shop_parts' });
+
+    $.post("controller.pl", data, kivi.eval_json_result);
+  };
+
+  ns.get_shop_parts_new = function() {
+    $.post("controller.pl", { action: 'ShopPart/get_shop_parts', type: 'get_new'}, kivi.eval_json_result);
+  };
 
+  ns.get_shop_order_one_initialize = function() {
+    kivi.popup_dialog({
+      id: 'get_one',
+      dialog: {
+        title: kivi.t8('Get one shoppart'),
+      }
+    });
+  };
+
+  ns.get_shop_parts_one_setup = function() {
+    kivi.ShopPart.get_shop_order_one_initialize();
+    //kivi.submit_ajax_form('controller.pl?action=ShopOrder/get_orders', $('#shoporder'));
+  };
 
   ns.setup = function() {
     kivi.ShopPart.massUploadInitialize();
index bdf2908..b74e728 100644 (file)
@@ -21,6 +21,5 @@
  </p>
  <p>
    [% L.hidden_tag('action', 'ShopPart/dispatch') %]
-   [% L.submit_tag('action_list_articles',LxERP.t8('renew')) %]
  </p>
 </form>
diff --git a/templates/webpages/shop_part/_get_one.html b/templates/webpages/shop_part/_get_one.html
new file mode 100644 (file)
index 0000000..0f4dcc7
--- /dev/null
@@ -0,0 +1,17 @@
+[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%]
+[% USE Dumper %]
+[% L.stylesheet_tag('webshop') %]
+[%- INCLUDE 'common/flash.html' %]
+<form id="get_one_shop_part_form" action="controller.pl" method="post" style="padding-left:1em;">
+ <table>
+    <tr>
+     <th align="right">[% 'Shop' | $T8 %]</th>
+     <td>[% L.select_tag('shop_id', SELF.shops, value_key = 'value', title_key = 'title', default=1) %]</td>
+    </tr>
+    <tr>
+     <th align="right">[% 'Shop partnumber' | $T8 %]</th>
+     <td>[% L.input_tag('part_number', "") %]</td>
+    </tr>
+ </table>
+  [%  L.button_tag("kivi.ShopPart.get_shop_parts_one()", LxERP.t8('Import part')) %]
+</form>
index 34d4045..83a6335 100644 (file)
@@ -1,5 +1,6 @@
 [%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%]
 
+[%- INCLUDE 'common/flash.html' %]
 <h1>[% title %]</h1>
 [%- PROCESS 'shop_part/_filter.html' filter=SELF.models.filtered.laundered %]
 <hr>
     [%- INCLUDE 'shop_part/_upload_status.html' %]
   </div>
 </form>
+ <div id="get_one" style="display:none;">
+   [% INCLUDE 'shop_part/_get_one.html' %]
+ </div>
 <hr>
 <script type="text/javascript">
 <!--