From 2f5ea2de698efeaf8e7c31dcbc27b4e996f5e2ca Mon Sep 17 00:00:00 2001 From: Tamino Date: Thu, 31 Dec 2020 12:23:21 +0100 Subject: [PATCH] ShopConnector get_part in WooCommerce implemented --- SL/Controller/ShopPart.pm | 73 +++++++- SL/ShopConnector/Shopware.pm | 2 +- SL/ShopConnector/WooCommerce.pm | 176 +++++++++++++++++- js/kivi.ShopPart.js | 28 ++- templates/webpages/shop_part/_filter.html | 1 - templates/webpages/shop_part/_get_one.html | 17 ++ .../webpages/shop_part/_list_articles.html | 4 + 7 files changed, 286 insertions(+), 15 deletions(-) create mode 100644 templates/webpages/shop_part/_get_one.html diff --git a/SL/Controller/ShopPart.pm b/SL/Controller/ShopPart.pm index fb2fe92fb..72ec9235a 100644 --- a/SL/Controller/ShopPart.pm +++ b/SL/Controller/ShopPart.pm @@ -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'); } diff --git a/SL/ShopConnector/Shopware.pm b/SL/ShopConnector/Shopware.pm index d56f5e679..79f7cd632 100644 --- a/SL/ShopConnector/Shopware.pm +++ b/SL/ShopConnector/Shopware.pm @@ -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; diff --git a/SL/ShopConnector/WooCommerce.pm b/SL/ShopConnector/WooCommerce.pm index f65570d96..3ce4f4186 100644 --- a/SL/ShopConnector/WooCommerce.pm +++ b/SL/ShopConnector/WooCommerce.pm @@ -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 = ( diff --git a/js/kivi.ShopPart.js b/js/kivi.ShopPart.js index 64a1e46d7..0d62fd6b3 100644 --- a/js/kivi.ShopPart.js +++ b/js/kivi.ShopPart.js @@ -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(); diff --git a/templates/webpages/shop_part/_filter.html b/templates/webpages/shop_part/_filter.html index bdf290801..b74e728e8 100644 --- a/templates/webpages/shop_part/_filter.html +++ b/templates/webpages/shop_part/_filter.html @@ -21,6 +21,5 @@

[% L.hidden_tag('action', 'ShopPart/dispatch') %] - [% L.submit_tag('action_list_articles',LxERP.t8('renew')) %]

diff --git a/templates/webpages/shop_part/_get_one.html b/templates/webpages/shop_part/_get_one.html new file mode 100644 index 000000000..0f4dcc7ea --- /dev/null +++ b/templates/webpages/shop_part/_get_one.html @@ -0,0 +1,17 @@ +[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%] +[% USE Dumper %] +[% L.stylesheet_tag('webshop') %] +[%- INCLUDE 'common/flash.html' %] +
+ + + + + + + + + +
[% 'Shop' | $T8 %][% L.select_tag('shop_id', SELF.shops, value_key = 'value', title_key = 'title', default=1) %]
[% 'Shop partnumber' | $T8 %][% L.input_tag('part_number', "") %]
+ [% L.button_tag("kivi.ShopPart.get_shop_parts_one()", LxERP.t8('Import part')) %] +
diff --git a/templates/webpages/shop_part/_list_articles.html b/templates/webpages/shop_part/_list_articles.html index 34d404585..83a633504 100644 --- a/templates/webpages/shop_part/_list_articles.html +++ b/templates/webpages/shop_part/_list_articles.html @@ -1,5 +1,6 @@ [%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%] +[%- INCLUDE 'common/flash.html' %]

[% title %]

[%- PROCESS 'shop_part/_filter.html' filter=SELF.models.filtered.laundered %]
@@ -123,6 +124,9 @@ [%- INCLUDE 'shop_part/_upload_status.html' %] +