1
0
mirror of synced 2025-03-23 00:23:51 +03:00

Fix bug with product tax

This commit is contained in:
Dima Uryvskiy 2022-09-05 19:20:27 +03:00 committed by GitHub
parent fdbac7a2ec
commit b77635f2c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 175 additions and 117 deletions

View File

@ -1,3 +1,6 @@
## 2022-09-05 4.4.9
* Fix bug with product tax
## 2022-09-02 4.4.8 ## 2022-09-02 4.4.8
* Fix a critical bug when working with taxes * Fix a critical bug when working with taxes

View File

@ -1 +1 @@
4.4.8 4.4.9

View File

@ -284,7 +284,7 @@ if (!class_exists('WC_Retailcrm_History')) :
} catch (Exception $exception) { } catch (Exception $exception) {
WC_Retailcrm_Logger::add( WC_Retailcrm_Logger::add(
sprintf( sprintf(
"[%s] - %s", '[%s] - %s',
$exception->getMessage(), $exception->getMessage(),
'Exception in file - ' . $exception->getFile() . ' on line ' . $exception->getLine() 'Exception in file - ' . $exception->getFile() . ' on line ' . $exception->getLine()
) )
@ -350,7 +350,10 @@ if (!class_exists('WC_Retailcrm_History')) :
} }
if (isset($order['delivery']['service']['code'])) { if (isset($order['delivery']['service']['code'])) {
$service = retailcrm_get_delivery_service($shipping->get_method_id(), $order['delivery']['service']['code']); $service = retailcrm_get_delivery_service(
$shipping->get_method_id(),
$order['delivery']['service']['code']
);
if ($service) { if ($service) {
$shipping->set_instance_id($order['delivery']['service']['code']); $shipping->set_instance_id($order['delivery']['service']['code']);
@ -446,25 +449,31 @@ if (!class_exists('WC_Retailcrm_History')) :
} }
if (array_key_exists('items', $order)) { if (array_key_exists('items', $order)) {
foreach ($order['items'] as $key => $item) { foreach ($order['items'] as $key => $crmProduct) {
if (!isset($item['offer'][$this->bindField])) { if (!isset($crmProduct['offer'][$this->bindField])) {
continue; continue;
} }
if (isset($item['create']) && $item['create'] == true) { if (isset($crmProduct['create']) && $crmProduct['create'] == true) {
$arItemsNew = []; $arItemsNew = [];
$arItemsOld = []; $arItemsOld = [];
$product = retailcrm_get_wc_product(
$item['offer'][$this->bindField], $wcProduct = retailcrm_get_wc_product(
$crmProduct['offer'][$this->bindField],
$this->retailcrmSettings $this->retailcrmSettings
); );
if (!$wcProduct) {
WC_Retailcrm_Logger::add('Product not found by ' . $this->bindField);
continue;
}
foreach ($wcOrder->get_items() as $orderItemId => $orderItem) { foreach ($wcOrder->get_items() as $orderItemId => $orderItem) {
$arItemsOld[$orderItemId] = $orderItemId; $arItemsOld[$orderItemId] = $orderItemId;
} }
if (isset($item['externalIds'])) { if (isset($crmProduct['externalIds'])) {
foreach ($item['externalIds'] as $externalId) { foreach ($crmProduct['externalIds'] as $externalId) {
if ($externalId['code'] == 'woocomerce') { if ($externalId['code'] == 'woocomerce') {
$itemExternalId = explode('_', $externalId['value']); $itemExternalId = explode('_', $externalId['value']);
} }
@ -475,7 +484,7 @@ if (!class_exists('WC_Retailcrm_History')) :
} }
} }
$wcOrder->add_product($product, $item['quantity']); $this->addProductInWcOrder($wcOrder, $wcProduct, $crmProduct);
foreach ($wcOrder->get_items() as $orderItemId => $orderItem) { foreach ($wcOrder->get_items() as $orderItemId => $orderItem) {
$arItemsNew[$orderItemId] = $orderItemId; $arItemsNew[$orderItemId] = $orderItemId;
@ -486,33 +495,37 @@ if (!class_exists('WC_Retailcrm_History')) :
$order['items'][$key]['woocomerceId'] = $result; $order['items'][$key]['woocomerceId'] = $result;
} else { } else {
foreach ($wcOrder->get_items() as $orderItem) { foreach ($wcOrder->get_items() as $wcOrderItem) {
if ( if (
isset($this->retailcrmSettings['bind_by_sku']) isset($this->retailcrmSettings['bind_by_sku'])
&& $this->retailcrmSettings['bind_by_sku'] == WC_Retailcrm_Base::YES && $this->retailcrmSettings['bind_by_sku'] == WC_Retailcrm_Base::YES
) { ) {
$offerId = $item['offer']['xmlId']; $offerId = $crmProduct['offer']['xmlId'];
} elseif ($orderItem['variation_id'] != 0) { } elseif ($wcOrderItem['variation_id'] != 0) {
$offerId = $orderItem['variation_id']; $offerId = $wcOrderItem['variation_id'];
} else { } else {
$offerId = $orderItem['product_id']; $offerId = $wcOrderItem['product_id'];
} }
if (isset($item['externalIds'])) { if (isset($crmProduct['externalIds'])) {
foreach ($item['externalIds'] as $externalId) { foreach ($crmProduct['externalIds'] as $externalId) {
if ($externalId['code'] == 'woocomerce') { if ($externalId['code'] == 'woocomerce') {
$itemExternalId = explode('_', $externalId['value']); $itemExternalId = explode('_', $externalId['value']);
} }
} }
} else { } else {
$itemExternalId = explode('_', $item['externalId']); $itemExternalId = explode('_', $crmProduct['externalId']);
} }
if ( if (
$offerId == $item['offer'][$this->bindField] $offerId == $crmProduct['offer'][$this->bindField]
&& (isset($itemExternalId) && $itemExternalId[1] == $orderItem->get_id()) && (isset($itemExternalId) && $itemExternalId[1] == $wcOrderItem->get_id())
) { ) {
$this->deleteOrUpdateOrderItem($item, $orderItem, $itemExternalId[1]); if (isset($crmProduct['delete']) && $crmProduct['delete'] == true) {
wc_delete_order_item($itemExternalId[1]);
}
$this->updateProductInWcOrder($wcOrderItem, $crmProduct);
} }
} }
} }
@ -599,40 +612,6 @@ if (!class_exists('WC_Retailcrm_History')) :
return $wcOrder->get_id(); return $wcOrder->get_id();
} }
/**
* @param array $item
* @param \WC_Order_Item $orderItem
* @param string $orderItemId
*
* @throws \Exception
*/
private function deleteOrUpdateOrderItem($item, $orderItem, $orderItemId)
{
if (isset($item['delete']) && $item['delete'] == true) {
wc_delete_order_item($orderItemId);
} else {
if (isset($item['quantity']) && $item['quantity']) {
$orderItem->set_quantity($item['quantity']);
$product = retailcrm_get_wc_product($item['offer'][$this->bindField], $this->retailcrmSettings);
$orderItem->set_subtotal($product->get_price());
$dataStore = $orderItem->get_data_store();
$dataStore->update($orderItem);
}
if (isset($item['summ']) && $item['summ']) {
$orderItem->set_total($item['summ']);
$dataStore = $orderItem->get_data_store();
$dataStore->update($orderItem);
}
}
}
/** /**
* Create order in WC * Create order in WC
* *
@ -700,7 +679,13 @@ if (!class_exists('WC_Retailcrm_History')) :
if (!empty($order['contact']['address'])) { if (!empty($order['contact']['address'])) {
$billingAddress = $order['contact']['address']; $billingAddress = $order['contact']['address'];
} else { } else {
WC_Retailcrm_Logger::add(sprintf('[%d] => %s', $order['id'], 'Error: Contact address is empty')); WC_Retailcrm_Logger::add(
sprintf(
'[%d] => %s',
$order['id'],
'Error: Contact address is empty'
)
);
} }
if (self::noRealDataInEntity($contactOrCustomer)) { if (self::noRealDataInEntity($contactOrCustomer)) {
@ -802,22 +787,24 @@ if (!class_exists('WC_Retailcrm_History')) :
$wcOrder->set_address($addressBilling, 'billing'); $wcOrder->set_address($addressBilling, 'billing');
$wcOrder->set_address($addressShipping, 'shipping'); $wcOrder->set_address($addressShipping, 'shipping');
$productData = $order['items'] ?? []; $crmOrderItems = $order['items'] ?? [];
if ($productData) { if ($crmOrderItems) {
foreach ($productData as $key => $product) { foreach ($crmOrderItems as $key => $crmProduct) {
if (isset($product['delete']) && $product['delete'] == true) { if (isset($crmProduct['delete']) && $crmProduct['delete'] == true) {
continue; continue;
} }
$arItemsNew = []; $arItemsNew = [];
$arItemsOld = []; $arItemsOld = [];
$item = retailcrm_get_wc_product($product['offer'][$this->bindField], $this->retailcrmSettings); $wcProduct = retailcrm_get_wc_product(
$crmProduct['offer'][$this->bindField],
$this->retailcrmSettings
);
if (!$item) { if (!$wcProduct) {
$logger = new WC_Logger(); WC_Retailcrm_Logger::add('Product not found by ' . $this->bindField);
$logger->add('retailcrm', 'Product not found by ' . $this->bindField);
continue; continue;
} }
@ -825,26 +812,7 @@ if (!class_exists('WC_Retailcrm_History')) :
$arItemsOld[$orderItemId] = $orderItemId; $arItemsOld[$orderItemId] = $orderItemId;
} }
$wcOrder->add_product( $this->addProductInWcOrder($wcOrder, $wcProduct, $crmProduct);
$item,
$product['quantity'],
[
'subtotal' => wc_get_price_excluding_tax(
$item,
[
'price' => $product['initialPrice'],
'qty' => $product['quantity'],
]
),
'total' => wc_get_price_excluding_tax(
$item,
[
'price' => $product['initialPrice'] - $product['discountTotal'],
'qty' => $product['quantity'],
]
),
]
);
foreach ($wcOrder->get_items() as $orderItemId => $orderItem) { foreach ($wcOrder->get_items() as $orderItemId => $orderItem) {
$arItemsNew[$orderItemId] = $orderItemId; $arItemsNew[$orderItemId] = $orderItemId;
@ -1021,6 +989,87 @@ if (!class_exists('WC_Retailcrm_History')) :
} }
} }
/**
* Add product in WC order.
*
* @param $wcOrder
* @param $wcProduct
* @param $crmProduct
*
* @return void
*/
private function addProductInWcOrder($wcOrder, $wcProduct, $crmProduct)
{
$discountTotal = $crmProduct['discountTotal'];
$productQuantity = $crmProduct['quantity'];
$wcOrder->add_product(
$wcProduct,
$productQuantity,
[
'total' => $this->getProductTotalPrice($wcProduct, $productQuantity, $discountTotal),
'subtotal' => $this->getProductSubTotalPrice($wcProduct, $productQuantity),
]
);
}
/**
* Update product in WC order.
*
* @param $wcOrderItem
* @param $crmProduct
*
* @return void
*/
private function updateProductInWcOrder($wcOrderItem, $crmProduct)
{
if (!empty($crmProduct['quantity'])) {
$wcProduct = retailcrm_get_wc_product($crmProduct['offer'][$this->bindField], $this->retailcrmSettings);
$productQuantity = $crmProduct['quantity'];
$subTotal = $this->getProductSubTotalPrice($wcProduct, $productQuantity);
$wcOrderItem->set_quantity($productQuantity);
$wcOrderItem->set_subtotal($subTotal);
$wcOrderItem->save();
}
// Be aware that discounts may be added.
if (!empty($crmProduct['summ'])) {
if (wc_tax_enabled()) {
$shippingTaxClass = get_option('woocommerce_shipping_tax_class');
$wcOrder = wc_get_order($wcOrderItem->get_order_id());
$itemRate = $shippingTaxClass == 'inherit'
? getOrderItemRate($wcOrder)
: getShippingRate();
$itemPrice = calculatePriceExcludingTax($crmProduct['summ'], $itemRate);
$wcOrderItem->set_total($itemPrice);
} else {
$wcOrderItem->set_total($crmProduct['summ']);
}
$wcOrderItem->save();
}
}
private function getProductSubTotalPrice($wcProduct, $quantity)
{
return wc_get_price_excluding_tax($wcProduct, ['qty' => $quantity]);
}
private function getProductTotalPrice($wcProduct, $quantity, $discountTotal)
{
return wc_get_price_excluding_tax(
$wcProduct,
[
'qty' => $quantity,
'price' => $wcProduct->get_price() - $discountTotal,
]
);
}
/** /**
* Handle customer data change (from individual to corporate, company change, etc) * Handle customer data change (from individual to corporate, company change, etc)
* *
@ -1151,9 +1200,7 @@ if (!class_exists('WC_Retailcrm_History')) :
return $deliveryCost; return $deliveryCost;
} }
$decimalPlaces = wc_get_price_decimals(); return calculatePriceExcludingTax($deliveryCost, $rate);
return round($deliveryCost / (1 + $rate / 100), $decimalPlaces);
} }
/** /**

View File

@ -383,7 +383,7 @@ if (!class_exists('WC_Retailcrm_Orders')) :
$shippingTaxClass = get_option('woocommerce_shipping_tax_class'); $shippingTaxClass = get_option('woocommerce_shipping_tax_class');
$rate = $shippingTaxClass == 'inherit' $rate = $shippingTaxClass == 'inherit'
? $this->getOrderItemRate($order) ? getOrderItemRate($order)
: getShippingRate(); : getShippingRate();
if ($rate !== null) { if ($rate !== null) {
@ -506,20 +506,6 @@ if (!class_exists('WC_Retailcrm_Orders')) :
return $this->payment; return $this->payment;
} }
/**
* @return mixed
*/
private function getOrderItemRate($order)
{
$orderItemTax = $order->get_taxes();
if (is_array($orderItemTax)) {
$orderItemTax = array_shift($orderItemTax);
}
return $orderItemTax instanceof WC_Order_Item_Tax ? $orderItemTax->get_rate_percent() : null;
}
/** /**
* Returns true if provided order is for corporate customer * Returns true if provided order is for corporate customer
* *

View File

@ -171,6 +171,29 @@ function getShippingRate()
return $shippingRates['rate'] ?? $shippingRates; return $shippingRates['rate'] ?? $shippingRates;
} }
/**
* Get order item rate.
*
* @return mixed
*/
function getOrderItemRate($wcOrder)
{
$orderItemTax = $wcOrder->get_taxes();
if (is_array($orderItemTax)) {
$orderItemTax = array_shift($orderItemTax);
}
return $orderItemTax instanceof WC_Order_Item_Tax ? $orderItemTax->get_rate_percent() : null;
}
function calculatePriceExcludingTax($priceIncludingTax, $rate)
{
$decimalPlaces = wc_get_price_decimals();
return round($priceIncludingTax / (1 + $rate / 100), $decimalPlaces);
}
/** /**
* Write base logs in retailcrm file. * Write base logs in retailcrm file.
* *

View File

@ -15,7 +15,7 @@ class WC_Retailcrm_Order extends WC_Retailcrm_Abstracts_Data
/** @var bool */ /** @var bool */
public $is_new = true; public $is_new = true;
protected $data = array( protected $data = [
'externalId' => 0, 'externalId' => 0,
'status' => '', 'status' => '',
'number' => '', 'number' => '',
@ -28,12 +28,12 @@ class WC_Retailcrm_Order extends WC_Retailcrm_Abstracts_Data
'paymentStatus' => '', 'paymentStatus' => '',
'phone' => '', 'phone' => '',
'countryIso' => '' 'countryIso' => ''
); ];
/** /**
* @var array * @var array
*/ */
protected $settings = array(); protected $settings = [];
/** /**
* WC_Retailcrm_Order constructor. * WC_Retailcrm_Order constructor.
@ -62,7 +62,7 @@ class WC_Retailcrm_Order extends WC_Retailcrm_Abstracts_Data
$dateCreate = $order->get_date_created(); $dateCreate = $order->get_date_created();
$data = array( $data = [
'externalId' => $order->get_id(), 'externalId' => $order->get_id(),
'createdAt' => !empty($dateCreate) ? $dateCreate->date('Y-m-d H:i:s') : date('Y-m-d H:i:s'), 'createdAt' => !empty($dateCreate) ? $dateCreate->date('Y-m-d H:i:s') : date('Y-m-d H:i:s'),
'firstName' => $firstName, 'firstName' => $firstName,
@ -71,7 +71,7 @@ class WC_Retailcrm_Order extends WC_Retailcrm_Abstracts_Data
'customerComment' => $order->get_customer_note(), 'customerComment' => $order->get_customer_note(),
'phone' => $order->get_billing_phone(), 'phone' => $order->get_billing_phone(),
'countryIso' => $order->get_shipping_country() 'countryIso' => $order->get_shipping_country()
); ];
if ($data['countryIso'] == '--' || empty($data['countryIso'])) { if ($data['countryIso'] == '--' || empty($data['countryIso'])) {
$countries = new WC_Countries(); $countries = new WC_Countries();
@ -103,7 +103,7 @@ class WC_Retailcrm_Order extends WC_Retailcrm_Abstracts_Data
public function reset_data() public function reset_data()
{ {
$this->data = array( $this->data = [
'externalId' => '', 'externalId' => '',
'status' => '', 'status' => '',
'number' => '', 'number' => '',
@ -116,6 +116,6 @@ class WC_Retailcrm_Order extends WC_Retailcrm_Abstracts_Data
'paymentStatus' => '', 'paymentStatus' => '',
'phone' => '', 'phone' => '',
'countryIso' => '' 'countryIso' => ''
); ];
} }
} }

View File

@ -5,7 +5,7 @@ Tags: Интеграция, Simla.com, simla
Requires PHP: 5.6 Requires PHP: 5.6
Requires at least: 5.3 Requires at least: 5.3
Tested up to: 6.0 Tested up to: 6.0
Stable tag: 4.4.8 Stable tag: 4.4.9
License: GPLv1 or later License: GPLv1 or later
License URI: http://www.gnu.org/licenses/gpl-1.0.html 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 == == Changelog ==
= 4.4.9 =
* Fix bug with product tax
= 4.4.8 = = 4.4.8 =
* Fix a critical bug when working with taxes * Fix a critical bug when working with taxes

View File

@ -5,7 +5,7 @@
* Description: Integration plugin for WooCommerce & Simla.com * Description: Integration plugin for WooCommerce & Simla.com
* Author: RetailDriver LLC * Author: RetailDriver LLC
* Author URI: http://retailcrm.pro/ * Author URI: http://retailcrm.pro/
* Version: 4.4.8 * Version: 4.4.9
* Tested up to: 6.0 * Tested up to: 6.0
* WC requires at least: 5.4 * WC requires at least: 5.4
* WC tested up to: 6.7 * WC tested up to: 6.7

View File

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

View File

@ -208,10 +208,6 @@ class WC_Retailcrm_History_Test extends WC_Retailcrm_Test_Case_Helper
$this->assertNotEquals($sinceId, $oldSinceId); $this->assertNotEquals($sinceId, $oldSinceId);
$this->assertEquals(0, get_option('retailcrm_customers_history_since_id')); $this->assertEquals(0, get_option('retailcrm_customers_history_since_id'));
// Check added products
$this->assertEquals(2, $wcOrderItem->get_quantity());
$this->assertEquals($product->get_id(), $wcOrderItem->get_product()->get_id());
} }
public function test_history_order_update() public function test_history_order_update()