parent
2765e7ecb4
commit
48af9ba5aa
@ -2992,12 +2992,12 @@ class WC_Retailcrm_Client_V5
|
||||
}
|
||||
|
||||
/** Maximum discount calculation */
|
||||
public function calculateDiscountLoyalty(string $site, array $order)
|
||||
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)]
|
||||
['site' => $site, 'order' => json_encode($order), 'bonuses' => $bonuses]
|
||||
);
|
||||
}
|
||||
|
||||
@ -3011,12 +3011,12 @@ class WC_Retailcrm_Client_V5
|
||||
);
|
||||
}
|
||||
|
||||
public function cancelBonusOrder(string $site, array $order)
|
||||
public function cancelBonusOrder(array $order)
|
||||
{
|
||||
return $this->client->makeRequest(
|
||||
"/orders/loyalty/cancel-bonus-operations",
|
||||
WC_Retailcrm_Request::METHOD_POST,
|
||||
['site' => $site, 'order' => json_encode($order)]
|
||||
['order' => json_encode($order)]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -346,12 +346,29 @@ if (!class_exists('WC_Retailcrm_Loyalty')) :
|
||||
return $discountLp;
|
||||
}
|
||||
|
||||
public function isValidOrder($wcUser, $wcOrder)
|
||||
public function isValidOrder($wcCustomer, $wcOrder)
|
||||
{
|
||||
return !(!$wcUser || (isCorporateUserActivate($this->settings) && isCorporateOrder($wcUser, $wcOrder)));
|
||||
return !(!$wcCustomer || (isCorporateUserActivate($this->settings) && isCorporateOrder($wcCustomer, $wcOrder)));
|
||||
}
|
||||
|
||||
public function applyLoyaltyDiscount($wcOrder, $discountLp, $createdOrder)
|
||||
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 = [];
|
||||
@ -378,9 +395,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 +424,37 @@ 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() || !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];
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
@ -44,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 = [];
|
||||
|
||||
@ -94,25 +100,34 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
$this->order_payment->resetData();
|
||||
|
||||
$wcOrder = wc_get_order($orderId);
|
||||
$privilegeType = 'none';
|
||||
|
||||
if ($this->loyalty) {
|
||||
$wcCustomer = null;
|
||||
$privilegeType = 'none';
|
||||
$discountLp = $this->loyalty->deleteLoyaltyCouponInOrder($wcOrder);
|
||||
$wcUser = $wcOrder->get_user();
|
||||
$dataOrder = $wcOrder->get_data();
|
||||
|
||||
if (!$this->loyalty->isValidOrder($wcUser, $wcOrder)) {
|
||||
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;
|
||||
} else {
|
||||
$privilegeType = 'none';
|
||||
} elseif ($this->loyalty->isValidUser($wcCustomer)) {
|
||||
$privilegeType = 'loyalty_level';
|
||||
}
|
||||
}
|
||||
|
||||
$this->processOrder($wcOrder);
|
||||
$this->order['privilegeType'] = $privilegeType;
|
||||
|
||||
if (isset($privilegeType)) {
|
||||
$this->order['privilegeType'] = $privilegeType;
|
||||
}
|
||||
|
||||
$response = $this->retailcrm->ordersCreate($this->order);
|
||||
|
||||
@ -124,7 +139,7 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
}
|
||||
|
||||
if (isset($discountLp) && $discountLp > 0) {
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, $discountLp, $response['order']);
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, $response['order'], $discountLp);
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
writeBaseLogs(
|
||||
@ -302,16 +317,39 @@ if (!class_exists('WC_Retailcrm_Orders')) :
|
||||
|
||||
try {
|
||||
$wcOrder = wc_get_order($orderId);
|
||||
$needRecalculate = false;
|
||||
|
||||
$this->processOrder($wcOrder, true);
|
||||
|
||||
$response = $this->retailcrm->ordersEdit($this->order);
|
||||
if ($this->cancelLoyalty) {
|
||||
$this->cancelLoyalty = false;
|
||||
$this->order_item->cancelLoyalty = false;
|
||||
$needRecalculate = true;
|
||||
|
||||
// Allows you to verify order changes and perform additional actions
|
||||
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);
|
||||
$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(
|
||||
@ -447,15 +485,32 @@ 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'];
|
||||
|
||||
$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;
|
||||
|
@ -213,7 +213,7 @@ function isCorporateUserActivate($settings)
|
||||
return isset($settings['corporate_enabled']) && $settings['corporate_enabled'] === WC_Retailcrm_Base::YES;
|
||||
}
|
||||
|
||||
function isCorporateOrder($wcUser, $wcOrder)
|
||||
function isCorporateOrder($wcCustomer, $wcOrder)
|
||||
{
|
||||
return !empty($wcUser->get_billing_company()) || !empty($wcOrder->get_billing_company());
|
||||
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
|
||||
{
|
||||
$loyaltyDiscount = 0;
|
||||
|
||||
/** If the number of sales items does not match */
|
||||
if (count($wcItems) !== count($crmItems)) {
|
||||
$this->cancelLoyalty = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($wcItems as $id => $item) {
|
||||
/** 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;
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ class WC_Retailcrm_Loyalty_Client_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
],
|
||||
[
|
||||
'method' => 'cancelBonusOrder',
|
||||
'parameters' => ['site', ['order']]
|
||||
'parameters' => [['order']]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@ -330,6 +330,7 @@ class WC_Retailcrm_Loyalty_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
{
|
||||
$products = DataLoyaltyRetailCrm::createProducts();
|
||||
$user = DataLoyaltyRetailcrm::createUsers()[0];
|
||||
$discountLoyalty = 50;
|
||||
|
||||
$wcOrder = wc_create_order([
|
||||
'status' => null,
|
||||
@ -391,7 +392,7 @@ class WC_Retailcrm_Loyalty_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
$this->setMockResponse($this->apiMock, 'applyBonusToOrder', $response);
|
||||
$this->loyalty = new WC_Retailcrm_Loyalty($this->apiMock, []);
|
||||
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, 50, $createdCrmOrderResponse);
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, $createdCrmOrderResponse, $discountLoyalty);
|
||||
|
||||
foreach ($wcOrder->get_items() as $id => $item) {
|
||||
$this->assertNotEquals($item->get_total(), $currentItemsPrice[$id]);
|
||||
@ -456,7 +457,7 @@ class WC_Retailcrm_Loyalty_Test extends WC_Retailcrm_Test_Case_Helper
|
||||
]
|
||||
];
|
||||
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, 0, $createdCrmOrderResponse);
|
||||
$this->loyalty->applyLoyaltyDiscount($wcOrder, $createdCrmOrderResponse);
|
||||
|
||||
foreach ($wcOrder->get_items() as $id => $item) {
|
||||
$this->assertNotEquals($item->get_total(), $currentItemsPrice[$id]);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user