Revision 289c5ed9
Von Werner Hahn vor mehr als 7 Jahren hinzugefügt
SL/Controller/ShopOrder.pm | ||
---|---|---|
32 | 32 |
foreach my $shop_config ( @{ $active_shops } ) { |
33 | 33 |
my $shop = SL::Shop->new( config => $shop_config ); |
34 | 34 |
my $new_orders = $shop->connector->get_new_orders; |
35 |
# push @{ $orders_fetched },@{ $new_orders };
|
|
35 |
push @{ $orders_fetched }, $new_orders ;
|
|
36 | 36 |
}; |
37 |
$main::lxdebug->dump(0, 'WH:OF ',$orders_fetched); |
|
38 | 37 |
|
39 |
# flash('info', t8('#1 shoporders has been fetched', scalar(@{$orders_fetched})-1)); |
|
40 |
$self->action_list; |
|
38 |
foreach my $shop_fetched(@{ $orders_fetched }) { |
|
39 |
flash_later('info', t8('From shop #1 : #2 shoporders has been fetched', $shop_fetched->{shop_id}, $shop_fetched->{number_of_orders})); |
|
40 |
} |
|
41 |
$self->redirect_to(controller => "ShopOrder", action => 'list'); |
|
41 | 42 |
} |
42 | 43 |
|
43 | 44 |
sub action_list { |
... | ... | |
108 | 109 |
die "Can't load shop_order form form->import_id" unless $self->shop_order; |
109 | 110 |
|
110 | 111 |
my $order = $self->shop_order->convert_to_sales_order(customer => $customer, employee => $employee); |
111 |
## price_tax_calculator |
|
112 |
$order->calculate_prices_and_taxes; |
|
113 |
|
|
112 | 114 |
if ($order->{error}){ |
113 | 115 |
flash_later('error',@{$order->{errors}}); |
114 |
$self->redirect_to(controller => "ShopOrder", action => 'show', id => $self->shop_order->id); |
|
116 |
$self->redirect_to(controller => "ShopOrder", action => 'show', id => $self->shop_order->id);
|
|
115 | 117 |
}else{ |
116 | 118 |
$order->save; |
117 | 119 |
|
... | ... | |
190 | 192 |
'phone' => $::form->{$what.'_phone'}, |
191 | 193 |
'email' => $::form->{$what.'_email'}, |
192 | 194 |
'greeting' => $::form->{$what.'_greeting'}, |
193 |
# TODO in shopconfig |
|
194 |
'taxincluded_checked' => $shop->pricetype eq "brutto" ? 1 : 0, |
|
195 |
'taxincluded' => $shop->pricetype eq "brutto" ? 1 : 0, |
|
196 |
'pricegroup_id' => (split '\/',$shop->price_source)[0] eq "pricegroup" ? (split '\/',$shop->price_source)[1] : undef, |
|
197 |
'taxzone_id' => $shop->taxzone_id, |
|
198 |
'currency' => 1, # TODO hardcoded |
|
199 |
#'payment_id' => 7345,# TODO hardcoded |
|
195 |
'taxincluded_checked' => $shop->pricetype eq "brutto" ? 1 : 0, |
|
196 |
'taxincluded' => $shop->pricetype eq "brutto" ? 1 : 0, |
|
197 |
'pricegroup_id' => (split '\/',$shop->price_source)[0] eq "pricegroup" ? (split '\/',$shop->price_source)[1] : undef, |
|
198 |
'taxzone_id' => $shop->taxzone_id, |
|
199 |
'currency' => $::instance_conf->get_currency_id, |
|
200 |
#'payment_id' => 7345,# TODO hardcoded |
|
200 | 201 |
); |
201 | 202 |
my $customer; |
202 | 203 |
if($::form->{cv_id}){ |
... | ... | |
233 | 234 |
# |
234 | 235 |
# Helper |
235 | 236 |
# |
236 |
sub check_address { |
|
237 |
my ($self,%address) = @_; |
|
238 |
my $addressdata = SL::DB::Manager::Customer->get_all( |
|
239 |
query => [ |
|
240 |
or => [ 'name' => { ilike => "%$address{'name'}%" }, 'name' => { ilike => $address{'company'} }, ], |
|
241 |
'street' => { ilike => $address{'street'} }, |
|
242 |
'zipcode'=> { ilike => $address{'zipcode'} }, |
|
243 |
'city' => { ilike => $address{'city'} }, |
|
244 |
]); |
|
245 |
return @{$addressdata}[0]; |
|
246 |
} |
|
247 | 237 |
|
248 | 238 |
sub init_shop_order { |
249 | 239 |
my ( $self ) = @_; |
... | ... | |
251 | 241 |
} |
252 | 242 |
|
253 | 243 |
sub init_transferred { |
254 |
# data for drop down filter options |
|
255 |
|
|
256 | 244 |
[ { title => t8("all"), value => '' }, |
257 | 245 |
{ title => t8("transferred"), value => 1 }, |
258 | 246 |
{ title => t8("not transferred"), value => 0 }, ] |
... | ... | |
290 | 278 |
|
291 | 279 |
=head1 NAME |
292 | 280 |
|
293 |
SL::Controller::ShopOrder - Handles th imported shoporders |
|
281 |
SL::Controller::ShopOrder - Shoporder CRUD Controller |
|
282 |
|
|
283 |
=head1 DESCRIPTION |
|
294 | 284 |
|
295 |
=head1 SYNOPSIS
|
|
285 |
Fetches the shoporders and transfers them to orders.
|
|
296 | 286 |
|
287 |
Relations for shoporders |
|
297 | 288 |
|
298 |
=head1 DESCRIPTION |
|
289 |
=over 2 |
|
290 |
|
|
291 |
=item shop_order_items |
|
292 |
|
|
293 |
=item shops |
|
294 |
|
|
295 |
=item shop_parts |
|
296 |
|
|
297 |
=back |
|
298 |
|
|
299 |
=head1 URL ACTIONS |
|
300 |
|
|
301 |
=over 4 |
|
302 |
|
|
303 |
=item C<action_get_orders> |
|
304 |
|
|
305 |
Fetches the shoporders with the shopconnector class |
|
306 |
|
|
307 |
=item C<action_list> |
|
308 |
|
|
309 |
List the shoporders by different filters. |
|
310 |
From the List you can transfer shoporders into orders in batch where it is possible or one by one. |
|
311 |
|
|
312 |
=item C<action_show> |
|
313 |
|
|
314 |
Shows one order. From here you can apply/change/select customer data and transfer the shoporder to an order. |
|
315 |
|
|
316 |
=item C<action_delete> |
|
317 |
|
|
318 |
Marks the shoporder as obsolete. It's for shoporders you don't want to transfer. |
|
319 |
|
|
320 |
=item C<action_undelete> |
|
321 |
|
|
322 |
Marks the shoporder obsolete = false |
|
323 |
|
|
324 |
=item C<action_transfer> |
|
325 |
|
|
326 |
Transfers one shoporder to an order. |
|
327 |
|
|
328 |
=item C<action_apply_customer> |
|
329 |
|
|
330 |
Applys a new customer from the shoporder. |
|
331 |
|
|
332 |
=back |
|
333 |
|
|
334 |
=head1 TASKSERVER ACTIONS |
|
335 |
|
|
336 |
=over 4 |
|
337 |
|
|
338 |
=item C<action_mass_transfer> |
|
339 |
|
|
340 |
Transfers more shoporders by backgroundjob called from the taskserver to orders. |
|
341 |
|
|
342 |
=item C<action_transfer_status> |
|
343 |
|
|
344 |
Shows the backgroundjobdata for the popup status window |
|
345 |
|
|
346 |
=back |
|
347 |
|
|
348 |
=head1 SETUP |
|
349 |
|
|
350 |
=over 4 |
|
351 |
|
|
352 |
=item C<setup> |
|
353 |
|
|
354 |
=back |
|
355 |
|
|
356 |
=head1 INITS |
|
357 |
|
|
358 |
=over 4 |
|
359 |
|
|
360 |
=item C<init_shoporder> |
|
361 |
|
|
362 |
=item C<init_transfered> |
|
363 |
|
|
364 |
Transferstatuses for the filter dropdown |
|
299 | 365 |
|
366 |
=back |
|
300 | 367 |
|
301 | 368 |
=head1 BUGS |
302 | 369 |
|
303 |
None yet. :)
|
|
370 |
None yet. :) |
|
304 | 371 |
|
305 | 372 |
=head1 AUTHOR |
306 | 373 |
|
307 |
W. Hahn E<lt>wh@futureworldsearch.netE<gt>
|
|
374 |
W. Hahn E<lt>wh@futureworldsearch.netE<gt> |
|
308 | 375 |
|
309 | 376 |
=cut |
SL/DB/ShopOrder.pm | ||
---|---|---|
5 | 5 |
|
6 | 6 |
use strict; |
7 | 7 |
|
8 |
use SL::DB::Shop; |
|
8 | 9 |
use SL::DB::MetaSetup::ShopOrder; |
9 | 10 |
use SL::DB::Manager::ShopOrder; |
10 | 11 |
use SL::DB::Helper::LinkedRecords; |
... | ... | |
42 | 43 |
unless($part){ |
43 | 44 |
push @error_report, t8('Part with partnumber: #1 not found', $_->partnumber); |
44 | 45 |
}else{ |
45 |
my $shop_part = SL::DB::Manager::ShopPart->find_by( shop_id => $self->shop_id, part_id => $part->id ); |
|
46 |
|
|
47 | 46 |
my $current_order_item = SL::DB::OrderItem->new( |
48 | 47 |
parts_id => $part->id, |
49 | 48 |
description => $part->description, |
... | ... | |
51 | 50 |
sellprice => $_->price, |
52 | 51 |
unit => $part->unit, |
53 | 52 |
position => $_->position, |
54 |
active_price_source => $shop_part->active_price_source,
|
|
53 |
active_price_source => $_->active_price_source,
|
|
55 | 54 |
); |
56 | 55 |
} |
57 | 56 |
}@{ $self->shop_order_items }; |
... | ... | |
130 | 129 |
( street % ? AND zipcode ILIKE ?) |
131 | 130 |
OR |
132 | 131 |
email ILIKE ? |
133 |
) |
|
132 |
) AND obsolete = 'F'
|
|
134 | 133 |
SQL |
135 | 134 |
my @values = ($lastname, $company, $self->billing_zipcode, $street, $self->billing_zipcode, $self->billing_email); |
136 | 135 |
my $customers = SL::DB::Manager::Customer->get_objects_from_sql( |
... | ... | |
140 | 139 |
return $customers; |
141 | 140 |
} |
142 | 141 |
|
143 |
#auslagern in eigene subroutine, da auch für andere connectoren genutzt werden muss |
|
144 | 142 |
sub get_customer{ |
145 | 143 |
my ($self, %params) = @_; |
146 |
|
|
144 |
my $shop = SL::DB::Manager::Shop->find_by(id => $self->shop_id); |
|
147 | 145 |
my $customer_proposals = $self->check_for_existing_customers; |
148 | 146 |
my $name = $self->billing_firstname . " " . $self->billing_lastname; |
149 |
my $customer;
|
|
147 |
my $customer = 0;
|
|
150 | 148 |
if(!scalar(@{$customer_proposals})){ |
151 | 149 |
my %address = ( 'name' => $name, |
152 | 150 |
'department_1' => $self->billing_company, |
... | ... | |
160 | 158 |
'fax' => $self->billing_fax, |
161 | 159 |
'phone' => $self->billing_phone, |
162 | 160 |
'ustid' => $self->billing_vat, |
163 |
'taxincluded_checked' => $self->config->pricetype eq "brutto" ? 1 : 0,
|
|
164 |
'taxincluded' => $self->config->pricetype eq "brutto" ? 1 : 0,
|
|
165 |
'pricegroup_id' => (split '\/',$self->config->price_source)[0] eq "pricegroup" ? (split '\/',$self->config->price_source)[1] : undef,
|
|
166 |
'taxzone_id' => $self->config->taxzone_id,
|
|
161 |
'taxincluded_checked' => $shop->pricetype eq "brutto" ? 1 : 0,
|
|
162 |
'taxincluded' => $shop->pricetype eq "brutto" ? 1 : 0,
|
|
163 |
'pricegroup_id' => (split '\/',$shop->price_source)[0] eq "pricegroup" ? (split '\/',$shop->price_source)[1] : undef,
|
|
164 |
'taxzone_id' => $shop->taxzone_id,
|
|
167 | 165 |
'currency' => $::instance_conf->get_currency_id, |
168 | 166 |
#'payment_id' => 7345,# TODO hardcoded |
169 | 167 |
); |
... | ... | |
180 | 178 |
)->save(); |
181 | 179 |
|
182 | 180 |
}elsif(scalar(@{$customer_proposals}) == 1){ |
183 |
# hier überprüfen ob Kundendaten wirklich übereinstimmen auc auf ungültig überprüfen |
|
184 |
$customer = $customer_proposals->[0]; |
|
185 |
}else{ |
|
186 |
# hier überprüfen ob Kundendaten wirklich übereinstimmen und ob es nur einen datensatz gibt auc auf ungültig überprüfen |
|
187 |
$customer = SL::DB::Manager::Customer->find_by( name => $name, |
|
188 |
street => $self->billing_street, |
|
189 |
zipcode => $self->billing_zipcode, |
|
190 |
email => $self->billing_email, |
|
191 |
); |
|
192 |
|
|
181 |
# check if the proposal is the right customer, could be different names under the same address. Depends on how first- and familyname is handled. Here is for customername = companyname or customername = "firstname familyname" |
|
182 |
$customer = SL::DB::Manager::Customer->find_by( id => $customer_proposals->[0]->id, |
|
183 |
name => $name, |
|
184 |
email => $self->billing_email, |
|
185 |
street => $self->billing_street, |
|
186 |
zipcode => $self->billing_zipcode, |
|
187 |
city => $self->billing_city, |
|
188 |
obsolete => 'F', |
|
189 |
); |
|
193 | 190 |
} |
194 |
return \$customer; |
|
191 |
|
|
192 |
return $customer; |
|
195 | 193 |
} |
196 |
## EOF AUslagern |
|
194 |
|
|
197 | 195 |
sub compare_to { |
198 | 196 |
my ($self, $other) = @_; |
199 | 197 |
|
... | ... | |
233 | 231 |
|
234 | 232 |
Returns all found customers as an arrayref of SL::DB::Customer objects. |
235 | 233 |
|
234 |
=item C<get_customer> |
|
235 |
|
|
236 |
returns only one customer from the check_for_existing_customers if the return from it is 0 or 1 customer. |
|
237 |
|
|
238 |
When it is 0 get customer creates a new customer object of the shop order billing data and returns it |
|
239 |
|
|
236 | 240 |
=item C<compare_to> |
237 | 241 |
|
238 | 242 |
=back |
239 | 243 |
|
244 |
=head1 TODO |
|
245 |
|
|
246 |
some variables like payments could be better implemented. Transaction description is hardcoded |
|
247 |
|
|
240 | 248 |
=head1 AUTHORS |
241 | 249 |
|
242 | 250 |
Werner Hahn E<lt>wh@futureworldsearch.netE<gt> |
SL/ShopConnector/Shopware.pm | ||
---|---|---|
33 | 33 |
my $url = $self->url; |
34 | 34 |
my $data = $self->connector->get($url . "api/orders?limit=1", %params); |
35 | 35 |
my $data_json = $data->content; |
36 |
$main::lxdebug->dump(0, 'WH:MAX1 ', $data->content); |
|
37 |
|
|
38 | 36 |
my $import = SL::JSON::decode_json($data_json); |
39 |
$main::lxdebug->dump(0, 'WH:MAX ', $import->{data}); |
|
40 |
|
|
41 | 37 |
} |
42 | 38 |
|
43 | 39 |
sub get_new_orders { |
... | ... | |
47 | 43 |
my $ordnumber = $self->config->last_order_number + 1; |
48 | 44 |
my $otf = $self->config->orders_to_fetch; |
49 | 45 |
my $of = 0; |
50 |
# $self->get_order_max;
|
|
51 |
for(1 .. $otf) {
|
|
46 |
my %params = ( filter => [ property => 'customerId',
|
|
47 |
value => 1,
|
|
52 | 48 |
|
53 |
my $data = $self->connector->get($url . "api/orders/$ordnumber?useNumberAsId=true"); |
|
54 |
my $data_json = $data->content; |
|
55 |
my $import = SL::JSON::decode_json($data_json); |
|
49 |
], |
|
50 |
); |
|
51 |
my @filter = ( { property => 'customerId', |
|
52 |
value => 1, |
|
53 |
} |
|
54 |
|
|
55 |
); |
|
56 |
%params = ( filter => [ @filter ]); |
|
57 |
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); |
|
58 |
my $orders_data_json = $orders_data->content; |
|
59 |
my $orders_import = SL::JSON::decode_json($orders_data_json); |
|
60 |
|
|
61 |
if ($orders_import->{success}){ |
|
62 |
foreach my $shoporder(@{ $orders_import->{data} }){ |
|
63 |
|
|
64 |
my $data = $self->connector->get($url . "api/orders/" . $shoporder->{id}); |
|
65 |
my $data_json = $data->content; |
|
66 |
my $import = SL::JSON::decode_json($data_json); |
|
56 | 67 |
|
57 |
if ($import->{success}){ |
|
58 | 68 |
my $shop_order = $self->map_data_to_shoporder($import); |
59 | 69 |
|
60 | 70 |
$shop_order->save; |
... | ... | |
82 | 92 |
} |
83 | 93 |
$shop_order->{positions} = $position-1; |
84 | 94 |
my $customer = $shop_order->get_customer; |
85 |
if(ref($customer) eq "SL::DB::Customer"){
|
|
95 |
if(ref($customer)){ |
|
86 | 96 |
$shop_order->kivi_customer_id($customer->id); |
87 | 97 |
$shop_order->save; |
88 | 98 |
} |
templates/webpages/shop_order/list.html | ||
---|---|---|
1 | 1 |
[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%] |
2 | 2 |
[% USE Dumper %] |
3 | 3 |
|
4 |
[%- INCLUDE 'common/flash.html' %] |
|
4 | 5 |
<h1>[% title %]<span style="float:right;">[% 'Number data sets' | $T8 %]: [% SHOPORDERS.size %]</span></h1> |
5 | 6 |
[%- PROCESS 'shop_order/_filter.html' filter=SELF.models.filtered.laundered %] |
6 | 7 |
|
... | ... | |
137 | 138 |
</form> |
138 | 139 |
<form method="post" action="controller.pl" name="shop_orders_list" id="shoporderslist"> |
139 | 140 |
[% FOREACH shop_order = SHOPORDERS %] |
140 |
[% IF shop_order.customer.id && shop_order.customer.order_lock == 0 && shop_order.open_invoices == 0 %] [% SET transferable = 1 %] [% SET transferable_class = 'style="background:rgba(43, 208, 54, 0.5);"' %] [% ELSE %] [% SET transferable = 0 %] [% SET transferable_class = '' %][% END %] |
|
141 |
[% # Dumper.dump_html(shop_order) %] |
|
142 |
[% IF shop_order.kivi_customer.id && shop_order.kivi_customer.order_lock == 0 && shop_order.open_invoices == 0 %] [% SET transferable = 1 %] [% SET transferable_class = 'style="background:rgba(43, 208, 54, 0.5);"' %] [% ELSE %] [% SET transferable = 0 %] [% SET transferable_class = '' %][% END %] |
|
141 | 143 |
<tr class="listrow"> |
142 | 144 |
<td>[% HTML.escape(shop_order.host) %]</td> |
143 | 145 |
<td>[% shop_order.order_date.dmy('.') _ ' ' _ shop_order.order_date.hms(':') %]</td> |
... | ... | |
153 | 155 |
<br>[% HTML.escape(shop_order.billing_street) %] |
154 | 156 |
<br>[% HTML.escape(shop_order.billing_zipcode) %] [% HTML.escape(shop_order.billing_city) %] |
155 | 157 |
<br>[% HTML.escape(shop_order.billing_country) %] |
156 |
<br>[% IF shop_order.open_invoices > 0 || shop_order.customer.order_lock == 1 %][% SET alertclass = 'style="background:rgba(255,0,0,1);"' %][% ELSE %][% SET alertclass = '' %][% END %]<span [% alertclass %]> [% HTML.escape(shop_order.customer.customernumber) %] -- [% shop_order.open_invoices %] </span></td> |
|
158 |
<br>[% IF shop_order.open_invoices > 0 || shop_order.customer.order_lock == 1 %][% SET alertclass = 'style="background:rgba(255,0,0,1);"' %][% ELSE %][% SET alertclass = '' %][% END %]<span [% alertclass %]> [% HTML.escape(shop_order.kivi_customer.customernumber) %] -- [% shop_order.open_invoices %] </span></td>
|
|
157 | 159 |
[% IF (shop_order.delivery_lastname != shop_order.billing_lastname || shop_order.delivery_firstname != shop_order.billing_firstname || shop_order.delivery_street != shop_order.billing_street || shop_order.delivery_city != shop_order.billing_city) %] [% SET deliveryclass = 'style="background:rgba(100, 100, 100, 0.5);"' %] [% ELSE %] [% SET deliveryclass = '' %] [% END %] |
158 | 160 |
<td [% deliveryclass %]>[% IF shop_order.customer_company %]<b>[% HTML.escape(shop_order.customer_company) %]</b><br>[% END %] |
159 | 161 |
<b>[% HTML.escape(shop_order.delivery_lastname) %], [% HTML.escape(shop_order.delivery_firstname) %]</b> |
templates/webpages/shop_order/show.html | ||
---|---|---|
133 | 133 |
<tr class="listheading"> |
134 | 134 |
<th colspan="7">Customer Proposals</td> |
135 | 135 |
</tr> |
136 |
[% FOREACH prop = PROPOSALS %][% IF prop.order_lock %][% SET orderlock_class = 'style="background:rgba(232, 32, 23, 0.2);"' %][% END %] |
|
136 |
[% FOREACH prop = PROPOSALS %][% IF prop.order_lock %][% SET orderlock_class = 'style="background:rgba(232, 32, 23, 0.2);"' %][% ELSE %][% SET orderlock_class = '' %][% END %]
|
|
137 | 137 |
<tr class="listrow" [% orderlock_class %]> |
138 | 138 |
<td>[% IF !prop.order_lock %][% L.radio_button_tag('customer', value=prop.id) %][% END %]</td> |
139 | 139 |
<td><a href="controller.pl?action=CustomerVendor/edit&id=[% prop.id %]&db=customer&callback=[% HTML.url('controller.pl?action=ShopOrder/show&id=' _ IMPORT.id) %]">[% HTML.escape(prop.customernumber) %]</a></td> |
Auch abrufbar als: Unified diff
Shopmodul: ShopOrders Verschiedene Sachen aus dem Shopware Connector
ausgelagert. Da diese auch für andere Connectoren gültigkeit haben.
Anzahl der zu holenden Bestellungen anders geregelt. Es werden zuerst
alle Kopfzeilen der Bestellungen geholt und anhand dessen die einzelne
Bestellung. So wird die Schleife nicht überlaufen wenn es keine
Bestellung mehr gibt und Shopware schreibt keinen Fehler.
POD