From d2ab6013df73f5c653bc3907f6849d7a61a5fd87 Mon Sep 17 00:00:00 2001 From: Ivan Chaplygin Date: Wed, 29 May 2024 14:13:31 +0300 Subject: [PATCH] ref #94823 Removed reapplication of loyalty program bonuses. Fixed recalculation of discount when bonuses are deleted. --- src/include/class-wc-retailcrm-base.php | 13 +++ src/include/class-wc-retailcrm-loyalty.php | 40 +++++++++- src/include/class-wc-retailcrm-orders.php | 79 +++++++------------ .../order/class-wc-retailcrm-order-item.php | 33 ++++---- 4 files changed, 95 insertions(+), 70 deletions(-) diff --git a/src/include/class-wc-retailcrm-base.php b/src/include/class-wc-retailcrm-base.php index 710a813..7c623a6 100644 --- a/src/include/class-wc-retailcrm-base.php +++ b/src/include/class-wc-retailcrm-base.php @@ -563,7 +563,20 @@ if (!class_exists('WC_Retailcrm_Base')) { return; } + /* as_schedule_single_action( + time() + 2, // when to run? 5 seconds later + 'action_update_order', // the hook name + array( $order_id ), // arguments to pass to the hook and the function + 'updateOrder', // group name, could be any string + true // should be unique? – yes + );*/ $this->orders->updateOrder($order_id); + + /*if (!wp_next_scheduled('action_update_order', [$order_id])) { + wp_schedule_single_event( time() + 2, 'action_update_order', [$order_id] ); + }*/ + + //$this->orders->updateOrder($order_id); } /** diff --git a/src/include/class-wc-retailcrm-loyalty.php b/src/include/class-wc-retailcrm-loyalty.php index 815a4d0..d5aec33 100644 --- a/src/include/class-wc-retailcrm-loyalty.php +++ b/src/include/class-wc-retailcrm-loyalty.php @@ -378,9 +378,14 @@ if (!class_exists('WC_Retailcrm_Loyalty')) : $items = $response['order']['items']; } + $this->calculateLoyaltyDiscount($wcOrder, $items); + } + + public function calculateLoyaltyDiscount($wcOrder, $orderItems) + { $wcItems = $wcOrder->get_items(); - foreach ($items as $item) { + foreach ($orderItems as $item) { $externalId = $item['externalIds'][0]['value']; $externalId = preg_replace('/^\d+\_/m', '', $externalId); @@ -402,6 +407,39 @@ if (!class_exists('WC_Retailcrm_Loyalty')) : $wcOrder->calculate_totals(); } + + public function getCrmItemsInfo($orderExternalId) + { + $discountType = null; + $crmItems = []; + + $response = $this->apiClient->ordersGet($orderExternalId); + + if (!$response instanceof WC_Retailcrm_Response || !$response->isSuccessful()) { + writeBaseLogs('Process order: Error when receiving an order from the crm. Order Id: ' . $orderExternalId); + + return []; + } + + if (isset($response['order'])) { + 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]; + } } endif; diff --git a/src/include/class-wc-retailcrm-orders.php b/src/include/class-wc-retailcrm-orders.php index 11ef9b4..31b1e1e 100644 --- a/src/include/class-wc-retailcrm-orders.php +++ b/src/include/class-wc-retailcrm-orders.php @@ -45,10 +45,10 @@ if (!class_exists('WC_Retailcrm_Orders')) : private $order = []; /** @var bool */ - private $cancelBonus = false; + private $cancelLoyalty = false; - /** @var float */ - private $appliedBonuses = 0; + /** @var string */ + private $loyaltyDiscountType = ''; /** @var array */ private $payment = []; @@ -308,32 +308,30 @@ if (!class_exists('WC_Retailcrm_Orders')) : try { $wcOrder = wc_get_order($orderId); + $needRecalculate = false; $this->processOrder($wcOrder, true); - if ($this->cancelBonus) { - $this->cancelBonus = false; - $this->order_item->cancelBonus = false; + if ($this->cancelLoyalty) { + $this->cancelLoyalty = false; + $this->order_item->cancelLoyalty = false; + $needRecalculate = true; - $this->retailcrm->cancelBonusOrder(['externalId' => $this->order['externalId']]);// проверка response - - $response = $this->retailcrm->ordersEdit($this->order); - - $response = apply_filters('retailcrm_order_update_after', $response, $wcOrder); - - if ($response instanceof WC_Retailcrm_Response && $response->isSuccessful()) { - $this->payment = $this->orderUpdatePaymentType($wcOrder); + if ($this->loyaltyDiscountType === 'bonus_charge') { + $this->retailcrm->cancelBonusOrder(['externalId' => $this->order['externalId']]); + } else { + $this->order['privilegeType'] = 'none'; } + } - $wcOrder->calculate_totals(); - } else { - $response = $this->retailcrm->ordersEdit($this->order); + $response = $this->retailcrm->ordersEdit($this->order); + $response = apply_filters('retailcrm_order_update_after', $response, $wcOrder); - // 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()) { + $this->payment = $this->orderUpdatePaymentType($wcOrder); - if ($response instanceof WC_Retailcrm_Response && $response->isSuccessful()) { - $this->payment = $this->orderUpdatePaymentType($wcOrder); + if ($needRecalculate) { + $this->loyalty->calculateLoyaltyDiscount($wcOrder, $response['order']['items']); } } } catch (Throwable $exception) { @@ -407,7 +405,7 @@ if (!class_exists('WC_Retailcrm_Orders')) : * @return void * @throws \Exception */ - protected function processOrder($order, $update = false)//TODO Возможно ли по хуку передать доп данные? Например что это приминеение бонусов к новому заказу + protected function processOrder($order, $update = false) { if (!$order instanceof WC_Order) { return; @@ -470,49 +468,28 @@ if (!class_exists('WC_Retailcrm_Orders')) : } $orderData['delivery']['address'] = $this->order_address->build($order)->getData(); + $orderItems = []; - $crmItems = []; // необходимо для обновления торговой позиции (определения кол-ва списываемых бонусов) - $loyaltyDiscountType = null; // вид скидки + $crmItems = []; $wcItems = $order->get_items(); if ($this->loyalty && $update) { - $response = $this->retailcrm->ordersGet($order->get_id()); + $result = $this->loyalty->getCrmItemsInfo($order->get_id()); - if (!$response instanceof WC_Retailcrm_Response || !$response->isSuccessful()) { - writeBaseLogs('Process order: Error when receiving an order from the crm. Order Id: ' . $order->get_id()); + if ($result !== []) { + $crmItems = $result['items']; - $crmOrder = null; - } else { - $crmOrder = $response['order'] ?? null; - $this->appliedBonuses = $crmOrder['bonusesChargeTotal'] ?? 0; + $this->cancelLoyalty = $this->order_item->isCancelLoyalty($wcItems, $crmItems); + $this->loyaltyDiscountType = $result['discountType']; } } - if ($crmOrder) { - foreach ($crmOrder['items'] as $item) { - $externalId = $item['externalIds'][0]['value']; - $externalId = preg_replace('/^\d+\_/m', '', $externalId); - $crmItems[$externalId] = $item; - - if (!$loyaltyDiscountType) { - foreach ($item['discounts'] as $discount) { - if (in_array($discount['type'], ['bonus_charge', 'loyalty_level'])) { - $loyaltyDiscountType = $discount['type']; - break; - } - } - } - } - - $this->cancelBonus = $this->order_item->isCancelBonus($wcItems, $crmItems); - } - /** @var WC_Order_Item_Product $item */ foreach ($wcItems as $id => $item) { $crmItem = $crmItems[$id] ?? null; $orderItems[] = $this->order_item->build($item, $crmItem)->getData(); - $this->order_item->resetData($this->cancelBonus); + $this->order_item->resetData($this->cancelLoyalty); } unset($crmItems, $crmItem); diff --git a/src/include/order/class-wc-retailcrm-order-item.php b/src/include/order/class-wc-retailcrm-order-item.php index 55477f7..c25f955 100644 --- a/src/include/order/class-wc-retailcrm-order-item.php +++ b/src/include/order/class-wc-retailcrm-order-item.php @@ -29,7 +29,7 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data protected $settings = []; /** @var bool */ - public $cancelBonus = false; + public $cancelLoyalty = false; /** * WC_Retailcrm_Order_Item constructor. @@ -122,8 +122,7 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data WC_Order_Item_Product $item, $price, int $decimalPlaces, - $crmItem = null, - $loyaltyDiscountType = null // по идее не нужно, т.к. если новая позиция, автоматом придет ответ по истории со скидкой + $crmItem = null ) { if ($crmItem) { $loyaltyDiscount = 0; @@ -138,15 +137,13 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data $productPrice = ($item->get_total() / $item->get_quantity()) + ($loyaltyDiscount / $crmItem['quantity']); - if ($this->cancelBonus && $productPrice > $price) { - $productPrice = $item->get_total() / $item->get_quantity(); - } elseif ($this->cancelBonus) { - $item->set_total($item->get_total() + $loyaltyDiscount); - $item->calculate_taxes(); - $item->save(); + 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(); - } elseif ($productPrice > $price) { $productPrice = $item->get_total() / $item->get_quantity(); } } else { @@ -162,7 +159,7 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data /** * Reset item data. */ - public function resetData($cancelBonus) + public function resetData($cancelLoyalty) { $this->data = [ 'offer' => [], @@ -171,28 +168,28 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data 'quantity' => 0.00 ]; - $this->cancelBonus = $cancelBonus; + $this->cancelLoyalty = $cancelLoyalty; } - public function isCancelBonus($wcItems, $crmItems): bool + public function isCancelLoyalty($wcItems, $crmItems): bool { $loyaltyDiscount = 0; if (count($wcItems) !== count($crmItems)) { - $this->cancelBonus = true; + $this->cancelLoyalty = true; return true; } foreach ($wcItems as $id => $item) { if (!isset($crmItems[$id])) { - $this->cancelBonus = true; + $this->cancelLoyalty = true; return true; } if ($item->get_quantity() !== $crmItems[$id]['quantity']) { - $this->cancelBonus = true; + $this->cancelLoyalty = true; return true; } @@ -206,7 +203,7 @@ class WC_Retailcrm_Order_Item extends WC_Retailcrm_Abstracts_Data } if (($item->get_total() + $loyaltyDiscount) > $item->get_subtotal()) { - $this->cancelBonus = true; + $this->cancelLoyalty = true; return true; }