From a23e96b4d6fccd07927756f1c3d4653319f01ae1 Mon Sep 17 00:00:00 2001 From: Kocmonavtik <61938582+Kocmonavtik@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:49:00 +0300 Subject: [PATCH] Transferring base price of goods for loyalty program (#342) --- CHANGELOG.md | 3 + VERSION | 2 +- doc/1.Setup/Cron tasks.md | 3 +- resources/pot/retailcrm-es_ES.pot | 31 ++- resources/pot/retailcrm-ru_RU.pot | 31 ++- src/assets/js/retailcrm-cron-info.js | 6 +- .../class-wc-retailcrm-abstracts-settings.php | 35 ++- .../api/class-wc-retailcrm-client-v5.php | 17 ++ src/include/class-wc-retailcrm-base.php | 39 +++ src/include/class-wc-retailcrm-icml.php | 11 +- src/include/class-wc-retailcrm-loyalty.php | 7 +- src/include/class-wc-retailcrm-plugin.php | 8 + ...ass-wc-retailcrm-upload-discount-price.php | 238 ++++++++++++++++++ .../order/class-wc-retailcrm-order-item.php | 10 +- src/languages/retailcrm-es_ES.l10n.php | 12 +- src/languages/retailcrm-es_ES.mo | Bin 18403 -> 19864 bytes src/languages/retailcrm-ru_RU.l10n.php | 12 +- src/languages/retailcrm-ru_RU.mo | Bin 22678 -> 24418 bytes src/readme.txt | 5 +- src/retailcrm.php | 3 +- src/uninstall.php | 2 +- .../datasets/data-upload-price-retailcrm.php | 56 +++++ ...est-wc-retailcrm-upload-discount-price.php | 74 ++++++ 23 files changed, 586 insertions(+), 19 deletions(-) create mode 100644 src/include/class-wc-retailcrm-upload-discount-price.php create mode 100644 tests/datasets/data-upload-price-retailcrm.php create mode 100644 tests/test-wc-retailcrm-upload-discount-price.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ce47b43..e950806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2024-09-13 4.8.4 +* Updated work with promotional items when loyalty program is enabled + ## 2024-09-11 4.8.3 * Added loyalty program coupon entry in the form by click diff --git a/VERSION b/VERSION index f99c658..57c4b30 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.8.3 +4.8.4 diff --git a/doc/1.Setup/Cron tasks.md b/doc/1.Setup/Cron tasks.md index c468c05..5fc51f2 100644 --- a/doc/1.Setup/Cron tasks.md +++ b/doc/1.Setup/Cron tasks.md @@ -14,6 +14,7 @@ 'icml' => 'three_hours', 'history' => 'five_minutes', 'inventories' => 'fiveteen_minutes', + 'loyalty_upload_price' => 'four_hours' ] ``` > Важно! При использовании фильтра **retailcrm_cron_schedules**, можно использовать ключи: 'icml', 'history', 'inventories'. @@ -49,5 +50,3 @@ function change_cron_tasks($cronTasks) return $cronTasks; } ``` - - diff --git a/resources/pot/retailcrm-es_ES.pot b/resources/pot/retailcrm-es_ES.pot index a09c4d5..13c0093 100644 --- a/resources/pot/retailcrm-es_ES.pot +++ b/resources/pot/retailcrm-es_ES.pot @@ -451,8 +451,11 @@ msgstr "Programa de fidelización" msgid "Activate program loyalty" msgstr "Activar programa de fidelización" -msgid "Enable this setting for activate program loyalty on site" -msgstr "Activa esta configuración para activar programa de fidelización en la página web" +msgid "Attention! When activating the loyalty program, the method of ICML catalog generation changes. Details in" +msgstr "¡Atención! Al activar el programa de fidelización, cambia el método de generación del catálogo ICML. Detalles en la" + +msgid "documentation loyalty program" +msgstr "documentación del programa de fidelización" msgid "Terms of loyalty program" msgstr "Condiciones del programa de fidelización" @@ -591,3 +594,27 @@ msgstr "Utiliza el cupón:" msgid "Points will be awarded upon completion of the order:" msgstr "Los puntos se concederán al finalizar el pedido:" + +msgid "Unloading promotional prices of offers" +msgstr "Descarga de precios promocionales de ofertas comerciales" + +msgid "Every 4 hours" +msgstr "Cada 4 horas" + +msgid "Upload prices now" +msgstr "Descargar precios ahora" + +msgid "Uploaded discount price" +msgstr "Descarga de precios promocionales" + +msgid "This functionality loads the promotional prices offers into Simla.com" +msgstr "Esta función carga los precios promocionales de las ofertas comerciales en Simla.com" + +msgid "Promotional prices unloaded" +msgstr "Se han cargado los precios promocionales" + +msgid "Woocommerce promotional price" +msgstr "Precio promocional Woocommerce" + +msgid "Promotional price type for Woocommerce store, generated automatically. Necessary for correct synchronization work when loyalty program is enabled (Do not delete. Do not deactivate)" +msgstr "Tipo de precio promocional para la tienda Woocommerce, generado automáticamente. Necesario para el correcto funcionamiento de la sincronización cuando el programa de fidelización está habilitado (No eliminar. No desactivar)" diff --git a/resources/pot/retailcrm-ru_RU.pot b/resources/pot/retailcrm-ru_RU.pot index d6cf7c0..53fdc24 100644 --- a/resources/pot/retailcrm-ru_RU.pot +++ b/resources/pot/retailcrm-ru_RU.pot @@ -460,8 +460,11 @@ msgstr "Программа лояльности" msgid "Activate program loyalty" msgstr "Активировать программу лояльности" -msgid "Enable this setting for activate program loyalty on site" -msgstr "Активируйте эту настройку для активации программы лояльности на сайте" +msgid "Attention! When activating the loyalty program, the method of ICML catalog generation changes. Details in" +msgstr "Внимание! При активации программы лояльности, изменяется способ генерации ICML каталога. Подробности в" + +msgid "documentation loyalty program" +msgstr "документации программы лояльности" msgid "Terms of loyalty program" msgstr "Условия программы лояльности" @@ -600,3 +603,27 @@ msgstr "Используйте купон:" msgid "Points will be awarded upon completion of the order:" msgstr "По завершению заказа будет начислено баллов:" + +msgid "Unloading promotional prices of offers" +msgstr "Выгрузка акционных цен торговых предложений" + +msgid "Every 4 hours" +msgstr "Каждые 4 часа" + +msgid "Upload prices now" +msgstr "Выгрузить цены сейчас" + +msgid "Uploaded discount price" +msgstr "Выгрузка акционных цен" + +msgid "This functionality loads the promotional prices offers into Simla.com" +msgstr "Эта функция загружает акционные цены торговых предложений в Simla.com" + +msgid "Promotional prices unloaded" +msgstr "Акционные цены выгружены" + +msgid "Woocommerce promotional price" +msgstr "Акционная цена Woocommerce" + +msgid "Promotional price type for Woocommerce store, generated automatically. Necessary for correct synchronization work when loyalty program is enabled (Do not delete. Do not deactivate)" +msgstr "Акционный тип цены для магазина Woocommerce, сгенерированный автоматически. Необходим для корректной работы синхронизации при включенной программы лояльности (Не удалять. Не деактивировать)" diff --git a/src/assets/js/retailcrm-cron-info.js b/src/assets/js/retailcrm-cron-info.js index 25083e3..5ca2076 100644 --- a/src/assets/js/retailcrm-cron-info.js +++ b/src/assets/js/retailcrm-cron-info.js @@ -16,6 +16,7 @@ jQuery(function () { this.history = 0; this.inventories = 0; this.messageSuccessful = ''; + this.loyaltyUploadPrice = 0; this.adminUrl = AdminUrl.url; @@ -33,12 +34,14 @@ jQuery(function () { _this.icml = response.icml; _this.inventories = response.inventories; _this.messageSuccessful = response.translate.tr_successful; + _this.loyaltyUploadPrice = response.loyaltyUploadPrice _this.displayInfoAboutCron( response.translate.tr_td_cron, response.translate.tr_td_icml, response.translate.tr_td_history, response.translate.tr_td_inventories, + response.translate.tr_td_loyaltyUploadPrice ); }) @@ -47,7 +50,7 @@ jQuery(function () { jQuery(this.submitButton).click(this.clearCronTasks); } - RetailcrmCronInfo.prototype.displayInfoAboutCron = function (cron, icml, history, inventories) { + RetailcrmCronInfo.prototype.displayInfoAboutCron = function (cron, icml, history, inventories, loyaltyUploadPrice) { this.table = jQuery(this.title).next(); this.table.append(''); this.infoTable = jQuery('tbody[class="retail-debug-info"]').get(0); @@ -56,6 +59,7 @@ jQuery(function () { jQuery(this.infoTable).append("" + icml + " " + this.icml + ""); jQuery(this.infoTable).append("" + history + " " + this.history + ""); jQuery(this.infoTable).append("" + inventories + " " + this.inventories + ""); + jQuery(this.infoTable).append("" + loyaltyUploadPrice + "" + this.loyaltyUploadPrice + ""); } RetailcrmCronInfo.prototype.clearCronTasks = function () { diff --git a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php index 9adf83b..8f7cb1a 100644 --- a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php +++ b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php @@ -72,6 +72,25 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration + + __('Loyalty program', 'retailcrm'), 'class' => 'checkbox', 'type' => 'checkbox', - 'description' => __('Enable this setting for activate program loyalty on site', 'retailcrm') + 'description' => '' . + __('Attention! When activating the loyalty program, the method of ICML catalog generation changes. Details in', 'retailcrm') . + ' <\b>' . __("documentation loyalty program", "retailcrm") ]; $this->form_fields['loyalty_terms'] = [ @@ -651,6 +672,18 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration ), ]; + $this->form_fields[] = [ + 'label' => __('Upload prices now', 'retailcrm'), + 'title' => __('Uploaded discount price', 'retailcrm'), + 'type' => 'button', + 'desc_tip' => true, + 'id' => 'upload-loyalty-price-retailcrm', + 'description' => __( + 'This functionality loads the promotional prices offers into Simla.com', + 'retailcrm' + ), + ]; + $this->form_fields['icml'] = [ 'label' => __('Generating ICML', 'retailcrm'), 'title' => __('Generating ICML catalog by wp-cron', 'retailcrm'), diff --git a/src/include/api/class-wc-retailcrm-client-v5.php b/src/include/api/class-wc-retailcrm-client-v5.php index 9d58993..e682805 100644 --- a/src/include/api/class-wc-retailcrm-client-v5.php +++ b/src/include/api/class-wc-retailcrm-client-v5.php @@ -3037,6 +3037,23 @@ class WC_Retailcrm_Client_V5 ); } + public function getPriceTypes() + { + return $this->client->makeRequest( + '/reference/price-types', + WC_Retailcrm_Request::METHOD_GET + ); + } + + public function editPriceType($priceType) + { + return $this->client->makeRequest( + sprintf('/reference/price-types/%s/edit', $priceType['code']), + WC_Retailcrm_Request::METHOD_POST, + ['priceType' => json_encode($priceType)] + ); + } + /** * Return current site * diff --git a/src/include/class-wc-retailcrm-base.php b/src/include/class-wc-retailcrm-base.php index c2404d5..9f8b65b 100644 --- a/src/include/class-wc-retailcrm-base.php +++ b/src/include/class-wc-retailcrm-base.php @@ -127,6 +127,9 @@ if (!class_exists('WC_Retailcrm_Base')) { add_action('woocommerce_applied_coupon', [$this, 'apply_coupon'], 11, 1); add_action('woocommerce_review_order_before_payment', [$this, 'reviewCreditBonus'], 11, 1); add_action('wp_trash_post', [$this, 'trash_order_action'], 10, 1); + add_action('retailcrm_loyalty_upload_price', [$this, 'upload_loyalty_price']); + add_action('admin_print_footer_scripts', [$this, 'ajax_upload_loyalty_price'], 99); + add_action('wp_ajax_upload_loyalty_price', [$this, 'upload_loyalty_price']); if ( !$this->get_option('deactivate_update_order') @@ -190,12 +193,23 @@ if (!class_exists('WC_Retailcrm_Base')) { */ public function api_sanitized($settings) { + $isLoyaltyUploadPrice = false; + + if ( + isset($settings['icml'], $settings['loyalty']) + && $settings['icml'] === static::YES + && $settings['loyalty'] === static::YES + ) { + $isLoyaltyUploadPrice = true; + } + $timeInterval = apply_filters( 'retailcrm_cron_schedules', [ 'icml' => 'three_hours', 'history' => 'five_minutes', 'inventories' => 'fiveteen_minutes', + 'loyalty_upload_price' => 'four_hours' ] ); @@ -223,6 +237,12 @@ if (!class_exists('WC_Retailcrm_Base')) { wp_clear_scheduled_hook('retailcrm_icml'); } + if ($isLoyaltyUploadPrice && !wp_next_scheduled('retailcrm_loyalty_upload_price')) { + wp_schedule_event(time(), $timeInterval['loyalty_upload_price'], 'retailcrm_loyalty_upload_price'); + } elseif (!$isLoyaltyUploadPrice) { + wp_clear_scheduled_hook('retailcrm_loyalty_upload_price'); + } + if (!$this->get_errors() && !get_option('retailcrm_active_in_crm')) { $this->activate_integration($settings); } @@ -268,6 +288,7 @@ if (!class_exists('WC_Retailcrm_Base')) { wp_clear_scheduled_hook('retailcrm_icml'); wp_clear_scheduled_hook('retailcrm_history'); wp_clear_scheduled_hook('retailcrm_inventories'); + wp_clear_scheduled_hook('retailcrm_loyalty_upload_price'); //Add new cron tasks $this->api_sanitized($this->settings); @@ -361,6 +382,16 @@ if (!class_exists('WC_Retailcrm_Base')) { } } + public function upload_loyalty_price() + { + if (!$this->apiClient instanceof WC_Retailcrm_Proxy) { + return null; + } + + $discountPriceUpload = new WC_Retailcrm_Upload_Discount_Price($this->apiClient); + $discountPriceUpload->upload(); + } + /** * Get history * @@ -930,12 +961,15 @@ if (!class_exists('WC_Retailcrm_Base')) { $icml = $defaultValue; $history = $defaultValue; $inventories = $defaultValue; + $loyaltyUploadPrice = $defaultValue; + $translate = [ 'tr_td_cron' => __('Cron launches', 'retailcrm'), 'tr_td_icml' => __('Generation ICML', 'retailcrm'), 'tr_td_history' => __('Syncing history', 'retailcrm'), 'tr_successful' => __('Cron tasks cleared', 'retailcrm'), 'tr_td_inventories' => __('Syncing inventories', 'retailcrm'), + 'tr_td_loyaltyUploadPrice' => __('Unloading promotional prices of offers', 'retailcrm') ]; if (isset($this->settings['history']) && $this->settings['history'] == static::YES) { @@ -944,6 +978,10 @@ if (!class_exists('WC_Retailcrm_Base')) { if (isset($this->settings['icml']) && $this->settings['icml'] == static::YES) { $icml = date('H:i:s d-m-Y', wp_next_scheduled('retailcrm_icml')); + + if (isset($this->settings['loyalty']) && $this->settings['loyalty'] === static::YES) { + $loyaltyUploadPrice = date('H:i:s d-m-Y', wp_next_scheduled('retailcrm_loyalty_upload_price')); + } } if (isset($this->settings['sync']) && $this->settings['sync'] == static::YES) { @@ -956,6 +994,7 @@ if (!class_exists('WC_Retailcrm_Base')) { 'icml' => $icml, 'inventories' => $inventories, 'translate' => $translate, + 'loyaltyUploadPrice' => $loyaltyUploadPrice ] ); diff --git a/src/include/class-wc-retailcrm-icml.php b/src/include/class-wc-retailcrm-icml.php index 5d0875f..9edc4c8 100644 --- a/src/include/class-wc-retailcrm-icml.php +++ b/src/include/class-wc-retailcrm-icml.php @@ -38,6 +38,8 @@ if (!class_exists('WC_Retailcrm_Icml')) : protected $unloadServices = false; + protected $activeLoyalty = false; + /** * WC_Retailcrm_Icml constructor. * @@ -53,6 +55,10 @@ if (!class_exists('WC_Retailcrm_Icml')) : isset($this->settings['icml_unload_services']) && $this->settings['icml_unload_services'] === WC_Retailcrm_Base::YES ); + + if (isset($this->settings['loyalty']) && $this->settings['loyalty'] === WC_Retailcrm_Base::YES) { + $this->activeLoyalty = true; + } } public function changeBindBySku($useXmlId) @@ -251,7 +257,10 @@ if (!class_exists('WC_Retailcrm_Icml')) : 'productId' => ($product->get_parent_id() > 0) ? $parent->get_id() : $product->get_id(), 'name' => $product->get_name(), 'productName' => ($product->get_parent_id() > 0) ? $parent->get_title() : $product->get_title(), - 'price' => wc_get_price_including_tax($product), + 'price' => $this->activeLoyalty + ? wc_get_price_including_tax($product, ["price" => $product->get_regular_price()]) + : wc_get_price_including_tax($product) + , 'picture' => $images, 'url' => ($product->get_parent_id() > 0) ? $parent->get_permalink() : $product->get_permalink(), 'quantity' => $quantity, diff --git a/src/include/class-wc-retailcrm-loyalty.php b/src/include/class-wc-retailcrm-loyalty.php index 8b9902c..282cfce 100644 --- a/src/include/class-wc-retailcrm-loyalty.php +++ b/src/include/class-wc-retailcrm-loyalty.php @@ -450,11 +450,14 @@ if (!class_exists('WC_Retailcrm_Loyalty')) : foreach ($cartItems as $item) { $product = $item['data']; + $productRegularPrice = wc_get_price_including_tax($product, ["price" => $product->get_regular_price()]); + $discount = $productRegularPrice - ($item['line_total'] / $item['quantity']); + $order['items'][] = [ 'offer' => $useXmlId ? ['xmlId' => $product->get_sku()] : ['externalId' => $product->get_id()], 'quantity' => $item['quantity'], - 'initialPrice' => wc_get_price_including_tax($product), - 'discountManualAmount' => ($item['line_subtotal'] - $item['line_total']) / $item['quantity'] + 'initialPrice' => $productRegularPrice, + 'discountManualAmount' => $discount ]; } diff --git a/src/include/class-wc-retailcrm-plugin.php b/src/include/class-wc-retailcrm-plugin.php index 1e9bdac..7a91dd3 100644 --- a/src/include/class-wc-retailcrm-plugin.php +++ b/src/include/class-wc-retailcrm-plugin.php @@ -58,6 +58,10 @@ class WC_Retailcrm_Plugin 'fiveteen_minutes' => [ 'interval' => 900, // seconds 'display' => __('Every 15 minutes') + ], + 'four_hours' => [ + 'interval' => 14400, //seconds + 'display' => __('Every 4 hours') ] ], apply_filters('retailcrm_add_cron_interval', $schedules) @@ -116,6 +120,10 @@ class WC_Retailcrm_Plugin if (wp_next_scheduled('retailcrm_inventories')) { wp_clear_scheduled_hook('retailcrm_inventories'); } + + if (wp_next_scheduled('retailcrm_loyalty_upload_price')) { + wp_clear_scheduled_hook('retailcrm_loyalty_upload_price'); + } } /** diff --git a/src/include/class-wc-retailcrm-upload-discount-price.php b/src/include/class-wc-retailcrm-upload-discount-price.php new file mode 100644 index 0000000..c36101d --- /dev/null +++ b/src/include/class-wc-retailcrm-upload-discount-price.php @@ -0,0 +1,238 @@ +settings = get_option(WC_Retailcrm_Base::$option_key); + $this->apiClient = $aplClient; + + if (isset($this->settings['loyalty']) && $this->settings['loyalty'] === WC_Retailcrm_Base::YES) { + $this->activeLoyalty = true; + } + } + + public function upload() + { + if (!$this->activeLoyalty) { + return; + } + + $error = $this->uploadSettings(); + + if ($error !== '') { + writeBaseLogs($error); + + return; + } + + $productStatuses = $this->getProductStatuses(); + + if (!$productStatuses) { + $productStatuses = ['publish']; + } + + $page = 1; + $requestData = []; + + do { + $products = wc_get_products( + [ + 'limit' => 1000, + 'status' => $productStatuses, + 'page' => $page, + 'paginate' => true + ] + ); + + /** WP version >= 6 */ + if (function_exists('wp_cache_flush_runtime')) { + wp_cache_flush_runtime(); + } else { + wp_cache_flush(); + } + + if (empty($products)) { + writeBaseLogs('Can`t get products!'); + + return; + } + + try { + foreach ($products->products as $offer) { + $type = $offer->get_type(); + + if (strpos($type, 'variable') !== false || strpos($type, 'variation') !== false) { + foreach ($offer->get_children() as $childId) { + $childProduct = wc_get_product($childId); + + if (!$childProduct) { + continue; + } + + $sendOffer = $this->getOfferData($childProduct); + + if ($sendOffer !== []) { + $requestData[] = $sendOffer; + } + } + } else { + $sendOffer = $this->getOfferData($offer); + + if ($sendOffer !== []) { + $requestData[] = $sendOffer; + } + } + } + + $chunks = array_chunk($requestData, 250); + + foreach ($chunks as $chunk) { + $this->apiClient->storePricesUpload($chunk, $this->site); + time_nanosleep(0, 200000000); + } + + unset($chunks); + } catch (\Throwable $exception) { + writeBaseLogs($exception->getMessage() . PHP_EOL . $exception->getTraceAsString()); + + return; + } + + ++$page; + } while ($page <= $products->max_num_pages); + } + + private function getOfferData(WC_Product $product) + { + $currentPrice = wc_get_price_including_tax($product); + $defaultPrice = wc_get_price_including_tax($product, ["price" => $product->get_regular_price()]); + + if ($currentPrice === $defaultPrice) { + return []; + } + + return [ + 'externalId' => $product->get_id(), + 'site' => $this->site, + 'prices' => [ + [ + 'code' => self::DISCOUNT_TYPE_PRICE, + 'price' => $currentPrice + ] + ] + ]; + } + + private function getProductStatuses() + { + $statuses = []; + + foreach (get_post_statuses() as $key => $value) { + if (isset($this->settings['p_' . $key]) && $this->settings['p_' . $key] == WC_Retailcrm_Base::YES) { + $statuses[] = $key; + } + } + + return $statuses; + } + + private function uploadSettings() + { + if (!$this->apiClient instanceof WC_Retailcrm_Proxy + && !$this->apiClient instanceof WC_Retailcrm_Client_V5 + ) { + return 'API client has not been initialized'; + } + + $this->site = $this->apiClient->getSingleSiteForKey(); + + if (empty($this->site)) { + return 'Error with CRM credentials: need an valid apiKey assigned to one certain site'; + } + + $response = $this->apiClient->getPriceTypes(); + + if ( + !$response instanceof WC_Retailcrm_Response + || !$response->offsetExists('priceTypes') + || empty($response['priceTypes']) + ) { + return 'Error getting price types'; + } + + $defaultPrice = null; + $discountPriceType = null; + + foreach ($response['priceTypes'] as $priceType) { + if ($priceType['default'] === true) { + $defaultPrice = $priceType; + } + + if ($priceType['code'] === self::DISCOUNT_TYPE_PRICE) { + $discountPriceType = $priceType; + } + } + + if ($discountPriceType === null) { + $discountPriceType = [ + 'code' => self::DISCOUNT_TYPE_PRICE, + 'name' => __('Woocommerce promotional price', 'retailcrm'), + 'active' => true, + 'description' => __('Promotional price type for Woocommerce store, generated automatically. + Necessary for correct synchronization work when loyalty program is enabled + (Do not delete. Do not deactivate)', 'retailcrm'), + 'ordering' => 999, + 'promo' => true + ]; + + if (isset($defaultPrice['geo'])) { + $discountPriceType['geo'] = $defaultPrice['geo']; + } + + if (isset($defaultPrice['groups'])) { + $discountPriceType['groups'] = $defaultPrice['groups']; + } + + if (isset($defaultPrice['currency'])) { + $discountPriceType['currency'] = $defaultPrice['currency']; + } + + if (isset($defaultPrice['filterExpression'])) { + $discountPriceType['filterExpression'] = $defaultPrice['filterExpression']; + } + + $response = $this->apiClient->editPriceType($discountPriceType); + + if (!$response instanceof WC_Retailcrm_Response || !$response['success']) { + return 'Error creating price type'; + } + } elseif ($discountPriceType['active'] === false || $discountPriceType['promo'] === false) { + $discountPriceType['active'] = true; + $discountPriceType['promo'] = true; + + $response = $this->apiClient->editPriceType($discountPriceType); + + if (!$response instanceof WC_Retailcrm_Response || !$response['success']) { + return 'Error activate price type'; + } + } + + return ''; + } + } + +endif; diff --git a/src/include/order/class-wc-retailcrm-order-item.php b/src/include/order/class-wc-retailcrm-order-item.php index 38b0a59..dd55769 100644 --- a/src/include/order/class-wc-retailcrm-order-item.php +++ b/src/include/order/class-wc-retailcrm-order-item.php @@ -106,7 +106,12 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data */ private function calculatePrice(WC_Order_Item_Product $item, int $decimalPlaces) { - $price = ($item['line_subtotal'] / $item->get_quantity()) + ($item['line_subtotal_tax'] / $item->get_quantity()); + if (isset($this->settings['loyalty']) && $this->settings['loyalty'] === WC_Retailcrm_Base::YES) { + $product = $item->get_product(); + $price = wc_get_price_including_tax($product, ["price" => $product->get_regular_price()]); + } else { + $price = ($item['line_subtotal'] / $item->get_quantity()) + ($item['line_subtotal_tax'] / $item->get_quantity()); + } return round($price, $decimalPlaces); } @@ -124,7 +129,8 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data int $decimalPlaces, $crmItem = null ) { - if ($crmItem) { + + if ($crmItem && isset($this->settings['loyalty']) && $this->settings['loyalty'] === WC_Retailcrm_Base::YES) { $loyaltyDiscount = 0; foreach ($crmItem['discounts'] as $discount) { diff --git a/src/languages/retailcrm-es_ES.l10n.php b/src/languages/retailcrm-es_ES.l10n.php index 5d58e8e..38195ad 100644 --- a/src/languages/retailcrm-es_ES.l10n.php +++ b/src/languages/retailcrm-es_ES.l10n.php @@ -202,7 +202,8 @@ return [ "Los bienes con la opción 'virtual' activada se cargarán en Simla como servicios", "Loyalty program" => "Programa de fidelización", "Activate program loyalty" => "Activar programa de fidelización", - "Enable this setting for activate program loyalty on site" => "Activa esta configuración para activar el programa de fidelización en la página web", + "Attention! When activating the loyalty program, the method of ICML catalog generation changes. Details in" => "¡Atención! Al activar el programa de fidelización, cambia el método de generación del catálogo ICML. Detalles en la", + "documentation loyalty program" => "documentación del programa de fidelización", "Terms of loyalty program" => "Condiciones del programa de fidelización", "Insert the terms and conditions of the loyalty program" => "Inserte las condiciones del programa de fidelización", "Conditions of personal data processing" => "Condiciones de procesamiento de datos personales", @@ -248,6 +249,15 @@ return [ "bonuses" => "bonificaciones", "Use coupon:" => "Utiliza el cupón:", "Points will be awarded upon completion of the order:" => "Los puntos se concederán al finalizar el pedido:", + "Unloading promotional prices of offers" => "Descarga de precios promocionales de ofertas comerciales", + "Every 4 hours" => "Cada 4 horas", + "Upload prices now" => "Descargar precios ahora", + "Uploaded discount price" => "Descarga de precios promocionales", + "This functionality loads the promotional prices offers into Simla.com" => "Esta función carga los precios promocionales de las ofertas comerciales en Simla.com", + "Promotional prices unloaded" => "Se han cargado los precios promocionales", + "Woocommerce promotional price" => "Precio promocional Woocommerce", + "Promotional price type for Woocommerce store, generated automatically. Necessary for correct synchronization work when loyalty program is enabled (Do not delete. Do not deactivate)" => + "Tipo de precio promocional para la tienda Woocommerce, generado automáticamente. Necesario para el correcto funcionamiento de la sincronización cuando el programa de fidelización está habilitado (No eliminar. No desactivar)" ], "language" => "es", "x-generator" => "GlotPress/2.4.0-alpha", diff --git a/src/languages/retailcrm-es_ES.mo b/src/languages/retailcrm-es_ES.mo index 051c9cfcec855e0095b33ddae0e6a9503a1de7f9..dc5cdc5ed84a2d7c1643181a6e1af267be9204c8 100644 GIT binary patch delta 5716 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 G+5ZN*CY)^m delta 4317 zcmZA4dr*~i9>?+T;U+3Uh@p7nAP6Lif(YoEA}WF?3X-;#7z%k=(=fUq)iE(IVYk}y~sxb22kIhz|r^-4m9&wuUNC;obciVoQ8w(QRD*Kjfr>|^}rADCj1!V@IR>Q ze#F^0u%GkbTD*nh2QeJCyXRZn<9(RQ^X(NXdf+Lf^L7#SfNzlh%)?Xkp#FTQXX&W# z^KlRs;Q*}0-q?WZP!rNg+m9N7qp0gYz<9ifu{_^G`#U|m1vS)OOu{ipr>q>+z-2fM zeW;Oo5A*Q{9EG`bcO@>v3_O9FvTLaCJv_A#Gf@qyL*Fne%~Z;;6V;PzI1ytxkh5_L zZb9AX�bVMvX)`UV8z@c z=)y+SNOYqvyn(t=Ec2t)n~3Vk2-NkJs2*;^WZZ*!cpT^9HO$9ZiB7|sQ1@-c5_}mo zHNO8**-7OFhT#scvk&+&lH+bvi{C)jk)1>>%Fj`&{R-+jtyndvH|lsOsspJw26He4 zYcK}4A=mqCHx;Jex{!5e@8d4~80myPz=Vy)R%B4@T};DIP``_$`x=oXT!0HuYo-e| zMVFDjSrkuy3`gO3JcvW}{(nj(gcCoacBl}xH_c@<@(fEv^{5avm!+tNR=D45T{jMU*z`|H4TD(cf^0Kj*$@6VC72U8AmthN*;}z797t`HiScSS_Lb@|| zBTz$}jXGa|df#WGhPV>Lu?96&t56NBN4*VO&=*PN2o*i(O;ij2hWg=W7={;+*|0CM z-owprbsD^hcTkI{12shlPz^eRy3gmRhJ1rsL!lYYeFmbYZej-G--pV4PUK>hdqJD) zQ7q*AN2s0+q1iG8nJpWIYCt*aK~<MhjbI_;kS67_)VsFCWI>HIziBRQ@_mVqrst*s_hLt1@Q z)RS)1>vI~_pfB9x>+bQ*W6T(JOGe#b4$>*B!Ufojv+y&VkE7`YKeflP4!bc6hx4Hk zuSAWwZwZyTRGvol_+Q9$SwuD~9J5e8+Jtj(KTg5RScy5~oUL~o#&G;TM&TKZ#`9Q& zU!z870`KZgI2ZZeXN#$5NLQn_+9s^PJ*XCbg&Q$#ywiYARD-Xg7Ev)5>A}^==vy6* z!M!*Q|B87S$44xdBByLI=Ii}$rJ^36z%smw{ct8Pu^O}p*+Z-zH3jX+n`rN%dh~Cc ziTazY>x+>#+ft0fU8t!#hd*z8jB%6bEmok8yHWSKg!=o#@;9r6VW<{w!gg#&y(U@w zN<){AYWXbGbrtUUdr%|xFsfnAH~`yl7vQA07^wFouT zHSX~aY~}b6vMJis0<-D30<}eVq0XN|E!OXlL9>LZX18M{&cIGo!@okkj$ws9wm~W* z*=36HFzSo%F$9xXL0YXTI0Uniy~yTbA8f>M+>A-M9f#wqs1AI9df@lSGO-w1t&u9m zWW3WyWiS<~2Xr9QVy~la_$^lB0GdA^8&Hex1fIe3s3|&DKNYMv{`vw0$zBYK|JbVjvHn3p%6`v*KIH@NAvVmyWH8nkDH5ILL zt%HZi?+CLHEGt}V^!|5q@M}^;9w)yg+F&-4-;*au7)c~vQb>M7eqNs9L^aVgsXR-X z$XleDyg(L^g=8sFN#*&$T}(UIi#qd@vX1&) zqVh+QMW&D?B!)akRJt63f4X0zzND3pNV1r85S61OoJ`gMCBh;2kIOr$KTXu|HDoz? zkmQqK@s@b2m#?d>^**$+euX!%KK40JU}Icl*^Q z<1dB;{0S`)fh*p!@W7L)r5^wFw2VM``Xx`GYUFL9f%MGxJb~J=e-HJ4J8p "Программа лояльности", "Activate program loyalty" => "Активировать программу лояльности", - "Enable this setting for activate program loyalty on site" => "Активируйте эту настройку для активации программы лояльности на сайте", + "Attention! When activating the loyalty program, the method of ICML catalog generation changes. Details in" => "Внимание! При активации программы лояльности, изменяется способ генерации ICML каталога. Подробности в", + "documentation loyalty program" => "документации программы лояльности", "Terms of loyalty program" => "Условия программы лояльности", "Insert the terms and conditions of the loyalty program" => "Вставьте условия участия в программе лояльности", "Conditions of personal data processing" => "Условия обработки персональных данных", @@ -247,6 +248,15 @@ return [ "bonuses" => "бонусов", "Use coupon:" => "Используйте купон:", "Points will be awarded upon completion of the order:" => "По завершению заказа будет начислено баллов:", + "Unloading promotional prices of offers" => "Выгрузка акционных цен торговых предложений", + "Every 4 hours" => "Каждые 4 часа", + "Upload prices now" => "Выгрузить цены сейчас", + "Uploaded discount price" => "Выгрузка акционных цен", + "This functionality loads the promotional prices offers into Simla.com" => "Эта функция загружает акционные цены торговых предложений в Simla.com", + "Promotional prices unloaded" => "Акционные цены выгружены", + "Woocommerce promotional price" => "Акционная цена Woocommerce", + "Promotional price type for Woocommerce store, generated automatically. Necessary for correct synchronization work when loyalty program is enabled (Do not delete. Do not deactivate)" => + "Акционный тип цены для магазина Woocommerce, сгенерированный автоматически. Необходим для корректной работы синхронизации при включенной программы лояльности (Не удалять. Не деактивировать)" ], "language" => "ru", "x-generator" => "GlotPress/2.4.0-alpha", diff --git a/src/languages/retailcrm-ru_RU.mo b/src/languages/retailcrm-ru_RU.mo index 5cb7b6941debe4458e6e9b8dbd8bccc9de072cf6..e004250710c57f2f6e0cc45e3cdd2df3c875bb4e 100644 GIT binary patch delta 5892 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 delta 4402 zcmYk;4N#R;9>?)>d6R??!9W7!f+#32>Qw?2Lv%&tZG8!~pa}G8tgEKrdvaUI#Vkwq zu4cKLY=XI(i9T7<3#H~XlkMiq&ZxPoTRSz2V>LV5Zm!Ml?Duz{$C=LXzn^oS=ef^w z&i|bAT)yaY?Kg*bkn7 zchfGySgb_dxE?ETBl2wX5#EEBF%-XXj(-(U z^A@UuXK*@xj>^;shF5@fn2o!!5zk;2j)}9Ut_F2}5l+J$=+hisq%sV@#wv_t7#c|p zACs`j@pUYs-H*D_DDth5%|~ToDJnB-umra_=Rd(n+JAA*-#~6*ZVzStm7*AWp)clP zCCBKcPb zTr7PLrX%Of0#t{ZP(5wKWZZ-F#q^>^d=V$(=cwzFxkw$zLuIBGb=`8DfSWK3dr)iY zEgu!8(R_?71Ri$Qj8gnX_${CI2&8A06)dR zVszX0^(9c5#ffax9IeIYu?<5omKDh0%uo!+JXDA8N7k2_hg!Uis8zoSb=?+Jhn{oV zub>8S2*+SArfdKAQ&Fm;mj9Vx?yjoJ%wjbslI?Z{#P7;H&L1X4nr|y6#3Vj4WyzT4nb{;3=GEyP!D<- z)xjpz7h5p|w<5D=wqvu)m?NkuNYAo6G6f%?U54twUethIMP;-vi~Q>bpK^fjntz}& zkVr3dJRi&PL7a=-I2CWV^%dxopBH+=Vl-8}G-jQLpUmvGxlnAKkPYkUp9=)EekP4e%Tm z;cc9PlYDejH(rmEupOiE6skiPQ62gom64Gi`$nax5v@i&;8~o9ub~^2o@tPZ+i)>1 z!*8(_YuF++=(|ScWh#@{0@LvdssqXQ*}Ebam(yO1blO}%jUbq}%VwO8di9>fm3R|t zv6iL27JE@^VC+PDcWl9U+MUP%eC7ld&G7})_8UeTSkR^rb>U*voIQbaup5<`@39>d zdH?DG`|xjg3%BB*3&|>a$+PZv4R!x8=B*mju~hqiBb9|5IE@ct62sG6t;JI8M9q0W z@@K|PWwqlfOu?^E4+tx^Q=W_T!K`vTjH$HyaS28+FRV+m8XJ97I;m(x1IfQqoQs;P zI*i1#n1z>7nF#rby(V%{9j`^D`Z&g7_6&O$O+~G(TIA0x<6|x!MP(wSg#5E!Od1u< zSv79NW4H=)7`E2JUepMB@K<=jX?sb}XSCZf1{-GCi+ByH-GhmE8i(U`RK|kK?B9yv zW#nHy&f$PAC`R?z>)4E%f;LnJKEY9V%Q20G!+JCon5OISJnl!P->k2&Q+^y-=O(Gr z-j;JvnQo~h|0}2*;lMLEtjd^Q;6YT1vVY1y4_Jnmup5`+=GpeD{}O{}N3$~Zri?{( zWE8676{tnL6P1y}sE&MqdO!TjM@2nNn`>{sI#kN`p%&x&s2e8Cv#%?}akMvJ1|CBC zZZ2Xjrm_{((b>2OGg<2DSQpNA@q2*-X-6!u*Oo8NsSHP*7>iLj8Ao6lhT-Fm>oA6P z3u*)%sO$TX9cli6nxb%4rjC0s9E*`zF=a?U0%eQ#KZ`n0y7_D*_%@sRd^3l*jOPI=6!Xw;jX z`f5BuOe5H3WfdfYVy#I0csz z+KN9eT5u{qw=t)1E3t!kmMA7v@@>pi{0*TU#!e0Fq*m-8wB1K4|2wH@K>iKmG!;z{CtLVKKdQs7_jcX24Oka(3?La5{r?-9$0eT2%RgrD$L@=;AZ zLOf3lCf*_Ll((G9AUsLDe&>W^GL{g(Cth%lO~94J3}TyetR7z?<~nWhipKq%bKnR* zPP|PV)iL)hcm2}UUaxyyWAkHf>*K*ET-MFlf?!v@|8PuvxO?RacT;1t*MB}P!Ag%m z8)W@A;dq$;dTO}!OlnD}6`xV=@;{wfV*MxcTbC7h#ox`F9k=_@g}; z*0F+HA=arWD + * @license http://retailcrm.ru Proprietary + * @link http://retailcrm.ru + * @see http://help.retailcrm.ru + */ +class DataUploadPriceRetailCrm +{ + public static function dataGetPriceTypes() { + return [ + 'success' => true, + 'priceTypes' => [ + [ + 'code' => 'test', + 'name' => 'test', + 'active' => true, + 'description' => 'test', + 'ordering' => 999, + 'promo' => true, + 'default' => false + ], + [ + 'code' => 'default', + 'name' => 'default', + 'active' => true, + 'description' => 'default', + 'ordering' => 999, + 'promo' => true, + 'default' => true + ], + ] + ]; + } + + public static function willSendPriceType() { + return [ + 'code' => 'woo-promotion-lp', + 'name' => 'Woocommerce promotional price', + 'active' => true, + 'description' => 'Promotional price type for Woocommerce store, generated automatically. + Necessary for correct synchronization work when loyalty program is enabled + (Do not delete. Do not deactivate)', + 'ordering' => 999, + 'promo' => true, + ]; + } +} diff --git a/tests/test-wc-retailcrm-upload-discount-price.php b/tests/test-wc-retailcrm-upload-discount-price.php new file mode 100644 index 0000000..0d3894c --- /dev/null +++ b/tests/test-wc-retailcrm-upload-discount-price.php @@ -0,0 +1,74 @@ + + * @license http://retailcrm.ru Proprietary + * @link http://retailcrm.ru + * @see http://help.retailcrm.ru + */ +class WC_Retailcrm_Upload_Discount_Price_Test extends WC_Retailcrm_Test_Case_Helper +{ + protected $apiMock; + protected $responseMock; + + public function setUp() + { + WC_Helper_Product::create_simple_product(); + WC_Helper_Product::create_variation_product(); + + $this->setOptions(); + + $this->responseMock = $this->getMockBuilder('\WC_Retailcrm_Response_Helper') + ->disableOriginalConstructor() + ->setMethods(['isSuccessful']) + ->getMock() + ; + + $this->apiMock = $this->getMockBuilder('\WC_Retailcrm_Client_V5') + ->disableOriginalConstructor() + ->setMethods(['storePricesUpload', 'getSingleSiteForKey', 'getPriceTypes', 'editPriceType']) + ->getMock() + ; + + $this->responseMock->setResponse(['success' => true]); + $this->setMockResponse($this->responseMock, 'isSuccessful', true); + $this->setMockResponse($this->apiMock, 'getSingleSiteForKey', 'woo'); + + $this->responseMock->setResponse(DataUploadPriceRetailCrm::dataGetPriceTypes()); + $this->setMockResponse($this->apiMock, 'getPriceTypes', $this->responseMock); + } + + public function testUpload() + { + $this->apiMock + ->expects($this->exactly(1)) + ->method('storePricesUpload') + ->with($this->callback( + function ($parameter) { + if (is_array($parameter)) { + return true; + } + + return false; + } + ), $this->equalTo('woo')) + ; + + $this->apiMock + ->expects($this->exactly(1)) + ->method('editPriceType') + ->with($this->identicalTo(DataUploadPriceRetailCrm::willSendPriceType())) + ->willReturn($this->responseMock) + ; + + $uploadService = new WC_Retailcrm_Upload_Discount_Price($this->apiMock); + $uploadService->upload(); + } +}