1
0
mirror of synced 2025-03-21 23:53:59 +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
* 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) {
WC_Retailcrm_Logger::add(
sprintf(
"[%s] - %s",
'[%s] - %s',
$exception->getMessage(),
'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'])) {
$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) {
$shipping->set_instance_id($order['delivery']['service']['code']);
@ -446,25 +449,31 @@ if (!class_exists('WC_Retailcrm_History')) :
}
if (array_key_exists('items', $order)) {
foreach ($order['items'] as $key => $item) {
if (!isset($item['offer'][$this->bindField])) {
foreach ($order['items'] as $key => $crmProduct) {
if (!isset($crmProduct['offer'][$this->bindField])) {
continue;
}
if (isset($item['create']) && $item['create'] == true) {
if (isset($crmProduct['create']) && $crmProduct['create'] == true) {
$arItemsNew = [];
$arItemsOld = [];
$product = retailcrm_get_wc_product(
$item['offer'][$this->bindField],
$wcProduct = retailcrm_get_wc_product(
$crmProduct['offer'][$this->bindField],
$this->retailcrmSettings
);
if (!$wcProduct) {
WC_Retailcrm_Logger::add('Product not found by ' . $this->bindField);
continue;
}
foreach ($wcOrder->get_items() as $orderItemId => $orderItem) {
$arItemsOld[$orderItemId] = $orderItemId;
}
if (isset($item['externalIds'])) {
foreach ($item['externalIds'] as $externalId) {
if (isset($crmProduct['externalIds'])) {
foreach ($crmProduct['externalIds'] as $externalId) {
if ($externalId['code'] == 'woocomerce') {
$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) {
$arItemsNew[$orderItemId] = $orderItemId;
@ -486,33 +495,37 @@ if (!class_exists('WC_Retailcrm_History')) :
$order['items'][$key]['woocomerceId'] = $result;
} else {
foreach ($wcOrder->get_items() as $orderItem) {
foreach ($wcOrder->get_items() as $wcOrderItem) {
if (
isset($this->retailcrmSettings['bind_by_sku'])
&& $this->retailcrmSettings['bind_by_sku'] == WC_Retailcrm_Base::YES
) {
$offerId = $item['offer']['xmlId'];
} elseif ($orderItem['variation_id'] != 0) {
$offerId = $orderItem['variation_id'];
$offerId = $crmProduct['offer']['xmlId'];
} elseif ($wcOrderItem['variation_id'] != 0) {
$offerId = $wcOrderItem['variation_id'];
} else {
$offerId = $orderItem['product_id'];
$offerId = $wcOrderItem['product_id'];
}
if (isset($item['externalIds'])) {
foreach ($item['externalIds'] as $externalId) {
if (isset($crmProduct['externalIds'])) {
foreach ($crmProduct['externalIds'] as $externalId) {
if ($externalId['code'] == 'woocomerce') {
$itemExternalId = explode('_', $externalId['value']);
}
}
} else {
$itemExternalId = explode('_', $item['externalId']);
$itemExternalId = explode('_', $crmProduct['externalId']);
}
if (
$offerId == $item['offer'][$this->bindField]
&& (isset($itemExternalId) && $itemExternalId[1] == $orderItem->get_id())
$offerId == $crmProduct['offer'][$this->bindField]
&& (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();
}
/**
* @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
*
@ -700,7 +679,13 @@ if (!class_exists('WC_Retailcrm_History')) :
if (!empty($order['contact']['address'])) {
$billingAddress = $order['contact']['address'];
} 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)) {
@ -802,22 +787,24 @@ if (!class_exists('WC_Retailcrm_History')) :
$wcOrder->set_address($addressBilling, 'billing');
$wcOrder->set_address($addressShipping, 'shipping');
$productData = $order['items'] ?? [];
$crmOrderItems = $order['items'] ?? [];
if ($productData) {
foreach ($productData as $key => $product) {
if (isset($product['delete']) && $product['delete'] == true) {
if ($crmOrderItems) {
foreach ($crmOrderItems as $key => $crmProduct) {
if (isset($crmProduct['delete']) && $crmProduct['delete'] == true) {
continue;
}
$arItemsNew = [];
$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) {
$logger = new WC_Logger();
$logger->add('retailcrm', 'Product not found by ' . $this->bindField);
if (!$wcProduct) {
WC_Retailcrm_Logger::add('Product not found by ' . $this->bindField);
continue;
}
@ -825,26 +812,7 @@ if (!class_exists('WC_Retailcrm_History')) :
$arItemsOld[$orderItemId] = $orderItemId;
}
$wcOrder->add_product(
$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'],
]
),
]
);
$this->addProductInWcOrder($wcOrder, $wcProduct, $crmProduct);
foreach ($wcOrder->get_items() as $orderItemId => $orderItem) {
$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)
*
@ -1151,9 +1200,7 @@ if (!class_exists('WC_Retailcrm_History')) :
return $deliveryCost;
}
$decimalPlaces = wc_get_price_decimals();
return round($deliveryCost / (1 + $rate / 100), $decimalPlaces);
return calculatePriceExcludingTax($deliveryCost, $rate);
}
/**

View File

@ -383,7 +383,7 @@ if (!class_exists('WC_Retailcrm_Orders')) :
$shippingTaxClass = get_option('woocommerce_shipping_tax_class');
$rate = $shippingTaxClass == 'inherit'
? $this->getOrderItemRate($order)
? getOrderItemRate($order)
: getShippingRate();
if ($rate !== null) {
@ -506,20 +506,6 @@ if (!class_exists('WC_Retailcrm_Orders')) :
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
*

View File

@ -171,6 +171,29 @@ function getShippingRate()
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.
*

View File

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

View File

@ -5,7 +5,7 @@ Tags: Интеграция, Simla.com, simla
Requires PHP: 5.6
Requires at least: 5.3
Tested up to: 6.0
Stable tag: 4.4.8
Stable tag: 4.4.9
License: GPLv1 or later
License URI: http://www.gnu.org/licenses/gpl-1.0.html
@ -82,6 +82,9 @@ Asegúrate de tener una clave API específica para cada tienda. Las siguientes i
== Changelog ==
= 4.4.9 =
* Fix bug with product tax
= 4.4.8 =
* Fix a critical bug when working with taxes

View File

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

View File

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

View File

@ -208,10 +208,6 @@ class WC_Retailcrm_History_Test extends WC_Retailcrm_Test_Case_Helper
$this->assertNotEquals($sinceId, $oldSinceId);
$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()