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
zZb9AXbVMvX)`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();
+ }
+}