1
0
mirror of synced 2025-02-20 08:53:14 +03:00

Transferring base price of goods for loyalty program (#342)

This commit is contained in:
Kocmonavtik 2024-09-18 11:49:00 +03:00 committed by GitHub
parent dac3c9f6f7
commit a23e96b4d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 586 additions and 19 deletions

View File

@ -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

View File

@ -1 +1 @@
4.8.3
4.8.4

View File

@ -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;
}
```

View File

@ -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 "<a href='https://docs.simla.com/Users/Integration/SiteModules/WooCommerce/PLWoocommerce'>documentation loyalty program</a>"
msgstr "<a href='https://docs.simla.com/es/Users/Integration/SiteModules/WooCommerce/PLWoocommerce'>documentación del programa de fidelización</a>"
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)"

View File

@ -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 "<a href='https://docs.simla.com/Users/Integration/SiteModules/WooCommerce/PLWoocommerce'>documentation loyalty program</a>"
msgstr "<a href='https://docs.retailcrm.ru/Users/Integration/SiteModules/WooCommerce/PLWoocommerce#h-2'>документации программы лояльности</a>"
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, сгенерированный автоматически. Необходим для корректной работы синхронизации при включенной программы лояльности (Не удалять. Не деактивировать)"

View File

@ -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('<tbody class="retail-debug-info"></tbody>');
this.infoTable = jQuery('tbody[class="retail-debug-info"]').get(0);
@ -56,6 +59,7 @@ jQuery(function () {
jQuery(this.infoTable).append("<tr><td>" + icml + "</td><td> " + this.icml + "</td></tr>");
jQuery(this.infoTable).append("<tr><td>" + history + "</td><td> " + this.history + "</td></tr>");
jQuery(this.infoTable).append("<tr><td>" + inventories + "</td><td> " + this.inventories + "</td></tr>");
jQuery(this.infoTable).append("<tr><td>" + loyaltyUploadPrice + "</td><td>" + this.loyaltyUploadPrice + "</td></tr>");
}
RetailcrmCronInfo.prototype.clearCronTasks = function () {

View File

@ -72,6 +72,25 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration
<?php
}
public function ajax_upload_loyalty_price()
{
$ajax_url = admin_url('admin-ajax.php');
?>
<script type="text/javascript">
jQuery('#upload-loyalty-price-retailcrm').bind('click', function () {
jQuery.ajax({
type: "POST",
url: '<?php echo $ajax_url; ?>?action=upload_loyalty_price',
success: function (response) {
alert('<?php echo __('Promotional prices unloaded', 'retailcrm');?>');
console.log('AJAX response : ', response);
}
});
})
</script>
<?php
}
/**
* Initialize integration settings form fields.
*/
@ -610,7 +629,9 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration
'title' => __('Loyalty program', 'retailcrm'),
'class' => 'checkbox',
'type' => 'checkbox',
'description' => __('Enable this setting for activate program loyalty on site', 'retailcrm')
'description' => '<b style="color: red">' .
__('Attention! When activating the loyalty program, the method of ICML catalog generation changes. Details in', 'retailcrm') .
' <\b>' . __("<a href='https://docs.simla.com/Users/Integration/SiteModules/WooCommerce/PLWoocommerce'>documentation loyalty program</a>", "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'),

View File

@ -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
*

View File

@ -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
]
);

View File

@ -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,

View File

@ -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
];
}

View File

@ -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');
}
}
/**

View File

@ -0,0 +1,238 @@
<?php
if (!class_exists('WC_Retailcrm_Upload_Discount_Price')):
class WC_Retailcrm_Upload_Discount_Price
{
const DISCOUNT_TYPE_PRICE = 'woo-promotion-lp';
protected $activeLoyalty = false;
protected $settings;
protected $site;
/** @var bool|WC_Retailcrm_Proxy|WC_Retailcrm_Client_V5 */
protected $apiClient;
public function __construct($aplClient = false)
{
$this->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;

View File

@ -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) {

View File

@ -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",
"<a href='https://docs.simla.com/Users/Integration/SiteModules/WooCommerce/PLWoocommerce'>documentation loyalty program</a>" => "<a href='https://docs.simla.com/es/Users/Integration/SiteModules/WooCommerce/PLWoocommerce'>documentación del programa de fidelización</a>",
"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",

Binary file not shown.

View File

@ -201,7 +201,8 @@ return [
"Товары с включенной опцией 'виртуальные' будут выгружаться в CRM как услуги",
"Loyalty program" => "Программа лояльности",
"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 каталога. Подробности в",
"<a href='https://docs.simla.com/Users/Integration/SiteModules/WooCommerce/PLWoocommerce'>documentation loyalty program</a>" => "<a href='https://docs.retailcrm.ru/Users/Integration/SiteModules/WooCommerce/PLWoocommerce#h-2'>документации программы лояльности</a>",
"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",

Binary file not shown.

View File

@ -5,7 +5,7 @@ Tags: Интеграция, Simla.com, simla
Requires PHP: 7.0
Requires at least: 5.3
Tested up to: 6.5
Stable tag: 4.8.3
Stable tag: 4.8.4
License: GPLv1 or later
License URI: http://www.gnu.org/licenses/gpl-1.0.html
@ -82,6 +82,9 @@ Asegúrate de tener una clave API específica para cada tienda. Las siguientes i
== Changelog ==
= 4.8.4 =
* Updated work with promotional items when loyalty program is enabled
= 4.8.3 =
* Added loyalty program coupon entry in the form by click

View File

@ -5,7 +5,7 @@
* Description: Integration plugin for WooCommerce & Simla.com
* Author: RetailDriver LLC
* Author URI: http://retailcrm.pro/
* Version: 4.8.3
* Version: 4.8.4
* Tested up to: 6.5
* Requires Plugins: woocommerce
* WC requires at least: 5.4
@ -136,6 +136,7 @@ if (!class_exists( 'WC_Integration_Retailcrm')) :
require_once(self::checkCustomFile('include/components/class-wc-retailcrm-loyalty-form.php'));
require_once(self::checkCustomFile('include/validators/loyalty-validator/class-wc-retailcrm-loyalty-constraint.php'));
require_once(self::checkCustomFile('include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php'));
require_once(self::checkCustomFile('include/class-wc-retailcrm-upload-discount-price.php'));
}
/**

View File

@ -16,7 +16,7 @@
*
* @link https://wordpress.org/plugins/woo-retailcrm/
*
* @version 4.8.3
* @version 4.8.4
*
* @package RetailCRM
*/

View File

@ -0,0 +1,56 @@
<?php
namespace datasets;
/**
* PHP version 7.0
*
* Class DataUploadPriceRetailCrm - Data set for WC_Retailcrm_Upload_Discount_Price_Test.
*
* @category Integration
* @author RetailCRM <integration@retailcrm.ru>
* @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,
];
}
}

View File

@ -0,0 +1,74 @@
<?php
use datasets\DataUploadPriceRetailCrm;
/**
* PHP version 7.0
*
* WC_Retailcrm_Upload_Discount_Price_Test
*
* @category Integration
* @author RetailCRM <integration@retailcrm.ru>
* @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();
}
}