From 5979c7cb0ee4f7a9991e5d5a88e0188cf72d6147 Mon Sep 17 00:00:00 2001 From: Dima Uryvskiy Date: Fri, 9 Jul 2021 13:46:28 +0300 Subject: [PATCH] Add export functionality --- resources/pot/retailcrm-es_ES.pot | 3 + resources/pot/retailcrm-ru_RU.pot | 4 + src/assets/css/progress-bar.css | 33 +++ src/assets/css/progress-bar.min.css | 1 + .../{whatsapp_icon.css => whatsapp-icon.css} | 0 ...app_icon.min.css => whatsapp-icon.min.css} | 0 src/assets/js/retailcrm-export.js | 152 +++++++++++ .../class-wc-retailcrm-abstracts-settings.php | 88 ++++--- src/include/class-wc-retailcrm-base.php | 154 ++++++------ src/include/class-wc-retailcrm-customers.php | 49 +--- src/include/class-wc-retailcrm-orders.php | 74 +----- src/include/class-wc-retailcrm-uploader.php | 236 ++++++++++++++++++ src/languages/retailcrm-es_ES.mo | Bin 7996 -> 8416 bytes src/languages/retailcrm-ru_RU.mo | Bin 9768 -> 10310 bytes src/retailcrm.php | 2 + tests/test-wc-retailcrm-customers.php | 19 -- tests/test-wc-retailcrm-orders.php | 17 -- tests/test-wc-retailcrm-uploader.php | 145 +++++++++++ 18 files changed, 717 insertions(+), 260 deletions(-) create mode 100644 src/assets/css/progress-bar.css create mode 100644 src/assets/css/progress-bar.min.css rename src/assets/css/{whatsapp_icon.css => whatsapp-icon.css} (100%) rename src/assets/css/{whatsapp_icon.min.css => whatsapp-icon.min.css} (100%) create mode 100644 src/assets/js/retailcrm-export.js create mode 100644 src/include/class-wc-retailcrm-uploader.php create mode 100644 tests/test-wc-retailcrm-uploader.php diff --git a/resources/pot/retailcrm-es_ES.pot b/resources/pot/retailcrm-es_ES.pot index 9128007..23a3f66 100644 --- a/resources/pot/retailcrm-es_ES.pot +++ b/resources/pot/retailcrm-es_ES.pot @@ -271,3 +271,6 @@ msgstr "Se abrirá una ventana de chat con este contacto en WhatsApp" msgid "Introduce the correct phone number" msgstr "Introduce el número de teléfono correcto" +msgid "You can export all orders and customers from CMS to Simla.com by clicking the «Upload» button. This process can take much time and before it is completed, you need to keep the tab open." +msgstr "Presionando el botón «Exportar» puedes descargar a todos los pedidos y clientes de CMS a Simla.com. Este proceso puede llevar mucho tiempo y es necesario mantener abierta la pestaña hasta que termine el proceso." + diff --git a/resources/pot/retailcrm-ru_RU.pot b/resources/pot/retailcrm-ru_RU.pot index ef5d29a..78c86ec 100644 --- a/resources/pot/retailcrm-ru_RU.pot +++ b/resources/pot/retailcrm-ru_RU.pot @@ -280,3 +280,7 @@ msgstr "Будет открыт чат в WhatsApp с данным контак msgid "Introduce the correct phone number" msgstr "Введите корректный номер телефона" +msgid "You can export all orders and customers from CMS to Simla.com by clicking the «Upload» button. This process can take much time and before it is completed, you need to keep the tab open." +msgstr "Вы можете экспортировать все заказы и клиентов из CMS в Simla.com, нажав кнопку «Выгрузить». Этот процесс может занять много времени, и до его завершения необходимо держать вкладку открытой." + + diff --git a/src/assets/css/progress-bar.css b/src/assets/css/progress-bar.css new file mode 100644 index 0000000..7cdc528 --- /dev/null +++ b/src/assets/css/progress-bar.css @@ -0,0 +1,33 @@ +.retail-progress { + border-radius: 18px; + border: 1px solid rgba(122, 122, 122, 0.15); + width: 400px; + height: 18px; + overflow: hidden; + transition: height 0.25s ease; +} + +.retail-progress__loader { + width: 0; + border-radius: 18px; + background: #6427D6; + color: white; + text-align: center; + padding: 0 30px; + font-size: 18px; + font-weight: 600; + transition: width 0.4s ease-in; + line-height: 18px; + box-sizing: border-box; +} + +.retail-hidden { + display: none !important; +} + +.retail-count-data-upload { + margin-bottom: 20px; + size: 30px; + color: #6427D6; + font-weight: bold; +} diff --git a/src/assets/css/progress-bar.min.css b/src/assets/css/progress-bar.min.css new file mode 100644 index 0000000..dfd9da6 --- /dev/null +++ b/src/assets/css/progress-bar.min.css @@ -0,0 +1 @@ +.retail-progress{border-radius:18px;border:1px solid rgba(122,122,122,0.15);width:400px;height:18px;overflow:hidden;transition:height .25s ease}.retail-progress__loader{width:0;border-radius:18px;background:#6427D6;color:#fff;text-align:center;padding:0 30px;font-size:18px;font-weight:600;transition:width .4s ease-in;line-height:18px;box-sizing:border-box}.retail-hidden{display:none!important}.retail-count-data-upload{margin-bottom:20px;size:30px;color:#6427D6;font-weight:700} \ No newline at end of file diff --git a/src/assets/css/whatsapp_icon.css b/src/assets/css/whatsapp-icon.css similarity index 100% rename from src/assets/css/whatsapp_icon.css rename to src/assets/css/whatsapp-icon.css diff --git a/src/assets/css/whatsapp_icon.min.css b/src/assets/css/whatsapp-icon.min.css similarity index 100% rename from src/assets/css/whatsapp_icon.min.css rename to src/assets/css/whatsapp-icon.min.css diff --git a/src/assets/js/retailcrm-export.js b/src/assets/js/retailcrm-export.js new file mode 100644 index 0000000..28f9ba3 --- /dev/null +++ b/src/assets/js/retailcrm-export.js @@ -0,0 +1,152 @@ +jQuery(function () { + function RetailcrmExportForm() + { + this.submitButton = jQuery('button[id="export-orders-submit"]').get(0); + + jQuery(this.submitButton).after('
', {class: 'retail-progress__loader', text: '0%'})) + + window.addEventListener('beforeunload', this.confirmLeave); + }; + + RetailcrmExportForm.prototype.updateProgressBar = function () { + let processedOrders = this.ordersStep * this.ordersStepSize; + + if (processedOrders > this.ordersCount) { + processedOrders = this.ordersCount; + } + + let processedCustomers = this.customersStep * this.customersStepSize; + + if (processedCustomers > this.customersCount) { + processedCustomers = this.customersCount; + } + + const processed = processedOrders + processedCustomers; + const total = this.ordersCount + this.customersCount; + const percents = Math.round(100 * processed / total); + + jQuery(this.progressBar).find('.retail-progress__loader').text(percents + '%'); + jQuery(this.progressBar).find('.retail-progress__loader').css('width', percents + '%'); + jQuery(this.progressBar).find('.retail-progress__loader').attr('title', processed + '/' + total); + }; + + RetailcrmExportForm.prototype.confirmLeave = function (event) { + event.preventDefault(); + event.returnValue = 'Export process has been started'; + } + + RetailcrmExportForm.prototype.exportDone = function () { + window.removeEventListener('beforeunload', this.confirmLeave); + alert('Done'); + } + + window.RetailcrmExportForm = RetailcrmExportForm; + + if (!(typeof RetailcrmExportForm === 'undefined')) { + new window.RetailcrmExportForm(); + } +}); diff --git a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php index d343a1e..3e3a035 100644 --- a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php +++ b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php @@ -23,7 +23,8 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration /** * WC_Retailcrm_Abstracts_Settings constructor. */ - public function __construct() { + public function __construct() + { $this->id = 'integration-retailcrm'; $this->method_title = __('Simla.com', 'retailcrm'); $this->method_description = __('Integration with Simla.com management system.', 'retailcrm'); @@ -35,27 +36,40 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration ) { add_action('init', array($this, 'init_settings_fields'), 99); } + + // Include js scripts + $this->includeJsScripts(); + + // Include css file + $this->includeCssFile(); + + }//end __construct() + + + /** + * In this method we include JS scripts. + * + * @return void + */ + private function includeJsScripts() + { + wp_register_script('retailcrm-export', plugins_url() . '/woo-retailcrm/assets/js/retailcrm-export.js'); + wp_enqueue_script('retailcrm-export'); } - public function ajax_upload() + + /** + * In this method we include CSS file + * + * @return void + */ + private function includeCssFile() { - $ajax_url = admin_url('admin-ajax.php'); - ?> - - array( 'title' => __( 'API of URL', 'retailcrm' ), 'type' => 'text', - 'description' => __( 'Enter API of URL (https://yourdomain.retailcrm.pro).', 'retailcrm' ), + 'description' => __( 'Enter API of URL (https://yourdomain.simla.com).', 'retailcrm' ), 'desc_tip' => true, 'default' => '' ), @@ -418,25 +432,21 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration /** * Uploads options */ - $options = array_filter(get_option(static::$option_key)); + $this->form_fields[] = array( + 'title' => __('Settings of uploading', 'retailcrm'), + 'type' => 'heading', + 'description' => '', + 'id' => 'upload_options' + ); - if (!isset($options['uploads'])) { - $this->form_fields[] = array( - 'title' => __('Settings of uploading', 'retailcrm'), - 'type' => 'heading', - 'description' => '', - 'id' => 'upload_options' - ); - - $this->form_fields['upload-button'] = array( - 'label' => __('Upload', 'retailcrm'), - 'title' => __('Uploading all customers and orders', 'retailcrm' ), - 'type' => 'button', - 'description' => __('Uploading the existing customers and orders to Simla.com', 'retailcrm' ), - 'desc_tip' => true, - 'id' => 'uploads-retailcrm' - ); - } + $this->form_fields['upload-button'] = array( + 'label' => __('Upload', 'retailcrm'), + 'title' => __('Uploading all customers and orders', 'retailcrm'), + 'type' => 'button', + 'description' => __('You can export all orders and customers from CMS to Simla.com by clicking the «Upload» button. This process can take much time and before it is completed, you need to keep the tab open.', 'retailcrm'), + 'desc_tip' => true, + 'id' => 'export-orders-submit' + ); /** * WhatsApp options @@ -636,11 +646,11 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration public function validate_online_assistant_field($key, $value) { $onlineAssistant = $_POST['woocommerce_integration-retailcrm_online_assistant']; - + if (!empty($onlineAssistant) && is_string($onlineAssistant)) { return wp_unslash($onlineAssistant); } - + return ''; } @@ -788,4 +798,4 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration ) ); } -} +} \ No newline at end of file diff --git a/src/include/class-wc-retailcrm-base.php b/src/include/class-wc-retailcrm-base.php index f157795..51405ea 100644 --- a/src/include/class-wc-retailcrm-base.php +++ b/src/include/class-wc-retailcrm-base.php @@ -1,4 +1,5 @@ customers = new WC_Retailcrm_Customers( $this->apiClient, $this->settings, - new WC_Retailcrm_Customer_Address + new WC_Retailcrm_Customer_Address() ); $this->orders = new WC_Retailcrm_Orders( $this->apiClient, $this->settings, new WC_Retailcrm_Order_Item($this->settings), - new WC_Retailcrm_Order_Address, + new WC_Retailcrm_Order_Address(), $this->customers, new WC_Retailcrm_Order($this->settings), new WC_Retailcrm_Order_Payment($this->settings) ); + $this->uploader = new WC_Retailcrm_Uploader($this->apiClient, $this->orders, $this->customers); + // Actions. add_action('woocommerce_update_options_integration_' . $this->id, array($this, 'process_admin_options')); add_filter('woocommerce_settings_api_sanitized_fields_' . $this->id, array($this, 'api_sanitized')); - add_action('admin_bar_menu', array($this, 'add_retailcrm_button'), 100 ); + add_action('admin_bar_menu', array($this, 'add_retailcrm_button'), 100); add_action('woocommerce_checkout_order_processed', array($this, 'retailcrm_process_order'), 10, 1); add_action('retailcrm_history', array($this, 'retailcrm_history_get')); add_action('retailcrm_icml', array($this, 'generate_icml')); add_action('retailcrm_inventories', array($this, 'load_stocks')); add_action('wp_ajax_do_upload', array($this, 'upload_to_crm')); + add_action('wp_ajax_content_upload', array($this, 'count_upload_data'), 99); add_action('wp_ajax_generate_icml', array($this, 'generate_icml')); add_action('wp_ajax_order_upload', array($this, 'order_upload')); - add_action('admin_print_footer_scripts', array($this, 'ajax_upload'), 99); add_action('admin_print_footer_scripts', array($this, 'ajax_generate_icml'), 99); add_action('admin_print_footer_scripts', array($this, 'ajax_selected_order'), 99); add_action('woocommerce_created_customer', array($this, 'create_customer'), 10, 1); @@ -98,7 +105,8 @@ if (!class_exists('WC_Retailcrm_Base')) { add_action('wp_print_footer_scripts', array($this, 'send_analytics'), 99); add_action('woocommerce_new_order', array($this, 'create_order'), 11, 1); - if (!$this->get_option('deactivate_update_order') + if ( + !$this->get_option('deactivate_update_order') || $this->get_option('deactivate_update_order') == static::NO ) { add_action('woocommerce_update_order', array($this, 'update_order'), 11, 1); @@ -155,7 +163,8 @@ if (!class_exists('WC_Retailcrm_Base')) { return $settings; } - public function generate_icml() { + public function generate_icml() + { /* * A temporary solution. * We have rebranded the module and changed the name of the ICML file. @@ -177,14 +186,14 @@ if (!class_exists('WC_Retailcrm_Base')) { $getSites = $this->apiClient->sitesList(); if (empty($getSites['sites']) === false && $getSites->isSuccessful() === true) { - if(empty($getSites['sites'][$codeSite]) === false) { + if (empty($getSites['sites'][$codeSite]) === false) { $dataSite = $getSites['sites'][$codeSite]; if (empty($dataSite['ymlUrl']) === false) { $ymlUrl = $dataSite['ymlUrl']; if (strpos($ymlUrl, 'simla') === false) { - $ymlUrl = str_replace('/retailcrm.xml', '/simla.xml', $ymlUrl); + $ymlUrl = str_replace('/retailcrm.xml', '/simla.xml', $ymlUrl); $dataSite['ymlUrl'] = $ymlUrl; $this->apiClient->sitesEdit($dataSite); @@ -196,14 +205,14 @@ if (!class_exists('WC_Retailcrm_Base')) { $retailCrmIcml = new WC_Retailcrm_Icml(); $retailCrmIcml->generate(); - } /** * Get history */ - public function retailcrm_history_get() { + public function retailcrm_history_get() + { $retailcrm_history = new WC_Retailcrm_History($this->apiClient); $retailcrm_history->getHistory(); } @@ -211,53 +220,28 @@ if (!class_exists('WC_Retailcrm_Base')) { /** * @param int $order_id */ - public function retailcrm_process_order($order_id) { + public function retailcrm_process_order($order_id) + { $this->orders->orderCreate($order_id); } /** * Load stock from retailCRM */ - public function load_stocks() { + public function load_stocks() + { $inventories = new WC_Retailcrm_Inventories($this->apiClient); $inventories->updateQuantity(); } /** * Upload selected orders + * + * @return void */ - public function order_upload() { - $ids = false; - - if (isset($_GET['order_ids_retailcrm'])) { - $appendix = array(); - $ids = explode(',', $_GET['order_ids_retailcrm']); - - foreach ($ids as $key => $id) { - if (stripos($id, '-') !== false) { - $idSplit = explode('-', $id); - - if (count($idSplit) == 2) { - $expanded = array(); - $first = (int) $idSplit[0]; - $last = (int) $idSplit[1]; - - for ($i = $first; $i <= $last; $i++) { - $expanded[] = $i; - } - - $appendix = array_merge($appendix, $expanded); - unset($ids[$key]); - } - } - } - - $ids = array_unique(array_merge($ids, $appendix)); - } - - if ($ids) { - $this->orders->ordersUpload($ids); - } + public function order_upload() + { + $this->uploader->uploadSelectedOrders(); } /** @@ -265,13 +249,14 @@ if (!class_exists('WC_Retailcrm_Base')) { */ public function upload_to_crm() { - $options = array_filter(get_option(static::$option_key)); + $page = filter_input(INPUT_POST, 'RETAILCRM_EXPORT_ORDERS_STEP'); + $entity = filter_input(INPUT_POST, 'Entity'); - $this->customers->customersUpload(); - $this->orders->ordersUpload(); - - $options['uploads'] = static::YES; - update_option(static::$option_key, $options); + if ($entity === 'customer') { + $this->uploader->uploadArchiveCustomers($page); + } else { + $this->uploader->uploadArchiveOrders($page); + } } /** @@ -288,40 +273,41 @@ if (!class_exists('WC_Retailcrm_Base')) { return; } - $client = $this->getApiClient(); + $client = $this->getApiClient(); - if (empty($client)) { - return; - } - - $wcCustomer = new WC_Customer($customer_id); - $email = $wcCustomer->get_billing_email(); - - if (empty($email)) { - $email = $wcCustomer->get_email(); + if (empty($client)) { + return; } - if (empty($email)) { - return; + $wcCustomer = new WC_Customer($customer_id); + $email = $wcCustomer->get_billing_email(); + + if (empty($email)) { + $email = $wcCustomer->get_email(); + } + + if (empty($email)) { + return; } else { - $wcCustomer->set_billing_email($email); - $wcCustomer->save(); + $wcCustomer->set_billing_email($email); + $wcCustomer->save(); } - $response = $client->customersList(array('email' => $email)); + $response = $client->customersList(array('email' => $email)); - if (!empty($response) + if ( + !empty($response) && $response->isSuccessful() && isset($response['customers']) && count($response['customers']) > 0 ) { - $customers = $response['customers']; - $customer = reset($customers); + $customers = $response['customers']; + $customer = reset($customers); - if (isset($customer['id'])) { - $this->customers->updateCustomerById($customer_id, $customer['id']); - $builder = new WC_Retailcrm_WC_Customer_Builder(); - $builder + if (isset($customer['id'])) { + $this->customers->updateCustomerById($customer_id, $customer['id']); + $builder = new WC_Retailcrm_WC_Customer_Builder(); + $builder ->setWcCustomer($wcCustomer) ->setPhones(isset($customer['phones']) ? $customer['phones'] : array()) ->setAddress(isset($customer['address']) ? $customer['address'] : false) @@ -329,7 +315,7 @@ if (!class_exists('WC_Retailcrm_Base')) { ->getResult() ->save(); } - } else { + } else { $this->customers->createCustomer($customer_id); } } @@ -434,7 +420,7 @@ if (!class_exists('WC_Retailcrm_Base')) { */ public function include_whatsapp_icon_style() { - wp_register_style('whatsapp_icon_style', plugins_url() . '/woo-retailcrm/assets/css/whatsapp_icon.min.css', false, '0.1'); + wp_register_style('whatsapp_icon_style', plugins_url() . '/woo-retailcrm/assets/css/whatsapp-icon.min.css', false, '0.1'); wp_enqueue_style('whatsapp_icon_style'); } @@ -458,6 +444,22 @@ if (!class_exists('WC_Retailcrm_Base')) { } + /** + * Rerurn count upload data + */ + public function count_upload_data() + { + echo json_encode( + array( + 'count_orders' => $this->uploader->getCountOrders(), + 'count_users' => $this->uploader->getCountUsers() + ) + ); + + wp_die(); + } + + /** * Get retailcrm api client * diff --git a/src/include/class-wc-retailcrm-customers.php b/src/include/class-wc-retailcrm-customers.php index 5aaa7e7..6ff9b2c 100644 --- a/src/include/class-wc-retailcrm-customers.php +++ b/src/include/class-wc-retailcrm-customers.php @@ -90,42 +90,6 @@ if (!class_exists('WC_Retailcrm_Customers')) : return $this->retailcrm->getCorporateEnabled(); } - /** - * Upload customers to CRM - * - * @param array $ids - * - * @return array mixed - */ - public function customersUpload($ids = array()) - { - if (!$this->retailcrm) { - return null; - } - - $users = get_users(array('include' => $ids)); - $data_customers = array(); - - foreach ($users as $user) { - if (!$this->isCustomer($user)) { - continue; - } - - $customer = $this->wcCustomerGet($user->ID); - $this->processCustomer($customer); - $data_customers[] = $this->customer; - } - - $data = \array_chunk($data_customers, 50); - - foreach ($data as $array_customers) { - $this->retailcrm->customersUpload($array_customers); - time_nanosleep(0, 250000000); - } - - return $data; - } - /** * Create customer in CRM * @@ -335,6 +299,19 @@ if (!class_exists('WC_Retailcrm_Customers')) : return $customerId; } + /** + * Process customer for upload + * + * @param WC_Customer $customer + * + * @return void + */ + public function processCustomerForUpload($customer) + { + $this->processCustomer($customer); + } + + /** * Process customer * diff --git a/src/include/class-wc-retailcrm-orders.php b/src/include/class-wc-retailcrm-orders.php index 67ce678..d176461 100644 --- a/src/include/class-wc-retailcrm-orders.php +++ b/src/include/class-wc-retailcrm-orders.php @@ -62,56 +62,6 @@ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) : $this->order_payment = $order_payment; } - /** - * Upload orders to CRM - * - * @param array $include - * - * @return array $uploadOrders | null - * @throws \Exception - */ - public function ordersUpload($include = array()) - { - if (!$this->retailcrm) { - return null; - } - - $uploader = new WC_Retailcrm_Customers( - $this->retailcrm, - $this->retailcrm_settings, - new WC_Retailcrm_Customer_Address() - ); - - $orders = get_posts(array( - 'numberposts' => -1, - 'post_type' => wc_get_order_types('view-orders'), - 'post_status' => array_keys(wc_get_order_statuses()), - 'include' => $include - )); - - $regularUploadErrors = array(); - $corporateUploadErrors = array(); - - foreach ($orders as $data_order) { - $order = wc_get_order($data_order->ID); - - $errorMessage = $this->orderCreate($data_order->ID); - - if (is_string($errorMessage)) { - if ($this->retailcrm->getCorporateEnabled() && self::isCorporateOrder($order)) { - $corporateUploadErrors[$data_order->ID] = $errorMessage; - } else { - $regularUploadErrors[$data_order->ID] = $errorMessage; - } - } - } - - static::logOrdersUploadErrors($regularUploadErrors, 'Error while uploading these regular orders'); - static::logOrdersUploadErrors($corporateUploadErrors, 'Error while uploading these corporate orders'); - - return array(); - } - /** * Create order. Returns wc_get_order data or error string. * @@ -599,27 +549,5 @@ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) : return $customerWasChanged; } - - /** - * Logs orders upload errors with prefix log message. - * Array keys must be orders ID's in WooCommerce, values must be strings (error messages). - * - * @param array $errors - * @param string $prefix - */ - public static function logOrdersUploadErrors($errors, $prefix = 'Errors while uploading these orders') - { - if (empty($errors)) { - return; - } - - WC_Retailcrm_Logger::add($prefix); - - foreach ($errors as $orderId => $error) { - WC_Retailcrm_Logger::add(sprintf("[%d] => %s", $orderId, $error)); - } - - WC_Retailcrm_Logger::add('=================================='); - } } -endif; +endif; \ No newline at end of file diff --git a/src/include/class-wc-retailcrm-uploader.php b/src/include/class-wc-retailcrm-uploader.php new file mode 100644 index 0000000..e74f43f --- /dev/null +++ b/src/include/class-wc-retailcrm-uploader.php @@ -0,0 +1,236 @@ +retailcrm = $retailcrm; + $this->orders = $orders; + $this->customers = $customers; + } + + + /** + * Uploads selected order in CRM + * + * @return void + * @throws Exception Invalid argument exception. + */ + public function uploadSelectedOrders() + { + $response = filter_input(INPUT_GET, 'order_ids_retailcrm'); + + if (empty($response) === false) { + $ids = array_unique(explode(',', $response)); + + if (empty($ids) === false) { + $this->uploadArchiveOrders(0, $ids); + } + } + } + + + /** + * Uploads archive order in CRM + * + * @param integer $page Number page uploads. + * @param array $ids Ids orders upload. + * + * @return array + * @throws Exception Invalid argument exception. + */ + public function uploadArchiveOrders($page, $ids = array()) + { + if (is_object($this->retailcrm) === false) { + return; + } + + $uploadErrors = array(); + $ordersCms = $this->getCmsOrders($page, $ids); + + foreach ($ordersCms as $dataOrder) { + $orderId = $dataOrder->ID; + $errorMessage = $this->orders->orderCreate($orderId); + + if (is_string($errorMessage) === true) { + $errorMessage = empty($errorMessage) === true ? 'Order exist. External id: ' . $orderId : $errorMessage; + $uploadErrors[$orderId] = $errorMessage; + } + } + + $this->logOrdersUploadErrors($uploadErrors); + + return array(); + } + + + /** + * Uploads archive customer in CRM + * + * @param integer $page Number page uploads. + * + * @return array + * @throws Exception Invalid argument exception. + */ + public function uploadArchiveCustomers($page) + { + if (is_object($this->retailcrm) === false) { + return; + } + + $users = $this->getCmsUsers($page); + + if (empty($users) === false) { + $dataCustomers = array(); + + foreach ($users as $user) { + if ($this->customers->isCustomer($user) === false) { + continue; + } + + $customer = new WC_Customer($user->ID); + $this->customers->processCustomerForUpload($customer); + $dataCustomers[] = $this->customers->getCustomer(); + } + + $this->retailcrm->customersUpload($dataCustomers); + } + + return $dataCustomers; + } + + + /** + * Return orders ids + * + * @param integer $page Number page uploads. + * @param array $ids Ids orders upload. + * + * @return mixed + */ + private function getCmsOrders($page, $ids = array()) + { + return get_posts( + array( + 'numberposts' => self::RETAILCRM_COUNT_OBJECT_UPLOAD, + 'offset' => self::RETAILCRM_COUNT_OBJECT_UPLOAD * $page, + 'post_type' => wc_get_order_types('view-orders'), + 'post_status' => array_keys(wc_get_order_statuses()), + 'include' => $ids, + ) + ); + } + + + /** + * Return count orders + * + * @return integer + */ + public function getCountOrders() + { + global $wpdb; + + $result = $wpdb->get_results("SELECT COUNT(ID) as `count` FROM $wpdb->posts WHERE post_type = 'shop_order'"); + + return empty($result[0]->count) === false ? $result[0]->count : 0; + } + + + /** + * Return users ids + * + * @param integer $page Number page uploads. + * + * @return mixed + */ + private function getCmsUsers($page) + { + return get_users( + array( + 'number' => self::RETAILCRM_COUNT_OBJECT_UPLOAD, + 'offset' => self::RETAILCRM_COUNT_OBJECT_UPLOAD * $page, + ) + ); + } + + + /** + * Return count users + * + * @return integer + */ + public function getCountUsers() + { + $userCount = count_users(); + + return empty($userCount['total_users']) === false ? $userCount['total_users'] : 0; + } + + + /** + * Array keys must be orders ID's in WooCommerce, values must be strings (error messages). + * + * @param array $errors Id order - key and message error - value. + * + * @return void + */ + private function logOrdersUploadErrors($errors) + { + if (empty($errors) === true) { + return; + } + + WC_Retailcrm_Logger::add('Errors while uploading these orders'); + + foreach ($errors as $orderId => $error) { + WC_Retailcrm_Logger::add(sprintf("[%d] => %s", $orderId, $error)); + } + + WC_Retailcrm_Logger::add('=================================='); + } + } +}//end if diff --git a/src/languages/retailcrm-es_ES.mo b/src/languages/retailcrm-es_ES.mo index 189d7482b7b80c5d821f2d491485b092e3bd36e3..e1f8f91f250c1b5866a92598f0f8795889112f86 100644 GIT binary patch delta 1876 zcmYM!UuYaf9Ki9pV6L?`wn?L@)wW|BE78k^U}$U&DbZAk#1c%?RQe!ucavnz-p*xr zPmG9XMIi-|)}Sbj5K2LUQZYfSw7xVTq7My4DTTBYQ4kaqe2`!Zet&xhhP(aD4tw+a zGqbtad$X@{qv?+K6@R0AAK?3Aol+Hir=AOcGwYP%qfT(yfTwUH&f#6SfSd74ybr&v z&ELdb-2Z|5aMOCF25|u8`48|O3H1pBS@0X|#P9KbyoIvB);p^|cmgHBAa27kyc>_> zgLo2KaS!v8J)LCj)=?RW+y&I&e2tN&&o3#V9BY(fdJn@bmVViS&GGfpEP z^)44#cn;-vKcGCfiv9Q}4qz8;lC6CmX{tJnvd&qoum|dE26RhZu03$A=Fi9)>UZqG zHIx>&QD!?H!iVuSl=E{IpTS$W9s9|u4s%GeltoE&ic1>b+)V%PWpIKCX~{flT*k-o z7bK?I-dL?PgYx__l*B{4fHNqS_jAeMD8?zJ-a?wI*0xj&NmI70*No(-b~n?1IXsUs zu@y&<mpakyYB8PMoiLD~si*Msjyoe9sDpG^0BWrnn3rYt&P!c{| zVbI2495tT8XK@ib@HU3n&WY;8d6WdNU=LnL3Al~yAHn_DjTWEBk5LNw3#H;FPP%kt z7fL589SmfTdutPeNKADMC4mt4;u+kJ*H8jA^A1v+I)HRnjnwWvlr5;>QTz;dU_IqC zRIMl-Ie;WuQA4$f8I(iw5f0&3XmLG9S6UpPyti+l1e~eO&!HUNb4WAPd6dJpf^ynd zQ9Ac4vU{q9Ao6x(FnRx{7#v|@9-qd4Q1-5uwB_^`P&zb@tf9&%{~X^#>C}fPhxc=o z&RoHLcpIrfb+bP`IE=CtCs8`Lh*xFs9RoQG^Sau)B|ZCU{khbU*|zk~)adL$`o+}9 z(n9+3hRO@Btn((&_LY(gV{Lq2yRcxxNSmOb^W`XZMY$UbT~R;v+^~+F9`=g9$>y2J zP3yexUZG-$BuH#>+LdgOo&9%5-_rTU{)Wm>Xd}-B zr0lfyb4)@pIp1-0+nm(9^IDacWgEtVY1us~ob*@T|cMZ=1LC1lRCVQjQ-h#19Y`3s{b W3m#)QyQB6rvUg;|`4A7VN+R>_I<{pcZ_OMd%{x3mCvc971BT z84M`ZIXaqn9kpOKX_aFL>#+m3;WR4KFX+KlOvk^d1UAspfydBKnY6X-NKvgH zHP0Z%*aI7*L$&OUGvI^cCu9!$iY2&;Dsc{J7Govu$4l6RgII%WxC={(DhV5qB3UCU z&=wjuM!nQOn@%@3RFb=xj}v$Z7m+p1laa_Y7d5^P6?iKu<1Q@1e!T25dx;d&iZc@l zRG{XmMPjoi)R{S#N&UCe>Ej05ZzIkZ<9L+od2B@=_0ob@P=~W0S;L-U8BSsz{>HuN zWiYW@8ESkDs&Z|pfN$Xe99I4F>CE79T)`3yl4cZJFo=t&0NtFdFlL|@tjB}cj^#Ln z4fqk2p`YxOaW$$U5mY7GP+J>|IyZWdHS7*5fG1dnpRocxJR(}C7Kzb1k>XgNbNvXl z1rykeOSl_DJga(Kn`u;$PE?@1iR+k6(a~XuXRgM0$erhk#80_T VyKG|8J)ahToPT(t*H`6H=RZMrkmmpZ diff --git a/src/languages/retailcrm-ru_RU.mo b/src/languages/retailcrm-ru_RU.mo index 96d71dfb3c995bb4fa0baab7e1776656b72e0756..55142233b51205542202718d75121c8946ab8ba7 100644 GIT binary patch delta 2033 zcmYk+e@xV69KiACC_teI1WPO9p)4)nlI5?IMGH+WbrHHa_=6qC7r21C>+VZRt`2ad z4vS4Rx7u|6Qw@j11LTlji^?^1^?bLsq_uuHbNyknW`DHx^ZmKIt=Qf7_5JaDKR=%5 zIX>Ke;f3h8i*7%r_^ai6Ki?Z^N=0!hodbXIOr`j!2@YBK5#E89F&pP`DgKzc{s;58 z&R(F@5?qE4;#zzXJ-8hQFjrE2&>L{E8AdbD>gYSb+E8vnT-?kQY=hO2T*WUL3|8 zyo5#gH7>_LQ4$tWbqUtt%Xkor@fK!EtA(_&iW@7?jWs9<4xl7Hg*)*Rya)5CQVJ=? zJFy(^!sn2Ws!d%tqm18!5~m*@!5B)Oc`TKwUO<$@6rlw4aF7JeDfg!CAHvn#KaPv= zG8W)>spr3;1WwCIzF&qi?it*KyKx)7i?Y<$Fv_ee7v)Q!ER>}vL}pK|L3v)0ax0QU zRpH}Uk22N$Sc;>#0MITz_!G*S-o(2xi=8Ah zQ-m5f;d-=?;?)Us;}FXDZ%`Vzg_F3D_GJb>BcuD|ekEF{Yl*or4pZvra6t z+K2M~+bD?#Q8xAG$nvWzm?OXc8;KL8{y^yy74s1%$4#J zNW&VG%~yvERj;5Fauj9reSj7CC6;5s!xS%_RdM3MV_1eaaR(Oh-$M365GC*lta9-) zLkXP0G)ds4D+dPC&$v7To{U0Q?LcQny{l$qK0{|mJ;4s`^9HoFHxvxp+S}HqgW*Oi z9MRrDqxN+~>|ncGHHCxix^hRgwu8Fb-`?hR`?%52seNsJU#maRtnC&{&z;^KY72TB z=O%SShiwM~ZoR9;AJL(3&}T&=iA=V))za-9z7}o!+smy)o(8Ka7`C+E)(j?asLisi z#uD90bpgw2l&r0m6-p$ry$w1TvI6dr-}8RS-)xRJecDW!8FS8zIXz}fJ8zluPPdsg zGfo#b;!YP2V`kXtaSm$}a`*I|h^(+oPtH>Mds zO{7_(@26EsY(_}2pI~tbJ~!#sW{8wCPLDRTlGk~YqPm^#|5cdGJ?-=->zPUf9WgUe zsjbV5(aRY3;^dBNGiqiu*E~6iM(DC(@!%W>4iWhUe;MoHPJo+*8j c9!3+TOL?4hIek*9nQ*HX+YUtr{?6O@FW(cnwg3PC delta 1502 zcmXZbZD^Hc7y#gB(;Y46=3IU>O}A{zbbhSVbck9iZ8`hc8f*9?LnzmN^drL}>ZPKj z{6Y`?2|_6a?ZY99sHPAFP=Y8(`dG6;vUq5u9 zEju-S%gd#ywgEnH}Wvcd4yv)$eVdGzrM&S*H<~2V@IcS zD;v0kt!(3~92cp6Fqq)R8AjkMY~sipQkud=i~#L4AwA1T_&RI2mlYgf9lzym{F9Ne z%BmZ=hEMT1&gNN;img`K#(Xy>aV}dJ2{tnl@8Sden3FidDq|s2IF^m9WHY_f{rPnl zH|F=B=K}Y)a6FIjCLYg!KgS4si7~&f zV)(f`xytoww(?EJQUAnDwbMTa5om~U6qUB4da0iA`@G!66g%C+d3=yj>Wp)^kGJy# zyEw%A*lsnq@NJgzQz~W}7^nWR(r~yGlxTy!K)juYF<%V487v8}OjOLr5EYVa=T*D6D#Xa1> zANdULmURX{U@Yi3qld1sos%V5#$Gn_eMY|DGlQ6TnK7|O$4qA{JJ`e3Jjz~<@Sj@8 zr@4pUaV2|Yi-3Jx#4q>=uW&xwlr<{%B46SsoW*RRZ5pTblq0=Bb5fCUmLKK!PjaT~ zzxXgG>Yx^G%stFF>me@Zy$(Do_X=Z!`xx<#F&6YUZ7551(}w?#+ZhQyqa5is#?G%X zcD71cB48(bxS6|ohRxhmJACGSjQL+O5}#r;bE(NrHI=i1wb#vbvO(-*8E10~pI|?u zWHmZ)D?9iyPcusQxag(aM#r3X(obnW^;tT`Xue;$oTL3!ma>H_`5LdisableOriginalConstructor() ->setMethods(array( 'ordersGet', - 'ordersUpload', 'ordersCreate', 'ordersEdit', 'customersGet', - 'customersUpload', 'customersCreate', 'customersEdit' )) @@ -59,23 +57,6 @@ class WC_Retailcrm_Customers_Test extends WC_Retailcrm_Test_Case_Helper $this->assertEquals($wc_customer, $retailcrm_customer->wcCustomerGet($this->customer->get_id())); } - /** - * @param retailcrm - * @dataProvider dataProviderApiClient - */ - public function test_customers_upload($retailcrm) - { - $retailcrm_customer = $this->getRetailcrmCustomer($retailcrm); - $data = $retailcrm_customer->customersUpload(); - - if ($retailcrm) { - $this->assertInternalType('array', $data); - $this->assertInternalType('array', $data[0]); - $this->assertArrayHasKey('externalId', $data[0][0]); - } else { - $this->assertEquals(null, $data); - } - } /** * @param $retailcrm diff --git a/tests/test-wc-retailcrm-orders.php b/tests/test-wc-retailcrm-orders.php index 888a4d5..b68a2e8 100644 --- a/tests/test-wc-retailcrm-orders.php +++ b/tests/test-wc-retailcrm-orders.php @@ -12,7 +12,6 @@ class WC_Retailcrm_Orders_Test extends WC_Retailcrm_Test_Case_Helper ->disableOriginalConstructor() ->setMethods(array( 'ordersGet', - 'ordersUpload', 'ordersCreate', 'ordersEdit', 'customersGet', @@ -26,22 +25,6 @@ class WC_Retailcrm_Orders_Test extends WC_Retailcrm_Test_Case_Helper parent::setUp(); } - /** - * @param $retailcrm - * @dataProvider dataProviderRetailcrm - */ - public function test_order_upload($retailcrm) - { - $this->options = $this->setOptions(); - $retailcrm_orders = $this->getRetailcrmOrders($retailcrm); - $upload_orders = $retailcrm_orders->ordersUpload(); - - if ($retailcrm) { - $this->assertInternalType('array', $upload_orders); - } else { - $this->assertEquals(null, $upload_orders); - } - } /** * @param $retailcrm diff --git a/tests/test-wc-retailcrm-uploader.php b/tests/test-wc-retailcrm-uploader.php new file mode 100644 index 0000000..b2e24be --- /dev/null +++ b/tests/test-wc-retailcrm-uploader.php @@ -0,0 +1,145 @@ +responseMock = $this->getMockBuilder('\WC_Retailcrm_Response') + ->disableOriginalConstructor() + ->setMethods(array( + 'isSuccessful' + )) + ->getMock(); + + $this->apiMock = $this->getMockBuilder('\WC_Retailcrm_Proxy') + ->disableOriginalConstructor() + ->setMethods(array( + 'customersUpload', + 'customersCreate', + 'uploadArchiveCustomers', + 'uploadArchiveOrders', + 'getCountUsers', + 'getCountOrders' + )) + ->getMock(); + + $this->responseMock->expects($this->any()) + ->method('isSuccessful') + ->willReturn(true); + + $this->apiMock->expects($this->any()) + ->method('customersCreate') + ->willReturn($this->responseMock); + + $this->customer = new WC_Customer(); + $this->customer->set_first_name('Tester'); + $this->customer->set_last_name('Tester'); + $this->customer->set_email(uniqid(md5(date('Y-m-d H:i:s'))) . '@mail.com'); + $this->customer->set_billing_email($this->customer->get_email()); + $this->customer->set_password('password'); + $this->customer->set_billing_phone('89000000000'); + $this->customer->set_date_created(date('Y-m-d H:i:s')); + $this->customer->save(); + } + + + /** + * @param retailcrm + * @dataProvider dataProviderApiClient + */ + public function test_customers_upload($retailcrm) + { + $retailcrm_uploader = $this->getRetailcrmUploader($retailcrm); + $data = $retailcrm_uploader->uploadArchiveCustomers(0); + + if ($retailcrm) { + $this->assertInternalType('array', $data); + $this->assertInternalType('array', $data[0]); + $this->assertArrayHasKey('externalId', $data[0]); + } else { + $this->assertEquals(null, $data); + } + } + + + /** + * @param $retailcrm + * @dataProvider dataProviderApiClient + */ + public function test_order_upload($retailcrm) + { + $retailcrm_uploader = $this->getRetailcrmUploader($retailcrm); + $data = $retailcrm_uploader->uploadArchiveOrders(0); + + if ($retailcrm) { + $this->assertInternalType('array', $data); + } else { + $this->assertEquals(null, $data); + } + } + + + /** + * @param retailcrm + * @dataProvider dataProviderApiClient + */ + public function test_get_count_orders_upload($retailcrm) + { + $retailcrm_uploader = $this->getRetailcrmUploader($retailcrm); + $data = $retailcrm_uploader->getCountOrders(); + + if ($retailcrm) { + $this->assertInternalType('int', $data); + } else { + $this->assertEquals(null, $data); + } + } + + + public function dataProviderApiClient() + { + $this->setUp(); + + return array( + array( + 'retailcrm' => $this->apiMock + ), + array( + 'retailcrm' => false + ) + ); + } + + /** + * @param $retailcrm + * + * @return WC_Retailcrm_Customers + */ + private function getRetailcrmUploader($retailcrm) + { + $customer = new WC_Retailcrm_Customers( + $retailcrm, + $this->getOptions(), + new WC_Retailcrm_Customer_Address() + ); + + $order = new WC_Retailcrm_Orders( + $retailcrm, + $this->getOptions(), + new WC_Retailcrm_Order_Item($this->getOptions()), + new WC_Retailcrm_Order_Address, + new WC_Retailcrm_Customers( + $retailcrm, $this->getOptions(), new WC_Retailcrm_Customer_Address + ), + new WC_Retailcrm_Order($this->getOptions()), + new WC_Retailcrm_Order_Payment($this->getOptions()) + ); + + return new WC_Retailcrm_Uploader($retailcrm, $order, $customer); + } +} +