use SL::DB::ShopOrder;
use SL::DB::ShopOrderItem;
use SL::DB::History;
+use SL::DB::PaymentTerm;
use DateTime::Format::Strptime;
use SL::DB::File;
use Data::Dumper;
'scalar --get_set_init' => [ qw(connector url) ],
);
+sub get_one_order {
+ my ($self, $ordnumber) = @_;
+
+ my $dbh = SL::DB::client;
+ my $of = 0;
+ my $url = $self->url;
+ my $data = $self->connector->get($url . "api/orders/$ordnumber?useNumberAsId=true");
+ my @errors;
+
+ my %fetched_orders;
+ if ($data->is_success && $data->content_type eq 'application/json'){
+ my $data_json = $data->content;
+ my $import = SL::JSON::decode_json($data_json);
+ my $shoporder = $import->{data};
+ $dbh->with_transaction( sub{
+ $self->import_data_to_shop_order($import);
+ 1;
+ })or do {
+ push @errors,($::locale->text('Saving failed. Error message from the database: #1', $dbh->error));
+ };
+
+ if(!@errors){
+ $self->set_orderstatus($import->{data}->{id}, "fetched");
+ $of++;
+ }else{
+ flash_later('error', $::locale->text('Database errors: #1', @errors));
+ }
+ %fetched_orders = (shop_description => $self->config->description, number_of_orders => $of);
+ } else {
+ my %error_msg = (
+ shop_id => $self->config->id,
+ shop_description => $self->config->description,
+ message => "Error: $data->status_line",
+ error => 1,
+ );
+ %fetched_orders = %error_msg;
+ }
+
+ return \%fetched_orders;
+}
+
sub get_new_orders {
my ($self, $id) = @_;
my $url = $self->url;
- my $ordnumber = $self->config->last_order_number + 1;
+ my $last_order_number = $self->config->last_order_number;
my $otf = $self->config->orders_to_fetch;
my $of = 0;
- my $orders_data = $self->connector->get($url . "api/orders?limit=$otf&filter[0][property]=number&filter[0][expression]=>&filter[0][value]=" . $self->config->last_order_number);
- my $orders_data_json = $orders_data->content;
- my $orders_import = SL::JSON::decode_json($orders_data_json);
-
- if ($orders_import->{success}){
+ my $last_data = $self->connector->get($url . "api/orders/$last_order_number?useNumberAsId=true");
+ my $last_data_json = $last_data->content;
+ my $last_import = SL::JSON::decode_json($last_data_json);
+
+ my $orders_data = $self->connector->get($url . "api/orders?limit=$otf&filter[1][property]=status&filter[1][value]=0&filter[0][property]=id&filter[0][expression]=>&filter[0][value]=" . $last_import->{data}->{id});
+
+ my $dbh = SL::DB->client;
+ my @errors;
+ my %fetched_orders;
+ if ($orders_data->is_success && $orders_data->content_type eq 'application/json'){
+ my $orders_data_json = $orders_data->content;
+ my $orders_import = SL::JSON::decode_json($orders_data_json);
foreach my $shoporder(@{ $orders_import->{data} }){
my $data = $self->connector->get($url . "api/orders/" . $shoporder->{id});
my $data_json = $data->content;
my $import = SL::JSON::decode_json($data_json);
- $self->import_data_to_shop_order($import);
-
- $self->config->assign_attributes( last_order_number => $ordnumber);
- $self->config->save;
- $ordnumber++;
- $of++;
+ $dbh->with_transaction( sub{
+ $self->import_data_to_shop_order($import);
+
+ $self->config->assign_attributes( last_order_number => $shoporder->{number});
+ $self->config->save;
+ 1;
+ })or do {
+ push @errors,($::locale->text('Saving failed. Error message from the database: #1', $dbh->error));
+ };
+
+ if(!@errors){
+ $self->set_orderstatus($shoporder->{id}, "fetched");
+ $of++;
+ }else{
+ flash_later('error', $::locale->text('Database errors: #1', @errors));
+ }
}
+ %fetched_orders = (shop_description => $self->config->description, number_of_orders => $of);
+ } else {
+ my %error_msg = (
+ shop_id => $self->config->id,
+ shop_description => $self->config->description,
+ message => "Error: $orders_data->status_line",
+ error => 1,
+ );
+ %fetched_orders = %error_msg;
}
- my $shop = $self->config->description;
- my %fetched_orders = (shop_id => $self->config->description, number_of_orders => $of);
+
return \%fetched_orders;
}
$shop_order->save;
my $id = $shop_order->id;
- my @positions = sort { Sort::Naturally::ncmp($a->{"partnumber"}, $b->{"partnumber"}) } @{ $import->{data}->{details} };
+ my @positions = sort { Sort::Naturally::ncmp($a->{"articleNumber"}, $b->{"articleNumber"}) } @{ $import->{data}->{details} };
+ #my @positions = sort { Sort::Naturally::ncmp($a->{"partnumber"}, $b->{"partnumber"}) } @{ $import->{data}->{details} };
my $position = 1;
my $active_price_source = $self->config->price_source;
#Mapping Positions
$pos_insert->save;
$position++;
}
- $shop_order->{positions} = $position-1;
+ $shop_order->positions($position-1);
+
+ if ( $self->config->shipping_costs_parts_id ) {
+ my $shipping_part = SL::DB::Part->find_by( id => $self->config->shipping_costs_parts_id);
+ my %shipping_pos = ( description => $import->{data}->{dispatch}->{name},
+ partnumber => $shipping_part->partnumber,
+ price => $import->{data}->{invoiceShipping},
+ quantity => 1,
+ position => $position,
+ shop_trans_id => 0,
+ shop_order_id => $id,
+ );
+ my $shipping_pos_insert = SL::DB::ShopOrderItem->new(%shipping_pos);
+ $shipping_pos_insert->save;
+ }
my $customer = $shop_order->get_customer;
if(ref($customer)){
$shop_order->kivi_customer_id($customer->id);
- $shop_order->save;
}
+ $shop_order->save;
}
sub map_data_to_shoporder {
my $shop_id = $self->config->id;
my $tax_included = $self->config->pricetype;
+
+ # Mapping Zahlungsmethoden muss an Firmenkonfiguration angepasst werden
+ my %payment_ids_methods = (
+ # shopware_paymentId => kivitendo_payment_id
+ );
+ my $default_payment = SL::DB::Manager::PaymentTerm->get_first();
+ my $default_payment_id = $default_payment ? $default_payment->id : undef;
# Mapping to table shoporders. See http://community.shopware.com/_detail_1690.html#GET_.28Liste.29
my %columns = (
amount => $import->{data}->{invoiceAmount},
netamount => $import->{data}->{invoiceAmountNet},
order_date => $orderdate,
payment_description => $import->{data}->{payment}->{description},
- payment_id => $import->{data}->{paymentId},
+ payment_id => $payment_ids_methods{$import->{data}->{paymentId}} || $default_payment_id,
remote_ip => $import->{data}->{remoteAddress},
sepa_account_holder => $import->{data}->{paymentIntances}->{accountHolder},
sepa_bic => $import->{data}->{paymentIntances}->{bic},
my @daten = @{$import->{data}};
my %categories = map { ($_->{id} => $_) } @daten;
+ my @categories_tree;
for(@daten) {
+ # ignore root with id=1
+ if( $_->{id} == 1) {
+ next;
+ }
my $parent = $categories{$_->{parentId}};
- $parent->{children} ||= [];
- push @{$parent->{children}},$_;
+ if($parent && $parent->{id} != 1) {
+ $parent->{children} ||= [];
+ push @{$parent->{children}},$_;
+ } else {
+ push @categories_tree, $_;
+ }
}
- return \@daten;
+ return \@categories_tree;
}
sub get_version {
die unless ref($shop_part) eq 'SL::DB::ShopPart';
my $url = $self->url;
- my $part = SL::DB::Part->new(id => $shop_part->{part_id})->load;
+ my $part = SL::DB::Part->new(id => $shop_part->part_id)->load;
# CVARS to map
my $cvars = { map { ($_->config->name => { value => $_->value_as_text, is_valid => $_->is_valid }) } @{ $part->cvars_by_config } };
my %shop_data;
if($todo eq "price"){
- %shop_data = ( mainDetail => { number => $part->{partnumber},
+ %shop_data = ( mainDetail => { number => $part->partnumber,
prices => [ { from => 1,
price => $price,
customerGroupKey => 'EK',
},
);
}elsif($todo eq "stock"){
- %shop_data = ( mainDetail => { number => $part->{partnumber},
- inStock => $part->{onhand},
+ %shop_data = ( mainDetail => { number => $part->partnumber,
+ inStock => $part->onhand,
},
);
}elsif($todo eq "price_stock"){
- %shop_data = ( mainDetail => { number => $part->{partnumber},
- inStock => $part->{onhand},
+ %shop_data = ( mainDetail => { number => $part->partnumber,
+ inStock => $part->onhand,
prices => [ { from => 1,
price => $price,
customerGroupKey => 'EK',
},
);
}elsif($todo eq "active"){
- %shop_data = ( mainDetail => { number => $part->{partnumber},
+ %shop_data = ( mainDetail => { number => $part->partnumber,
},
- active => ($part->{partnumber} == 1 ? 0 : 1),
+ active => ($part->partnumber == 1 ? 0 : 1),
);
}elsif($todo eq "all"){
# mapping to shopware still missing attributes,metatags
- %shop_data = ( name => $part->{description},
- mainDetail => { number => $part->{partnumber},
- inStock => $part->{onhand},
+ %shop_data = ( name => $part->description,
+ mainDetail => { number => $part->partnumber,
+ inStock => $part->onhand,
prices => [ { from => 1,
price => $price,
customerGroupKey => 'EK',
#attribute => { attr1 => $cvars->{CVARNAME}->{value}, } , #HowTo handle attributes
},
supplier => 'AR', # Is needed by shopware,
- descriptionLong => $shop_part->{shop_description},
+ descriptionLong => $shop_part->shop_description,
active => $shop_part->active,
images => [ @upload_img ],
__options_images => { replace => 1, },
categories => [ @cat ],
- description => $shop_part->{shop_description},
+ description => $shop_part->shop_description,
categories => [ @cat ],
tax => $taxrate,
)
my $upload_content;
my $upload;
my ($import,$data,$data_json);
- my $partnumber = $::form->escape($part->{partnumber});#shopware don't accept / in articlenumber
+ my $partnumber = $::form->escape($part->partnumber);#shopware don't accept / in articlenumber
# Shopware RestApi sends an erroremail if configured and part not found. But it needs this info to decide if update or create a new article
# LWP->post = create LWP->put = update
$data = $self->connector->get($url . "api/articles/$partnumber?useNumberAsId=true");
$import = SL::JSON::decode_json($data_json);
if($import->{success}){
#update
- my $partnumber = $::form->escape($part->{partnumber});#shopware don't accept / in articlenumber
+ my $partnumber = $::form->escape($part->partnumber);#shopware don't accept / in articlenumber
$upload = $self->connector->put($url . "api/articles/$partnumber?useNumberAsId=true", Content => $dataString);
my $data_json = $upload->content;
$upload_content = SL::JSON::decode_json($data_json);
}
# don't know if this is needed
if(@upload_img) {
- my $partnumber = $::form->escape($part->{partnumber});#shopware don't accept / in articlenumber
+ my $partnumber = $::form->escape($part->partnumber);#shopware don't accept / in articlenumber
my $imgup = $self->connector->put($url . "api/generatearticleimages/$partnumber?useNumberAsId=true");
}
return SL::JSON::decode_json($data_json);
}
+sub set_orderstatus {
+ my ($self,$order_id, $status) = @_;
+ if ($status eq "fetched") { $status = 1; }
+ if ($status eq "completed") { $status = 2; }
+ my %new_status = (orderStatusId => $status);
+ my $new_status_json = SL::JSON::to_json(\%new_status);
+ $self->connector->put($self->url . "api/orders/$order_id", Content => $new_status_json);
+}
+
sub init_url {
my ($self) = @_;
$self->url($self->config->protocol . "://" . $self->config->server . ":" . $self->config->port . $self->config->path);
=head1 NAME
-SL::Shopconnecter::Shopware - connector for shopware 5
+SL::Shopconnector::Shopware - connector for shopware 5
=head1 SYNOPSIS
=over 4
+=item C<get_one_order>
+
+Fetches one order specified by ordnumber
+
=item C<get_new_orders>
+Fetches new order by parameters from shop configuration
+
=item C<import_data_to_shop_order>
Creates on shoporder object from json