diff --git a/resources/pot/retailcrm-es_ES.pot b/resources/pot/retailcrm-es_ES.pot
index b794686..356d5f0 100644
--- a/resources/pot/retailcrm-es_ES.pot
+++ b/resources/pot/retailcrm-es_ES.pot
@@ -449,31 +449,112 @@ msgid "Loyalty program"
msgstr "Programa de fidelización"
msgid "Activate program loyalty"
-msgstr "Activar el programa de fidelización"
+msgstr "Activar programa de fidelización"
msgid "Enable this setting for activate program loyalty on site"
-msgstr "Active esta opción para activar el programa de fidelización en el sitio web"
+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 fidelidad"
+msgstr "Condiciones del programa de fidelización"
msgid "Insert the terms and conditions of the loyalty program"
-msgstr "Inserte las condiciones de participación en el programa de fidelidad"
+msgstr "Introduce las condiciones del programa de fidelización"
msgid "Conditions of personal data processing"
-msgstr "Condiciones del tratamiento de datos personales"
+msgstr "Condiciones de procesamiento de datos personales"
msgid "Insert the terms and conditions for processing personal data"
-msgstr "Inserte las condiciones para el tratamiento de datos personales"
+msgstr "Introduce las condiciones para el procesamiento de datos personales"
msgid "To activate the loyalty program it is necessary to activate the 'enable use of coupons option'"
-msgstr "Para activar el programa de fidelización es necesario activar la opción 'habilitar uso de cupones'."
+msgstr "Para activar el programa de fidelización es necesario activar la opción 'habilitar el uso de cupones'"
+
+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"
@@ -482,19 +563,28 @@ 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ó ninguna participación activa en el programa de fidelización"
+msgstr "No se detectó la participación activa en el programa de fidelización"
msgid "No bonuses for debiting"
-msgstr "Sin bonificaciones por adeudo"
+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 "El programa de fidelización no está activo"
+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:"
diff --git a/resources/pot/retailcrm-ru_RU.pot b/resources/pot/retailcrm-ru_RU.pot
index d75fdfc..193c76e 100644
--- a/resources/pot/retailcrm-ru_RU.pot
+++ b/resources/pot/retailcrm-ru_RU.pot
@@ -572,10 +572,10 @@ msgid "Error when searching for participation in loyalty programs"
msgstr "Ошибка при поиске участия в программах лояльности"
msgid "No active participation in the loyalty program was detected"
-msgstr "Активного участия в программе лояльности не обнаружено"
+msgstr "Не обнаружено активного участия в программе лояльности"
msgid "No bonuses for debiting"
-msgstr "Бонусы на списание отсутствуют"
+msgstr "Нет бонусов для списания"
msgid "Loyalty program not found"
msgstr "Программа лояльности не найдена"
@@ -588,3 +588,12 @@ msgstr "Программа лояльности заблокирована"
msgid "This user is a corporate person"
msgstr "Данный пользователь является корпоратиным лицом"
+
+msgid "It is possible to write off"
+msgstr "Возможно списать"
+
+msgid "bonuses"
+msgstr "бонусов"
+
+msgid "Use coupon:"
+msgstr "Используйте купон:"
diff --git a/src/include/api/class-wc-retailcrm-client-v5.php b/src/include/api/class-wc-retailcrm-client-v5.php
index 485db22..35b75b1 100644
--- a/src/include/api/class-wc-retailcrm-client-v5.php
+++ b/src/include/api/class-wc-retailcrm-client-v5.php
@@ -2992,12 +2992,12 @@ class WC_Retailcrm_Client_V5
}
/** Maximum discount calculation */
- public function calculateDiscountLoyalty(string $site, array $order, float $bonuses)
+ public function calculateDiscountLoyalty(string $site, array $order)
{
return $this->client->makeRequest(
"/loyalty/calculate",
WC_Retailcrm_Request::METHOD_POST,
- ['site' => $site, 'order' => json_encode($order), 'bonuses' => $bonuses]
+ ['site' => $site, 'order' => json_encode($order)]
);
}
diff --git a/src/include/class-wc-retailcrm-base.php b/src/include/class-wc-retailcrm-base.php
index f7d29f5..710a813 100644
--- a/src/include/class-wc-retailcrm-base.php
+++ b/src/include/class-wc-retailcrm-base.php
@@ -104,12 +104,22 @@ if (!class_exists('WC_Retailcrm_Base')) {
add_action('woocommerce_new_order', [$this, 'create_order'], 11, 1);
- if (isset($this->settings['loyalty']) && $this->settings['loyalty'] === static::YES) {
+ 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);
}
// Subscribed hooks
@@ -680,6 +690,59 @@ if (!class_exists('WC_Retailcrm_Base')) {
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());
+ }
+ }
+
/**
* In this method we include CSS file
*
diff --git a/src/include/class-wc-retailcrm-loyalty.php b/src/include/class-wc-retailcrm-loyalty.php
index 936ec3d..c6da194 100644
--- a/src/include/class-wc-retailcrm-loyalty.php
+++ b/src/include/class-wc-retailcrm-loyalty.php
@@ -27,12 +27,18 @@ if (!class_exists('WC_Retailcrm_Loyalty')) :
/** @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)
@@ -40,25 +46,13 @@ if (!class_exists('WC_Retailcrm_Loyalty')) :
$result = [];
try {
- $response = $this->apiClient->customersGet($userId);
-
- if (!isset($response['customer']['id'])) {
- return $result;
- }
-
- $filter['customerId'] = $response['customer']['id'];
-
- $response = $this->apiClient->getLoyaltyAccountList($filter);
+ $response = $this->getLoyaltyAccounts($userId);
} catch (Throwable $exception) {
writeBaseLogs('Exception get loyalty accounts: ' . $exception->getMessage());
return $result;
}
- if (!$response->isSuccessful() || !$response->offsetExists('loyaltyAccounts')) {
- return $result;
- }
-
$loyaltyAccount = $response['loyaltyAccounts'][0] ?? null;
if ($loyaltyAccount && (int) $loyaltyAccount['customer']['externalId'] === $userId) {
@@ -116,6 +110,298 @@ if (!class_exists('WC_Retailcrm_Loyalty')) :
return false;
}
}
+
+ private function getDiscountLoyalty($cartItems, $site, $customerId)
+ {
+ $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);
+
+ if (!$response->isSuccessful() || !isset($response['calculations'])) {
+ 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 .= '
' . __('It is possible to write off', 'retailcrm') . ' ' . $lpDiscountSum . ' ' . __('bonuses', 'retailcrm') . '
';
+ return $resultString. '' . __('Use coupon:', 'retailcrm') . ' ' . $coupon->get_code() . '
';
+ }
+
+ 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($wcUser, $wcOrder)
+ {
+ return !(!$wcUser || (isCorporateUserActivate($this->settings) && isCorporateOrder($wcUser, $wcOrder)));
+ }
+
+ public function applyLoyaltyDiscount($wcOrder, $discountLp, $createdOrder)
+ {
+ $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'];
+ }
+
+ $wcItems = $wcOrder->get_items();
+
+ foreach ($items 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();
+ }
}
endif;
diff --git a/src/include/class-wc-retailcrm-orders.php b/src/include/class-wc-retailcrm-orders.php
index 4b202b3..6bfe6ec 100644
--- a/src/include/class-wc-retailcrm-orders.php
+++ b/src/include/class-wc-retailcrm-orders.php
@@ -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;
@@ -64,6 +67,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);
}
@@ -87,8 +94,25 @@ if (!class_exists('WC_Retailcrm_Orders')) :
$this->order_payment->resetData();
$wcOrder = wc_get_order($orderId);
+ $privilegeType = 'none';
+
+ if ($this->loyalty) {
+ $discountLp = $this->loyalty->deleteLoyaltyCouponInOrder($wcOrder);
+ $wcUser = $wcOrder->get_user();
+
+ if (!$this->loyalty->isValidOrder($wcUser, $wcOrder)) {
+ if ($discountLp > 0) {
+ writeBaseLogs('The user does not meet the requirements for working with the loyalty program. Order Id: ' . $orderId);
+ }
+
+ $discountLp = 0;
+ } else {
+ $privilegeType = 'loyalty_level';
+ }
+ }
$this->processOrder($wcOrder);
+ $this->order['privilegeType'] = $privilegeType;
$response = $this->retailcrm->ordersCreate($this->order);
@@ -98,6 +122,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, $discountLp, $response['order']);
+ }
} catch (Throwable $exception) {
writeBaseLogs(
sprintf(
diff --git a/src/include/functions.php b/src/include/functions.php
index 4f82f5b..b1afd25 100644
--- a/src/include/functions.php
+++ b/src/include/functions.php
@@ -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($wcUser, $wcOrder)
+{
+ return !empty($wcUser->get_billing_company()) || !empty($wcOrder->get_billing_company());
+}
diff --git a/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php b/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php
index 6c46155..2e08d09 100644
--- a/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php
+++ b/src/include/validators/loyalty-validator/class-wc-retailcrm-loyalty-validator.php
@@ -16,10 +16,13 @@ if (!class_exists('WC_Retailcrm_Loyalty_Validator')) :
{
/** @var WC_Retailcrm_Client_V5 */
protected $apiClient;
- protected $crmUser;
- protected $loyaltyAccount;
+
protected $isActiveCorp;
+ public $customer;
+
+ public $loyaltyAccount;
+
public function __construct($apiClient, $isActiveCorp)
{
$this->apiClient = $apiClient;
@@ -30,7 +33,7 @@ if (!class_exists('WC_Retailcrm_Loyalty_Validator')) :
{
try {
$this->checkUser($userId);
- $this->checkLoyaltyAccount($this->crmUser['id']);
+ $this->checkLoyaltyAccount($this->customer['id']);
$this->checkActiveLoyalty($this->loyaltyAccount['loyalty']['id']);
return true;
@@ -56,19 +59,19 @@ if (!class_exists('WC_Retailcrm_Loyalty_Validator')) :
$customer = new WC_Customer($userId);
- if ($this->isActiveCorp && !empty($customer->get_shipping_company())) {
+ if ($this->isActiveCorp && !empty($customer->get_billing_company())) {
throw new ValidatorException($this->isCorporateUser, 400);
}
- $this->crmUser = $responseUser['customer'];
+ $this->customer = $responseUser['customer'];
}
/**
* @throws ValidatorException
*/
- private function checkLoyaltyAccount($crmUserId)
+ private function checkLoyaltyAccount($customerId)
{
- $filter['customerId'] = $crmUserId;
+ $filter['customerId'] = $customerId;
$responseLoyalty = $this->apiClient->getLoyaltyAccountList($filter);
if (!$responseLoyalty->isSuccessful() || !$responseLoyalty->offsetExists('loyaltyAccounts')) {
diff --git a/src/languages/retailcrm-es_ES.l10n.php b/src/languages/retailcrm-es_ES.l10n.php
index e3fb869..7a6b3e6 100644
--- a/src/languages/retailcrm-es_ES.l10n.php
+++ b/src/languages/retailcrm-es_ES.l10n.php
@@ -199,7 +199,54 @@ 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 'enable use of coupons option'" =>
+ "Para activar el programa de fidelización es necesario activar la opción 'habilitar el uso de cupones'",
+ "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:",
],
"language" => "es",
"x-generator" => "GlotPress/2.4.0-alpha",
diff --git a/src/languages/retailcrm-es_ES.mo b/src/languages/retailcrm-es_ES.mo
index 3ba8896..43567c3 100644
Binary files a/src/languages/retailcrm-es_ES.mo and b/src/languages/retailcrm-es_ES.mo differ
diff --git a/src/languages/retailcrm-ru_RU.l10n.php b/src/languages/retailcrm-ru_RU.l10n.php
index 857338c..514c7e5 100644
--- a/src/languages/retailcrm-ru_RU.l10n.php
+++ b/src/languages/retailcrm-ru_RU.l10n.php
@@ -198,7 +198,54 @@ 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 'enable use of coupons option'" =>
+ "Для активации программы лояльности необходимо активировать опцию 'включить использование купонов'",
+ "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:" => "Используйте купон:",
],
"language" => "ru",
"x-generator" => "GlotPress/2.4.0-alpha",
diff --git a/src/languages/retailcrm-ru_RU.mo b/src/languages/retailcrm-ru_RU.mo
index 6f819be..acd4ebf 100644
Binary files a/src/languages/retailcrm-ru_RU.mo and b/src/languages/retailcrm-ru_RU.mo differ
diff --git a/tests/datasets/data-loyalty-retailcrm.php b/tests/datasets/data-loyalty-retailcrm.php
index ec44910..6793410 100644
--- a/tests/datasets/data-loyalty-retailcrm.php
+++ b/tests/datasets/data-loyalty-retailcrm.php
@@ -1,7 +1,4 @@
['customer' => ['id' => 1]],
'wcUserType' => 'corp',
'throwMessage' => 'This user is a corporate person',
- 'isCorpActive' => true,
+ 'isCorpActive' => true
],
[
'responseApiMethod' => ['customer' => ['id' => 1]],
'wcUserType' => 'corp',
'throwMessage' => null,
- 'isCorpActive' => false,
+ 'isCorpActive' => false
],
[
'responseApiMethod' => ['customer' => ['id' => 1]],
'wcUserType' => 'individual',
'throwMessage' => null,
- 'isCorpActive' => true,
+ 'isCorpActive' => true
],
];
}
@@ -151,4 +148,198 @@ class DataLoyaltyRetailCrm
]
];
}
+
+ 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];
+ }
}
diff --git a/tests/loyalty/test-wc-retailcrm-client-v5.php b/tests/loyalty/test-wc-retailcrm-client-v5.php
index 967ed1d..9c5ad52 100644
--- a/tests/loyalty/test-wc-retailcrm-client-v5.php
+++ b/tests/loyalty/test-wc-retailcrm-client-v5.php
@@ -116,7 +116,7 @@ class WC_Retailcrm_Loyalty_Client_Test extends WC_Retailcrm_Test_Case_Helper
],
[
'method' => 'calculateDiscountLoyalty',
- 'parameters' => ['site', ['order'], 100]
+ 'parameters' => ['site', ['order']]
],
[
'method' => 'applyBonusToOrder',
diff --git a/tests/test-wc-retailcrm-loyalty.php b/tests/test-wc-retailcrm-loyalty.php
index 9e6f653..d0e11b3 100644
--- a/tests/test-wc-retailcrm-loyalty.php
+++ b/tests/test-wc-retailcrm-loyalty.php
@@ -1,6 +1,6 @@
apiMock = $this->getMockBuilder('\WC_Retailcrm_Client_V5')
->disableOriginalConstructor()
- ->setMethods(['customersGet', 'getLoyaltyAccountList', 'createLoyaltyAccount', 'activateLoyaltyAccount'])
+ ->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 responseLoyalty
+ * @dataProvider DataLoyaltyRetailCrm::getDataLoyalty()
*/
public function testGetForm($isSuccessful, $body, $expected)
{
@@ -85,8 +86,409 @@ class WC_Retailcrm_Loyalty_Test extends WC_Retailcrm_Test_Case_Helper
$this->assertTrue($result);
}
- public function responseLoyalty()
+ /**
+ * @dataProvider DataLoyaltyRetailCrm::getDataCalculation()
+ */
+ public function testGetDiscountLoyalty($response, $expected)
{
- return DataLoyaltyRetailCrm::getDataLoyalty();
+ $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];
+
+ $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, 50, $createdCrmOrderResponse);
+
+ 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, 0, $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,
+ ],
+ ];
}
}
diff --git a/tests/validators/test-wc-retailcrm-loyalty-validator.php b/tests/validators/test-wc-retailcrm-loyalty-validator.php
index f25694f..5640f69 100644
--- a/tests/validators/test-wc-retailcrm-loyalty-validator.php
+++ b/tests/validators/test-wc-retailcrm-loyalty-validator.php
@@ -1,6 +1,6 @@
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_shipping_company('TEST COMPANY');
+ $this->corpClient->set_billing_company('TEST COMPANY');
$this->corpClient->save();
}
- /** @dataProvider datasets\DataLoyaltyRetailCrm::dataCheckUser() */
+ /**
+ * @dataProvider DataLoyaltyRetailCrm::dataCheckUser()
+ */
public function testCheckUser($responseApiMethod, $wcUserType, $throwMessage, $isCorpActive)
{
$this->setResponseMock();
@@ -57,7 +59,7 @@ class WC_Retailcrm_Loyalty_Validator_Test extends WC_Retailcrm_Test_Case_Helper
}
}
- /** @dataProvider datasets\DataLoyaltyRetailCrm::dataLoyaltyAccount() */
+ /** @dataProvider DataLoyaltyRetailCrm::dataLoyaltyAccount() */
public function testGetLoyaltyAccount($responseMock, $throwMessage)
{
$this->setResponseMock($responseMock);
@@ -79,7 +81,7 @@ class WC_Retailcrm_Loyalty_Validator_Test extends WC_Retailcrm_Test_Case_Helper
}
}
- /** @dataProvider datasets\DataLoyaltyRetailCrm::dataCheckActiveLoyalty() */
+ /** @dataProvider DataLoyaltyRetailCrm::dataCheckActiveLoyalty() */
public function testCheckActivateLoyalty($responseMock, $throwMessage)
{
$this->setResponseMock($responseMock);