PluginProbe
AliNext – WooCommerce Dropshipping Plugin for AliExpress / trunk
AliNext – WooCommerce Dropshipping Plugin for AliExpress vtrunk
ali2woo-lite / includes / classes / controller / OrderFulfillmentController.php

OrderFulfillmentController.php in AliNext – WooCommerce Dropshipping Plugin for AliExpress trunk, at includes/classes/controller/OrderFulfillmentController.php

839 lines 34.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Description of OrderFulfillmentController
5 *
6 * @author Ali2Woo Team
7 *
8 * @autoload: a2wl_admin_init
9 *
10 * @ajax: true
11 */
12 // phpcs:ignoreFile WordPress.Security.EscapeOutput.OutputNotEscaped
13 namespace AliNext_Lite;;
14
15 use Pages;
16 use RuntimeException;
17 use Throwable;
18 use WC_Order;
19 use Automattic\WooCommerce\Utilities\OrderUtil;
20
21 class OrderFulfillmentController extends AbstractController
22 {
23 protected ProductShippingDataRepository $ProductShippingDataRepository;
24 protected ProductShippingDataService $ProductShippingDataService;
25 protected WoocommerceService $WoocommerceService;
26 protected Woocommerce $WoocommerceModel;
27 protected OrderFulfillmentService $OrderFulfillmentService;
28 protected ProductService $ProductService;
29 protected ImportedProductServiceFactory $ImportedProductServiceFactory;
30 protected OrderShippingDataService $OrderShippingDataService;
31
32 protected static array $shipping_fields = [];
33 protected static array $additional_shipping_fields = [];
34
35 public function __construct(
36 ProductShippingDataRepository $ProductShippingDataRepository,
37 ProductShippingDataService $ProductShippingDataService,
38 WoocommerceService $WoocommerceService,
39 Woocommerce $WoocommerceModel,
40 OrderFulfillmentService $OrderFulfillmentService,
41 ProductService $ProductService,
42 ImportedProductServiceFactory $ImportedProductServiceFactory,
43 OrderShippingDataService $OrderShippingDataService,
44 ) {
45 parent::__construct(A2WL()->plugin_path() . '/view/');
46
47 $this->ProductShippingDataRepository = $ProductShippingDataRepository;
48 $this->ProductShippingDataService = $ProductShippingDataService;
49 $this->WoocommerceService = $WoocommerceService;
50 $this->WoocommerceModel = $WoocommerceModel;
51 $this->OrderFulfillmentService = $OrderFulfillmentService;
52 $this->ProductService = $ProductService;
53 $this->ImportedProductServiceFactory = $ImportedProductServiceFactory;
54 $this->OrderShippingDataService = $OrderShippingDataService;
55
56 add_action('admin_init', [$this, 'admin_init']);
57
58 add_filter('a2wl_wcol_bulk_actions_init', array($this, 'bulk_actions'));
59 //todo: rudiment method for chrome extension fulfillment
60 add_action('wp_ajax_a2wl_get_aliexpress_order_data', [$this, 'ajax_get_aliexpress_order_data']);
61
62 add_action('wp_ajax_a2wl_load_fulfillment_model', [$this, 'ajaxLoadFulfillmentPopup']);
63 add_action('wp_ajax_a2wl_load_fulfillment_orders', [$this, 'ajax_load_fulfillment_orders_html']);
64 add_action('wp_ajax_a2wl_load_fulfillment_orders_service', [$this, 'ajax_load_fulfillment_orders_service_html']);
65 add_action('wp_ajax_a2wl_save_order_shipping_info', [$this, 'ajax_save_order_shipping_info']);
66
67 add_action('wp_ajax_a2wl_fulfillment_place_order', [$this, 'ajax_load_fulfillment_place_order']);
68
69 add_action('wp_ajax_a2wl_update_fulfillment_shipping', [$this, 'ajax_update_fulfillment_shipping']);
70
71 add_action('wp_ajax_a2wl_sync_order_info', [$this, 'ajax_sync_order_info']);
72
73 add_filter('a2wl_fill_additional_shipping_fields', array($this, 'fill_additional_shipping_fields'), 10, 3);
74 add_action('a2wl_update_custom_shipping_field', [$this, 'update_custom_shipping_field'], 10, 3);
75
76 $this->init();
77 }
78
79 public function admin_init(): void
80 {
81 if (function_exists('WC') && OrderUtil::custom_orders_table_usage_is_enabled()) {
82 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
83 $currentPage = $_REQUEST['page'] ?? '';
84 if ($currentPage === 'wc-orders') {
85 add_action('admin_enqueue_scripts', [$this, 'assets']);
86 add_action('admin_footer', [$this, 'place_orders_bulk_popup']);
87 add_action('admin_footer', [$this, 'place_shipping_modal']);
88 }
89 }
90 else {
91 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
92 $post_type = $_GET['post_type'] ?? ($_REQUEST['post_type'] ?? "");
93 if (is_admin() && $post_type == "shop_order") {
94 add_action('admin_enqueue_scripts', [$this, 'assets']);
95 add_action('admin_footer', [$this, 'place_orders_bulk_popup']);
96 add_action('admin_footer', [$this, 'place_shipping_modal']);
97 }
98 }
99 }
100
101 public function init(): void
102 {
103 $woocommerceCountries = [];
104 if (function_exists('WC')) {
105 $woocommerceCountries = WC()->countries->get_shipping_countries();
106 }
107
108 self::$shipping_fields = apply_filters(
109 'woocommerce_admin_shipping_fields',
110 [
111 'first_name' => array(
112 'label' => esc_html__( 'First name', 'woocommerce' ),
113 'show' => false,
114 ),
115 'last_name' => array(
116 'label' => esc_html__( 'Last name', 'woocommerce' ),
117 'show' => false,
118 ),
119 'company' => array(
120 'label' => esc_html__( 'Company', 'woocommerce' ),
121 'show' => false,
122 ),
123 'address_1' => array(
124 'label' => esc_html__( 'Address line 1', 'woocommerce' ),
125 'show' => false,
126 ),
127 'address_2' => array(
128 'label' => esc_html__( 'Address line 2', 'woocommerce' ),
129 'show' => false,
130 ),
131 'city' => array(
132 'label' => esc_html__( 'City', 'woocommerce' ),
133 'show' => false,
134 ),
135 'postcode' => array(
136 'label' => esc_html__( 'Postcode / ZIP', 'woocommerce' ),
137 'show' => false,
138 ),
139 'country' => array(
140 'label' => esc_html__( 'Country / Region', 'woocommerce' ),
141 'show' => false,
142 'type' => 'select',
143 'class' => 'js_field-country select short',
144 'options' => array( '' => esc_html__( 'Select a country / region&hellip;', 'woocommerce' ) ) + $woocommerceCountries,
145 ),
146 'state' => array(
147 'label' => esc_html__( 'State / County', 'woocommerce' ),
148 'class' => 'js_field-state select short',
149 'show' => false,
150 ),
151 'phone' => array(
152 'label' => esc_html__( 'Phone', 'woocommerce' ),
153 ),
154 ],
155 false,
156 false
157 );
158
159 self::$additional_shipping_fields = apply_filters(
160 'woocommerce_admin_additional_shipping_fields',
161 array(
162 'passport_no' => array(
163 'label' => esc_html__( 'Passport Number', 'ali2woo' ),
164 'show' => false,
165 ),
166 'passport_no_date' => array(
167 'label' => esc_html__( 'Passport Expiry Date', 'ali2woo' ),
168 'show' => false,
169 ),
170 'passport_organization' => array(
171 'label' => esc_html__( 'Passport Issuing Authority', 'ali2woo' ),
172 'show' => false,
173 ),
174 'tax_number' => array(
175 'label' => esc_html__( 'Tax Identification Number', 'ali2woo' ),
176 'show' => false,
177 ),
178 'foreigner_passport_no' => array(
179 'label' => esc_html__( 'Foreign Tax ID', 'ali2woo' ),
180 'show' => false,
181 ),
182 'is_foreigner' => array(
183 'type' => 'checkbox',
184 'label' => esc_html__( 'Is Foreigner', 'ali2woo' ),
185 'show' => false,
186 'cbvalue' => '1',
187 ),
188 'vat_no' => array(
189 'label' => esc_html__( 'VAT Registration Number', 'ali2woo' ),
190 'show' => false,
191 ),
192 'tax_company' => array(
193 'label' => esc_html__( 'Company Name', 'ali2woo' ),
194 'show' => false,
195 ),
196 )
197 );
198 }
199
200 public function assets()
201 {
202 wp_enqueue_style('a2wl-admin-style', A2WL()->plugin_url() . '/assets/css/admin_style.css', array(), A2WL()->version);
203 wp_enqueue_style(
204 'a2wl-admin-fulfillment',
205 A2WL()->plugin_url() . '/assets/css/pages/admin-fulfillment.css',
206 array('a2wl-admin-style'),
207 A2WL()->version
208 );
209
210 wp_enqueue_script('a2wl-admin-script',
211 A2WL()->plugin_url() . '/assets/js/admin_script.js',
212 array('jquery'),
213 A2WL()->version
214 );
215 AbstractAdminPage::localizeAdminScript();
216 wp_enqueue_script('a2wl-ali-orderfulfill-js', A2WL()->plugin_url() . '/assets/js/orderfulfill.js', array('a2wl-admin-script'), A2WL()->version, true);
217
218 wp_enqueue_script('a2wl-sprintf-script', A2WL()->plugin_url() . '/assets/js/sprintf.js', array(), A2WL()->version);
219
220 $lang_data = array(
221 'placing_orders_d_of_d' => _x('Placing orders %d/%d...', 'Status', 'ali2woo'),
222 'please_wait_data_loads' => _x('Please wait, data loads..', 'Status', 'ali2woo'),
223 'process_update_d_of_d_erros_d' => _x('Process update %d of %d. Errors: %d.', 'Status', 'ali2woo'),
224 'process_sync_d_of_d_erros_d' => _x('Process sync %d of %d. Errors: %d.', 'Status', 'ali2woo'),
225 'complete_result_updated_d_erros_d' => _x('Complete! Result updated: %d; errors: %d.', 'Status', 'ali2woo'),
226 'complete_result_sync_d_erros_d' => _x('Complete! Successfully synced: %d; errors: %d.', 'Status', 'ali2woo'),
227 'install_chrome_ext' => _x('Please install and connect to your website the Ali2Woo chrome extension to use this feature.', 'Status', 'ali2woo'),
228 'please_connect_chrome_extension_check_d' => _x('Please connect the Chrome extension to your store and then continue. Need help? Check out <a href="%s">the instruction</a>', 'Status', 'ali2woo'),
229 'we_found_old_order' => _x('We found an old order fulfillment process and removed it. Press the "Continue" button.', 'Status', 'ali2woo'),
230 'login_into_aliexpress_account' => _x('Please switch to AliExpress tab and login into your AliExpress account.', 'Status', 'ali2woo'),
231 'detected_old_aliexpress_interface' => _x('Detected old AliExpress interface. Please contact Ali2Woo support.', 'Status', 'ali2woo'),
232 'your_customer_address_entered' => _x('Your customer address is entered. Wait...', 'Status', 'ali2woo'),
233 'product_is_added_to_cart' => _x('Product (%d) is added to the cart. Wait...', 'Status', 'ali2woo'),
234 'all_products_are_added' => _x('All products are added to the cart. Wait...', 'Status', 'ali2woo'),
235 'cart_is_cleared' => _x('The previous cart data is cleared. Wait...', 'Status', 'ali2woo'),
236 'get_no_responces_from_chrome_ext_d' => _x('Get no responces from the chrome extension for 30s. Check out <a href="%s">the instruction</a>', 'Status', 'ali2woo'),
237 'fill_order_note' => _x('Filling order notes...', 'Status', 'ali2woo'),
238 'cant_add_product_to_cart_d' => _x('Can`t add this product to the cart. Switch to AliExpress and choose another one or add a similar product from another supplier manually. Then continue. Check out <a href="%s">the instruction</a>', 'Status', 'ali2woo'),
239 'please_type_customer_address' => _x('Please switch to AliExpress tab, type the address or skip this order.', 'Status', 'ali2woo'),
240 'please_input_captcha' => _x('Please switch to AliExpress and input the Captcha code manually or wait for your Captcha solver to do the job...', 'Status', 'ali2woo'),
241 'order_is_placed' => _x('The order is placed. Wait...', 'Status', 'ali2woo'),
242 'internal_aliexpress_error' => _x('Internal AliExpress error. Please continue to try again or skip this order.', 'Status', 'ali2woo'),
243 'all_orders_are_placed' => _x('All orders are placed! Click "Orders List" to be directed to the orders list on the AliExpress website.', 'Status', 'ali2woo'),
244 'cant_process_your_orders' => _x('We can`t process your orders. Check out the "Status Page" for more details.', 'Status', 'ali2woo'),
245 'cant_get_order_id' => _x('Can`t get the external order ID, please copy it manually to your WC order. Then continue.', 'Status', 'ali2woo'),
246 'payment_is_failed' => _x('The payment is failed, please finish this order manually. Then continue.', 'Status', 'ali2woo'),
247 'done_pay_manually' => _x('Please switch to AliExpress and pay for the order.', 'Status', 'ali2woo'),
248 'choose_payment_method' => _x('Please switch to AliExpress and choose payment method.', 'Status', 'ali2woo'),
249
250 'please_activate_right_store_apikey_in_chrome' => _x('This website is not connected to the Ali2Woo chrome extension. Please check that you choose right API key.', 'Status', 'ali2woo'),
251
252 'bad_product_id' => _x('Can`t find the WC order with a given ID.', 'Status', 'ali2woo'),
253 'no_variable_data' => _x('This order has a variable product but doesn`t contain the variable data for some reason. Check out <a href="%s">the instruction</a>', 'Status', 'ali2woo'),
254 'no_product_url' => _x('This order doesn`t contain the `product_url` field for some reason. Check out <a href="%s">the instruction</a>', 'Status', 'ali2woo'),
255 'no_ali_products' => _x('No AliExpress products in the current order. Check out <a href="%s">the instruction</a>', 'Status', 'ali2woo'),
256
257 'unknown_error' => _x('Unknown error occured. Please contact support.', 'Status', 'ali2woo'),
258 'server_error' => _x('Server error. Continue to try again.', 'Status', 'ali2woo'),
259 );
260
261 $data = [
262 'ajaxurl' => admin_url('admin-ajax.php'),
263 'nonce_action' => wp_create_nonce(self::AJAX_NONCE_ACTION),
264 'lang' => $lang_data,
265 ];
266
267 wp_localize_script('a2wl-ali-orderfulfill-js', 'a2wl_ali_orderfulfill_js', $data);
268
269 $lang_data = [
270 'sync_failed_in_fulfillment_popup' => esc_html_x(
271 'Product can`t be synchronized, so its shipping information cannot be loaded.',
272 'Status',
273 'ali2woo'
274 ),
275 ];
276 wp_localize_script('a2wl-admin-script', 'a2wl_sync_data', ['lang' => $lang_data]);
277 }
278
279 public function bulk_actions(array $bulk_actions): array
280 {
281 $bulk_actions['a2wl_order_place_bulk'] = esc_html__("Place on AliExpress", 'ali2woo');
282 $bulk_actions['a2wl_order_sync_bulk'] = esc_html__("Sync with AliExpress", 'ali2woo');
283
284 return $bulk_actions;
285 }
286
287 public function fill_additional_shipping_fields($additional_shipping_fields, $order, $country = false)
288 {
289 if (!$country) {
290 $country = $this->get_order_shipping_to_country($order);
291 }
292
293 $rutMetaKey = get_setting('fulfillment_rut_meta_key', '');
294
295 $custom_attributes = [];
296
297 $value = '';
298
299 if (empty($rutMetaKey)) {
300 $custom_attributes['disabled'] = 'disabled';
301 } else {
302 $value = get_post_meta($order->get_id(), $rutMetaKey, true);
303 }
304
305 $additional_shipping_fields['rut'] = [
306 'id' => 'rut',
307 'description' => esc_html__('You have to configure RUT meta field in the plugin settings', 'ali2woo'),
308 'desc_tip' => true,
309 'label' => esc_html__( 'RUT', 'ali2woo' ),
310 'show' => false,
311 'wrapper_class' => '_shipping_rut '.($country !== 'CL' ? 'hidden' : ''),
312 'custom_attributes' => $custom_attributes,
313 'value' => $value,
314 'custom' => [
315 'meta_key' => $rutMetaKey
316 ]
317 ];
318
319 $cpfMetaKey = get_setting('fulfillment_cpf_meta_key', '');
320
321 $custom_attributes = [];
322
323 $value = '';
324
325 if (empty($cpfMetaKey)) {
326 $custom_attributes['disabled'] = 'disabled';
327 } else {
328 $value = get_post_meta($order->get_id(), $cpfMetaKey, true);
329 }
330
331 $additional_shipping_fields['cpf'] = [
332 'id' => 'cpf',
333 'description' => esc_html__('You have to configure CPF meta field in the plugin settings', 'ali2woo'),
334 'desc_tip' => true,
335 'label' => esc_html__( 'CPF', 'ali2woo' ),
336 'show' => false,
337 'wrapper_class' => '_shipping_cpf '.($country !== 'BR' ? 'hidden' : ''),
338 'custom_attributes' => $custom_attributes,
339 'value' => $value,
340 'custom' => [
341 'meta_key' => $cpfMetaKey
342 ]
343 ];
344
345 $passportSetting = get_setting(Settings::SETTING_FULFILLMENT_PASSPORT_NUMBER, '');
346 if ($passportSetting !== '') {
347 $additional_shipping_fields['passport_no']['value'] = $passportSetting;
348 } else {
349 $additional_shipping_fields['passport_no']['value'] = get_post_meta(
350 $order->get_id(),
351 '_shipping_passport_no',
352 true
353 );
354 }
355
356 $foreignTaxIdSetting = get_setting(Settings::SETTING_FULFILLMENT_FOREIGN_TAX_ID, '');
357 if ($foreignTaxIdSetting !== '') {
358 $additional_shipping_fields['foreigner_passport_no']['value'] = $foreignTaxIdSetting;
359 } else {
360 $additional_shipping_fields['foreigner_passport_no']['value'] = get_post_meta(
361 $order->get_id(),
362 '_shipping_foreigner_passport_no',
363 true
364 );
365 }
366
367 $isForeignerSetting = get_setting(Settings::SETTING_FULFILLMENT_IS_FOREIGNER, false);
368 if ($isForeignerSetting) {
369 $additional_shipping_fields['is_foreigner']['value'] = '1';
370 } else {
371 $additional_shipping_fields['is_foreigner']['value'] = get_post_meta($order->get_id(), '_shipping_is_foreigner', true);
372 }
373
374 return $additional_shipping_fields;
375 }
376
377 public function update_custom_shipping_field($key, $field, $order): void
378 {
379 // phpcs:ignore WordPress.Security.NonceVerification.Missing
380 if (in_array($key, ['rut', 'cpf']) && $field['custom']['meta_key'] && !empty($_POST[$key])) {
381 // phpcs:ignore WordPress.Security.NonceVerification.Missing
382 update_post_meta($order->get_id(), $field['custom']['meta_key'], $_POST[$key]);
383 }
384 }
385
386 public function place_orders_bulk_popup()
387 {
388 $this->include_view('includes/place_orders_bulk_popup.php');
389 }
390
391 public function place_shipping_modal()
392 {
393 $this->model_put('countries', WC()->countries->get_countries());
394 $this->model_put('disableCountryTo', true);
395 $this->include_view('includes/shipping-modal/modal.php');
396 }
397
398 public function ajax_get_aliexpress_order_data(): void
399 {
400 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
401
402 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
403 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
404 echo wp_json_encode($result);
405 wp_die();
406 }
407
408 $post_id = $_POST['id'] ?? false;
409
410 if (!$post_id) {
411 $result = ResultBuilder::buildError('', array('error_code' => -1));
412 echo wp_json_encode($result);
413 wp_die();
414 }
415
416 $post_id = intval($post_id);
417
418 $order = new WC_Order($post_id);
419
420 try {
421 $result = $this->OrderShippingDataService->buildOrderContent($order, $post_id);
422 } catch (RuntimeException $e) {
423 $result = ResultBuilder::buildError('', array('error_code' => $e->getCode()));
424 }
425
426 echo wp_json_encode($result);
427 wp_die();
428 }
429
430 public function ajaxLoadFulfillmentPopup(): void
431 {
432 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
433
434 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
435 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
436 echo wp_json_encode($result);
437 wp_die();
438 }
439
440 if (EditionHelper::isLite()) {
441 $purchase_code = 1;
442 } else {
443 $purchase_code = Account::getInstance()->get_purchase_code();
444 }
445
446 $this->model_put('purchase_code', $purchase_code);
447 $this->include_view('order-fulfillment/fulfillment_modal.php');
448
449 wp_die();
450 }
451
452 public function get_order_shipping_to_country($order): string
453 {
454 $shipping_address = $order->get_address('shipping');
455 if (empty($shipping_address['country'])) {
456 $shipping_address = $order->get_address('billing');
457 }
458
459 $AliexpressHelper = A2WL()->getDI()->get('AliNext_Lite\AliexpressHelper');
460
461 return $AliexpressHelper->convertToAliexpressCountryCode($shipping_address['country']);
462 }
463
464 /**
465 * On order fulfillment popup loading
466 * @return void
467 */
468 public function ajax_load_fulfillment_orders_html(): void
469 {
470 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
471
472 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
473 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
474 echo wp_json_encode($result);
475 wp_die();
476 }
477
478 $ids = array_map(
479 'intval',
480 isset($_POST['ids']) ? (is_array($_POST['ids']) ? $_POST['ids'] : [$_POST['ids']]) : []
481 );
482
483 $orders = [];
484 if (!empty($ids)) {
485 foreach ($ids as $order_id) {
486 $orders[] = new WC_Order($order_id);
487 }
488 }
489
490 $is_wpml = $this->isWpml();
491
492 try {
493 $orders_data = $this->OrderFulfillmentService->getFulfillmentOrdersData($orders, $is_wpml);
494 } catch (RepositoryException|ServiceException $Exception) {
495 $this->model_put("text", $Exception->getMessage());
496 $this->include_view("order-fulfillment/error_container.php");
497 wp_die();
498 }
499
500 if (empty($orders_data)) {
501 $text = esc_html__("Orders not found", 'ali2woo');
502 $this->model_put("text", $text);
503 $this->include_view("order-fulfillment/error_container.php");
504 } else {
505 $this->model_put("shipping_fields", self::$shipping_fields);
506 $this->model_put("additional_shipping_fields", self::$additional_shipping_fields);
507 $this->model_put("countries", WC()->countries->get_countries());
508 $this->model_put('ProductShippingDataRepository', $this->ProductShippingDataRepository);
509 $this->model_put("ProductShippingDataService", $this->ProductShippingDataService);
510 $this->model_put("ImportedProductServiceFactory", $this->ImportedProductServiceFactory);
511
512 foreach ($orders_data as $order_data) {
513 $urls_to_data = '';
514 if (!empty($order_data['sign_urls'])) {
515 $urls_to_data = implode(';', $order_data['sign_urls']);
516 }
517
518 $this->model_put("order_data", $order_data);
519 $this->model_put("urls_to_data", $urls_to_data);
520 $this->include_view("order-fulfillment/single_order_container.php");
521 }
522 }
523
524 wp_die();
525 }
526
527 public function ajax_load_fulfillment_orders_service_html(): void
528 {
529 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
530
531 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
532 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
533 echo wp_json_encode($result);
534 wp_die();
535 }
536
537 //todo: should support single id only!
538 $ids = array_map(
539 'intval',
540 isset($_POST['ids']) ? (is_array($_POST['ids']) ? $_POST['ids'] : [$_POST['ids']]) : []
541 );
542
543 // $orders = [];
544 if (!empty($ids)) {
545 foreach ($ids as $order_id) {
546 // $orders[] = new WC_Order($order_id);
547 $WC_Order = new WC_Order($order_id);
548 }
549 }
550
551 $is_wpml = $this->isWpml();
552
553 $orderData = $this->OrderFulfillmentService->getFulfillmentOrderServiceData($WC_Order, $is_wpml);
554
555 if (!($orderData)) {
556 wp_die();
557 }
558
559 $columns = [
560 [
561 'title' => esc_html__('Item', 'ali2woo'),
562 'class' => 'name',
563 'colspan' => 2,
564 ],
565 [
566 'title' => esc_html__('Shipping Company', 'ali2woo'),
567 'class' => 'shipping_company',
568 ],
569 [
570 'title' => esc_html__('Delivery Time', 'ali2woo'),
571 'class' => 'delivery_time',
572 ],
573 [
574 'title' => esc_html__('Shipping Cost', 'ali2woo'),
575 'class' => 'shipping_cost',
576 ],
577 [
578 'title' => esc_html__('Cost', 'ali2woo'),
579 'class' => 'cost',
580 ],
581 [
582 'title' => esc_html__('Total', 'ali2woo'),
583 'class' => 'total',
584 ],
585 [
586 'title' => '',
587 'class' => 'actions',
588 ]
589 ];
590
591 $this->model_put("table_class", 'service-fulfillment-order-items');
592 $this->model_put("columns", $columns);
593 $this->model_put("order_data", $orderData);
594 $this->include_view("order-fulfillment/partials/table_order_items.php");
595
596 wp_die();
597 }
598
599 public function ajax_save_order_shipping_info(): void
600 {
601 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
602
603 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
604 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
605 echo wp_json_encode($result);
606 wp_die();
607 }
608
609 $shipping_to_country = $_POST['_shipping_country'] ?? false;
610
611 if (empty($_POST['order_id'])) {
612 $result = ResultBuilder::buildError('waiting for order id');
613 echo wp_json_encode($result);
614 wp_die();
615 }
616
617 // Get order object.
618 $order = wc_get_order($_POST['order_id']);
619 $props = [];
620
621 $additional_shipping_fields = apply_filters(
622 'a2wl_fill_additional_shipping_fields',
623 self::$additional_shipping_fields,
624 $order,
625 $shipping_to_country
626 );
627
628 $shipping_fields = array_merge(self::$shipping_fields, $additional_shipping_fields);
629
630 // Update shipping fields.
631 if ( !empty($shipping_fields)) {
632 foreach ($shipping_fields as $key => $field) {
633 if (!isset($field['id'])) {
634 $field['id'] = '_shipping_' . $key;
635 }
636
637 if (!isset($_POST[$field['id']])) {
638 continue;
639 }
640
641 if (!empty($field['custom'])) {
642 do_action('a2wl_update_custom_shipping_field', $key, $field, $order);
643 } else {
644 if (is_callable(array($order, 'set_shipping_' . $key))) {
645 $props['shipping_' . $key] = wc_clean(wp_unslash($_POST[$field['id']]));
646 } else {
647 $order->update_meta_data($field['id'], wc_clean(wp_unslash($_POST[$field['id']])));
648 }
649 }
650 }
651 }
652
653 // Save order data.
654 $order->set_props($props);
655 $order->save();
656
657 if ($shipping_to_country) {
658 foreach ($order->get_items() as $item) {
659 $WC_Product = $item->get_product();
660
661 $quantity = $item->get_quantity();
662 $countryFromCode = 'CN';
663 try {
664 $importedProduct = $this->WoocommerceService
665 ->updateProductShippingItems($WC_Product, $shipping_to_country, $countryFromCode, $quantity);
666
667 $shippingItems = $this->ProductService->getShippingItems(
668 $importedProduct, $shipping_to_country, $countryFromCode
669 );
670 } catch (RepositoryException|ServiceException $Exception) {
671 a2wl_error_log($Exception->getMessage());
672 continue;
673 }
674
675 $ShippingItemDto = $this->ProductService->findDefaultFromShippingItems(
676 $shippingItems, $importedProduct
677 );
678
679 $shipping_meta_data = $item->get_meta(Shipping::get_order_item_shipping_meta_key());
680 $shipping_meta_data = $shipping_meta_data ? json_decode($shipping_meta_data, true) :
681 [
682 'company' => '',
683 'service_name' => '',
684 'delivery_time' => '',
685 'shipping_cost' => '',
686 'quantity' => $item->get_quantity(),
687 'cost_added' => true
688 ];
689
690 foreach ($shippingItems as $shippingItem) {
691 if ($shippingItem['serviceName'] === $ShippingItemDto->getMethodName()) {
692 $shipping_meta_data['company'] = $shippingItem['company'];
693 $shipping_meta_data['service_name'] = $shippingItem['serviceName'];
694 $shipping_meta_data['shipping_cost'] = $shippingItem['freightAmount']['value'];
695 $shipping_meta_data['delivery_time'] = $shippingItem['time'];
696 }
697 }
698
699 $item->update_meta_data(
700 Shipping::get_order_item_shipping_meta_key(), wp_json_encode($shipping_meta_data)
701 );
702 $item->save_meta_data();
703 }
704 }
705
706 echo wp_json_encode(ResultBuilder::buildOK());
707 wp_die();
708 }
709
710 public function ajax_update_fulfillment_shipping(): void
711 {
712 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
713
714 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
715 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
716 echo wp_json_encode($result);
717 wp_die();
718 }
719
720 $errorText = _x('Shipping method not found', 'error text', 'ali2woo');
721 $result = ResultBuilder::buildError($errorText);
722
723 $is_wpml = $this->isWpml();
724
725 $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
726 $shiping_to_country = $_POST['shiping_to_country'] ?? false;
727 $items = isset($_POST['items']) && is_array($_POST['items']) ? $_POST['items'] : [];
728
729 $order_items = [];
730 foreach ($items as $item) {
731 $order_items[] = new OrderItemShippingDto($item['order_item_id'], $item['shipping']);
732 }
733
734 if ($shiping_to_country && $order_id) {
735 $order = new WC_Order($order_id);
736
737 $UpdateFulfillmentShippingResult = $this->OrderFulfillmentService->updateFulfillmentShipping(
738 $order, $order_items, $shiping_to_country, $is_wpml
739 );
740
741 $result = ResultBuilder::buildOk(['result' => [
742 'order_id' => $order_id,
743 'total_order_price' => wc_price(
744 $UpdateFulfillmentShippingResult->getTotalOrderPrice(),
745 ['currency' => $order->get_currency()]
746 ),
747 'items' => $UpdateFulfillmentShippingResult->getResultItems(),
748 ]]);
749 } else {
750 $errorText = _x('wrong params', 'error text', 'ali2woo');
751 $result = ResultBuilder::buildError($errorText);
752 }
753
754 echo wp_json_encode($result);
755 wp_die();
756 }
757
758 public function ajax_load_fulfillment_place_order(): void
759 {
760 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
761
762 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
763 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
764 echo wp_json_encode($result);
765 wp_die();
766 }
767
768 $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
769 $orderItemsIds = isset($_POST['items']) && is_array($_POST['items']) ?
770 array_map('intval', $_POST['items']) : [];
771
772 if ($order_id && $orderItemsIds) {
773 $WC_Order = new WC_Order($order_id);
774 $OrderItems = [];
775 foreach ($WC_Order->get_items() as $orderItem) {
776 if (in_array($orderItem->get_id(), $orderItemsIds)) {
777 $OrderItems[] = $orderItem;
778 }
779 }
780 $result = $this->OrderFulfillmentService->placeOrder($WC_Order, $OrderItems);
781 } else {
782 $result = ResultBuilder::buildError('Wrong params');
783 }
784
785 echo wp_json_encode($result);
786 wp_die();
787 }
788
789 public function ajax_sync_order_info(): void
790 {
791 check_admin_referer(self::AJAX_NONCE_ACTION, self::NONCE);
792
793 if (!PageGuardHelper::canAccessPage(Pages::ORDER_MANAGEMENT)) {
794 $result = ResultBuilder::buildError($this->getErrorTextNoPermissions());
795 echo wp_json_encode($result);
796 wp_die();
797 }
798
799 if (empty($_POST['order_id'])) {
800 $result = ResultBuilder::buildError('wrong params');
801 } else {
802
803 $orderId = intval($_POST['order_id']);
804 a2wl_init_error_handler();
805 try {
806 $result = ResultBuilder::buildOk();
807 $WC_Order = wc_get_order($orderId);
808 if (!$WC_Order) {
809 $errorMessage = esc_html_x('Order not found', 'error text', 'ali2woo');
810 $result = ResultBuilder::buildError($errorMessage);
811 }
812
813 $this->WoocommerceService->syncOrderWithAliexpress($WC_Order);
814
815 } catch (Throwable $Exception) {
816 a2wl_print_throwable($Exception);
817 $result = ResultBuilder::buildError($Exception->getMessage());
818 }
819 }
820
821 echo wp_json_encode($result);
822 wp_die();
823 }
824
825 private function isWpml(): bool
826 {
827 $is_wpml = false;
828 if (is_plugin_active('sitepress-multilingual-cms/sitepress.php')) {
829 $default_lang = apply_filters('wpml_default_language', null);
830 $current_language = apply_filters('wpml_current_language', null);
831 if ($current_language && $current_language !== $default_lang) {
832 $is_wpml = true;
833 }
834 }
835
836 return $is_wpml;
837 }
838 }
839