parent
69ef4e24c5
commit
01fe3c9741
@ -1,3 +1,6 @@
|
||||
## 2024-07-15 4.8.0
|
||||
* Added loyalty program
|
||||
|
||||
## 2024-06-27 4.7.9
|
||||
* Fixed undefined array key number in order history
|
||||
|
||||
|
@ -445,8 +445,149 @@ msgstr "Se requiere clave API con acceso a una tienda"
|
||||
msgid "The currency of the site differs from the currency of the store in CRM. For the integration to work correctly, the currencies in CRM and CMS must match"
|
||||
msgstr "La moneda del sitio web es distinto a la tienda del CRM. Para el funcionamiento correcto de la integración, las monedas del CMS y CRM deben coincid"
|
||||
|
||||
msgid "Loyalty program"
|
||||
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 "Terms of loyalty program"
|
||||
msgstr "Condiciones del programa de fidelización"
|
||||
|
||||
msgid "Insert the terms and conditions of the loyalty program"
|
||||
msgstr "Introduce las condiciones del programa de fidelización"
|
||||
|
||||
msgid "Conditions of personal data processing"
|
||||
msgstr "Condiciones de procesamiento de datos personales"
|
||||
|
||||
msgid "Insert the terms and conditions for processing personal data"
|
||||
msgstr "Introduce las condiciones para el procesamiento de datos personales"
|
||||
|
||||
msgid "To activate the loyalty program it is necessary to activate the <a href='?page=wc-settings'>'enable use of coupons option'</a>"
|
||||
msgstr "Para activar el programa de fidelización es necesario activar la opción <a href='?page=wc-settings'>'habilitar el uso de cupones'</a>"
|
||||
|
||||
msgid "Bonus account"
|
||||
msgstr "Cuenta de bonos"
|
||||
|
||||
msgid "Participation ID: "
|
||||
msgstr "ID de participación: "
|
||||
|
||||
msgid "Current level: "
|
||||
msgstr "Nivel actual: "
|
||||
|
||||
msgid "Bonuses on the account: "
|
||||
msgstr "Bonos en la cuenta: "
|
||||
|
||||
msgid "Bonus card number: "
|
||||
msgstr "Número de tarjeta de bonos: "
|
||||
|
||||
msgid "Date of registration: "
|
||||
msgstr "Fecha de registro: "
|
||||
|
||||
msgid "Current level rules"
|
||||
msgstr "Reglas del nivel actual"
|
||||
|
||||
msgid "Required amount of purchases to move to the next level: "
|
||||
msgstr "Cantidad de compras necesarias para pasar al siguiente nivel: "
|
||||
|
||||
msgid "Activate participation in the loyalty program"
|
||||
msgstr "Activar participación en el programa de fidelización"
|
||||
|
||||
msgid "Send"
|
||||
msgstr "Enviar"
|
||||
|
||||
msgid "To register in the loyalty program, fill in the form:"
|
||||
msgstr "Para registrarse en el programa de fidelización, rellena el formulario:"
|
||||
|
||||
msgid " I agree with "
|
||||
msgstr " Estoy de acuerdo con "
|
||||
|
||||
msgid "loyalty program terms"
|
||||
msgstr "términos del programa de fidelización"
|
||||
|
||||
msgid "terms of personal data processing"
|
||||
msgstr "términos de procesamiento de datos personales"
|
||||
|
||||
msgid "Phone"
|
||||
msgstr "Teléfono"
|
||||
|
||||
msgid "Error while registering in the loyalty program. Try again later"
|
||||
msgstr "Error al registrarse en el programa de fidelización. Inténtalo de nuevo más tarde"
|
||||
|
||||
msgid "The card is not linked"
|
||||
msgstr "La tarjeta no está vinculada"
|
||||
|
||||
msgid "Error while retrieving data. Try again later"
|
||||
msgstr "Error al recuperar los datos. Inténtalo de nuevo más tarde"
|
||||
|
||||
msgid "Error when activating the loyalty program. Try again later"
|
||||
msgstr "Error al activar el programa de fidelización. Inténtalo de nuevo más tarde"
|
||||
|
||||
msgid "Enter the correct phone number"
|
||||
msgstr "Introduce el número de teléfono correcto"
|
||||
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
|
||||
msgid "Ordinary products: accrual of 1 bonus for each %s %s"
|
||||
msgstr "Productos ordinarios: acumulación de 1 bono por cada %s %s"
|
||||
|
||||
msgid "Promotional products: accrual of 1 bonus for each %s %s"
|
||||
msgstr "Productos promocionales: acumulación de 1 bono por cada %s %s"
|
||||
|
||||
msgid "Ordinary products: bonus accrual in the amount of %s%% of the purchase amount"
|
||||
msgstr "Productos ordinarios: acumulación de bonos en la cantidad de %s%% de la suma de la compra"
|
||||
|
||||
msgid "Promotional products: bonus accrual in the amount of %s%% of the purchase amount"
|
||||
msgstr "Productos promocionales: acumulación de bonos en la cantidad de %s%% de la suma de la compra"
|
||||
|
||||
msgid "Ordinary products: %s%% discount"
|
||||
msgstr "Productos ordinarios: %s%% de descuento"
|
||||
|
||||
msgid "Promotional products: %s%% discount"
|
||||
msgstr "Productos promocionales: %s%% de descuento"
|
||||
|
||||
msgid "Uploading services"
|
||||
msgstr "Descarga de servicios"
|
||||
msgstr "Subida de servicios"
|
||||
|
||||
msgid "Goods with the 'virtual' option enabled will be uploaded to Simla as services"
|
||||
msgstr "Los bienes con la opción 'virtual' activada se cargarán en Simla como servicios"
|
||||
msgstr "Los productos con la opción 'virtual' activada se subirán a Simla como servicios"
|
||||
|
||||
msgid "User not found in the system"
|
||||
msgstr "Usuario no encontrado en el sistema"
|
||||
|
||||
msgid "Error when searching for participation in loyalty programs"
|
||||
msgstr "Error al buscar la participación en programas de fidelización"
|
||||
|
||||
msgid "No active participation in the loyalty program was detected"
|
||||
msgstr "No se detectó la participación activa en el programa de fidelización"
|
||||
|
||||
msgid "No bonuses for debiting"
|
||||
msgstr "No hay bonos para debitar"
|
||||
|
||||
msgid "Loyalty program not found"
|
||||
msgstr "Programa de fidelización no encontrado"
|
||||
|
||||
msgid "Loyalty program is not active"
|
||||
msgstr "Programa de fidelización no está activo"
|
||||
|
||||
msgid "Loyalty program blocked"
|
||||
msgstr "Programa de fidelización bloqueado"
|
||||
|
||||
msgid "This user is a corporate person"
|
||||
msgstr "Este usuario es una persona jurídica"
|
||||
|
||||
msgid "It is possible to write off"
|
||||
msgstr "Es posible debitar"
|
||||
|
||||
msgid "bonuses"
|
||||
msgstr "bonos"
|
||||
|
||||
msgid "Use coupon:"
|
||||
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:"
|
||||
|
@ -454,8 +454,149 @@ msgstr "Требуется API ключ с доступом к одному ма
|
||||
msgid "The currency of the site differs from the currency of the store in CRM. For the integration to work correctly, the currencies in CRM and CMS must match"
|
||||
msgstr "Валюта сайта отличается от валюты магазина в CRM. Для корректной работы интеграции, валюты в CRM и CMS должны совпадать"
|
||||
|
||||
msgid "Loyalty program"
|
||||
msgstr "Программа лояльности"
|
||||
|
||||
msgid "Activate program loyalty"
|
||||
msgstr "Активировать программу лояльности"
|
||||
|
||||
msgid "Enable this setting for activate program loyalty on site"
|
||||
msgstr "Активируйте эту настройку для активации программы лояльности на сайте"
|
||||
|
||||
msgid "Terms of loyalty program"
|
||||
msgstr "Условия программы лояльности"
|
||||
|
||||
msgid "Insert the terms and conditions of the loyalty program"
|
||||
msgstr "Вставьте условия участия в программе лояльности"
|
||||
|
||||
msgid "Conditions of personal data processing"
|
||||
msgstr "Условия обработки персональных данных"
|
||||
|
||||
msgid "Insert the terms and conditions for processing personal data"
|
||||
msgstr "Вставьте условия обработки персональных данных"
|
||||
|
||||
msgid "To activate the loyalty program it is necessary to activate the <a href='?page=wc-settings'>'enable use of coupons option'</a>"
|
||||
msgstr "Для активации программы лояльности необходимо активировать опцию <a href='?page=wc-settings'>'включить использование купонов'</a>"
|
||||
|
||||
msgid "Bonus account"
|
||||
msgstr "Бонусный счёт"
|
||||
|
||||
msgid "Participation ID: "
|
||||
msgstr "ID участия: "
|
||||
|
||||
msgid "Current level: "
|
||||
msgstr "Текущий уровень: "
|
||||
|
||||
msgid "Bonuses on the account: "
|
||||
msgstr "Бонусов на счёте: "
|
||||
|
||||
msgid "Bonus card number: "
|
||||
msgstr "Номер бонусной карты: "
|
||||
|
||||
msgid "Date of registration: "
|
||||
msgstr "Дата регистрации: "
|
||||
|
||||
msgid "Current level rules"
|
||||
msgstr "Правила текущего уровня"
|
||||
|
||||
msgid "Required amount of purchases to move to the next level: "
|
||||
msgstr "Необходимая сумма покупок для перехода на следующий уровень: "
|
||||
|
||||
msgid "Activate participation in the loyalty program"
|
||||
msgstr "Активировать участие в программе лояльности"
|
||||
|
||||
msgid "Send"
|
||||
msgstr "Отправить"
|
||||
|
||||
msgid "To register in the loyalty program, fill in the form:"
|
||||
msgstr "Для регистрации в программе лояльности заполните форму:"
|
||||
|
||||
msgid " I agree with "
|
||||
msgstr " Я согласен с "
|
||||
|
||||
msgid "loyalty program terms"
|
||||
msgstr "условиями программы лояльности"
|
||||
|
||||
msgid "terms of personal data processing"
|
||||
msgstr "условиями обработки персональных данных"
|
||||
|
||||
msgid "Phone"
|
||||
msgstr "Телефон"
|
||||
|
||||
msgid "Error while registering in the loyalty program. Try again later"
|
||||
msgstr "Ошибка при регистрации в программе лояльности. Попробуйте позже"
|
||||
|
||||
msgid "The card is not linked"
|
||||
msgstr "Карта не привязана"
|
||||
|
||||
msgid "Error while retrieving data. Try again later"
|
||||
msgstr "Ошибка при получении данных. Попробуйте позже"
|
||||
|
||||
msgid "Error when activating the loyalty program. Try again later"
|
||||
msgstr "Ошибка при активации программы лояльности. Попробуйте позже"
|
||||
|
||||
msgid "Enter the correct phone number"
|
||||
msgstr "Введите корректный номер телефона"
|
||||
|
||||
msgid "Close"
|
||||
msgstr "Закрыть"
|
||||
|
||||
msgid "Ordinary products: accrual of 1 bonus for each %s %s"
|
||||
msgstr "Обычные товары: начисление 1 бонуса за каждые %s %s"
|
||||
|
||||
msgid "Promotional products: accrual of 1 bonus for each %s %s"
|
||||
msgstr "Акционные товары: начисление 1 бонуса за каждые %s %s"
|
||||
|
||||
msgid "Ordinary products: bonus accrual in the amount of %s%% of the purchase amount"
|
||||
msgstr "Обычные товары: начисление бонусов в размере %s%% от суммы покупки"
|
||||
|
||||
msgid "Promotional products: bonus accrual in the amount of %s%% of the purchase amount"
|
||||
msgstr "Акционные товары: начисление бонусов в размере %s%% от суммы покупки"
|
||||
|
||||
msgid "Ordinary products: %s%% discount"
|
||||
msgstr "Обычные товары: %s%% скидка"
|
||||
|
||||
msgid "Promotional products: %s%% discount"
|
||||
msgstr "Акционные товары: %s%% скидка"
|
||||
|
||||
msgid "Uploading services"
|
||||
msgstr "Выгрузка услуг"
|
||||
|
||||
msgid "Goods with the 'virtual' option enabled will be uploaded to Simla as services"
|
||||
msgstr "Товары с включенной опцией 'виртуальные' будут выгружаться в CRM как услуги"
|
||||
|
||||
msgid "User not found in the system"
|
||||
msgstr "Пользователь не найден в системе"
|
||||
|
||||
msgid "Error when searching for participation in loyalty programs"
|
||||
msgstr "Ошибка при поиске участия в программах лояльности"
|
||||
|
||||
msgid "No active participation in the loyalty program was detected"
|
||||
msgstr "Не обнаружено активного участия в программе лояльности"
|
||||
|
||||
msgid "No bonuses for debiting"
|
||||
msgstr "Нет бонусов для списания"
|
||||
|
||||
msgid "Loyalty program not found"
|
||||
msgstr "Программа лояльности не найдена"
|
||||
|
||||
msgid "Loyalty program is not active"
|
||||
msgstr "Программа лояльности не активна"
|
||||
|
||||
msgid "Loyalty program blocked"
|
||||
msgstr "Программа лояльности заблокирована"
|
||||
|
||||
msgid "This user is a corporate person"
|
||||
msgstr "Данный пользователь является корпоратиным лицом"
|
||||
|
||||
msgid "It is possible to write off"
|
||||
msgstr "Возможно списать"
|
||||
|
||||
msgid "bonuses"
|
||||
msgstr "бонусов"
|
||||
|
||||
msgid "Use coupon:"
|
||||
msgstr "Используйте купон:"
|
||||
|
||||
msgid "Points will be awarded upon completion of the order:"
|
||||
msgstr "По завершению заказа будет начислено баллов:"
|
||||
|
34
src/assets/css/retailcrm-loyalty-style.css
Normal file
34
src/assets/css/retailcrm-loyalty-style.css
Normal file
@ -0,0 +1,34 @@
|
||||
.popup-fade-loyalty {
|
||||
display: none;
|
||||
}
|
||||
.popup-fade-loyalty:before {
|
||||
content: '';
|
||||
background: #000;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.7;
|
||||
z-index: 9999;
|
||||
}
|
||||
.popup-loyalty {
|
||||
position: fixed;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
padding: 20px;
|
||||
width: 1000px;
|
||||
margin-left: -500px;
|
||||
height: 50%;
|
||||
background: #fff;
|
||||
border: 1px solid orange;
|
||||
border-radius: 4px;
|
||||
z-index: 99999;
|
||||
opacity: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
.popup-close-loyalty {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
121
src/assets/js/retailcrm-loyalty-actions.js
Normal file
121
src/assets/js/retailcrm-loyalty-actions.js
Normal file
@ -0,0 +1,121 @@
|
||||
jQuery(function() {
|
||||
jQuery('#loyaltyRegisterForm').on("submit", function (event) {
|
||||
var termsCheck = jQuery('#termsLoyalty');
|
||||
var privacyCheck = jQuery('#privacyLoyalty');
|
||||
|
||||
if (termsCheck.length) {
|
||||
if (!termsCheck.is(':checked')) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (privacyCheck.length) {
|
||||
if (!privacyCheck.is(':checked')) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let phone = jQuery('#phoneLoyalty');
|
||||
|
||||
if (!phone.val().match(/(?:\+|\d)[\d\-\(\) ]{7,}\d/)) {
|
||||
|
||||
if (!jQuery('#warningLoyaltyPhone').length) {
|
||||
phone.parent().append('<span style="color: red" id="warningLoyaltyPhone">' + messagePhone + '</span>')
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
return false;
|
||||
} else {
|
||||
jQuery('#warningLoyaltyPhone').remove();
|
||||
}
|
||||
|
||||
jQuery.ajax({
|
||||
url: loyaltyUrl.url + '/admin-ajax.php?action=register_customer_loyalty',
|
||||
method: 'POST',
|
||||
timeout: 0,
|
||||
data: {ajax: 1, phone: phone.val(), userId: customerId},
|
||||
dataType: 'json'
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.hasOwnProperty('error')) {
|
||||
jQuery('#loyaltyRegisterForm').append('<p style="color: red">'+ response.error + '</p>')
|
||||
|
||||
event.preventDefault();
|
||||
return false;
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
jQuery('#loyaltyActivateForm').on("submit", function (event) {
|
||||
var activateCheckbox = jQuery('#loyaltyActiveCheckbox');
|
||||
|
||||
if (activateCheckbox.length) {
|
||||
if (!activateCheckbox.is(':checked')) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
jQuery.ajax({
|
||||
url: loyaltyUrl.url + '/admin-ajax.php?action=activate_customer_loyalty',
|
||||
method: 'POST',
|
||||
timeout: 0,
|
||||
data: {ajax: 1, loyaltyId: loyaltyId},
|
||||
dataType: 'json'
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.hasOwnProperty('error')) {
|
||||
jQuery('#loyaltyRegisterForm').append('<p style="color: red">'+ response.error + '</p>')
|
||||
|
||||
event.preventDefault();
|
||||
return false;
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
jQuery('.popup-open-loyalty').click(function() {
|
||||
if (jQuery(this).attr('id') === 'terms-popup') {
|
||||
jQuery('#popup-loyalty-text').html(termsLoyalty);
|
||||
} else {
|
||||
jQuery('#popup-loyalty-text').html(privacyLoyalty);
|
||||
}
|
||||
|
||||
jQuery('.popup-fade-loyalty').fadeIn();
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery('.popup-close-loyalty').click(function() {
|
||||
jQuery(this).parents('.popup-fade-loyalty').fadeOut();
|
||||
return false;
|
||||
});
|
||||
|
||||
jQuery(document).keydown(function(e) {
|
||||
if (e.keyCode === 27) { // Key Escape
|
||||
e.stopPropagation();
|
||||
jQuery('.popup-fade-loyalty').fadeOut();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('.popup-fade-loyalty').click(function(e) {
|
||||
if (jQuery(e.target).closest('.popup-loyalty').length == 0) {
|
||||
jQuery(this).fadeOut();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('#phoneLoyalty').keydown(function (e) {
|
||||
let key = e.key;
|
||||
|
||||
return (key >= '0' && key <= '9') || key == '+' || key == '(' || key == ')'|| key == '-' ||
|
||||
key == 'ArrowLeft' || key == 'ArrowRight' || key == 'Delete' || key == 'Backspace';
|
||||
});
|
||||
});
|
36
src/assets/js/retailcrm-loyalty.js
Normal file
36
src/assets/js/retailcrm-loyalty.js
Normal file
@ -0,0 +1,36 @@
|
||||
jQuery(function() {
|
||||
if (jQuery('#woocommerce_integration-retailcrm_loyalty').is(':checked')) {
|
||||
checkActiveCoupon();
|
||||
}
|
||||
|
||||
jQuery('#woocommerce_integration-retailcrm_loyalty').change(function () {
|
||||
if (this.checked) {
|
||||
checkActiveCoupon();
|
||||
}
|
||||
})
|
||||
|
||||
function checkActiveCoupon()
|
||||
{
|
||||
jQuery.ajax({
|
||||
url: AdminUrl.url + '/admin-ajax.php?action=get_status_coupon',
|
||||
method: 'POST',
|
||||
timeout: 0,
|
||||
data: {ajax: 1},
|
||||
dataType: 'json'
|
||||
})
|
||||
.done(function (response) {
|
||||
if (response.coupon_status !== 'yes') {
|
||||
var checkElement = jQuery('#woocommerce_integration-retailcrm_loyalty');
|
||||
checkElement.parent().css('color', 'red');
|
||||
checkElement.css('border-color', 'red');
|
||||
checkElement.prop('checked', false);
|
||||
|
||||
if (!jQuery('#coupon_warning').length) {
|
||||
checkElement.parent().parent().append(
|
||||
"<p id='coupon_warning' style='color: red'>" + response.translate.coupon_warning + "</p>"
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
@ -117,6 +117,7 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration
|
||||
|
||||
$this->form_fields['online_assistant'] = [
|
||||
'title' => __('Online assistant', 'retailcrm'),
|
||||
'css' => 'width:400px; height:215px; resize: horizontal;',
|
||||
'type' => 'textarea',
|
||||
'id' => 'online_assistant',
|
||||
'placeholder' => __('Insert the Online consultant code here', 'retailcrm')
|
||||
@ -593,6 +594,41 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration
|
||||
'description' => __('WhatsApp chat will be opened with this contact', 'retailcrm')
|
||||
];
|
||||
|
||||
/**
|
||||
* Loyalty Program
|
||||
*/
|
||||
|
||||
$this->form_fields[] = [
|
||||
'title' => __('Loyalty program', 'retailcrm'),
|
||||
'type' => 'heading',
|
||||
'description' => '',
|
||||
'id' => 'loyalty_options'
|
||||
];
|
||||
|
||||
$this->form_fields['loyalty'] = [
|
||||
'label' => __('Activate program loyalty', 'retailcrm'),
|
||||
'title' => __('Loyalty program', 'retailcrm'),
|
||||
'class' => 'checkbox',
|
||||
'type' => 'checkbox',
|
||||
'description' => __('Enable this setting for activate program loyalty on site', 'retailcrm')
|
||||
];
|
||||
|
||||
$this->form_fields['loyalty_terms'] = [
|
||||
'title' => __('Terms of loyalty program', 'retailcrm'),
|
||||
'css' => 'width:400px; height:215px; resize: horizontal;',
|
||||
'type' => 'textarea',
|
||||
'id' => 'loyalty_terms',
|
||||
'placeholder' => __('Insert the terms and conditions of the loyalty program', 'retailcrm')
|
||||
];
|
||||
|
||||
$this->form_fields['loyalty_personal'] = [
|
||||
'title' => __('Conditions of personal data processing', 'retailcrm'),
|
||||
'css' => 'width:400px; height:215px; resize: horizontal;',
|
||||
'type' => 'textarea',
|
||||
'id' => 'loyalty_personal',
|
||||
'placeholder' => __('Insert the terms and conditions for processing personal data', 'retailcrm')
|
||||
];
|
||||
|
||||
/**
|
||||
* Generate icml file
|
||||
*/
|
||||
|
@ -169,17 +169,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function customersCorporateList(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/customers-corporate',
|
||||
@ -273,17 +263,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function customersCorporateNotesList(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/customers-corporate/notes',
|
||||
@ -421,17 +401,8 @@ class WC_Retailcrm_Client_V5
|
||||
) {
|
||||
$this->checkIdParameter($by);
|
||||
|
||||
$parameters = ['by' => $by];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
$parameters['by'] = $by;
|
||||
|
||||
return $this->client->makeRequest(
|
||||
"/customers-corporate/$id/addresses",
|
||||
@ -537,17 +508,8 @@ class WC_Retailcrm_Client_V5
|
||||
) {
|
||||
$this->checkIdParameter($by);
|
||||
|
||||
$parameters = ['by' => $by];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
$parameters['by'] = $by;
|
||||
|
||||
return $this->client->makeRequest(
|
||||
"/customers-corporate/$id/companies",
|
||||
@ -640,17 +602,8 @@ class WC_Retailcrm_Client_V5
|
||||
) {
|
||||
$this->checkIdParameter($by);
|
||||
|
||||
$parameters = ['by' => $by];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
$parameters['by'] = $by;
|
||||
|
||||
return $this->client->makeRequest(
|
||||
"/customers-corporate/$id/contacts",
|
||||
@ -769,17 +722,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function usersList(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/users',
|
||||
@ -840,17 +783,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function segmentsList(array $filter = [], $limit = null, $page = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/segments',
|
||||
@ -870,17 +803,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function customFieldsList(array $filter = [], $limit = null, $page = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/custom-fields',
|
||||
@ -994,17 +917,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function customDictionariesList(array $filter = [], $limit = null, $page = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/custom-fields/dictionaries',
|
||||
@ -1101,17 +1014,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function ordersList(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/orders',
|
||||
@ -1445,17 +1348,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function customersList(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/customers',
|
||||
@ -1666,16 +1559,8 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function customersNotesList(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/customers/notes',
|
||||
WC_Retailcrm_Request::METHOD_GET,
|
||||
@ -1748,17 +1633,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function ordersPacksList(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/orders/packs',
|
||||
@ -1899,17 +1774,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function tasksList(array $filter = [], $limit = null, $page = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/tasks',
|
||||
@ -2008,17 +1873,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function storeProductsGroups(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/store/product-groups',
|
||||
@ -2042,17 +1897,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function storeInventories(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/store/inventories',
|
||||
@ -2180,17 +2025,7 @@ class WC_Retailcrm_Client_V5
|
||||
*/
|
||||
public function storeProducts(array $filter = [], $page = null, $limit = null)
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
if (null !== $page) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
if (null !== $limit) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
$parameters = $this->buildParameters($filter, $page, $limit);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/store/products',
|
||||
@ -3008,6 +2843,183 @@ class WC_Retailcrm_Client_V5
|
||||
);
|
||||
}
|
||||
|
||||
/** Loyalty program */
|
||||
|
||||
/** Customer registration in the loyalty program */
|
||||
public function createLoyaltyAccount(array $parameters, $site = null)
|
||||
{
|
||||
if ([] === $parameters) {
|
||||
throw new InvalidArgumentException(
|
||||
'Parameter `parameters` must contains a data'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/loyalty/account/create',
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
$this->fillSite($site, ['loyaltyAccount' => json_encode($parameters)])
|
||||
);
|
||||
}
|
||||
|
||||
/** Receiving information about participation in the loyalty program */
|
||||
public function getLoyaltyClientInfo(int $clientIdLoyalty)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/account/$clientIdLoyalty",
|
||||
WC_Retailcrm_Request::METHOD_GET
|
||||
);
|
||||
}
|
||||
|
||||
/** Activation of participation in the loyalty program */
|
||||
public function activateLoyaltyAccount(int $clientIdLoyalty)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/account/$clientIdLoyalty/activate",
|
||||
WC_Retailcrm_Request::METHOD_POST
|
||||
);
|
||||
}
|
||||
|
||||
/** Editing participation in the loyalty program */
|
||||
public function editLoyaltyAccount(int $clientIdLoyalty, array $parameters)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/account/$clientIdLoyalty/edit",
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
['id' => $clientIdLoyalty, 'loyaltyAccount' => json_encode($parameters)]
|
||||
);
|
||||
}
|
||||
|
||||
/** List of participation in the loyalty program */
|
||||
public function getLoyaltyAccountList(array $filter = [], $limit = null, $page = null)
|
||||
{
|
||||
$parameters = $this->buildParameters($filter, $limit, $page);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/loyalty/accounts',
|
||||
WC_Retailcrm_Request::METHOD_GET,
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
|
||||
/** List of loyalty programs */
|
||||
public function getListLoyalty(array $filter = [], $limit = null, $page = null)
|
||||
{
|
||||
$parameters = $this->buildParameters($filter, $limit, $page);
|
||||
|
||||
return $this->client->makeRequest(
|
||||
'/loyalty/loyalties',
|
||||
WC_Retailcrm_Request::METHOD_GET,
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
|
||||
/** Receiving information about the loyalty program */
|
||||
public function getLoyalty(int $idLoyalty)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/loyalties/$idLoyalty",
|
||||
WC_Retailcrm_Request::METHOD_GET
|
||||
);
|
||||
}
|
||||
|
||||
/** Charge bonus */
|
||||
public function chargeBonusLoyalty(int $clientIdLoyalty, float $amount, string $comment = '')
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/account/$clientIdLoyalty/bonus/charge",
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
['amount' => $amount, 'comment' => $comment]
|
||||
);
|
||||
}
|
||||
|
||||
public function creditBonusLoyalty(int $clientIdLoyalty, array $parameters)
|
||||
{
|
||||
if (!isset($parameters['amount'])) {
|
||||
throw new InvalidArgumentException(
|
||||
'Parameter `amount` does not exist'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/account/$clientIdLoyalty/bonus/credit",
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
|
||||
/** History of the client's bonus account */
|
||||
public function getClientBonusHistory(int $clientIdLoyalty, array $filter = [], $limit = null, $page = null)
|
||||
{
|
||||
$parameters = $this->buildParameters($filter, $limit, $page);
|
||||
$parameters['id'] = $clientIdLoyalty;
|
||||
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/account/$clientIdLoyalty/bonus/operations",
|
||||
WC_Retailcrm_Request::METHOD_GET,
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
|
||||
public function getDetailClientBonus(
|
||||
int $clientIdLoyalty,
|
||||
string $status,
|
||||
array $filter = [],
|
||||
$limit = null,
|
||||
$page = null
|
||||
) {
|
||||
$parameters = $this->buildParameters($filter, $limit, $page);
|
||||
$parameters['id'] = $clientIdLoyalty;
|
||||
$parameters['status'] = $status;
|
||||
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/account/$clientIdLoyalty/bonus/$status/details",
|
||||
WC_Retailcrm_Request::METHOD_GET,
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
|
||||
/** Bonus account history for all participants */
|
||||
public function getBonusHistory(string $cursor, array $filter = [], $limit = null)
|
||||
{
|
||||
$parameters = $this->buildParameters($filter, $limit);
|
||||
$parameters['cursor'] = $cursor;
|
||||
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/bonus/operations",
|
||||
WC_Retailcrm_Request::METHOD_GET,
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
|
||||
/** Maximum discount calculation */
|
||||
public function calculateDiscountLoyalty(string $site, array $order, $bonuses = 0)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/loyalty/calculate",
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
['site' => $site, 'order' => json_encode($order), 'bonuses' => $bonuses]
|
||||
);
|
||||
}
|
||||
|
||||
/** Application of bonuses under the loyalty program */
|
||||
public function applyBonusToOrder(string $site, array $order, float $bonuses)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/orders/loyalty/apply",
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
['site' => $site, 'order' => json_encode($order), 'bonuses' => $bonuses]
|
||||
);
|
||||
}
|
||||
|
||||
public function cancelBonusOrder(array $order)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/orders/loyalty/cancel-bonus-operations",
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
['order' => json_encode($order)]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update CRM basic statistic
|
||||
*
|
||||
@ -3121,4 +3133,23 @@ class WC_Retailcrm_Client_V5
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
protected function buildParameters(array $filter = [], $limit = null, $page = null): array
|
||||
{
|
||||
$parameters = [];
|
||||
|
||||
if (count($filter)) {
|
||||
$parameters['filter'] = $filter;
|
||||
}
|
||||
|
||||
if (isset($page)) {
|
||||
$parameters['page'] = (int) $page;
|
||||
}
|
||||
|
||||
if (isset($limit)) {
|
||||
$parameters['limit'] = (int) $limit;
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,12 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
/** @var WC_Retailcrm_Cart */
|
||||
protected $cart;
|
||||
|
||||
/** @var WC_Retailcrm_Loyalty */
|
||||
protected $loyalty;
|
||||
|
||||
/** @var array */
|
||||
protected $updatedOrderId = [];
|
||||
|
||||
/**
|
||||
* Init and hook in the integration.
|
||||
*
|
||||
@ -86,6 +92,7 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
add_action('wp_ajax_generate_icml', [$this, 'generate_icml']);
|
||||
add_action('wp_ajax_upload_selected_orders', [$this, 'upload_selected_orders']);
|
||||
add_action('wp_ajax_clear_cron_tasks', [$this, 'clear_cron_tasks']);
|
||||
add_action('wp_ajax_get_status_coupon', [$this, 'get_status_coupon']);
|
||||
add_action('admin_print_footer_scripts', [$this, 'ajax_generate_icml'], 99);
|
||||
add_action('woocommerce_update_customer', [$this, 'update_customer'], 10, 1);
|
||||
add_action('user_register', [$this, 'create_customer'], 10, 2);
|
||||
@ -99,6 +106,42 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
add_action('admin_enqueue_scripts', [$this, 'include_files_for_admin'], 101);
|
||||
add_action('woocommerce_new_order', [$this, 'create_order'], 11, 1);
|
||||
|
||||
|
||||
if (isLoyaltyActivate($this->settings)) {
|
||||
add_action('wp_ajax_register_customer_loyalty', [$this, 'register_customer_loyalty']);
|
||||
add_action('wp_ajax_activate_customer_loyalty', [$this, 'activate_customer_loyalty']);
|
||||
add_action('init', [$this, 'add_loyalty_endpoint'], 11, 1);
|
||||
add_action('woocommerce_account_menu_items', [$this, 'add_loyalty_item'], 11, 1);
|
||||
add_action('woocommerce_account_loyalty_endpoint', [$this, 'show_loyalty'], 11, 1);
|
||||
|
||||
// Add coupon hooks for loyalty program
|
||||
add_action('woocommerce_cart_coupon', [$this, 'coupon_info'], 11, 1);
|
||||
//Remove coupons when cart changes
|
||||
add_action('woocommerce_add_to_cart', [$this, 'refresh_loyalty_coupon'], 11, 1);
|
||||
add_action('woocommerce_after_cart_item_quantity_update', [$this, 'refresh_loyalty_coupon'], 11, 1);
|
||||
add_action('woocommerce_cart_item_removed', [$this, 'refresh_loyalty_coupon'], 11, 1);
|
||||
add_action('woocommerce_before_cart_empted', [$this, 'clear_loyalty_coupon'], 11, 1);
|
||||
add_action('woocommerce_removed_coupon', [$this, 'remove_coupon'], 11, 1);
|
||||
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);
|
||||
|
||||
if (
|
||||
!$this->get_option('deactivate_update_order')
|
||||
|| $this->get_option('deactivate_update_order') == static::NO
|
||||
) {
|
||||
add_action('woocommerce_update_order', [$this, 'take_update_order'], 11, 1);
|
||||
add_action('shutdown', [$this, 'update_order_loyalty'], -1);
|
||||
add_action('woocommerce_saved_order_items', [$this, 'update_order_items'], 10, 1);
|
||||
}
|
||||
} elseif (
|
||||
!$this->get_option('deactivate_update_order')
|
||||
|| $this->get_option('deactivate_update_order') == static::NO
|
||||
) {
|
||||
add_action('woocommerce_update_order', [$this, 'update_order'], 10, 1);
|
||||
}
|
||||
|
||||
|
||||
// Subscribed hooks
|
||||
add_action('register_form', [$this, 'subscribe_register_form'], 99);
|
||||
add_action('woocommerce_register_form', [$this, 'subscribe_woocommerce_register_form'], 99);
|
||||
@ -111,13 +154,6 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!$this->get_option('deactivate_update_order')
|
||||
|| $this->get_option('deactivate_update_order') == static::NO
|
||||
) {
|
||||
add_action('woocommerce_update_order', [$this, 'update_order'], 11, 1);
|
||||
}
|
||||
|
||||
if ($this->get_option('abandoned_carts_enabled') === static::YES) {
|
||||
$this->cart = new WC_Retailcrm_Cart($this->apiClient, $this->settings);
|
||||
|
||||
@ -127,6 +163,8 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
add_action('woocommerce_cart_emptied', [$this, 'clear_cart']);
|
||||
}
|
||||
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiClient, $this->settings);
|
||||
|
||||
// Deactivate hook
|
||||
add_action('retailcrm_deactivate', [$this, 'deactivate']);
|
||||
|
||||
@ -523,6 +561,15 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
}
|
||||
}
|
||||
|
||||
public function update_order($orderId)
|
||||
{
|
||||
if (WC_Retailcrm_Plugin::history_running() === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->orders->updateOrder($orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit order in retailCRM
|
||||
*
|
||||
@ -532,13 +579,38 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function update_order($order_id)
|
||||
public function take_update_order($order_id)
|
||||
{
|
||||
if (WC_Retailcrm_Plugin::history_running() === true) {
|
||||
if (
|
||||
WC_Retailcrm_Plugin::history_running() === true
|
||||
|| did_action('woocommerce_checkout_order_processed')
|
||||
|| did_action('woocommerce_new_order')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->orders->updateOrder($order_id);
|
||||
$this->updatedOrderId[$order_id] = $order_id;
|
||||
}
|
||||
|
||||
public function update_order_loyalty()
|
||||
{
|
||||
if ($this->updatedOrderId !== []) {
|
||||
foreach ($this->updatedOrderId as $orderId) {
|
||||
$this->orders->updateOrder($orderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function update_order_items($orderId)
|
||||
{
|
||||
$this->orders->updateOrder($orderId);
|
||||
}
|
||||
|
||||
public function trash_order_action($id)
|
||||
{
|
||||
if ('shop_order' == get_post_type($id)) {
|
||||
$this->orders->updateOrder($id, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -607,6 +679,126 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
$this->include_js_scripts_for_admin();
|
||||
}
|
||||
|
||||
public function get_status_coupon()
|
||||
{
|
||||
echo json_encode(
|
||||
[
|
||||
'coupon_status' => get_option('woocommerce_enable_coupons'),
|
||||
'translate' => [
|
||||
'coupon_warning' => __(
|
||||
"To activate the loyalty program it is necessary to activate the <a href='?page=wc-settings'>'enable use of coupons option'</a>",
|
||||
'retailcrm'
|
||||
)
|
||||
]
|
||||
]);
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
public function register_customer_loyalty()
|
||||
{
|
||||
$phone = filter_input(INPUT_POST, 'phone');
|
||||
$userId = filter_input(INPUT_POST, 'userId');
|
||||
$site = $this->apiClient->getSingleSiteForKey();
|
||||
$isSuccessful = false;
|
||||
|
||||
if (!empty($site) && $userId && $phone) {
|
||||
$isSuccessful = $this->loyalty->registerCustomer($userId, $phone, $site);
|
||||
}
|
||||
|
||||
if (!$isSuccessful) {
|
||||
writeBaseLogs('Errors when registering a loyalty program. Passed parameters: ' .
|
||||
json_encode(['site' => $site, 'userId' => $userId, 'phone' => $phone])
|
||||
);
|
||||
echo json_encode(['error' => __('Error while registering in the loyalty program. Try again later', 'retailcrm')]);
|
||||
} else {
|
||||
echo json_encode(['isSuccessful' => true]);
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
public function activate_customer_loyalty()
|
||||
{
|
||||
$loyaltyId = filter_input(INPUT_POST, 'loyaltyId');
|
||||
$isSuccessful = false;
|
||||
|
||||
if ($loyaltyId) {
|
||||
$isSuccessful = $this->loyalty->activateLoyaltyCustomer($loyaltyId);
|
||||
}
|
||||
|
||||
if (!$isSuccessful) {
|
||||
writeBaseLogs('Errors when activate loyalty program. Passed parameters: ' . json_encode(['loyaltyId' => $loyaltyId]));
|
||||
echo json_encode(['error' => __('Error when activating the loyalty program. Try again later', 'retailcrm')]);
|
||||
} else {
|
||||
echo json_encode(['isSuccessful' => true]);
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
public function coupon_info()
|
||||
{
|
||||
try {
|
||||
$result = $this->loyalty->createLoyaltyCoupon();
|
||||
|
||||
if ($result) {
|
||||
echo $result;
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function refresh_loyalty_coupon()
|
||||
{
|
||||
try {
|
||||
$this->loyalty->createLoyaltyCoupon(true);
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function clear_loyalty_coupon()
|
||||
{
|
||||
try {
|
||||
$this->loyalty->clearLoyaltyCoupon();
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function remove_coupon($couponCode)
|
||||
{
|
||||
try {
|
||||
if (!$this->loyalty->deleteLoyaltyCoupon($couponCode)) {
|
||||
$this->loyalty->createLoyaltyCoupon(true);
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function apply_coupon($couponCode)
|
||||
{
|
||||
try {
|
||||
if (!$this->loyalty->isLoyaltyCoupon($couponCode)) {
|
||||
$this->loyalty->createLoyaltyCoupon(true);
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function reviewCreditBonus()
|
||||
{
|
||||
$resultHtml = $this->loyalty->getCreditBonuses();
|
||||
|
||||
if ($resultHtml) {
|
||||
echo $resultHtml;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In this method we include CSS file
|
||||
*
|
||||
@ -645,9 +837,10 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
'retailcrm-cron-info',
|
||||
'retailcrm-meta-fields',
|
||||
'retailcrm-module-settings',
|
||||
'retailcrm-loyalty'
|
||||
];
|
||||
|
||||
$wpAdminUrl = ['url' => get_admin_url()];
|
||||
$wpAdminUrl = ['url' => get_admin_url()];
|
||||
$jsScriptsPath = plugins_url() . '/woo-retailcrm/assets/js/';
|
||||
|
||||
foreach ($jsScripts as $scriptName) {
|
||||
@ -803,6 +996,53 @@ if (!class_exists('WC_Retailcrm_Base')) {
|
||||
wp_die();
|
||||
}
|
||||
|
||||
public function add_loyalty_item($items)
|
||||
{
|
||||
$items['loyalty'] = __('Loyalty program', 'retailcrm');
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function add_loyalty_endpoint()
|
||||
{
|
||||
add_rewrite_endpoint('loyalty', EP_PAGES);
|
||||
}
|
||||
|
||||
public function show_loyalty()
|
||||
{
|
||||
$userId = get_current_user_id();
|
||||
|
||||
if (!isset($userId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$jsScript = 'retailcrm-loyalty-actions';
|
||||
$loyaltyUrl = ['url' => get_admin_url()];
|
||||
$jsScriptsPath = plugins_url() . '/woo-retailcrm/assets/js/';
|
||||
$cssPath = plugins_url() . '/woo-retailcrm/assets/css/';
|
||||
$messagePhone = __('Enter the correct phone number', 'retailcrm');
|
||||
|
||||
wp_register_script($jsScript, $jsScriptsPath . $jsScript . '.js', false, '0.1');
|
||||
wp_enqueue_script($jsScript, $jsScriptsPath . $jsScript . '.js', '', '', true);
|
||||
wp_localize_script($jsScript, 'loyaltyUrl', $loyaltyUrl);
|
||||
wp_localize_script($jsScript, 'customerId', $userId);
|
||||
wp_localize_script($jsScript, 'messagePhone', $messagePhone);
|
||||
wp_localize_script($jsScript, 'termsLoyalty', $this->settings['loyalty_terms']);
|
||||
wp_localize_script($jsScript, 'privacyLoyalty', $this->settings['loyalty_personal']);
|
||||
wp_register_style('retailcrm-loyalty-style', $cssPath . 'retailcrm-loyalty-style.css', false, '0.1');
|
||||
wp_enqueue_style('retailcrm-loyalty-style');
|
||||
|
||||
$result = $this->loyalty->getForm($userId);
|
||||
|
||||
if ([] === $result) {
|
||||
echo '<p style="color: red">'. __('Error while retrieving data. Try again later', 'retailcrm') . '</p>';
|
||||
} else {
|
||||
wp_localize_script($jsScript, 'loyaltyId', $result['loyaltyId'] ?? null);
|
||||
echo $result['form'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get custom fields with CRM
|
||||
*
|
||||
|
539
src/include/class-wc-retailcrm-loyalty.php
Normal file
539
src/include/class-wc-retailcrm-loyalty.php
Normal file
@ -0,0 +1,539 @@
|
||||
<?php
|
||||
|
||||
if (!class_exists('WC_Retailcrm_Loyalty')) :
|
||||
if (!class_exists('WC_Retailcrm_Loyalty_Form')) {
|
||||
include_once(WC_Integration_Retailcrm::checkCustomFile('include/components/class-wc-retailcrm-loyalty-form.php'));
|
||||
}
|
||||
/**
|
||||
* PHP version 7.0
|
||||
*
|
||||
* Class WC_Retailcrm_Loyalty - Allows transfer data carts with CMS.
|
||||
*
|
||||
* @category Integration
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license http://retailcrm.ru Proprietary
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://help.retailcrm.ru
|
||||
*/
|
||||
class WC_Retailcrm_Loyalty
|
||||
{
|
||||
/** @var WC_Retailcrm_Client_V5 */
|
||||
protected $apiClient;
|
||||
|
||||
protected $dateFormat;
|
||||
|
||||
protected $settings;
|
||||
|
||||
/** @var WC_Retailcrm_Loyalty_Form */
|
||||
protected $loyaltyForm;
|
||||
|
||||
protected $validator;
|
||||
|
||||
public function __construct($apiClient, $settings)
|
||||
{
|
||||
$this->apiClient = $apiClient;
|
||||
$this->settings = $settings;
|
||||
$this->dateFormat = 'Y-m-d H:i:sP';
|
||||
$this->loyaltyForm = new WC_Retailcrm_Loyalty_Form();
|
||||
$this->validator = new WC_Retailcrm_Loyalty_Validator(
|
||||
$this->apiClient,
|
||||
isCorporateUserActivate($this->settings)
|
||||
);
|
||||
}
|
||||
|
||||
public function getForm(int $userId)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
try {
|
||||
$response = $this->getLoyaltyAccounts($userId);
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs('Exception get loyalty accounts: ' . $exception->getMessage());
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$loyaltyAccount = $response['loyaltyAccounts'][0] ?? null;
|
||||
|
||||
if ($loyaltyAccount && (int) $loyaltyAccount['customer']['externalId'] === $userId) {
|
||||
if ($loyaltyAccount['active'] === true) {
|
||||
$result['form'] = $this->loyaltyForm->getInfoLoyalty($loyaltyAccount);
|
||||
} else {
|
||||
$result['form'] = $this->loyaltyForm->getActivationForm();
|
||||
|
||||
$result['loyaltyId'] = $loyaltyAccount['id'];
|
||||
}
|
||||
} else {
|
||||
$result['form'] = $this->loyaltyForm->getRegistrationForm();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function registerCustomer(int $userId, string $phone, string $site): bool
|
||||
{
|
||||
$parameters = [
|
||||
'phoneNumber' => $phone,
|
||||
'customer' => [
|
||||
'externalId' => $userId
|
||||
]
|
||||
];
|
||||
|
||||
try {
|
||||
$response = $this->apiClient->createLoyaltyAccount($parameters, $site);
|
||||
|
||||
if (!$response->isSuccessful()) {
|
||||
writeBaseLogs('Error while registering in the loyalty program: ' . $response->getRawResponse());
|
||||
}
|
||||
|
||||
return $response->isSuccessful();
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs('Exception while registering in the loyalty program: ' . $exception->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function activateLoyaltyCustomer(int $loyaltyId)
|
||||
{
|
||||
try {
|
||||
$response = $this->apiClient->activateLoyaltyAccount($loyaltyId);
|
||||
|
||||
if (!$response->isSuccessful()) {
|
||||
writeBaseLogs('Error while registering in the loyalty program: ' . $response->getRawResponse());
|
||||
}
|
||||
|
||||
return $response->isSuccessful();
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs('Exception while activate loyalty account: ' . $exception->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function getDiscountLoyalty($cartItems, $site, $customerId)
|
||||
{
|
||||
$response = $this->calculateDiscountLoyalty($cartItems, $site, $customerId);
|
||||
|
||||
if ($response === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$discount = 0;
|
||||
|
||||
//Checking if the loyalty discount is a percent discount
|
||||
foreach ($response['order']['items'] as $item) {
|
||||
if (!isset($item['discounts'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($item['discounts'] as $discountItem) {
|
||||
if ($discountItem['type'] === 'loyalty_level') {
|
||||
$discount += $discountItem['amount'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If the discount has already been given, do not work with points deduction
|
||||
if ($discount === 0) {
|
||||
foreach ($response['calculations'] as $calculate) {
|
||||
if ($calculate['privilegeType'] !== 'loyalty_level') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$discount = $calculate['maxChargeBonuses'];
|
||||
}
|
||||
}
|
||||
|
||||
return $discount;
|
||||
}
|
||||
|
||||
private function getLoyaltyAccounts(int $userId)
|
||||
{
|
||||
$response = $this->apiClient->customersGet($userId);
|
||||
|
||||
if (!isset($response['customer']['id'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$filter['customerId'] = $response['customer']['id'];
|
||||
|
||||
$response = $this->apiClient->getLoyaltyAccountList($filter);
|
||||
|
||||
if (!$response->isSuccessful() || !$response->offsetExists('loyaltyAccounts')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function createLoyaltyCoupon($refreshCoupon = false)
|
||||
{
|
||||
global $woocommerce;
|
||||
|
||||
$site = $this->apiClient->getSingleSiteForKey();
|
||||
$cartItems = $woocommerce->cart->get_cart();
|
||||
$customerId = $woocommerce->customer ? $woocommerce->customer->get_id() : null;
|
||||
|
||||
$resultString = '';
|
||||
|
||||
if (!$customerId || !$cartItems) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$couponsLp = [];
|
||||
// Check exists used loyalty coupons
|
||||
foreach ($woocommerce->cart->get_coupons() as $code => $coupon) {
|
||||
if ($this->isLoyaltyCoupon($code)) {
|
||||
$couponsLp[] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
// if you need to refresh coupon that does not exist
|
||||
if (count($couponsLp) === 0 && $refreshCoupon) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//If one loyalty coupon is used, not generate a new one
|
||||
if (count($couponsLp) === 1 && !$refreshCoupon) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if more than 1 loyalty coupon is used, delete all coupons
|
||||
if (count($couponsLp) > 1 || $refreshCoupon) {
|
||||
foreach ($couponsLp as $code) {
|
||||
$woocommerce->cart->remove_coupon($code);
|
||||
|
||||
$coupon = new WC_Coupon($code);
|
||||
|
||||
$coupon->delete(true);
|
||||
}
|
||||
|
||||
$woocommerce->cart->calculate_totals();
|
||||
}
|
||||
|
||||
if (!$this->validator->checkAccount($customerId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$lpDiscountSum = $this->getDiscountLoyalty($woocommerce->cart->get_cart(), $site, $customerId);
|
||||
|
||||
if ($lpDiscountSum === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Check the existence of loyalty coupons and delete them
|
||||
$coupons = $this->getCouponLoyalty($woocommerce->customer->get_email());
|
||||
|
||||
foreach ($coupons as $item) {
|
||||
$coupon = new WC_Coupon($item['code']);
|
||||
|
||||
$coupon->delete(true);
|
||||
}
|
||||
|
||||
//Generate new coupon
|
||||
$coupon = new WC_Coupon();
|
||||
|
||||
$coupon->set_usage_limit(0);
|
||||
$coupon->set_amount($lpDiscountSum);
|
||||
$coupon->set_email_restrictions($woocommerce->customer->get_email());
|
||||
$coupon->set_code('loyalty' . mt_rand());
|
||||
$coupon->save();
|
||||
|
||||
if ($refreshCoupon) {
|
||||
$woocommerce->cart->apply_coupon($coupon->get_code());
|
||||
|
||||
return $resultString;
|
||||
}
|
||||
|
||||
//If a percentage discount, automatically apply a loyalty coupon
|
||||
if ($this->validator->loyaltyAccount['level']['type'] === 'discount') {
|
||||
$woocommerce->cart->apply_coupon($coupon->get_code());
|
||||
|
||||
return $resultString;
|
||||
}
|
||||
|
||||
$resultString .= ' <div style="text-align: left; line-height: 3"><b>' . __('It is possible to write off', 'retailcrm') . ' ' . $lpDiscountSum . ' ' . __('bonuses', 'retailcrm') . '</b></div>';
|
||||
return $resultString. '<div style="text-align: left;"><b>' . __('Use coupon:', 'retailcrm') . ' <u><i>' . $coupon->get_code() . '</i></u></i></b></div>';
|
||||
}
|
||||
|
||||
public function clearLoyaltyCoupon()
|
||||
{
|
||||
global $woocommerce;
|
||||
|
||||
foreach ($woocommerce->cart->get_coupons() as $code => $coupon) {
|
||||
if ($this->isLoyaltyCoupon($code)) {
|
||||
$woocommerce->cart->remove_coupon($code);
|
||||
|
||||
$coupon = new WC_Coupon($code);
|
||||
|
||||
$coupon->delete(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteLoyaltyCoupon($couponCode)
|
||||
{
|
||||
if ($this->isLoyaltyCoupon($couponCode)) {
|
||||
$coupon = new WC_Coupon($couponCode);
|
||||
|
||||
$coupon->delete(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isLoyaltyCoupon($couponCode): bool
|
||||
{
|
||||
return preg_match('/^loyalty\d+$/m', $couponCode) === 1;
|
||||
}
|
||||
|
||||
public function getCouponLoyalty($email)
|
||||
{
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT posts.post_name code FROM {$wpdb->prefix}posts AS posts
|
||||
LEFT JOIN {$wpdb->prefix}postmeta AS postmeta ON posts.ID = postmeta.post_id
|
||||
WHERE posts.post_type = 'shop_coupon' AND posts.post_name LIKE 'loyalty%'
|
||||
AND postmeta.meta_key = 'customer_email' AND postmeta.meta_value LIKE %s",
|
||||
'%' . $email . '%'
|
||||
), ARRAY_A
|
||||
);
|
||||
}
|
||||
|
||||
public function deleteLoyaltyCouponInOrder($wcOrder)
|
||||
{
|
||||
$discountLp = 0;
|
||||
$coupons = $wcOrder->get_coupons();
|
||||
|
||||
foreach ($coupons as $coupon) {
|
||||
$code = $coupon->get_code();
|
||||
|
||||
if ($this->isLoyaltyCoupon($code)) {
|
||||
$discountLp = $coupon->get_discount();
|
||||
$wcOrder->remove_coupon($code);
|
||||
$objectCoupon = new WC_Coupon($code);
|
||||
$objectCoupon->delete(true);
|
||||
|
||||
$wcOrder->recalculate_coupons();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $discountLp;
|
||||
}
|
||||
|
||||
public function isValidOrder($wcCustomer, $wcOrder)
|
||||
{
|
||||
return !(!$wcCustomer || (isCorporateUserActivate($this->settings) && isCorporateOrder($wcCustomer, $wcOrder)));
|
||||
}
|
||||
|
||||
public function isValidUser($wcCustomer)
|
||||
{
|
||||
if (empty($wcCustomer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->getLoyaltyAccounts($wcCustomer->get_id());
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs('Exception get loyalty accounts: ' . $exception->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return isset($response['loyaltyAccounts'][0]);
|
||||
}
|
||||
|
||||
public function applyLoyaltyDiscount($wcOrder, $createdOrder, $discountLp = 0)
|
||||
{
|
||||
$isPercentDiscount = false;
|
||||
$items = [];
|
||||
|
||||
// Verification of automatic creation of the percentage discount of the loyalty program
|
||||
foreach ($createdOrder['items'] as $item) {
|
||||
foreach ($item['discounts'] as $discount) {
|
||||
if ($discount['type'] === 'loyalty_level') {
|
||||
$isPercentDiscount = true;
|
||||
$items = $createdOrder['items'];
|
||||
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isPercentDiscount) {
|
||||
$response = $this->apiClient->applyBonusToOrder($createdOrder['site'], ['externalId' => $createdOrder['externalId']], (float) $discountLp);
|
||||
|
||||
if (!$response instanceof WC_Retailcrm_Response || !$response->isSuccessful()) {
|
||||
return $response->getErrorString();
|
||||
}
|
||||
|
||||
$items = $response['order']['items'];
|
||||
}
|
||||
|
||||
$this->calculateLoyaltyDiscount($wcOrder, $items);
|
||||
}
|
||||
|
||||
public function calculateLoyaltyDiscount($wcOrder, $orderItems)
|
||||
{
|
||||
$wcItems = $wcOrder->get_items();
|
||||
|
||||
foreach ($orderItems as $item) {
|
||||
$externalId = $item['externalIds'][0]['value'];
|
||||
$externalId = preg_replace('/^\d+\_/m', '', $externalId);
|
||||
|
||||
if (isset($wcItems[(int) $externalId])) {
|
||||
$discountLoyaltyTotal = 0;
|
||||
|
||||
foreach ($item['discounts'] as $discount) {
|
||||
if (in_array($discount['type'], ['bonus_charge', 'loyalty_level'])) {
|
||||
$discountLoyaltyTotal += $discount['amount'];
|
||||
}
|
||||
}
|
||||
|
||||
$wcItem = $wcItems[(int) $externalId];
|
||||
$wcItem->set_total($wcItem->get_total() - $discountLoyaltyTotal);
|
||||
$wcItem->calculate_taxes();
|
||||
$wcItem->save();
|
||||
}
|
||||
}
|
||||
|
||||
$wcOrder->calculate_totals();
|
||||
}
|
||||
|
||||
public function getCrmItemsInfo($orderExternalId)
|
||||
{
|
||||
$discountType = null;
|
||||
$crmItems = [];
|
||||
|
||||
$response = $this->apiClient->ordersGet($orderExternalId);
|
||||
|
||||
if (!$response instanceof WC_Retailcrm_Response || !$response->isSuccessful() || !isset($response['order'])) {
|
||||
writeBaseLogs('Process order: Error when receiving an order from the CRM. Order Id: ' . $orderExternalId);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($response['order']['items'] as $item) {
|
||||
$externalId = $item['externalIds'][0]['value'];
|
||||
$externalId = preg_replace('/^\d+\_/m', '', $externalId);
|
||||
$crmItems[$externalId] = $item;
|
||||
|
||||
if (!$discountType) {
|
||||
foreach ($item['discounts'] as $discount) {
|
||||
if (in_array($discount['type'], ['bonus_charge', 'loyalty_level'])) {
|
||||
$discountType = $discount['type'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ['items' => $crmItems, 'discountType' => $discountType];
|
||||
}
|
||||
|
||||
public function calculateDiscountLoyalty($cartItems, $site, $customerId, $bonuses = 0)
|
||||
{
|
||||
$order = [
|
||||
'site' => $site,
|
||||
'customer' => ['externalId' => $customerId],
|
||||
'privilegeType' => 'loyalty_level'
|
||||
];
|
||||
|
||||
$useXmlId = isset($this->settings['bind_by_sku']) && $this->settings['bind_by_sku'] === WC_Retailcrm_Base::YES;
|
||||
|
||||
foreach ($cartItems as $item) {
|
||||
$product = $item['data'];
|
||||
|
||||
$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']
|
||||
];
|
||||
}
|
||||
|
||||
$response = $this->apiClient->calculateDiscountLoyalty($site, $order, (float) $bonuses);
|
||||
|
||||
if (!$response->isSuccessful() || !isset($response['calculations'])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function getCreditBonuses(): string
|
||||
{
|
||||
global $woocommerce;
|
||||
|
||||
$customerId = $woocommerce->customer ? $woocommerce->customer->get_id() : null;
|
||||
$site = $this->apiClient->getSingleSiteForKey();
|
||||
|
||||
if (
|
||||
!$customerId
|
||||
|| !$woocommerce->cart
|
||||
|| !$woocommerce->cart->get_cart()
|
||||
|| !$site
|
||||
|| !$this->validator->checkAccount($customerId)
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$loyaltyCoupon = null;
|
||||
$coupons = $woocommerce->cart->get_applied_coupons();
|
||||
|
||||
foreach ($coupons as $coupon) {
|
||||
if ($this->isLoyaltyCoupon($coupon)) {
|
||||
$loyaltyCoupon = new WC_Coupon($coupon);
|
||||
|
||||
$woocommerce->cart->remove_coupon($coupon);
|
||||
$woocommerce->cart->calculate_totals();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($loyaltyCoupon) {
|
||||
$chargeBonuses = $loyaltyCoupon->get_amount();
|
||||
}
|
||||
|
||||
$cartItems = $woocommerce->cart->get_cart();
|
||||
$response = $this->calculateDiscountLoyalty($cartItems, $site, $customerId, $chargeBonuses ?? 0);
|
||||
|
||||
if ($loyaltyCoupon) {
|
||||
$coupon = new WC_Coupon();
|
||||
$coupon->set_usage_limit(0);
|
||||
$coupon->set_amount($loyaltyCoupon->get_amount());
|
||||
$coupon->set_email_restrictions($loyaltyCoupon->get_email_restrictions());
|
||||
$coupon->set_code($loyaltyCoupon->get_code());
|
||||
$coupon->save();
|
||||
|
||||
$woocommerce->cart->apply_coupon($coupon->get_code());
|
||||
$woocommerce->cart->calculate_totals();
|
||||
}
|
||||
|
||||
if ($response === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$creditBonuses = $response['order']['bonusesCreditTotal'];
|
||||
|
||||
if ($creditBonuses) {
|
||||
return $this->getHtmlCreditBonuses($creditBonuses);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function getHtmlCreditBonuses($creditBonuses)
|
||||
{
|
||||
return '<b style="font-size: large">' . __("Points will be awarded upon completion of the order:", 'retailcrm') . ' <u style="color: green"><i>' . $creditBonuses . '</u></i></b>';
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
@ -17,6 +17,9 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
/** @var bool|WC_Retailcrm_Proxy|WC_Retailcrm_Client_V5 */
|
||||
protected $retailcrm;
|
||||
|
||||
/** @var WC_Retailcrm_Loyalty|null */
|
||||
protected $loyalty = null;
|
||||
|
||||
/** @var array */
|
||||
protected $retailcrm_settings;
|
||||
|
||||
@ -41,6 +44,12 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
/** @var array */
|
||||
private $order = [];
|
||||
|
||||
/** @var bool */
|
||||
private $cancelLoyalty = false;
|
||||
|
||||
/** @var string */
|
||||
private $loyaltyDiscountType = '';
|
||||
|
||||
/** @var array */
|
||||
private $payment = [];
|
||||
|
||||
@ -64,6 +73,10 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
$this->orders = $orders;
|
||||
$this->order_payment = $order_payment;
|
||||
|
||||
if (isLoyaltyActivate($retailcrm_settings)) {
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($retailcrm, $retailcrm_settings);
|
||||
}
|
||||
|
||||
if (!empty($retailcrm_settings['order-meta-data-retailcrm'])) {
|
||||
$this->customFields = json_decode($retailcrm_settings['order-meta-data-retailcrm'], true);
|
||||
}
|
||||
@ -88,8 +101,34 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
|
||||
$wcOrder = wc_get_order($orderId);
|
||||
|
||||
if ($this->loyalty) {
|
||||
$wcCustomer = null;
|
||||
$privilegeType = 'none';
|
||||
$discountLp = $this->loyalty->deleteLoyaltyCouponInOrder($wcOrder);
|
||||
$dataOrder = $wcOrder->get_data();
|
||||
|
||||
if (isset($dataOrder['customer_id'])) {
|
||||
$wcCustomer = new WC_Customer($dataOrder['customer_id']) ?? null;
|
||||
}
|
||||
|
||||
if (!$this->loyalty->isValidOrder($wcCustomer, $wcOrder)) {
|
||||
if ($discountLp > 0) {
|
||||
writeBaseLogs('The user does not meet the requirements for working with the loyalty program. Order Id: ' . $orderId);
|
||||
}
|
||||
|
||||
$discountLp = 0;
|
||||
$privilegeType = 'none';
|
||||
} elseif ($this->loyalty->isValidUser($wcCustomer)) {
|
||||
$privilegeType = 'loyalty_level';
|
||||
}
|
||||
}
|
||||
|
||||
$this->processOrder($wcOrder);
|
||||
|
||||
if (isset($privilegeType)) {
|
||||
$this->order['privilegeType'] = $privilegeType;
|
||||
}
|
||||
|
||||
$response = $this->retailcrm->ordersCreate($this->order);
|
||||
|
||||
// Allows you to verify order creation and perform additional actions
|
||||
@ -98,6 +137,10 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
if (!$response instanceof WC_Retailcrm_Response || !$response->isSuccessful()) {
|
||||
return $response->getErrorString();
|
||||
}
|
||||
|
||||
if (isset($discountLp) && $discountLp > 0) {
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, $response['order'], $discountLp);
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs(
|
||||
sprintf(
|
||||
@ -266,7 +309,7 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
* @return WC_Order $order | null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function updateOrder($orderId)
|
||||
public function updateOrder($orderId, $statusTrash = false)
|
||||
{
|
||||
if (!$this->retailcrm instanceof WC_Retailcrm_Proxy) {
|
||||
return null;
|
||||
@ -274,16 +317,39 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
|
||||
try {
|
||||
$wcOrder = wc_get_order($orderId);
|
||||
$needRecalculate = false;
|
||||
|
||||
$this->processOrder($wcOrder, true);
|
||||
$this->processOrder($wcOrder, true, $statusTrash);
|
||||
|
||||
if ($this->cancelLoyalty) {
|
||||
$this->cancelLoyalty = false;
|
||||
$this->order_item->cancelLoyalty = false;
|
||||
$needRecalculate = true;
|
||||
|
||||
if ($this->loyaltyDiscountType === 'loyalty_level') {
|
||||
$this->order['privilegeType'] = 'none';
|
||||
}
|
||||
|
||||
if ($this->loyaltyDiscountType === 'bonus_charge') {
|
||||
$responseCancelBonus = $this->retailcrm->cancelBonusOrder(['externalId' => $this->order['externalId']]);
|
||||
|
||||
if (!$responseCancelBonus instanceof WC_Retailcrm_Response || !$responseCancelBonus->isSuccessful()) {
|
||||
writeBaseLogs('Error when canceling bonuses');
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$response = $this->retailcrm->ordersEdit($this->order);
|
||||
|
||||
// Allows you to verify order changes and perform additional actions
|
||||
$response = apply_filters('retailcrm_order_update_after', $response, $wcOrder);
|
||||
|
||||
if ($response instanceof WC_Retailcrm_Response && $response->isSuccessful()) {
|
||||
if ($response instanceof WC_Retailcrm_Response && $response->isSuccessful() && isset($response['order'])) {
|
||||
$this->payment = $this->orderUpdatePaymentType($wcOrder);
|
||||
|
||||
if ($needRecalculate) {
|
||||
$this->loyalty->calculateLoyaltyDiscount($wcOrder, $response['order']['items']);
|
||||
}
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs(
|
||||
@ -356,7 +422,7 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function processOrder($order, $update = false)
|
||||
protected function processOrder($order, $update = false, $statusTrash = false)
|
||||
{
|
||||
if (!$order instanceof WC_Order) {
|
||||
return;
|
||||
@ -419,15 +485,44 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
}
|
||||
|
||||
$orderData['delivery']['address'] = $this->order_address->build($order)->getData();
|
||||
|
||||
$orderItems = [];
|
||||
$crmItems = [];
|
||||
$wcItems = $order->get_items();
|
||||
|
||||
if ($this->loyalty && $update) {
|
||||
$result = $this->loyalty->getCrmItemsInfo($order->get_id());
|
||||
|
||||
if ($result !== []) {
|
||||
$crmItems = $result['items'];
|
||||
|
||||
if (
|
||||
$statusTrash
|
||||
|| (
|
||||
$result['discountType'] !== null
|
||||
&& in_array($order->get_status(), ['cancelled', 'refunded'])
|
||||
)
|
||||
) {
|
||||
$this->cancelLoyalty = true;
|
||||
$this->order_item->cancelLoyalty = true;
|
||||
} else {
|
||||
$this->cancelLoyalty = $this->order_item->isCancelLoyalty($wcItems, $crmItems);
|
||||
}
|
||||
|
||||
$this->loyaltyDiscountType = $result['discountType'];
|
||||
}
|
||||
}
|
||||
|
||||
/** @var WC_Order_Item_Product $item */
|
||||
foreach ($order->get_items() as $item) {
|
||||
$orderItems[] = $this->order_item->build($item)->getData();
|
||||
foreach ($wcItems as $id => $item) {
|
||||
$crmItem = $crmItems[$id] ?? null;
|
||||
$orderItems[] = $this->order_item->build($item, $crmItem)->getData();
|
||||
|
||||
$this->order_item->resetData();
|
||||
$this->order_item->resetData($this->cancelLoyalty);
|
||||
}
|
||||
|
||||
unset($crmItems, $crmItem);
|
||||
|
||||
$orderData['items'] = $orderItems;
|
||||
$orderData['discountManualAmount'] = 0;
|
||||
$orderData['discountManualPercent'] = 0;
|
||||
|
90
src/include/components/class-wc-retailcrm-loyalty-form.php
Normal file
90
src/include/components/class-wc-retailcrm-loyalty-form.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
if (!class_exists('WC_Retailcrm_Loyalty')) :
|
||||
|
||||
|
||||
class WC_Retailcrm_Loyalty_Form
|
||||
{
|
||||
public function getRegistrationForm()
|
||||
{
|
||||
return sprintf(
|
||||
'
|
||||
<form id="loyaltyRegisterForm" method="post">
|
||||
<p>%s</p>
|
||||
<p><input type="checkbox" name="terms" id="termsLoyalty" required>%s<a id="terms-popup" class="popup-open-loyalty" href="#">%s</a>.</p>
|
||||
<p><input type="checkbox" name="privacy" id="privacyLoyalty" required>%s<a id="privacy-popup" class="popup-open-loyalty" href="#">%s</a>.</p>
|
||||
<p><input type="text" name="phone" id="phoneLoyalty" placeholder="%s" required></p>
|
||||
<p><input type="submit" value="%s"></p>
|
||||
</form>
|
||||
<div class="popup-fade-loyalty">
|
||||
<div class="popup-loyalty">
|
||||
<a class="popup-close-loyalty" href="#">%s</a>
|
||||
<br>
|
||||
<div id="popup-loyalty-text"></div>
|
||||
</div>
|
||||
</div>
|
||||
',
|
||||
__('To register in the loyalty program, fill in the form:', 'retailcrm'),
|
||||
__(' I agree with ', 'retailcrm'),
|
||||
__('loyalty program terms', 'retailcrm'),
|
||||
__(' I agree with ', 'retailcrm'),
|
||||
__('terms of personal data processing', 'retailcrm'),
|
||||
__('Phone', 'retailcrm'),
|
||||
__('Send', 'retailcrm'),
|
||||
__('Close', 'retailcrm')
|
||||
);
|
||||
}
|
||||
|
||||
public function getActivationForm()
|
||||
{
|
||||
return sprintf('
|
||||
<form id="loyaltyActivateForm" method="post">
|
||||
<p><input type="checkbox" id="loyaltyActiveCheckbox" name="loyaltyCheckbox" required> %s</p>
|
||||
<input type="submit" value="%s">
|
||||
</form>',
|
||||
__('Activate participation in the loyalty program', 'retailcrm'),
|
||||
__('Send', 'retailcrm')
|
||||
);
|
||||
}
|
||||
|
||||
public function getInfoLoyalty(array $loyaltyAccount)
|
||||
{
|
||||
$data = [
|
||||
'<b>' . __('Bonus account', 'retailcrm') . '</b>',
|
||||
__('Participation ID: ', 'retailcrm') . $loyaltyAccount['id'],
|
||||
__('Current level: ', 'retailcrm') . $loyaltyAccount['level']['name'],
|
||||
__('Bonuses on the account: ', 'retailcrm') . $loyaltyAccount['amount'],
|
||||
__('Bonus card number: ' , 'retailcrm') . ($loyaltyAccount['cardNumber'] ?? __('The card is not linked', 'retailcrm')),
|
||||
__('Date of registration: ', 'retailcrm') . $loyaltyAccount['activatedAt'],
|
||||
'<br>',
|
||||
'<b>' . __('Current level rules', 'retailcrm') . '</b>',
|
||||
__('Required amount of purchases to move to the next level: ', 'retailcrm') . $loyaltyAccount['nextLevelSum'] . ' ' . $loyaltyAccount['loyalty']['currency']
|
||||
];
|
||||
|
||||
switch ($loyaltyAccount['level']['type']) {
|
||||
case 'bonus_converting':
|
||||
$data[] = sprintf(__('Ordinary products: accrual of 1 bonus for each %s %s', 'retailcrm'), $loyaltyAccount['level']['privilegeSize'], $loyaltyAccount['loyalty']['currency']);
|
||||
$data[] = sprintf(__('Promotional products: accrual of 1 bonus for each %s %s', 'retailcrm'), $loyaltyAccount['level']['privilegeSizePromo'], $loyaltyAccount['loyalty']['currency']);
|
||||
break;
|
||||
case 'bonus_percent':
|
||||
$data[] = sprintf(__('Ordinary products: bonus accrual in the amount of %s%% of the purchase amount', 'retailcrm'), $loyaltyAccount['level']['privilegeSize']);
|
||||
$data[] = sprintf(__('Promotional products: bonus accrual in the amount of %s%% of the purchase amount', 'retailcrm'), $loyaltyAccount['level']['privilegeSizePromo']);
|
||||
break;
|
||||
case 'discount':
|
||||
$data[] = sprintf(__('Ordinary products: %s%% discount', 'retailcrm'), $loyaltyAccount['level']['privilegeSize']);
|
||||
$data[] = sprintf(__('Promotional products: %s%% discount', 'retailcrm'), $loyaltyAccount['level']['privilegeSizePromo']);
|
||||
break;
|
||||
}
|
||||
|
||||
$result = '';
|
||||
|
||||
foreach ($data as $line) {
|
||||
$result .= "<p style='line-height: 1'>$line</p>";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
endif;
|
@ -202,3 +202,18 @@ function useHpos()
|
||||
return class_exists(Automattic\WooCommerce\Utilities\OrderUtil::class)
|
||||
&& Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
|
||||
}
|
||||
|
||||
function isLoyaltyActivate($settings)
|
||||
{
|
||||
return isset($settings['loyalty']) && $settings['loyalty'] === WC_Retailcrm_Base::YES;
|
||||
}
|
||||
|
||||
function isCorporateUserActivate($settings)
|
||||
{
|
||||
return isset($settings['corporate_enabled']) && $settings['corporate_enabled'] === WC_Retailcrm_Base::YES;
|
||||
}
|
||||
|
||||
function isCorporateOrder($wcCustomer, $wcOrder)
|
||||
{
|
||||
return !empty($wcCustomer->get_billing_company()) || !empty($wcOrder->get_billing_company());
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data
|
||||
*/
|
||||
protected $settings = [];
|
||||
|
||||
/** @var bool */
|
||||
public $cancelLoyalty = false;
|
||||
|
||||
/**
|
||||
* WC_Retailcrm_Order_Item constructor.
|
||||
*
|
||||
@ -43,13 +46,13 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function build($item)
|
||||
public function build($item, $crmItem = null)
|
||||
{
|
||||
$decimalPlaces = wc_get_price_decimals();
|
||||
|
||||
// Calculate price and discount
|
||||
$price = $this->calculatePrice($item, $decimalPlaces);
|
||||
$discountPrice = $this->calculateDiscount($item, $price, $decimalPlaces);
|
||||
$discountPrice = $this->calculateDiscount($item, $price, $decimalPlaces, $crmItem);
|
||||
|
||||
$data['productName'] = $item['name'];
|
||||
$data['initialPrice'] = $price;
|
||||
@ -112,12 +115,44 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data
|
||||
* @param WC_Order_Item_Product $item
|
||||
* @param $price
|
||||
* @param int $decimalPlaces Price rounding from WC settings
|
||||
*
|
||||
* @param array|null $crmItem Current trade position in CRM
|
||||
* @return float|int
|
||||
*/
|
||||
private function calculateDiscount(WC_Order_Item_Product $item, $price, int $decimalPlaces)
|
||||
{
|
||||
$productPrice = $item->get_total() ? $item->get_total() / $item->get_quantity() : 0;
|
||||
private function calculateDiscount(
|
||||
WC_Order_Item_Product $item,
|
||||
$price,
|
||||
int $decimalPlaces,
|
||||
$crmItem = null
|
||||
) {
|
||||
if ($crmItem) {
|
||||
$loyaltyDiscount = 0;
|
||||
|
||||
foreach ($crmItem['discounts'] as $discount) {
|
||||
if (in_array($discount['type'], ['bonus_charge', 'loyalty_level'])) {
|
||||
$loyaltyDiscount += $discount['amount'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The loyalty program discount is calculated within the CRM system. It must be deleted during transfer to avoid duplication.
|
||||
*/
|
||||
$productPrice = ($item->get_total() / $item->get_quantity()) + ($loyaltyDiscount / $crmItem['quantity']);
|
||||
|
||||
if ($this->cancelLoyalty) {
|
||||
if ($item->get_total() + $loyaltyDiscount <= $item->get_subtotal()) {
|
||||
$item->set_total($item->get_total() + $loyaltyDiscount);
|
||||
$item->calculate_taxes();
|
||||
$item->save();
|
||||
}
|
||||
|
||||
$productPrice = $item->get_total() / $item->get_quantity();
|
||||
}
|
||||
} else {
|
||||
$productPrice = $item->get_total() ? $item->get_total() / $item->get_quantity() : 0;
|
||||
}
|
||||
|
||||
$productTax = $item->get_total_tax() ? $item->get_total_tax() / $item->get_quantity() : 0;
|
||||
$itemPrice = $productPrice + $productTax;
|
||||
|
||||
@ -127,7 +162,7 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data
|
||||
/**
|
||||
* Reset item data.
|
||||
*/
|
||||
public function resetData()
|
||||
public function resetData($cancelLoyalty)
|
||||
{
|
||||
$this->data = [
|
||||
'offer' => [],
|
||||
@ -135,5 +170,63 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data
|
||||
'initialPrice' => 0.00,
|
||||
'quantity' => 0.00
|
||||
];
|
||||
|
||||
$this->cancelLoyalty = $cancelLoyalty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking whether the loyalty program discount needs to be canceled. (Changing the sales items in the order)
|
||||
*
|
||||
* @param array $wcItems
|
||||
* @param array $crmItems
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCancelLoyalty($wcItems, $crmItems): bool
|
||||
{
|
||||
/** If the number of sales items does not match */
|
||||
if (count($wcItems) !== count($crmItems)) {
|
||||
$this->cancelLoyalty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($wcItems as $id => $item) {
|
||||
$loyaltyDiscount = 0;
|
||||
|
||||
/** If a trading position has been added/deleted */
|
||||
if (!isset($crmItems[$id])) {
|
||||
$this->cancelLoyalty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** If the quantity of goods in a trade item does not match */
|
||||
if ($item->get_quantity() !== $crmItems[$id]['quantity']) {
|
||||
$this->cancelLoyalty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($crmItems[$id]['discounts'] as $discount) {
|
||||
if (in_array($discount['type'], ['bonus_charge', 'loyalty_level'])) {
|
||||
$loyaltyDiscount = $discount['amount'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*If the sum of the trade item including discounts and loyalty program discount exceeds the cost without discounts.
|
||||
* (Occurs when recalculating an order, deleting/adding coupons)
|
||||
*/
|
||||
if (($item->get_total() + $loyaltyDiscount) > $item->get_subtotal()) {
|
||||
$this->cancelLoyalty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
if (!class_exists('WC_Retailcrm_Loyalty_Constraint')) :
|
||||
/**
|
||||
* PHP version 7.0
|
||||
*
|
||||
* Class WC_Retailcrm_Loyalty_Constraint - Constraint for CRM loyalty.
|
||||
*
|
||||
* @category Integration
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license http://retailcrm.ru Proprietary
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://help.retailcrm.ru
|
||||
*/
|
||||
class WC_Retailcrm_Loyalty_Constraint
|
||||
{
|
||||
public $notFoundCrmUser = 'User not found in the system';
|
||||
|
||||
public $errorFoundLoyalty = 'Error when searching for participation in loyalty programs';
|
||||
|
||||
public $notFoundActiveParticipation = 'No active participation in the loyalty program was detected';
|
||||
|
||||
public $notExistBonuses = 'No bonuses for debiting';
|
||||
|
||||
public $notFoundLoyalty = 'Loyalty program not found';
|
||||
|
||||
public $loyaltyInactive = 'Loyalty program is not active';
|
||||
|
||||
public $loyaltyBlocked = 'Loyalty program blocked';
|
||||
|
||||
public $isCorporateUser = 'This user is a corporate person';
|
||||
}
|
||||
endif;
|
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
if (!class_exists('WC_Retailcrm_Loyalty_Validator')) :
|
||||
/**
|
||||
* PHP version 7.0
|
||||
*
|
||||
* Class WC_Retailcrm_Loyalty_Validator - Validate CRM loyalty.
|
||||
*
|
||||
* @category Integration
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license http://retailcrm.ru Proprietary
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://help.retailcrm.ru
|
||||
*/
|
||||
class WC_Retailcrm_Loyalty_Validator extends WC_Retailcrm_Loyalty_Constraint
|
||||
{
|
||||
/** @var WC_Retailcrm_Client_V5 */
|
||||
protected $apiClient;
|
||||
|
||||
protected $isActiveCorp;
|
||||
|
||||
public $customer;
|
||||
|
||||
public $loyaltyAccount;
|
||||
|
||||
public function __construct($apiClient, $isActiveCorp)
|
||||
{
|
||||
$this->apiClient = $apiClient;
|
||||
$this->isActiveCorp = $isActiveCorp;
|
||||
}
|
||||
|
||||
public function checkAccount(int $userId): bool
|
||||
{
|
||||
try {
|
||||
$this->checkUser($userId);
|
||||
$this->checkLoyaltyAccount($this->customer['id']);
|
||||
$this->checkActiveLoyalty($this->loyaltyAccount['loyalty']['id']);
|
||||
|
||||
return true;
|
||||
} catch (ValidatorException $exception) {
|
||||
WC_Admin_Settings::add_error((esc_html__($exception->getMessage(), 'retailcrm')) . "userId: $userId");
|
||||
} catch (Throwable $exception) {
|
||||
WC_Admin_Settings::add_error($exception->getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidatorException
|
||||
*/
|
||||
private function checkUser($userId)
|
||||
{
|
||||
$responseUser = $this->apiClient->customersGet($userId);
|
||||
|
||||
if (!isset($responseUser['customer']['id'])) {
|
||||
throw new ValidatorException($this->notFoundCrmUser, 400);
|
||||
}
|
||||
|
||||
$customer = new WC_Customer($userId);
|
||||
|
||||
if ($this->isActiveCorp && !empty($customer->get_billing_company())) {
|
||||
throw new ValidatorException($this->isCorporateUser, 400);
|
||||
}
|
||||
|
||||
$this->customer = $responseUser['customer'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidatorException
|
||||
*/
|
||||
private function checkLoyaltyAccount($customerId)
|
||||
{
|
||||
$filter['customerId'] = $customerId;
|
||||
$responseLoyalty = $this->apiClient->getLoyaltyAccountList($filter);
|
||||
|
||||
if (!$responseLoyalty->isSuccessful() || !$responseLoyalty->offsetExists('loyaltyAccounts')) {
|
||||
throw new ValidatorException($this->errorFoundLoyalty, 400);
|
||||
}
|
||||
|
||||
$actualAccount = null;
|
||||
|
||||
foreach ($responseLoyalty['loyaltyAccounts'] as $loyaltyAccount) {
|
||||
if ($loyaltyAccount['active'] === true) {
|
||||
$actualAccount = $loyaltyAccount;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($actualAccount)) {
|
||||
throw new ValidatorException($this->notFoundActiveParticipation, 400);
|
||||
}
|
||||
|
||||
if ($actualAccount['amount'] === 0 && $actualAccount['level']['type'] !== 'discount') {
|
||||
throw new ValidatorException($this->notExistBonuses, 400);
|
||||
}
|
||||
|
||||
$this->loyaltyAccount = $actualAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidatorException
|
||||
*/
|
||||
private function checkActiveLoyalty($idLoyalty)
|
||||
{
|
||||
$responseLoyalty = $this->apiClient->getLoyalty($idLoyalty);
|
||||
|
||||
if (!$responseLoyalty->isSuccessful() || !$responseLoyalty->offsetExists('loyalty')) {
|
||||
throw new ValidatorException($this->notFoundLoyalty, 400);
|
||||
}
|
||||
|
||||
if ($responseLoyalty['loyalty']['active'] !== true) {
|
||||
throw new ValidatorException($this->loyaltyInactive, 400);
|
||||
}
|
||||
|
||||
if ($responseLoyalty['loyalty']['blocked'] === true) {
|
||||
throw new ValidatorException($this->loyaltyBlocked, 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
endif;
|
@ -199,7 +199,55 @@ return [
|
||||
"La moneda del sitio web es distinto a la tienda del CRM. Para el funcionamiento correcto de la integración, las monedas del CMS y CRM deben coincid",
|
||||
"Uploading services" => "Descarga de servicios",
|
||||
"Goods with the 'virtual' option enabled will be uploaded to Simla as services" =>
|
||||
"Los bienes con la opción 'virtual' activada se cargarán en Simla como servicios"
|
||||
"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",
|
||||
"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",
|
||||
"Insert the terms and conditions for processing personal data" => "Inserte las condiciones para el procesamiento de datos personales",
|
||||
"To activate the loyalty program it is necessary to activate the <a href='?page=wc-settings'>'enable use of coupons option'</a>" =>
|
||||
"Para activar el programa de fidelización es necesario activar la opción <a href='?page=wc-settings'>'habilitar el uso de cupones'</a>",
|
||||
"Bonus account" => "Cuenta de bonificación",
|
||||
"Participation ID: " => "ID de participación: ",
|
||||
"Current level: " => "Nivel actual: ",
|
||||
"Bonuses on the account: " => "Bonificaciones en la cuenta: ",
|
||||
"Bonus card number: " => "Número de tarjeta de bonificación: ",
|
||||
"Date of registration: " => "Fecha de registro: ",
|
||||
"Current level rules" => "Reglas del nivel actual",
|
||||
"Required amount of purchases to move to the next level: " => "Cantidad de compras necesarias para pasar al siguiente nivel: ",
|
||||
"Activate participation in the loyalty program" => "Activar participación en el programa de fidelización",
|
||||
"Send" => "Enviar",
|
||||
"To register in the loyalty program, fill in the form:" => "Para registrarse en el programa de fidelización, rellene el formulario:",
|
||||
" I agree with " => " Acepto ",
|
||||
"loyalty program terms" => "términos del programa de fidelización",
|
||||
"terms of personal data processing" => "términos de procesamiento de datos personales",
|
||||
"Phone" => "Teléfono",
|
||||
"Error while registering in the loyalty program. Try again later" => "Error al registrarse en el programa de fidelización. Inténtalo de nuevo más tarde",
|
||||
"The card is not linked" => "La tarjeta no está vinculada",
|
||||
"Error while retrieving data. Try again later" => "Error al recuperar los datos. Inténtalo de nuevo más tarde",
|
||||
"Error when activating the loyalty program. Try again later" => "Error al activar el programa de fidelización. Inténtalo de nuevo más tarde",
|
||||
"Enter the correct phone number" => "Introduce el número de teléfono correcto",
|
||||
"Close" => "Cerrar",
|
||||
"Ordinary products: accrual of 1 bonus for each %s %s" => "Productos ordinarios: acumulación de 1 bonificación por cada %s %s",
|
||||
"Promotional products: accrual of 1 bonus for each %s %s" => "Productos promocionales: acumulación de 1 bonificación por cada %s %s",
|
||||
"Ordinary products: bonus accrual in the amount of %s%% of the purchase amount" => "Productos ordinarios: acumulación de bonificación en la cantidad de %s%% del monto de la compra",
|
||||
"Promotional products: bonus accrual in the amount of %s%% of the purchase amount" => "Productos promocionales: acumulación de bonificación en la cantidad de %s%% del monto de la compra",
|
||||
"Ordinary products: %s%% discount" => "Productos ordinarios: descuento del %s%%",
|
||||
"Promotional products: %s%% discount" => "Productos promocionales: descuento del %s%%",
|
||||
"User not found in the system" => "Usuario no encontrado en el sistema",
|
||||
"Error when searching for participation in loyalty programs" => "Error al buscar la participación en programas de fidelización",
|
||||
"No active participation in the loyalty program was detected" => "No se detectó participación activa en el programa de fidelización",
|
||||
"No bonuses for debiting" => "No hay bonificaciones para debitar",
|
||||
"Loyalty program not found" => "Programa de fidelización no encontrado",
|
||||
"Loyalty program is not active" => "El programa de fidelización no está activo",
|
||||
"Loyalty program blocked" => "Programa de fidelización bloqueado",
|
||||
"This user is a corporate person" => "Este usuario es una persona jurídica",
|
||||
"It is possible to write off" => "Es posible debitar",
|
||||
"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:",
|
||||
],
|
||||
"language" => "es",
|
||||
"x-generator" => "GlotPress/2.4.0-alpha",
|
||||
|
Binary file not shown.
@ -198,7 +198,55 @@ return [
|
||||
"Валюта сайта отличается от валюты магазина в CRM. Для корректной работы интеграции, валюты в CRM и CMS должны совпадать",
|
||||
"Uploading services" => "Выгрузка услуг",
|
||||
"Goods with the 'virtual' option enabled will be uploaded to Simla as services" =>
|
||||
"Товары с включенной опцией 'виртуальные' будут выгружаться в CRM как услуги"
|
||||
"Товары с включенной опцией 'виртуальные' будут выгружаться в CRM как услуги",
|
||||
"Loyalty program" => "Программа лояльности",
|
||||
"Activate program loyalty" => "Активировать программу лояльности",
|
||||
"Enable this setting for activate program loyalty on site" => "Активируйте эту настройку для активации программы лояльности на сайте",
|
||||
"Terms of loyalty program" => "Условия программы лояльности",
|
||||
"Insert the terms and conditions of the loyalty program" => "Вставьте условия участия в программе лояльности",
|
||||
"Conditions of personal data processing" => "Условия обработки персональных данных",
|
||||
"Insert the terms and conditions for processing personal data" => "Вставьте условия обработки персональных данных",
|
||||
"To activate the loyalty program it is necessary to activate the <a href='?page=wc-settings'>'enable use of coupons option'</a>" =>
|
||||
"Для активации программы лояльности необходимо активировать опцию <a href='?page=wc-settings'>'включить использование купонов'</a>",
|
||||
"Bonus account" => "Бонусный счет",
|
||||
"Participation ID: " => "ID участия: ",
|
||||
"Current level: " => "Текущий уровень: ",
|
||||
"Bonuses on the account: " => "Бонусов на счету: ",
|
||||
"Bonus card number: " => "Номер бонусной карты: ",
|
||||
"Date of registration: " => "Дата регистрации: ",
|
||||
"Current level rules" => "Правила текущего уровня",
|
||||
"Required amount of purchases to move to the next level: " => "Необходимая сумма покупок для перехода на следующий уровень: ",
|
||||
"Activate participation in the loyalty program" => "Активировать участие в программе лояльности",
|
||||
"Send" => "Отправить",
|
||||
"To register in the loyalty program, fill in the form:" => "Для регистрации в программе лояльности заполните форму:",
|
||||
" I agree with " => " Я согласен с ",
|
||||
"loyalty program terms" => "условиями программы лояльности",
|
||||
"terms of personal data processing" => "условиями обработки персональных данных",
|
||||
"Phone" => "Телефон",
|
||||
"Error while registering in the loyalty program. Try again later" => "Ошибка при регистрации в программе лояльности. Попробуйте позже",
|
||||
"The card is not linked" => "Карта не привязана",
|
||||
"Error while retrieving data. Try again later" => "Ошибка при получении данных. Попробуйте позже",
|
||||
"Error when activating the loyalty program. Try again later" => "Ошибка при активации программы лояльности. Попробуйте позже",
|
||||
"Enter the correct phone number" => "Введите корректный номер телефона",
|
||||
"Close" => "Закрыть",
|
||||
"Ordinary products: accrual of 1 bonus for each %s %s" => "Обычные товары: начисление 1 бонуса за каждые %s %s",
|
||||
"Promotional products: accrual of 1 bonus for each %s %s" => "Акционные товары: начисление 1 бонуса за каждые %s %s",
|
||||
"Ordinary products: bonus accrual in the amount of %s%% of the purchase amount" => "Обычные товары: начисление бонуса в размере %s%% от суммы покупки",
|
||||
"Promotional products: bonus accrual in the amount of %s%% of the purchase amount" => "Акционные товары: начисление бонуса в размере %s%% от суммы покупки",
|
||||
"Ordinary products: %s%% discount" => "Обычные товары: скидка %s%%",
|
||||
"Promotional products: %s%% discount" => "Акционные товары: скидка %s%%",
|
||||
"User not found in the system" => "Пользователь не найден в системе",
|
||||
"Error when searching for participation in loyalty programs" => "Ошибка при поиске участия в программах лояльности",
|
||||
"No active participation in the loyalty program was detected" => "Не обнаружено активного участия в программе лояльности",
|
||||
"No bonuses for debiting" => "Нет бонусов для списания",
|
||||
"Loyalty program not found" => "Программа лояльности не найдена",
|
||||
"Loyalty program is not active" => "Программа лояльности не активна",
|
||||
"Loyalty program blocked" => "Программа лояльности заблокирована",
|
||||
"This user is a corporate person" => "Этот пользователь является корпоративным лицом",
|
||||
"It is possible to write off" => "Возможно списать",
|
||||
"bonuses" => "бонусов",
|
||||
"Use coupon:" => "Используйте купон:",
|
||||
"Points will be awarded upon completion of the order:" => "По завершению заказа будет начислено баллов:",
|
||||
],
|
||||
"language" => "ru",
|
||||
"x-generator" => "GlotPress/2.4.0-alpha",
|
||||
|
Binary file not shown.
@ -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.7.9
|
||||
Stable tag: 4.8.0
|
||||
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.0 =
|
||||
* Added loyalty program
|
||||
|
||||
= 4.7.9 =
|
||||
* Fixed undefined array key number in order history
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Description: Integration plugin for WooCommerce & Simla.com
|
||||
* Author: RetailDriver LLC
|
||||
* Author URI: http://retailcrm.pro/
|
||||
* Version: 4.7.9
|
||||
* Version: 4.8.0
|
||||
* Tested up to: 6.5
|
||||
* Requires Plugins: woocommerce
|
||||
* WC requires at least: 5.4
|
||||
@ -121,6 +121,7 @@ if (!class_exists( 'WC_Integration_Retailcrm')) :
|
||||
require_once(self::checkCustomFile('include/icml/class-wc-retailcrm-icml-writer.php'));
|
||||
require_once(self::checkCustomFile('include/class-wc-retailcrm-orders.php'));
|
||||
require_once(self::checkCustomFile('include/class-wc-retailcrm-cart.php'));
|
||||
require_once(self::checkCustomFile('include/class-wc-retailcrm-loyalty.php'));
|
||||
require_once(self::checkCustomFile('include/class-wc-retailcrm-customers.php'));
|
||||
require_once(self::checkCustomFile('include/class-wc-retailcrm-inventories.php'));
|
||||
require_once(self::checkCustomFile('include/class-wc-retailcrm-history.php'));
|
||||
@ -132,6 +133,9 @@ if (!class_exists( 'WC_Integration_Retailcrm')) :
|
||||
require_once(self::checkCustomFile('include/validators/url-validator/class-wc-retailcrm-url-constraint.php'));
|
||||
require_once(self::checkCustomFile('include/validators/url-validator/class-wc-retailcrm-url-validator.php'));
|
||||
require_once(self::checkCustomFile('include/validators/class-wc-retailcrm-validator-exception.php'));
|
||||
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'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@
|
||||
*
|
||||
* @link https://wordpress.org/plugins/woo-retailcrm/
|
||||
*
|
||||
* @version 4.7.9
|
||||
* @version 4.8.0
|
||||
*
|
||||
* @package RetailCRM
|
||||
*/
|
||||
|
345
tests/datasets/data-loyalty-retailcrm.php
Normal file
345
tests/datasets/data-loyalty-retailcrm.php
Normal file
@ -0,0 +1,345 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP version 7.0
|
||||
*
|
||||
* Class DataLoyaltyRetailCrm - Data set for WC_Retailcrm_Loyalty_Test.
|
||||
*
|
||||
* @category Integration
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @license http://retailcrm.ru Proprietary
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://help.retailcrm.ru
|
||||
*/
|
||||
|
||||
class DataLoyaltyRetailCrm
|
||||
{
|
||||
public static function getDataLoyalty()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'isSuccessful' => true,
|
||||
'body' => json_encode(['loyaltyAccounts' => []]),
|
||||
'expected' => 'id="loyaltyRegisterForm"'
|
||||
],
|
||||
[
|
||||
'isSuccessful' => true,
|
||||
'body' => json_encode(
|
||||
[
|
||||
'loyaltyAccounts' => [
|
||||
0 => [
|
||||
'active' => false,
|
||||
'customer' => [
|
||||
'externalId' => 1
|
||||
],
|
||||
'id' => 1
|
||||
]
|
||||
]
|
||||
]
|
||||
),
|
||||
'expected' => 'id="loyaltyActivateForm"'
|
||||
],
|
||||
[
|
||||
'isSuccessful' => true,
|
||||
'body' => json_encode(
|
||||
[
|
||||
'loyaltyAccounts' => [
|
||||
0 => [
|
||||
'id' => 1,
|
||||
'level' => [
|
||||
'name' => 'Test level',
|
||||
'privilegeSize' => 5,
|
||||
'privilegeSizePromo' => 3,
|
||||
'type' => 'bonus_converting'
|
||||
],
|
||||
'amount' => 1000,
|
||||
'cardNumber' => '12345',
|
||||
'activatedAt' => '2024-04-10 15:00:00',
|
||||
'nextLevelSum' => 15000,
|
||||
'loyalty' => [
|
||||
'currency' => 'USD'
|
||||
],
|
||||
'customer' => [
|
||||
'externalId' => 1
|
||||
],
|
||||
'active' => true
|
||||
]
|
||||
]
|
||||
]
|
||||
),
|
||||
'expected' => 'Ordinary products: accrual of 1 bonus for each'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public static function dataCheckUser()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'responseApiMethod' => [],
|
||||
'wcUserType' => 'individual',
|
||||
'throwMessage' => 'User not found in the system',
|
||||
'isCorpActive' => false
|
||||
],
|
||||
[
|
||||
'responseApiMethod' => ['customer' => ['id' => 1]],
|
||||
'wcUserType' => 'corp',
|
||||
'throwMessage' => 'This user is a corporate person',
|
||||
'isCorpActive' => true
|
||||
],
|
||||
[
|
||||
'responseApiMethod' => ['customer' => ['id' => 1]],
|
||||
'wcUserType' => 'corp',
|
||||
'throwMessage' => null,
|
||||
'isCorpActive' => false
|
||||
],
|
||||
[
|
||||
'responseApiMethod' => ['customer' => ['id' => 1]],
|
||||
'wcUserType' => 'individual',
|
||||
'throwMessage' => null,
|
||||
'isCorpActive' => true
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public static function dataLoyaltyAccount()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'responseMock' => ['success' => true],
|
||||
'throwMessage' => 'Error when searching for participation in loyalty programs'
|
||||
],
|
||||
[
|
||||
'responseMock' => ['success' => true, 'loyaltyAccounts' => []],
|
||||
'throwMessage' => 'No active participation in the loyalty program was detected'
|
||||
],
|
||||
[
|
||||
'responseMock' => ['success' => true, 'loyaltyAccounts' => [['active' => true, 'amount' => 0, 'level' => ['type' => 'bonus_converting']]]],
|
||||
'throwMessage' => 'No bonuses for debiting'
|
||||
],
|
||||
[
|
||||
'responseMock' => ['success' => true, 'loyaltyAccounts' => [['active' => true, 'amount' => 0, 'level' => ['type' => 'discount']]]],
|
||||
'throwMessage' => null
|
||||
],
|
||||
[
|
||||
'responseMock' => ['success' => true, 'loyaltyAccounts' => [['active' => true, 'amount' => 100, 'level' => ['type' => 'bonus_converting']]]],
|
||||
'throwMessage' => null
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public static function dataCheckActiveLoyalty()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'responseMock' => ['success' => true],
|
||||
'throwMessage' => 'Loyalty program not found'
|
||||
],
|
||||
[
|
||||
'responseMock' => ['success' => true, 'loyalty' => ['active' => false]],
|
||||
'throwMessage' => 'Loyalty program is not active'
|
||||
],
|
||||
[
|
||||
'responseMock' => ['success' => true, 'loyalty' => ['active' => true, 'blocked' => true]],
|
||||
'throwMessage' => 'Loyalty program blocked'
|
||||
],
|
||||
[
|
||||
'responseMock' => ['success' => true, 'loyalty' => ['active' => true, 'blocked' => false]],
|
||||
'throwMessage' => null
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public static function createProducts()
|
||||
{
|
||||
$product1 = new WC_Product();
|
||||
$product1->set_name('Test product 1');
|
||||
$product1->set_sku('test1' . mt_rand());
|
||||
$product1->set_regular_price('200');
|
||||
$product1->set_sale_price('200');
|
||||
$product1->save();
|
||||
|
||||
$product2 = new WC_Product();
|
||||
$product2->set_name('Test product 2');
|
||||
$product2->set_sku('test2' . mt_rand());
|
||||
$product2->set_regular_price('100');
|
||||
$product2->set_sale_price('50');
|
||||
$product2->save();
|
||||
|
||||
return [$product1, $product2];
|
||||
}
|
||||
|
||||
public static function getDataCalculation()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'response' => [
|
||||
'calculations' => [],
|
||||
'order' => [
|
||||
'items' => [
|
||||
[
|
||||
'discounts' => [
|
||||
[
|
||||
'type' => 'loyalty_level',
|
||||
'amount' => 20
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
'discounts' => [
|
||||
[
|
||||
'type' => 'loyalty_level',
|
||||
'amount' => 20
|
||||
],
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'expected' => 40
|
||||
],
|
||||
[
|
||||
'response' => [
|
||||
'calculations' => [
|
||||
[
|
||||
'privilegeType' => 'test'
|
||||
],
|
||||
[
|
||||
'privilegeType' => 'loyalty_level',
|
||||
'maxChargeBonuses' => 50
|
||||
]
|
||||
],
|
||||
'order' => [
|
||||
'items' => [['discounts' => null], ['discounts' => null]],
|
||||
]
|
||||
],
|
||||
'expected' => 50
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public static function dataCheckLoyaltyCoupon()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'code' => 'loyalty49844894548',
|
||||
'expected' => true
|
||||
],
|
||||
[
|
||||
'code' => '56556446548484',
|
||||
'expected' => false
|
||||
],
|
||||
[
|
||||
'code' => 'dfhdfh54655pl',
|
||||
'expected' => false
|
||||
],
|
||||
[
|
||||
'code' => '654844pl18498',
|
||||
'expected' => false
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public static function dataGetEmailsForPersonalCoupon()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'email' => 'test1@gmail.com',
|
||||
'code' => 'loyalty' . mt_rand()
|
||||
],
|
||||
[
|
||||
'email' => 'test2@gmail.com',
|
||||
'code' => 'loyalty' . mt_rand()
|
||||
],
|
||||
[
|
||||
'email' => 'test3@gmail.com',
|
||||
'expectedCode' => false
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public static function dataValidUser()
|
||||
{
|
||||
$users = self::createUsers();
|
||||
|
||||
return [
|
||||
[
|
||||
'customer' => $users[0],
|
||||
'corporate_enabled' => 'yes',
|
||||
'expected' => true,
|
||||
'orderCorporate' => false
|
||||
],
|
||||
[
|
||||
'customer' => $users[1],
|
||||
'corporate_enabled' => 'yes',
|
||||
'expected' => false,
|
||||
'orderCorporate' => false
|
||||
],
|
||||
[
|
||||
'customer' => $users[1],
|
||||
'corporate_enabled' => 'no',
|
||||
'expected' => true,
|
||||
'orderCorporate' => false
|
||||
],
|
||||
[
|
||||
'customer' => null,
|
||||
'corporate_enabled' => 'yes',
|
||||
'expected' => false,
|
||||
'orderCorporate' => false
|
||||
|
||||
],
|
||||
[
|
||||
'customer' => $users[0],
|
||||
'corporate_enabled' => 'yes',
|
||||
'expected' => false,
|
||||
'orderCorporate' => true
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public static function createUsers()
|
||||
{
|
||||
$customer = new WC_Customer();
|
||||
|
||||
$customer->set_first_name('Tester 1');
|
||||
$customer->set_last_name('Tester 1');
|
||||
$customer->set_email(uniqid(md5(date('Y-m-d H:i:s'))) . '@mail.com');
|
||||
$customer->set_password('password');
|
||||
$customer->set_billing_phone('89000000000');
|
||||
$customer->set_date_created(date('Y-m-d H:i:s'));
|
||||
$customer->save();
|
||||
|
||||
$customer1 = new WC_Customer();
|
||||
|
||||
$customer1->set_first_name('Tester 1');
|
||||
$customer1->set_last_name('Tester 1');
|
||||
$customer1->set_email(uniqid(md5(date('Y-m-d H:i:s'))) . '@mail.com');
|
||||
$customer1->set_password('password');
|
||||
$customer1->set_billing_phone('89000000000');
|
||||
$customer1->set_date_created(date('Y-m-d H:i:s'));
|
||||
$customer1->set_billing_company('OOO TEST');
|
||||
$customer1->save();
|
||||
|
||||
return [$customer, $customer1];
|
||||
}
|
||||
|
||||
public static function createCoupons($email1 = 'test1@gmail.com', $email2 = 'test2@gmail.com')
|
||||
{
|
||||
$coupon = new WC_Coupon();
|
||||
|
||||
$coupon->set_usage_limit(0);
|
||||
$coupon->set_amount(100);
|
||||
$coupon->set_email_restrictions($email1);
|
||||
$coupon->set_code('loyalty' . mt_rand());
|
||||
$coupon->save();
|
||||
|
||||
$coupon1 = new WC_Coupon();
|
||||
|
||||
$coupon1->set_usage_limit(0);
|
||||
$coupon1->set_amount(100);
|
||||
$coupon1->set_email_restrictions($email2);
|
||||
$coupon1->set_code('loyalty' . mt_rand());
|
||||
$coupon1->save();
|
||||
|
||||
return [$coupon, $coupon1];
|
||||
}
|
||||
}
|
@ -80,7 +80,10 @@ class WC_Retailcrm_Test_Case_Helper extends WC_Unit_Test_Case
|
||||
'product_description' => 'full',
|
||||
'stores_for_uploading' => ['woocommerce', 'main'],
|
||||
'woo_coupon_apply_field' => 'testField',
|
||||
'icml_unload_services' => 'yes'
|
||||
'icml_unload_services' => 'yes',
|
||||
'loyalty' => 'yes',
|
||||
'loyalty_terms' => 'Test terms',
|
||||
'loyalty_personal' => 'Test privacy'
|
||||
];
|
||||
|
||||
update_option(WC_Retailcrm_Base::$option_key, $options);
|
||||
|
131
tests/loyalty/test-wc-retailcrm-client-v5.php
Normal file
131
tests/loyalty/test-wc-retailcrm-client-v5.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
if (!class_exists('WC_Retailcrm_Client_V5')) {
|
||||
include_once(WC_Integration_Retailcrm::checkCustomFile('include/api/class-wc-retailcrm-client-v5.php'));
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP version 7.0
|
||||
*
|
||||
* Class WC_Retailcrm_Loyalty_Client_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_Loyalty_Client_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
{
|
||||
protected $responseMock;
|
||||
protected $apiMock;
|
||||
|
||||
/** @var \WC_Retailcrm_Client_V5 */
|
||||
protected $clientMock;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->responseMock = $this->getMockBuilder('\WC_Retailcrm_Response_Helper')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['isSuccessful'])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$this->responseMock->setResponse(['success' => true]);
|
||||
$this->setMockResponse($this->responseMock, 'isSuccessful', true);
|
||||
|
||||
$this->apiMock = $this->getMockBuilder('\WC_Retailcrm_Request')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['makeRequest'])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$this->setMockResponse($this->apiMock, 'makeRequest', $this->responseMock);
|
||||
|
||||
$this->clientMock = new \WC_Retailcrm_Client_V5('https://test@retailcrm.ru', 'test', 'test');
|
||||
|
||||
$reflection = new ReflectionClass($this->clientMock);
|
||||
$reflection_property = $reflection->getProperty('client');
|
||||
$reflection_property->setAccessible(true);
|
||||
|
||||
$reflection_property->setValue($this->clientMock, $this->apiMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider requestLoyaltyData
|
||||
*/
|
||||
public function testLoyaltyRequest($method, $parameters)
|
||||
{
|
||||
/** @var WC_Retailcrm_Response $test */
|
||||
$test = call_user_func([$this->clientMock, $method], ...$parameters);
|
||||
|
||||
$this->assertTrue($test->isSuccessful());
|
||||
}
|
||||
|
||||
public function requestLoyaltyData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
'method' => 'createLoyaltyAccount',
|
||||
'parameters' => [['test'], 'testSite']
|
||||
],
|
||||
[
|
||||
'method' => 'getLoyaltyClientInfo',
|
||||
'parameters' => [1]
|
||||
],
|
||||
[
|
||||
'method' => 'activateLoyaltyAccount',
|
||||
'parameters' => [1]
|
||||
],
|
||||
[
|
||||
'method' => 'editLoyaltyAccount',
|
||||
'parameters' => [1, ['test']]
|
||||
],
|
||||
[
|
||||
'method' => 'getLoyaltyAccountList',
|
||||
'parameters' => [['filter'], 20, 1]
|
||||
],
|
||||
[
|
||||
'method' => 'getListLoyalty',
|
||||
'parameters' => [['filter'], 20, 1]
|
||||
],
|
||||
[
|
||||
'method' => 'getLoyalty',
|
||||
'parameters' => [1]
|
||||
],
|
||||
[
|
||||
'method' => 'chargeBonusLoyalty',
|
||||
'parameters' => [1, 100, 'test']
|
||||
],
|
||||
[
|
||||
'method' => 'creditBonusLoyalty',
|
||||
'parameters' => [1, ['amount' => 100]]
|
||||
],
|
||||
[
|
||||
'method' => 'getClientBonusHistory',
|
||||
'parameters' => [1, ['filter'], 20, 1]
|
||||
],
|
||||
[
|
||||
'method' => 'getDetailClientBonus',
|
||||
'parameters' => [1, 'status', ['filter'], 20, 1]
|
||||
],
|
||||
[
|
||||
'method' => 'getBonusHistory',
|
||||
'parameters' => ['cursor', ['filter'], 20]
|
||||
],
|
||||
[
|
||||
'method' => 'calculateDiscountLoyalty',
|
||||
'parameters' => ['site', ['order']]
|
||||
],
|
||||
[
|
||||
'method' => 'applyBonusToOrder',
|
||||
'parameters' => ['site', ['order'], 100]
|
||||
],
|
||||
[
|
||||
'method' => 'cancelBonusOrder',
|
||||
'parameters' => [['order']]
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -132,6 +132,11 @@ class WC_Retailcrm_Base_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
$this->assertArrayHasKey('bind_by_sku', $this->baseRetailcrm->form_fields);
|
||||
$this->assertArrayHasKey('update_number', $this->baseRetailcrm->form_fields);
|
||||
$this->assertArrayHasKey('product_description', $this->baseRetailcrm->form_fields);
|
||||
|
||||
//loyalty
|
||||
$this->assertArrayHasKey('loyalty', $this->baseRetailcrm->form_fields);
|
||||
$this->assertArrayHasKey('loyalty_terms', $this->baseRetailcrm->form_fields);
|
||||
$this->assertArrayHasKey('loyalty_personal', $this->baseRetailcrm->form_fields);
|
||||
}
|
||||
|
||||
public function test_retailcrm_form_fields_value()
|
||||
|
495
tests/test-wc-retailcrm-loyalty.php
Normal file
495
tests/test-wc-retailcrm-loyalty.php
Normal file
@ -0,0 +1,495 @@
|
||||
<?php
|
||||
|
||||
use DataLoyaltyRetailCrm;
|
||||
|
||||
if (!class_exists('WC_Retailcrm_Loyalty')) {
|
||||
include_once(WC_Integration_Retailcrm::checkCustomFile('class-wc-retailcrm-loyalty.php'));
|
||||
}
|
||||
|
||||
if (!class_exists('WC_Retailcrm_Response')) {
|
||||
include_once(WC_Integration_Retailcrm::checkCustomFile('include/api/class-wc-retailcrm-response.php'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PHP version 7.0
|
||||
*
|
||||
* Class WC_Retailcrm_Loyalty_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_Loyalty_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
{
|
||||
protected $responseMock;
|
||||
protected $apiMock;
|
||||
|
||||
/** @var \WC_Retailcrm_Loyalty */
|
||||
protected $loyalty;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->responseMock = $this->getMockBuilder('\WC_Retailcrm_Response_Helper')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['isSuccessful'])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$this->responseMock->setResponse(['success' => true]);
|
||||
$this->setMockResponse($this->responseMock, 'isSuccessful', true);
|
||||
|
||||
$this->apiMock = $this->getMockBuilder('\WC_Retailcrm_Client_V5')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['customersGet', 'getLoyaltyAccountList', 'createLoyaltyAccount', 'activateLoyaltyAccount', 'calculateDiscountLoyalty', 'getSingleSiteForKey', 'applyBonusToOrder'])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$this->setMockResponse($this->apiMock, 'customersGet', ['customer' => ['id' => 1]]);
|
||||
$this->setMockResponse($this->apiMock, 'createLoyaltyAccount', $this->responseMock);
|
||||
$this->setMockResponse($this->apiMock, 'activateLoyaltyAccount', $this->responseMock);
|
||||
$this->setMockResponse($this->apiMock, 'getSingleSiteForKey', 'woo');
|
||||
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider DataLoyaltyRetailCrm::getDataLoyalty()
|
||||
*/
|
||||
public function testGetForm($isSuccessful, $body, $expected)
|
||||
{
|
||||
$response = new WC_Retailcrm_Response($isSuccessful ? 200 : 400, $body);
|
||||
|
||||
$this->setMockResponse($this->apiMock, 'getLoyaltyAccountList', $response);
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
|
||||
$result = $this->loyalty->getForm(1);
|
||||
|
||||
if (isset($result['form'])) {
|
||||
$this->assertTrue((bool) stripos($result['form'], $expected));
|
||||
}
|
||||
}
|
||||
|
||||
public function testRegistrationLoyalty()
|
||||
{
|
||||
$result = $this->loyalty->registerCustomer(1, '89999999999', 'test');
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testActivateLoyalty()
|
||||
{
|
||||
$result = $this->loyalty->activateLoyaltyCustomer(1);
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider DataLoyaltyRetailCrm::getDataCalculation()
|
||||
*/
|
||||
public function testGetDiscountLoyalty($response, $expected)
|
||||
{
|
||||
$responseMock = new WC_Retailcrm_Response(200, json_encode($response));
|
||||
$this->setMockResponse($this->apiMock, 'calculateDiscountLoyalty', $responseMock);
|
||||
|
||||
$cartItems = $this->createCart();
|
||||
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
|
||||
$method = $this->getPrivateMethod('getDiscountLoyalty', $this->loyalty);
|
||||
|
||||
$discount = $method->invokeArgs($this->loyalty, [$cartItems, 'test', 1]);
|
||||
$this->assertEquals($expected, $discount);
|
||||
|
||||
foreach ($cartItems as $items) {
|
||||
$items['data']->delete(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider DataLoyaltyRetailCrm::dataCheckLoyaltyCoupon()
|
||||
*/
|
||||
public function testIsLoyaltyCoupon($code, $expected)
|
||||
{
|
||||
$this->assertEquals($expected, $this->loyalty->isLoyaltyCoupon($code));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider DataLoyaltyRetailCrm::dataValidUser();
|
||||
*/
|
||||
public function testIsValidOrder($customer, $corporate_enabled, $expected, $orderCorporate)
|
||||
{
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, ['corporate_enabled' => $corporate_enabled]);
|
||||
$wcOrder = new WC_Order();
|
||||
|
||||
if ($orderCorporate) {
|
||||
$wcOrder->set_billing_company('OOO TEST');
|
||||
}
|
||||
|
||||
$this->assertEquals($expected, $this->loyalty->isValidOrder($customer, $wcOrder));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider DataLoyaltyRetailCrm::dataGetEmailsForPersonalCoupon()
|
||||
*/
|
||||
public function testGetCouponLoyalty($email, $code)
|
||||
{
|
||||
if ($code) {
|
||||
$coupon = new WC_Coupon();
|
||||
|
||||
$coupon->set_usage_limit(0);
|
||||
$coupon->set_amount(100);
|
||||
$coupon->set_email_restrictions($email);
|
||||
$coupon->set_code($code);
|
||||
$coupon->save();
|
||||
}
|
||||
|
||||
$coupons = $this->loyalty->getCouponLoyalty($email);
|
||||
|
||||
if (!$coupons && $code === false) {
|
||||
$this->assertTrue(true);
|
||||
} else {
|
||||
$result = false;
|
||||
|
||||
foreach ($coupons as $item) {
|
||||
$coupon = new WC_Coupon($item['code']);
|
||||
$result = true;
|
||||
|
||||
$this->assertTrue($code === $item['code']);
|
||||
$coupon->delete(true);
|
||||
}
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
||||
|
||||
public function testCreateLoyaltyCouponWithoutAppliedCoupon()
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
$user = DataLoyaltyRetailcrm::createUsers()[0];
|
||||
|
||||
$cart = new WC_Cart();
|
||||
$cart->add_to_cart($products[0]->get_id());
|
||||
$cart->add_to_cart($products[1]->get_id());
|
||||
|
||||
$woocommerce = wc();
|
||||
$woocommerce->cart = $cart;
|
||||
$woocommerce->customer = $user;
|
||||
|
||||
$validatorMock = $this->getMockBuilder('\WC_Retailcrm_Loyalty_Validator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$this->setMockResponse($validatorMock, 'checkAccount', true);
|
||||
$validatorMock->loyaltyAccount['level']['type'] = 'loyalty_level';
|
||||
|
||||
$responseCalculation = DataLoyaltyRetailCrm::getDataCalculation()[1];
|
||||
$responseMock = new WC_Retailcrm_Response(200, json_encode($responseCalculation['response']));
|
||||
$this->setMockResponse($this->apiMock, 'calculateDiscountLoyalty', $responseMock);
|
||||
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
$reflection = new \ReflectionClass($this->loyalty);
|
||||
$reflection_property = $reflection->getProperty('validator');
|
||||
$reflection_property->setAccessible(true);
|
||||
$reflection_property->setValue($this->loyalty, $validatorMock);
|
||||
|
||||
$GLOBALS['woocommerce'] = $woocommerce;
|
||||
$result = $this->loyalty->createLoyaltyCoupon();
|
||||
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertNotEmpty($this->loyalty->getCouponLoyalty($woocommerce->customer->get_email()));
|
||||
}
|
||||
|
||||
public function testCreateLoyaltyCouponWithPercentDiscount()
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
$user = DataLoyaltyRetailcrm::createUsers()[0];
|
||||
|
||||
$cart = new WC_Cart();
|
||||
$cart->add_to_cart($products[0]->get_id());
|
||||
$cart->add_to_cart($products[1]->get_id());
|
||||
|
||||
$woocommerce = wc();
|
||||
$woocommerce->cart = $cart;
|
||||
$woocommerce->customer = $user;
|
||||
|
||||
$validatorMock = $this->getMockBuilder('\WC_Retailcrm_Loyalty_Validator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$this->setMockResponse($validatorMock, 'checkAccount', true);
|
||||
$validatorMock->loyaltyAccount['level']['type'] = 'discount';
|
||||
|
||||
$responseCalculation = DataLoyaltyRetailCrm::getDataCalculation()[1];
|
||||
$responseMock = new WC_Retailcrm_Response(200, json_encode($responseCalculation['response']));
|
||||
$this->setMockResponse($this->apiMock, 'calculateDiscountLoyalty', $responseMock);
|
||||
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
$reflection = new \ReflectionClass($this->loyalty);
|
||||
$reflection_property = $reflection->getProperty('validator');
|
||||
$reflection_property->setAccessible(true);
|
||||
$reflection_property->setValue($this->loyalty, $validatorMock);
|
||||
|
||||
$GLOBALS['woocommerce'] = $woocommerce;
|
||||
$result = $this->loyalty->createLoyaltyCoupon();
|
||||
|
||||
$this->assertEmpty($result);
|
||||
$this->assertNotEmpty($this->loyalty->getCouponLoyalty($woocommerce->customer->get_email()));
|
||||
$this->assertNotEmpty($woocommerce->cart->get_coupons());
|
||||
}
|
||||
|
||||
public function testCreateLoyaltyCouponWithRefreshCoupon()
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
$user = DataLoyaltyRetailcrm::createUsers()[0];
|
||||
|
||||
$cart = new WC_Cart();
|
||||
$cart->add_to_cart($products[0]->get_id());
|
||||
$cart->add_to_cart($products[1]->get_id());
|
||||
|
||||
$coupon = new WC_Coupon();
|
||||
$coupon->set_usage_limit(0);
|
||||
$coupon->set_amount('50');
|
||||
$coupon->set_email_restrictions($user->get_email());
|
||||
$coupon->set_code('loyalty' . mt_rand());
|
||||
$coupon->save();
|
||||
$cart->apply_coupon($coupon->get_code());
|
||||
|
||||
$couponCode = $coupon->get_code();
|
||||
$woocommerce = wc();
|
||||
$woocommerce->cart = $cart;
|
||||
$woocommerce->customer = $user;
|
||||
|
||||
$validatorMock = $this->getMockBuilder('\WC_Retailcrm_Loyalty_Validator')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
;
|
||||
$this->setMockResponse($validatorMock, 'checkAccount', true);
|
||||
$validatorMock->loyaltyAccount['level']['type'] = 'discount';
|
||||
|
||||
$responseCalculation = DataLoyaltyRetailCrm::getDataCalculation()[1];
|
||||
$responseMock = new WC_Retailcrm_Response(200, json_encode($responseCalculation['response']));
|
||||
$this->setMockResponse($this->apiMock, 'calculateDiscountLoyalty', $responseMock);
|
||||
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
$reflection = new \ReflectionClass($this->loyalty);
|
||||
$reflection_property = $reflection->getProperty('validator');
|
||||
$reflection_property->setAccessible(true);
|
||||
$reflection_property->setValue($this->loyalty, $validatorMock);
|
||||
|
||||
$GLOBALS['woocommerce'] = $woocommerce;
|
||||
$result = $this->loyalty->createLoyaltyCoupon(true);
|
||||
|
||||
$this->assertEmpty($result);
|
||||
$this->assertNotEmpty($this->loyalty->getCouponLoyalty($woocommerce->customer->get_email()));
|
||||
|
||||
$coupons = $woocommerce->cart->get_coupons();
|
||||
|
||||
$this->assertNotEmpty($coupons);
|
||||
$this->assertFalse(isset($coupons[$couponCode]));
|
||||
}
|
||||
|
||||
public function testDeleteLoyaltyCouponInOrder()
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
$user = DataLoyaltyRetailcrm::createUsers()[0];
|
||||
|
||||
$coupon = new WC_Coupon();
|
||||
$coupon->set_usage_limit(0);
|
||||
$coupon->set_amount('50');
|
||||
$coupon->set_email_restrictions($user->get_email());
|
||||
$coupon->set_code('loyalty' . mt_rand());
|
||||
$coupon->save();
|
||||
|
||||
$wcOrder = wc_create_order([
|
||||
'status' => null,
|
||||
'customer_id' => $user->get_id(),
|
||||
'customer_note' => null,
|
||||
'parent' => null,
|
||||
'created_via' => null,
|
||||
'cart_hash' => null,
|
||||
'order_id' => 0,
|
||||
]);
|
||||
|
||||
$wcOrder->add_product($products[0]);
|
||||
$wcOrder->add_product($products[1]);
|
||||
$wcOrder->apply_coupon($coupon->get_code());
|
||||
$wcOrder->calculate_totals();
|
||||
$wcOrder->save();
|
||||
|
||||
$this->assertNotEmpty($wcOrder->get_coupons());
|
||||
$this->loyalty->deleteLoyaltyCouponInOrder($wcOrder);
|
||||
$this->assertEmpty($wcOrder->get_coupons());
|
||||
|
||||
$wcOrder->delete(true);
|
||||
}
|
||||
|
||||
public function testApplyLoyaltyDiscountWithBonuses()
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
$user = DataLoyaltyRetailcrm::createUsers()[0];
|
||||
$discountLoyalty = 50;
|
||||
|
||||
$wcOrder = wc_create_order([
|
||||
'status' => null,
|
||||
'customer_id' => $user->get_id(),
|
||||
'customer_note' => null,
|
||||
'parent' => null,
|
||||
'created_via' => null,
|
||||
'cart_hash' => null,
|
||||
'order_id' => 0,
|
||||
]);
|
||||
|
||||
$wcOrder->add_product($products[0]);
|
||||
$wcOrder->add_product($products[1]);
|
||||
$wcOrder->calculate_totals();
|
||||
$wcOrder->save();
|
||||
|
||||
foreach ($wcOrder->get_items() as $id => $item) {
|
||||
$currentItemsPrice[$id] = $item->get_total();
|
||||
$itemIds[] = $id;
|
||||
}
|
||||
|
||||
$createdCrmOrderResponse = ['site' => 'test', 'externalId' => 1, 'items' => [['discounts' => [],], ['discounts' => []]]];
|
||||
$response = new WC_Retailcrm_Response(
|
||||
200,
|
||||
json_encode([
|
||||
'order' => [
|
||||
'items' => [
|
||||
[
|
||||
'externalIds' => [
|
||||
[
|
||||
'value' => '11_' . $itemIds[0]
|
||||
]
|
||||
],
|
||||
'discounts' => [
|
||||
[
|
||||
'type' => 'bonus_charge',
|
||||
'amount' => 25
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'externalIds' => [
|
||||
[
|
||||
'value' => '22_' . $itemIds[1]
|
||||
]
|
||||
],
|
||||
'discounts' => [
|
||||
[
|
||||
'type' => 'bonus_charge',
|
||||
'amount' => 25
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
])
|
||||
);
|
||||
|
||||
$this->setMockResponse($this->apiMock, 'applyBonusToOrder', $response);
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, $createdCrmOrderResponse, $discountLoyalty);
|
||||
|
||||
foreach ($wcOrder->get_items() as $id => $item) {
|
||||
$this->assertNotEquals($item->get_total(), $currentItemsPrice[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
public function testApplyLoyaltyDiscountWithPercentDiscount()
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
$user = DataLoyaltyRetailcrm::createUsers()[0];
|
||||
|
||||
$wcOrder = wc_create_order([
|
||||
'status' => null,
|
||||
'customer_id' => $user->get_id(),
|
||||
'customer_note' => null,
|
||||
'parent' => null,
|
||||
'created_via' => null,
|
||||
'cart_hash' => null,
|
||||
'order_id' => 0,
|
||||
]);
|
||||
|
||||
$wcOrder->add_product($products[0]);
|
||||
$wcOrder->add_product($products[1]);
|
||||
$wcOrder->calculate_totals();
|
||||
$wcOrder->save();
|
||||
|
||||
foreach ($wcOrder->get_items() as $id => $item) {
|
||||
$currentItemsPrice[$id] = $item->get_total();
|
||||
$itemIds[] = $id;
|
||||
}
|
||||
|
||||
$createdCrmOrderResponse = [
|
||||
'site' => 'test',
|
||||
'externalId' => 1,
|
||||
'items' => [
|
||||
[
|
||||
'externalIds' => [
|
||||
[
|
||||
'value' => '11_' . $itemIds[0]
|
||||
]
|
||||
],
|
||||
'discounts' => [
|
||||
[
|
||||
'type' => 'loyalty_level',
|
||||
'amount' => 25
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'externalIds' => [
|
||||
[
|
||||
'value' => '22_' . $itemIds[1]
|
||||
]
|
||||
],
|
||||
'discounts' => [
|
||||
[
|
||||
'type' => 'loyalty_level',
|
||||
'amount' => 25
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, $createdCrmOrderResponse);
|
||||
|
||||
foreach ($wcOrder->get_items() as $id => $item) {
|
||||
$this->assertNotEquals($item->get_total(), $currentItemsPrice[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getPrivateMethod($method, $class)
|
||||
{
|
||||
$reflection = new ReflectionClass($class);
|
||||
$method = $reflection->getMethod($method);
|
||||
$method->setAccessible(true);
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
private function createCart()
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
|
||||
return [
|
||||
[
|
||||
'data' => $products[0],
|
||||
'quantity' => 1,
|
||||
'line_subtotal' => $products[0]->get_regular_price(),
|
||||
'line_total' => $products[0]->get_regular_price(),//When sale_price identical regular price, sale is empty
|
||||
],
|
||||
[
|
||||
'data' => $products[1],
|
||||
'quantity' => 3,
|
||||
'line_subtotal' => $products[1]->get_regular_price() * 3,
|
||||
'line_total' => $products[1]->get_sale_price() * 3,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -642,9 +642,12 @@ class WC_Retailcrm_Orders_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
*/
|
||||
private function getRetailcrmOrders($retailcrm)
|
||||
{
|
||||
$options = $this->getOptions();
|
||||
unset($options['loyalty']);
|
||||
|
||||
return new WC_Retailcrm_Orders(
|
||||
$retailcrm,
|
||||
$this->getOptions(),
|
||||
$options,
|
||||
new WC_Retailcrm_Order_Item($this->getOptions()),
|
||||
new WC_Retailcrm_Order_Address(),
|
||||
new WC_Retailcrm_Customers(
|
||||
@ -669,4 +672,3 @@ class WC_Retailcrm_Orders_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
->getMock();
|
||||
}
|
||||
}
|
||||
|
||||
|
142
tests/validators/test-wc-retailcrm-loyalty-validator.php
Normal file
142
tests/validators/test-wc-retailcrm-loyalty-validator.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
use DataLoyaltyRetailCrm;
|
||||
|
||||
class WC_Retailcrm_Loyalty_Validator_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
{
|
||||
protected $responseMock;
|
||||
protected $apiMock;
|
||||
protected $individualClient;
|
||||
protected $corpClient;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->individualClient = new WC_Customer();
|
||||
$this->individualClient->set_first_name('Test');
|
||||
$this->individualClient->set_last_name('Test');
|
||||
$this->individualClient->set_email(uniqid(md5(date('Y-m-d H:i:s'))) . '@mail.com');
|
||||
$this->individualClient->set_billing_email( $this->individualClient->get_email());
|
||||
$this->individualClient->set_password('password');
|
||||
$this->individualClient->set_billing_phone('89000000000');
|
||||
$this->individualClient->set_date_created(date('Y-m-d H:i:s'));
|
||||
$this->individualClient->save();
|
||||
|
||||
$this->corpClient = new WC_Customer();
|
||||
$this->corpClient->set_first_name('Test');
|
||||
$this->corpClient->set_last_name('Test');
|
||||
$this->corpClient->set_email(uniqid(md5(date('Y-m-d H:i:s'))) . '@mail.com');
|
||||
$this->corpClient->set_billing_email($this->corpClient->get_email());
|
||||
$this->corpClient->set_password('password');
|
||||
$this->corpClient->set_billing_phone('89000000000');
|
||||
$this->corpClient->set_date_created(date('Y-m-d H:i:s'));
|
||||
$this->corpClient->set_billing_company('TEST COMPANY');
|
||||
$this->corpClient->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider DataLoyaltyRetailCrm::dataCheckUser()
|
||||
*/
|
||||
public function testCheckUser($responseApiMethod, $wcUserType, $throwMessage, $isCorpActive)
|
||||
{
|
||||
$this->setResponseMock();
|
||||
$this->setApiMock('customersGet', $responseApiMethod);
|
||||
|
||||
$validator = new WC_Retailcrm_Loyalty_Validator($this->apiMock, $isCorpActive);
|
||||
$method = $this->getPrivateMethod('checkUser', $validator);
|
||||
|
||||
$wcUserId = $wcUserType === 'individual' ? $this->individualClient->get_id() : $this->corpClient->get_id();
|
||||
|
||||
try {
|
||||
$method->invokeArgs($validator, [$wcUserId]);
|
||||
|
||||
if ($throwMessage) {
|
||||
$this->fail('ValidatorException was not thrown');
|
||||
} else {
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
} catch (ValidatorException $exception) {
|
||||
$this->assertEquals($throwMessage, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** @dataProvider DataLoyaltyRetailCrm::dataLoyaltyAccount() */
|
||||
public function testGetLoyaltyAccount($responseMock, $throwMessage)
|
||||
{
|
||||
$this->setResponseMock($responseMock);
|
||||
$this->setApiMock('getLoyaltyAccountList', $this->responseMock);
|
||||
|
||||
$validator = new WC_Retailcrm_Loyalty_Validator($this->apiMock, true);
|
||||
$method = $this->getPrivateMethod('checkLoyaltyAccount', $validator);
|
||||
|
||||
try {
|
||||
$method->invokeArgs($validator, [777]);
|
||||
|
||||
if ($throwMessage) {
|
||||
$this->fail('ValidatorException was not thrown');
|
||||
} else {
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
} catch (ValidatorException $exception) {
|
||||
$this->assertEquals($throwMessage, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** @dataProvider DataLoyaltyRetailCrm::dataCheckActiveLoyalty() */
|
||||
public function testCheckActivateLoyalty($responseMock, $throwMessage)
|
||||
{
|
||||
$this->setResponseMock($responseMock);
|
||||
$this->setApiMock('getLoyalty', $this->responseMock);
|
||||
|
||||
$validator = new WC_Retailcrm_Loyalty_Validator($this->apiMock, true);
|
||||
$method = $this->getPrivateMethod('checkActiveLoyalty', $validator);
|
||||
|
||||
try {
|
||||
$method->invokeArgs($validator, [1]);
|
||||
|
||||
if ($throwMessage) {
|
||||
$this->fail('ValidatorException was not thrown');
|
||||
} else {
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
} catch (ValidatorException $exception) {
|
||||
$this->assertEquals($throwMessage, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function setResponseMock($response = ['success' => true])
|
||||
{
|
||||
$this->responseMock = $this->getMockBuilder('\WC_Retailcrm_Response_Helper')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(['isSuccessful'])
|
||||
->getMock()
|
||||
;
|
||||
|
||||
$this->responseMock->setResponse($response);
|
||||
$this->setMockResponse($this->responseMock, 'isSuccessful', true);
|
||||
}
|
||||
|
||||
private function setApiMock($method, $response)
|
||||
{
|
||||
$this->apiMock = $this->getMockBuilder('\WC_Retailcrm_Client_V5')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods([$method])
|
||||
->getMock()
|
||||
;
|
||||
$this->setMockResponse($this->apiMock, $method, $response);
|
||||
}
|
||||
|
||||
private function getPrivateMethod($method, $class)
|
||||
{
|
||||
$reflection = new ReflectionClass($class);
|
||||
$method = $reflection->getMethod($method);
|
||||
$method->setAccessible(true);
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->individualClient->delete();
|
||||
$this->corpClient->delete();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user