diff --git a/CHANGELOG.md b/CHANGELOG.md index b56b849..9008b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2023-08-31 4.6.11 +* Added the ability to work with coupons through the CRM system + ## 2023-07-19 4.6.10 * Abandoned cart transfer fix diff --git a/VERSION b/VERSION index e26a327..4381da6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.6.10 \ No newline at end of file +4.6.11 \ No newline at end of file diff --git a/resources/pot/retailcrm-es_ES.pot b/resources/pot/retailcrm-es_ES.pot index 8e72c43..fb4510f 100644 --- a/resources/pot/retailcrm-es_ES.pot +++ b/resources/pot/retailcrm-es_ES.pot @@ -124,6 +124,21 @@ msgstr "Ajustes del stock" msgid "Statuses" msgstr "Los estados" +msgid "Coupon" +msgstr "Cupón" + +msgid "When working with coupons via CRM, it is impossible to transfer manual discounts." +msgstr "El trabajo con cupones a través del CRM no permite transferir descuentos manuales." + +msgid "The user field must be in the String or Text format." +msgstr "El campo personalizado debe tener el formato Hilo o Texto." + +msgid "When using multiple coupons, separation is supported using spaces, line breaks, characters `;` `,`." +msgstr "Si se usan varios cupones, es posible separarlos por espacios, nueva línea o caracteres `;` `,`." + +msgid "For example: code_coupon_1; code_coupon_2, code_coupon_3 code_coupon_4" +msgstr "Por ejemplo, code_coupon_1; code_coupon_2, code_coupon_3 code_coupon_4" + msgid "Payment types" msgstr "Métodos de pago" diff --git a/resources/pot/retailcrm-ru_RU.pot b/resources/pot/retailcrm-ru_RU.pot index cbfb439..9c4d653 100644 --- a/resources/pot/retailcrm-ru_RU.pot +++ b/resources/pot/retailcrm-ru_RU.pot @@ -133,6 +133,21 @@ msgstr "Настройка управления остатками" msgid "Statuses" msgstr "Статусы" +msgid "Coupon" +msgstr "Купон" + +msgid "When working with coupons via CRM, it is impossible to transfer manual discounts." +msgstr "При работе с купонами через CRM невозможно передавать ручные скидки." + +msgid "The user field must be in the String or Text format." +msgstr "Пользовательское поле должно быть формата Строка или Текст." + +msgid "When using multiple coupons, separation is supported using spaces, line breaks, characters `;` `,`." +msgstr "При использовании нескольких купонов, поддерживается разделение с помощью пробелов, переноса строки, символами `;` `,`." + +msgid "For example: code_coupon_1; code_coupon_2, code_coupon_3 code_coupon_4" +msgstr "Например: code_coupon_1; code_coupon_2, code_coupon_3 code_coupon_4" + msgid "Payment types" msgstr "Способы оплаты" diff --git a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php index b73fff2..076ae69 100644 --- a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php +++ b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php @@ -341,6 +341,52 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration } } + /** + * Coupon options + */ + $coupon_option_list = ['not-upload' => __("Don't send to CRM", 'retailcrm')]; + $retailcrm_metaFiels_list = $this->apiClient->customFieldsList( + ['entity' => 'order', 'type' => ['string', 'text']] + ); + + if (!empty($retailcrm_metaFiels_list) && $retailcrm_metaFiels_list->isSuccessful()) { + foreach ($retailcrm_metaFiels_list['customFields'] as $retailcrm_metaField) { + $coupon_option_list[$retailcrm_metaField['code']] = $retailcrm_metaField['name']; + } + + $this->form_fields[] = [ + 'title' => __("Coupon", 'retailcrm'), + 'type' => 'heading', + 'description' => '', + 'id' => 'coupon_options' + ]; + + $this->form_fields['coupon_notification'] = [ + 'id' => 'coupon_options', + 'css' => 'max-width:400px;resize: none;height:215px;', + 'type' => 'textarea', + 'title' => __('Attention!', 'retailcrm'), + 'value' => '', + 'placeholder' => __('When working with coupons via CRM, it is impossible to transfer manual discounts.', 'retailcrm') . + PHP_EOL . PHP_EOL . + __('The user field must be in the String or Text format.', 'retailcrm') . + PHP_EOL . + __('When using multiple coupons, separation is supported using spaces, line breaks, characters `;` `,`.', 'retailcrm') . + PHP_EOL . + __('For example: code_coupon_1; code_coupon_2, code_coupon_3 code_coupon_4', 'retailcrm'), + 'custom_attributes' => ['readonly' => 'readonly'], + ]; + + $this->form_fields['woo_coupon_apply_field'] = [ + 'title' => __('Coupon', 'retailcrm'), + 'css' => 'min-width:350px;', + 'class' => 'select', + 'type' => 'select', + 'options' => $coupon_option_list, + 'desc_tip' => true, + ]; + } + /** * Meta data options */ diff --git a/src/include/class-wc-retailcrm-history.php b/src/include/class-wc-retailcrm-history.php index 86c9595..f9d6b03 100644 --- a/src/include/class-wc-retailcrm-history.php +++ b/src/include/class-wc-retailcrm-history.php @@ -31,6 +31,9 @@ if (!class_exists('WC_Retailcrm_History')) : /** @var string */ protected $bindField = 'externalId'; + /** @var bool */ + protected $recalculateCoupons = false; + /** * WC_Retailcrm_History constructor. * @@ -270,19 +273,30 @@ if (!class_exists('WC_Retailcrm_History')) : $this->updateMetaData($customFields, $order, $wcOrder); $wcOrderNumber = $wcOrder->get_order_number(); + $orderEditData = []; if ( $order['number'] != $wcOrderNumber && isset($this->retailcrmSettings['update_number']) && $this->retailcrmSettings['update_number'] == WC_Retailcrm_Base::YES ) { - $this->retailcrm->ordersEdit( - ['id' => $order['id'], 'number' => $wcOrderNumber], - 'id' - ); + $orderEditData['number'] = $wcOrderNumber; + } + + $items = $this->updateItemsForUsedCoupons($orderHistory, $wcOrder); + + if (!empty($items)) { + $orderEditData['items'] = $items; + $orderEditData['discountManualAmount'] = 0; + $orderEditData['discountManualPercent'] = 0; + } + + if (!empty($orderEditData)) { + $orderEditData['id'] = $order['id']; + + $this->retailcrm->ordersEdit($orderEditData, 'id'); } } - // @codeCoverageIgnoreStart } catch (Exception $exception) { WC_Retailcrm_Logger::add( sprintf( @@ -294,7 +308,6 @@ if (!class_exists('WC_Retailcrm_History')) : continue; } - // @codeCoverageIgnoreEnd } } else { break; @@ -454,6 +467,8 @@ if (!class_exists('WC_Retailcrm_History')) : } if (array_key_exists('items', $order)) { + $this->recalculateCoupons = true; + foreach ($order['items'] as $key => $crmProduct) { if (!isset($crmProduct['offer'][$this->bindField])) { continue; @@ -999,6 +1014,72 @@ if (!class_exists('WC_Retailcrm_History')) : } } + /** + * Checks use coupons and updates offers + * + * @param array $orderHistory + * @param array $wcOrder + * + * @return array + */ + private function updateItemsForUsedCoupons($orderHistory, $wcOrder) + { + $couponField = $this->retailcrmSettings['woo_coupon_apply_field']; + + if ($couponField === 'not-upload') { + return []; + } + + $rewriteItems = false; + $wcOrderCoupons = $wcOrder->get_coupon_codes(); + + if (isset($orderHistory['customFields']) + && array_key_exists($couponField, $orderHistory['customFields']) + && empty($orderHistory['customFields'][$couponField]) + && $wcOrderCoupons + ) { + foreach ($wcOrderCoupons as $code) { + $wcOrder->remove_coupon($code); + + $rewriteItems = true; + } + } + + if (!empty($orderHistory['customFields'][$couponField])) { + $masCoupons = preg_split("/[\s,;]+/", $orderHistory['customFields'][$couponField]); + + foreach (array_diff($masCoupons, $wcOrderCoupons) as $coupon) { + $wcOrder->apply_coupon($coupon); + + $rewriteItems = true; + } + + foreach (array_diff($wcOrderCoupons, $masCoupons) as $coupon) { + $wcOrder->remove_coupon($coupon); + + $rewriteItems = true; + } + } + + if (($rewriteItems || $this->recalculateCoupons) + && ($wcOrderCoupons || !empty($orderHistory['customFields'][$couponField]))) { + $wcOrder->recalculate_coupons(); + + $orderItem = new WC_Retailcrm_Order_Item($this->retailcrmSettings); + $orderItems = []; + + foreach ($wcOrder->get_items() as $item) { + $orderItems[] = $orderItem->build($item)->getData(); + + $orderItem->resetData(); + } + + return $orderItems; + } + + return []; + } + /** * Returns data for address_1 and address_2(if exist data for this field) for WC order. * diff --git a/src/include/class-wc-retailcrm-orders.php b/src/include/class-wc-retailcrm-orders.php index e543c2c..d7261d3 100644 --- a/src/include/class-wc-retailcrm-orders.php +++ b/src/include/class-wc-retailcrm-orders.php @@ -435,6 +435,20 @@ if (!class_exists('WC_Retailcrm_Orders')) : } } + $couponCustomField = $this->retailcrm_settings['woo_coupon_apply_field']; + + if ($couponCustomField !== 'not-upload') { + $codeCoupons = []; + + foreach ($order->get_coupons() as $coupon) { + if (!empty($coupon->get_code())) { + $codeCoupons[] = $coupon->get_code(); + } + } + + $orderData['customFields'][$couponCustomField] = implode('; ', $codeCoupons); + } + $this->order = WC_Retailcrm_Plugin::clearArray($orderData); $this->processOrderCustomerInfo($order, $update); diff --git a/src/languages/retailcrm-es_ES.mo b/src/languages/retailcrm-es_ES.mo index 1d0853c..082c4b3 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.mo b/src/languages/retailcrm-ru_RU.mo index 60c038b..f8c2000 100644 Binary files a/src/languages/retailcrm-ru_RU.mo and b/src/languages/retailcrm-ru_RU.mo differ diff --git a/src/readme.txt b/src/readme.txt index 388e8e5..1ba4236 100644 --- a/src/readme.txt +++ b/src/readme.txt @@ -5,7 +5,7 @@ Tags: Интеграция, Simla.com, simla Requires PHP: 7.0 Requires at least: 5.3 Tested up to: 6.2 -Stable tag: 4.6.10 +Stable tag: 4.6.11 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.6.11 = +* Added the ability to work with coupons through the CRM system + = 4.6.10 = * Abandoned cart transfer fix diff --git a/src/retailcrm.php b/src/retailcrm.php index cedfb0d..c55b08e 100644 --- a/src/retailcrm.php +++ b/src/retailcrm.php @@ -5,7 +5,7 @@ * Description: Integration plugin for WooCommerce & Simla.com * Author: RetailDriver LLC * Author URI: http://retailcrm.pro/ - * Version: 4.6.10 + * Version: 4.6.11 * Tested up to: 6.2 * WC requires at least: 5.4 * WC tested up to: 7.8 diff --git a/src/uninstall.php b/src/uninstall.php index 44a93bc..dab4ce7 100644 --- a/src/uninstall.php +++ b/src/uninstall.php @@ -16,7 +16,7 @@ * * @link https://wordpress.org/plugins/woo-retailcrm/ * - * @version 4.6.10 + * @version 4.6.11 * * @package RetailCRM */ diff --git a/tests/helpers/class-wc-retailcrm-test-case-helper.php b/tests/helpers/class-wc-retailcrm-test-case-helper.php index 7b1ebbe..4b46519 100644 --- a/tests/helpers/class-wc-retailcrm-test-case-helper.php +++ b/tests/helpers/class-wc-retailcrm-test-case-helper.php @@ -79,6 +79,7 @@ class WC_Retailcrm_Test_Case_Helper extends WC_Unit_Test_Case ), 'product_description' => 'full', 'stores_for_uploading' => ['woocommerce', 'main'], + 'woo_coupon_apply_field' => 'testField', ]; update_option(WC_Retailcrm_Base::$option_key, $options); diff --git a/tests/test-wc-retailcrm-orders.php b/tests/test-wc-retailcrm-orders.php index c1889b6..4aba7a9 100644 --- a/tests/test-wc-retailcrm-orders.php +++ b/tests/test-wc-retailcrm-orders.php @@ -120,6 +120,7 @@ class WC_Retailcrm_Orders_Test extends WC_Retailcrm_Test_Case_Helper $this->assertEquals($orderData['customFields']['crm_order'], 'test_custom_fields'); $this->assertEquals($orderData['customerComment'], 'crm_customer_comment_test'); $this->assertEquals($orderData['delivery']['address']['text'], 'crm_address_text_test'); + $this->assertEquals($orderData['customFields']['testField'], 'test1; test2'); } else { $this->assertEquals(null, $order); } @@ -596,6 +597,11 @@ class WC_Retailcrm_Orders_Test extends WC_Retailcrm_Test_Case_Helper { /** @var WC_Order order */ $this->order = WC_Helper_Order::create_order(0); + $coupon1 = WC_Helper_Coupon::create_coupon('test1'); + $coupon2 = WC_Helper_Coupon::create_coupon('test2'); + + $this->order->apply_coupon($coupon1); + $this->order->apply_coupon($coupon2); foreach ($this->order->get_address('billing') as $prop => $value) { if (method_exists($this->order, 'set_shipping_' . $prop)) {