From 28d81a0ba74ed1f69f7336a4d9f36abfe4fdee61 Mon Sep 17 00:00:00 2001 From: Uryvskiy Dima Date: Tue, 3 Oct 2023 12:18:48 +0300 Subject: [PATCH] ref #92047 Added currency validation --- CHANGELOG.md | 3 ++ Makefile | 2 +- VERSION | 2 +- resources/pot/retailcrm-es_ES.pot | 8 ++- resources/pot/retailcrm-ru_RU.pot | 6 +++ .../class-wc-retailcrm-abstracts-settings.php | 46 +++++++++++++++--- src/languages/retailcrm-es_ES.mo | Bin 12902 -> 13327 bytes src/languages/retailcrm-ru_RU.mo | Bin 15923 -> 16456 bytes src/readme.txt | 2 +- src/retailcrm.php | 2 +- src/uninstall.php | 2 +- tests/datasets/data-base-retailcrm.php | 8 +++ tests/test-wc-retailcrm-base.php | 16 +++++- 13 files changed, 83 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9008b43..add7146 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2023-10-02 4.6.12 +* Added currency verification when configuring the module + ## 2023-08-31 4.6.11 * Added the ability to work with coupons through the CRM system diff --git a/Makefile b/Makefile index e3a8fed..1faab50 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ local_test: run_tests: docker-compose --no-ansi up -d --build mysql docker-compose --no-ansi run --rm --no-deps app make local_test - docker-compose stop + docker-compose down -v coverage: wget https://phar.phpunit.de/phpcov-2.0.2.phar && php phpcov-2.0.2.phar merge coverage/ --clover coverage.xml diff --git a/VERSION b/VERSION index 4381da6..42c7f00 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.6.11 \ No newline at end of file +4.6.12 \ No newline at end of file diff --git a/resources/pot/retailcrm-es_ES.pot b/resources/pot/retailcrm-es_ES.pot index fb4510f..19988df 100644 --- a/resources/pot/retailcrm-es_ES.pot +++ b/resources/pot/retailcrm-es_ES.pot @@ -437,4 +437,10 @@ msgid "Select warehouses to receive balances from CRM. To select several warehou msgstr "Selecciona los almacenes para recibir el stock desde CRM. Para seleccionar varios mantén pulsado CTRL (para Windows y Linux) o ⌘ Command (para MacOS)" msgid "I agree to receive promotional newsletters" -msgstr "Estoy de acuerdo en recibir los boletines informativos" \ No newline at end of file +msgstr "Estoy de acuerdo en recibir los boletines informativos" + +msgid "API key with one-shop access required" +msgstr "Se requiere clave API con acceso a una tienda" + +msgid "The currency of the site differs from the currency of the store in CRM. For the integration to work correctly, the currencies in CRM and CMS must match" +msgstr "La moneda del sitio web es distinto a la tienda del CRM. Para el funcionamiento correcto de la integración, las monedas del CMS y CRM deben coincid" \ No newline at end of file diff --git a/resources/pot/retailcrm-ru_RU.pot b/resources/pot/retailcrm-ru_RU.pot index 9c4d653..8d45170 100644 --- a/resources/pot/retailcrm-ru_RU.pot +++ b/resources/pot/retailcrm-ru_RU.pot @@ -447,3 +447,9 @@ msgstr "Выберите склады для получения остатков msgid "I agree to receive promotional newsletters" msgstr "Согласен на рекламно-информационные рассылки" + +msgid "API key with one-shop access required" +msgstr "Требуется API ключ с доступом к одному магазину" + +msgid "The currency of the site differs from the currency of the store in CRM. For the integration to work correctly, the currencies in CRM and CMS must match" +msgstr "Валюта сайта отличается от валюты магазина в CRM. Для корректной работы интеграции, валюты в CRM и CMS должны совпадать" diff --git a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php index 076ae69..cadf1ef 100644 --- a/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php +++ b/src/include/abstracts/class-wc-retailcrm-abstracts-settings.php @@ -72,7 +72,6 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration apiClient) { + // The field is highlighted in red if the CRM site is invalid + $this->form_fields['api_key']['class'] = $this->isValidCrmSite($this->apiClient) + ? '' + : 'red-selected-retailcrm'; + if ( isset($_GET['page']) && $_GET['page'] == 'wc-settings' && isset($_GET['tab']) && $_GET['tab'] == 'integration' @@ -816,20 +820,48 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration return $value; } - $api = new WC_Retailcrm_Proxy($this->crmUrl, $value); - $response = $api->apiVersions(); + $isValidCrmSite = $this->isValidCrmSite(new WC_Retailcrm_Proxy($this->crmUrl, $value)); - if (empty($response) || !$response->isSuccessful()) { - $value = ''; + // The field is highlighted in red if the CRM site is invalid + if ($isValidCrmSite) { + $this->form_fields['api_key']['class'] = ''; - WC_Admin_Settings::add_error(esc_html__('Enter the correct API key', 'retailcrm')); - } else { header("Refresh:0"); + } else { + $value = ''; + $this->form_fields['api_key']['class'] = 'red-selected-retailcrm'; } return $value; } + private function isValidCrmSite($api) + { + $errorMessage = ''; + $isValidCrmSite = true; + $response = $api->sitesList(); + + if (empty($response['sites']) || !$response->isSuccessful()) { + $errorMessage = 'Enter the correct API key'; + $isValidCrmSite = false; + } elseif (count($response['sites']) > 1) { + $errorMessage = 'API key with one-shop access required'; + $isValidCrmSite = false; + } else { + $site = current($response['sites']); + + if (get_woocommerce_currency() !== $site['currency']) { + $errorMessage = 'The currency of the site differs from the currency of the store in CRM. For the integration to work correctly, the currencies in CRM and CMS must match'; + $isValidCrmSite = false; + } + } + + if ('' !== $errorMessage) { + WC_Admin_Settings::add_error(esc_html__($errorMessage, 'retailcrm')); + } + + return $isValidCrmSite; + } /** * Validate whatsapp phone number diff --git a/src/languages/retailcrm-es_ES.mo b/src/languages/retailcrm-es_ES.mo index 082c4b3d04c453fb928f1970b6074d5dee0651f8..30154f7d1dff520e05ab0a8d08b4663497b14d3c 100644 GIT binary patch delta 3540 zcmZYBS!`5Q9LMoPZA+nLD_{`>ZiN;Kl&vBliXoAb(~RAIVsa{V;_6u>~K) zz0UWa;uBn-!6nT7 zelcnwt1u56P%}M;6Yws2F`Z7vV;lCQe{+V49{3#R<8P<|Orq6dEI^HTKk}71j+)_l zq)l@P^RdhMK9gyaT{9i^{Q}hc%bjZVE2A^8X|iiyKSzzDv4&fx+f}^nmmEtR?=WpWMcppdL9(Hy%cHnUA!ZG*&`7;?27FrpY zi{%(Xt>p!z4Ksips28&^4i}-0TOld~<*1ZbqXyoJ%H&(fWX(Iy_Z_Iy^&`%}yQrm& zWV2UNMh|gjic~r`l<2kHF4J3onDdkg88Jdf_zZ8|33e<6}L1oyF zTCyf&&qPcc6^;BXYDDKzFMNmm7MUv;?qSR|R7a&uLn&Q@>aY#<-T_pHM^S5h7Ii!? zqEdYub$pYo*!_VxU*~@s75&0BIc`R+?G99jpI{}PLuFt%t&$XzgGzM?YDVQqAI9t4 z--#O7E>uR}N4#`-y1|VKOy(`^ z1rO@{`jC@i+EA%Ig46K~Y6iER`@Q%{bAYWiIc3~3ULM`20)Naq@NN51F99QCAt{ai0niLj(0p=jv!!)7p zN8Y8PHT@Ew#-DKojwHVeu^u(j&yZy`moN_h!an#n>L)gFa_nEVQP`X75=_8VsP@;P zI^K#T+Z;xgDq=2C(JoJ7I%;S%&c3pc?S{z$3Rp);<6|!g!p;G%jYO`ELrS=YLNfOvOJy1oddyQx#wDC3(&l7$k zOsHsoJVK~#Ev*VoME_IMgewW{zi4T8RLAR_`a=q-C_^fXVnmlh)geTqbFap6J}T9$ zO!TLlG@EI}E`nr7{}Tey677GLbK!9mONi$P?fxoa0O2EM5?hGPL_N`$V9OYbm_y7W zRD#5-#7-ifC?m9tZxF=S?Zj$*p|Xw8IbTn_Ow1!xiipvKO>87yBE}J=gi1>c z)8MF`zJXZiT%+Atg2w3E_(NWPlW?P+w%IYyk$ibt^7bR`jponwyT4#us7hh!U3x>5L|D$ z1GMiB`R-G&Ct~q%uturyZ%#MxJrYE=0)nHqi zotw6!^9WcjtKRRj!d~0&ah+@!ai>qDj;VTFmdEyK9$toES6X!C@rJ?-POtbLz7c&Y zI{Z>s&}H#TRlVQM&|P)3$g|GK13aj=oXNSpU!C+%;6})b^+xNws|hrxDji%_+J4^l N(wgUF<%Iaee*sXGpYQ+x delta 3120 zcmY+_Ymk>!9S86O;&NL+R#T|uvbHR{37DE1k`XLITtu)$C=HNHqNH+>O)>wjX%HX; zW3@G-Gm7yhoNTaKeUUG0#vyEKtkh(ta*D=!Vb(-mV6xA5{|^nF+28Xy&-I-1JLmj& z&&_{XUHg60fNvIMw`dl-29)v~PY!ZW-WgiTK)%Z%?AKU|ztZU7QW?z=oWQeqDMxd5 zb$DP6 zjx#?G%U`Se|7PBAkd8b*mLK61uHZ7(W~e-?k`JBa+3a*MsB%5?!dkX*Fa4EX zhberK8Q}?Lj@!>EPIQOvsx%I`ok6Fh*V7}W+kCb0fa>}31mH#Y;vM>aw5;O)cuv|4jK7UF5yEpm8Aa9^lZ7n z0?3PNQ61hXBVp(K{0%y#`(b^U#2ceO}I zw%zK=^=!@l->i~`zQdb%fEoGV@%2=VV^Tbg8Ocm~q+G{bzmw_MJxnHdGVedmbgY+o z{xxRg?{NapaPzF1N{5Q$ESLctj!}*VxweSZfrEf8dX^e$2kDHmf zeU2OWCNJWO57#rZkC!=rgtco_exs5ewrc%a&Z2LYZ!@WWhRM)jW~47Oi}n~Z(n*Gs zDVoXLU&Lf$Ijz64g=z2`yq_=dYR+qu|8$_Itv+{eFb(#zXC`wbFXVJ)zuwM#sGC{U zz042PKe&+1?ez}b%51Z4CWAj_GWByV<=Y&{MIG{QeUzp0YT=hICbj!`IrlRoI9gpl z&TP*Ht*&7!)4&e)@KL6tm;0el19O@Ci<#?dn5pgJVD6}?WZyr`bmSn1@(2g<6=v@K z$gK7z!$=1vR$fI(E2}t*J7~JgFRSbSWTtYobY8(}ypCIV6>Bf5q=!vbjA%yX|*zRslj4N5{e!DO`k;`;Y5V*dY> zIVzcp8`zKO#5R$KKPggnirYojNTwm%cCAQ8Qmz+S*>gqGnqpJ+m9IHk7Uc|apZJpa zg2;5Q%!e)!mx_5}i`XO%=|cRLSbU^VCUYc0y90GP6$KZmFt$TRFc6cZs{Ji%I<`@l~-|+#$Xw zs!}T()v_{IRab6fR%qt*A(4G->dGymNh}bj%4by`6eGpzQx|!I$gaBiv}-e}dMiIA zTEwhOWTVPtF-N3q5D)a#>i-XJRqqm8#rEp@rz=CZm@2ZWcZm_=T5+Ywf=y|zQ|7Z> zd`|2TW3*q^3yZ&eUVL2)6&8Kp56o<)>=xE%-u`@ wA(n`%#X>PejLIJUzcORd-0}0*+;wPS<5NQqeQVSU4TpA)`}?r{Bc?R`7YSG$X8-^I diff --git a/src/languages/retailcrm-ru_RU.mo b/src/languages/retailcrm-ru_RU.mo index f8c20008c9807bc94ca0cba095689209f984805e..4249a72d103a3bdb3201064cc25bd9eb398aa3d3 100644 GIT binary patch delta 3721 zcmZY932anF9LMn~La`ieftG?5Is$?s6hQ@16tHqsD3%sHD^iy&T}yZA?jn@KEiG8E zKm|O|C{Z*R5`)E7<*ecXYSg@^MB*JU&;SY1s8JK+_xJYI5S{ej&&+#o=gs_Q=C!VT zr!FP&RqxJ^7|K@SLZYp+F>m9{H2zWM_b{d_mgB`3!fx1%{Fx{C*Bzh73~a^z_@;mT zOYBAaC+vrR;ULWFY0P+I5@sBgTrSk09@vO^xD)lFBRCUX%*27|#$@9t?1EEJ*Jq&m zDZ^A;hWx}Nus3e>+fU;Kw0C0;?>FyK(PY0tjqDVv!*r&jndG5c!Wi`YAy@AHYJq50!z}u^B%=ZSuQF!}+*8hy1JK1}@OI z*@k4->_+X0*Zl|IL%rx@zkL!lkh3@n|HdJh&kj~bOHt1U@G)G912Kd39Etfj0Lv0o zhEZ9LJY#mCGH?KI!Lz6(n8ps|9cB~ihdZ$ozJ)q|M^PF07?twxQ8VnyPE;l{k;$7J ziEPoOe)8uw!-MyCNCLZ$v) zRHi=huYZrq&{^d8l7I4|RHvfWE)%tR2BT(Bj2h7GsPkTle4|Vl<0;0(P%rwCS`dbdEJn?A4XT45egDAGw7Zc%?Ue}_ z!&x{O-#}&T1nPI$T%>A-;`LaF`hKj#;k@5$rDCxiHL|a9BBrsUuERo91{(1id=%BO zi#%$+MZGYU@3Ve?6|!y2-AFP_EtcZrXz>i*fa#pU#Di33Q>nr)@J^i0j@*vVVF4Cg zl6+w!UPXHwR^x|wIZoiMtFRjNT{wl>WPNF9(~d?Bs1TLm0J8k%#o^?icbE_S2Y*HS zG(9g%ZmzMY8LmUE?F;xFrm#WQ;SabB!<;Gga}w2Y2I-iKBXK%5pfdBm-~J7!(VjSp z{43Rs9O5`0MV8l0U|J!ZhZ?{;sF|MTUlk5u18CE&N5*6xMGgE7SI0d`%+0%fE zFcYg#{jbC=xIN)t7|o9Rj0>fxHO}WF&>KUj4p*WEvJJJS2Qdx5z&?1wzyBwu(;mn= z$&siGOh65EEh-axd=sBjakOS})*yp7YfvxThZ@icEWp9n@(sX+NOsL( z)SCZ-MVQOOEUO9OaomP0aPf8i2MUW*7!+r)8`n!&_Z~X`^SlacgSxQ{IU%M2Q*oDX z3u>URq6YXLD#gE}Qkps`*}fdlr#%sQpO?+qNMa4i^S&9%Kr=Bg!M`np3Yqb~YyrHG zSWc+p211`+l}$;^T4b|(sa@h<6Rf5Q60-=#8nWot7$}u1%%eK zJMjQm%Rh6wt%tq`=R1)im4a8s~F@k@2 z#63hu(Ybzz$RzF~w3{y>&Mgo6joz3~Xd*hE9c2`iImA3-E|Es4bRue1nOt0GtAfL7 z{YtG}8j4riNH{n$RvB4r%L9R6EM}v@nkAuVa6#+UJ}KFRC4JZbzYDEcxrKB3m9_U<-;$ZS|5^+*X&z1C_0|-^tW6XNOzoyzK088=RNj zdUv(kY&Ah=zjMIdqzfBL5j z=cQyyoQLVPS%YnN>%4jFr$Y^EpQYL2>``ZK(`@Svte%Os>bm;??Y$%Z^A@jDp7iph dNi(!pm`{_2+|GzzqsKOWUGHvaJ$z*}?H`K4IdT91 delta 3178 zcmYk;c~F&A7{~Dk(u)WvqNs@4l@wXTU5HFs1QlFD5yDV&NlR43BsbJck-4Us+GJTa zE;CmC6;`&4rM6gEO*xa>j5Ep9I5yg1IZU26=e+m5?>Xl==e&BNKCE$N z=t5kJ9Y)zobS3t+FguEUBKe^7k2Z_I0oWR|kv}WoBMK*ATbzmsxWHXsi|uG{!_K%L zlkf;;swH9%OhbJ?7B!G*I09Fo zW_kqs;GZ}bd(lZcZovrpxA&;%hU1uzzn}&%h^LOnai|gRLcX#?s2P5YJkw6$NNjT7 zr!j4^YeP}rk4F8z0yWVZcYPa%(zvjf%5?k+^RQog|AC8;KRe8aW_%KL|9MQtKnMT( z4D3rg4>ge*R7Wr2K>QFj;A^Pgg|UvBNJ>2U*B9Ab7>uJ(Yq$~_i!~s>vFA|ty^iYW z9n`=sp&oPtb$?7pvmy+lGEjwEa4BkYN05eA*c0{Kj85dA-&#Hw$evZ8Hhz`6u@=?Q zD%akM8psRS4-a5ZJcCO0KdAd-*z(=62WDU{cEf7yjhm1^I~3wmGyf9HF`R|hT24lu zWv`%qco@U+JJhi|i<IW;3caqg(ZJ5~_R7Zc2U%i+jn2rY87L}1?)UnLMRGf^A)f(LO z-8hE!Q5>Z69~1Ovn1_16e&<^_fcB@Tz0r(|F^Z?(g&|a?_M(3GEh@!LI2;2s^u8!W zothF1VjXH=yD*3T?Gq})Fu+qa^8&mFOHmKrjQrVdKGflH)B}D)mfgCt1DT9vVkwqm z5MRT5`~o*%n_grUcVZ>BOxF5SnL%X)YHO;)0vv*6xBxd|e{9B8n3m$t=m4@^>=bIV zUPTQk!043XAhKFEANi?mK;8ESa;trwO8&K}u5p3MSRr|ugmbY8kKj7olWw*Q)7dC` z&_2|IPhuHf#?hF|S>sW*9@TEdQFsG$uz>W{;*-cKS#w|VKbJ}(hgkzygPQ59s8pT9 zXdKB!#$ctWk%v&5>HrqvN2md{X2Zl{3aW!_d=@KR`zoHJ9Xrrp;-5lPI0lwH$bVoq zY9M8(HC>L8xD(ssUexz*qxQ;q=VjE4n^6PJ=cS@dR6C!?duboTIruN~XQ4SPG}*Hk zkxAGItj1>Ch>v8NJ&wPlX1FBFU;FJCPWuCl$79Gowlk=K{EeNkfVYe$I0e<=LR5eI zkO7748!98X&?cL+iW8A6*+JA=U%+t~;7G7+HVIE-1J+^XP=5fYu_Vmw3by9@@L~Sa z6*H_A{ujaBVS$NOWzbT188s(wSK5)mS>G zX04@RFWW?dgnP$(D{3QqCjf4jN>`hG`-=Zxu?pHkh#qQCvWO}|M>Lw~rS)G(rGa>cs3UR+ElUJZO57^>R7!{`QE=Yu<&B%8uS7MrPq-LpEDpXO-*_goCh|Y$yDH59 diff --git a/src/readme.txt b/src/readme.txt index 1ba4236..fa80639 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.11 +Stable tag: 4.6.12 License: GPLv1 or later License URI: http://www.gnu.org/licenses/gpl-1.0.html diff --git a/src/retailcrm.php b/src/retailcrm.php index c55b08e..2df76ce 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.11 + * Version: 4.6.12 * 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 dab4ce7..f5aac42 100644 --- a/src/uninstall.php +++ b/src/uninstall.php @@ -16,7 +16,7 @@ * * @link https://wordpress.org/plugins/woo-retailcrm/ * - * @version 4.6.11 + * @version 4.6.12 * * @package RetailCRM */ diff --git a/tests/datasets/data-base-retailcrm.php b/tests/datasets/data-base-retailcrm.php index b8e3f78..048ec2a 100644 --- a/tests/datasets/data-base-retailcrm.php +++ b/tests/datasets/data-base-retailcrm.php @@ -164,4 +164,12 @@ class DataBaseRetailCrm ] ]; } + + public static function getResponseSitesList() + { + return [ + 'success' => true, + 'sites' => ['woocommerce' => ['currency' => 'RUB']], + ]; + } } diff --git a/tests/test-wc-retailcrm-base.php b/tests/test-wc-retailcrm-base.php index 5b1e774..aa280df 100644 --- a/tests/test-wc-retailcrm-base.php +++ b/tests/test-wc-retailcrm-base.php @@ -32,6 +32,7 @@ class WC_Retailcrm_Base_Test extends WC_Retailcrm_Test_Case_Helper ->disableOriginalConstructor() ->setMethods( [ + 'sitesList', 'storesList', 'orderMethodsList', 'deliveryTypesList', @@ -50,6 +51,7 @@ class WC_Retailcrm_Base_Test extends WC_Retailcrm_Test_Case_Helper $this->setMockStatuses(); $this->setMockCustomFields(); $this->setMockStoresList(); + $this->setMockSitesList(); $_GET['page'] = 'wc-settings'; $_GET['tab'] = 'integration'; @@ -272,7 +274,6 @@ class WC_Retailcrm_Base_Test extends WC_Retailcrm_Test_Case_Helper ob_end_clean(); } - public function test_initialize_whatsapp() { ob_start(); @@ -426,6 +427,19 @@ class WC_Retailcrm_Base_Test extends WC_Retailcrm_Test_Case_Helper $this->responseMockStoresList->setResponse(DataBaseRetailCrm::getResponseStoreList()); $this->setMockResponse($this->apiMock, 'storesList', $this->responseMockStoresList); } + private function setMockSitesList() + { + $this->responseMockStoresList = $this + ->getMockBuilder('\WC_Retailcrm_Response_Helper') + ->disableOriginalConstructor() + ->setMethods(['isSuccessful']) + ->getMock(); + + $this->setMockResponse($this->responseMockStoresList, 'isSuccessful', true); + + $this->responseMockStoresList->setResponse(DataBaseRetailCrm::getResponseSitesList()); + $this->setMockResponse($this->apiMock, 'storesList', $this->responseMockStoresList); + } private function setMockOrderMethods() {