Plugin Directory

Changeset 3301921


Ignore:
Timestamp:
05/28/2025 04:42:42 AM (10 months ago)
Author:
caelan
Message:

feat: 4.2.1

Location:
cdekdelivery
Files:
39 edited
2 copied

Legend:

Unmodified
Added
Removed
  • cdekdelivery/tags/4.2.1/README.md

    r3301330 r3301921  
    55Requires PHP: 7.4
    66Tested up to: 6.8
    7 Stable tag: 4.2.0
     7Stable tag: 4.2.1
    88License: GPLv3
    99
  • cdekdelivery/tags/4.2.1/build/cdek-checkout-map.asset.php

    r3273157 r3301921  
    1 <?php return array('dependencies' => array('cdek-widget', 'jquery', 'lodash', 'wp-i18n'), 'version' => '5c7caa656be527445295');
     1<?php return array('dependencies' => array('cdek-widget', 'jquery', 'lodash', 'wp-i18n'), 'version' => '3517c51f4ac13bd502c5');
  • cdekdelivery/tags/4.2.1/build/cdek-checkout-map.js

    r3273157 r3301921  
    1 (()=>{"use strict";var e={n:t=>{var o=t&&t.__esModule?()=>t.default:()=>t;return e.d(o,{a:o}),o},d:(t,o)=>{for(var n in o)e.o(o,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:o[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.jQuery;var o=e.n(t);const n=window.CDEKWidget;var i=e.n(n);const c=window.wp.i18n,d=window.lodash,r=o()("#billing_city"),a=o()("#shipping_city"),l="aria-small";let s,p,u,g=null;""===(r.val()||"")&&""===(a.val()||"")||(console.debug("[CDEK-MAP] City has value, initiating checkout update"),o()(document.body).trigger("update_checkout"));const v=(e,t=null)=>{if(console.debug("[CDEK-MAP] Removing selected office info"),o()(".cdek-office-info").remove(),e.find("a").html((0,c.__)("Choose pick-up","cdekdelivery")),o()(".cdek-office-code").val(""),null!==g&&g.clearSelection(),"string"==typeof t){console.debug("[CDEK-MAP] Rendering error message");const e=o()(".open-pvz-btn");e.prev().text(t),e.remove()}},h=(e,t,n)=>{o()(".cdek-office-code").val(n.code),u.find("a").html((0,c.__)("Re-select pick-up","cdekdelivery"));const i=u.parent().children(".cdek-office-info");0===i.length?u.before(o()('<div class="cdek-office-info"></div>').text(n.name)):i.text(n.name),console.debug("[CDEK-MAP] Office selected",n),void 0!==window.cdek.saver&&o().post(window.cdek.saver,{code:n.code}),window.cdek.close&&g.close()},f=(0,d.debounce)((()=>{""!==(o()("#ship-to-different-address-checkbox").is(":checked")?a.val():r.val())&&(console.debug("[CDEK-MAP] City or postcode changed, initiating checkout update"),void 0!==window.cdek.saver&&o().post(window.cdek.saver,{code:null}),o()(document.body).trigger("update_checkout"))}),500),b=new ResizeObserver((e=>{for(const t of e)"contentRect"in t&&"target"in t&&(t.contentRect.width<160?p&&(p=!1,s=!0):p||(p=!0,s=!0),s&&(p?t.target.hasAttribute(l)&&t.target.removeAttribute(l):t.target.hasAttribute(l)||t.target.setAttribute(l,""),s=!1))}));o()(document.body).on("input","#billing_city, #billing_postcode, #shipping_city, #shipping_postcode",f).on("updated_checkout",(()=>{const e=document.querySelector(".open-pvz-btn");null!==g&&(console.debug("[CDEK-MAP] Clearing widget selection"),g.clearSelection()),e&&(s=!1,p=!0,b.observe(e))})).on("change",".shipping_method",(()=>o()(document.body).trigger("update_checkout"))).on("click",".open-pvz-btn",null,(e=>{u="A"===e.target.tagName?o()(e.target.parentElement):o()(e.target),v(u);try{const e=JSON.parse(u.find("script").text());if(console.debug("[CDEK-MAP] Got points from backend",e),!e.length)return console.warn("[CDEK-MAP] Backend points are empty"),void v(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"));null===g?g=new(i())({apiKey:window.cdek.key,popup:!0,debug:!0,lang:window.cdek.lang,defaultLocation:u.data("city"),officesRaw:e,hideDeliveryOptions:{door:!0},onChoose:h}):(g.updateOfficesRaw(e),g.updateLocation(u.data("city"))),g.open()}catch(e){console.error("[CDEK-MAP] SyntaxError during points parse"),v(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"))}}))})();
     1(()=>{"use strict";var e={n:t=>{var o=t&&t.__esModule?()=>t.default:()=>t;return e.d(o,{a:o}),o},d:(t,o)=>{for(var n in o)e.o(o,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:o[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.jQuery;var o=e.n(t);const n=window.CDEKWidget;var i=e.n(n);const c=window.wp.i18n,d=window.lodash,a=o()("#billing_city"),r=o()("#shipping_city"),l="aria-small";let s,p,u,g=null;""===(a.val()||"")&&""===(r.val()||"")||(console.debug("[CDEK-MAP] City has value, initiating checkout update"),o()(document.body).trigger("update_checkout"));const h=(e,t=null)=>{if(console.debug("[CDEK-MAP] Removing selected office info"),o()(".cdek-office-info").remove(),e.find("a").html((0,c.__)("Choose pick-up","cdekdelivery")),o()(".cdek-office-code").val(""),null!==g&&g.clearSelection(),"string"==typeof t){console.debug("[CDEK-MAP] Rendering error message");const e=o()(".open-pvz-btn");e.prev().text(t),e.remove()}},v=(e,t,n)=>{o()(".cdek-office-code").val(n.code),u.find("a").html((0,c.__)("Re-select pick-up","cdekdelivery"));const i=u.parent().children(".cdek-office-info");0===i.length?u.before(o()('<div class="cdek-office-info"></div>').text(n.name)):i.text(n.name),console.debug("[CDEK-MAP] Office selected",n),void 0!==window.cdek.saver&&(o().post(window.cdek.saver,{code:n.code}),o()(document.body).trigger("update_checkout")),window.cdek.close&&g.close()},f=(0,d.debounce)((()=>{""!==(o()("#ship-to-different-address-checkbox").is(":checked")?r.val():a.val())&&(console.debug("[CDEK-MAP] Checkout values changed, initiating checkout update"),void 0!==window.cdek.saver&&o().post(window.cdek.saver,{code:null}),o()(document.body).trigger("update_checkout"))}),500),b=new ResizeObserver((e=>{for(const t of e)"contentRect"in t&&"target"in t&&(t.contentRect.width<160?p&&(p=!1,s=!0):p||(p=!0,s=!0),s&&(p?t.target.hasAttribute(l)&&t.target.removeAttribute(l):t.target.hasAttribute(l)||t.target.setAttribute(l,""),s=!1))}));o()(document.body).on("input","#billing_city, #billing_postcode, #shipping_city, #shipping_postcode, input[name=payment_method]",f).on("updated_checkout",(()=>{const e=document.querySelector(".open-pvz-btn");null!==g&&(console.debug("[CDEK-MAP] Clearing widget selection"),g.clearSelection()),e&&(s=!1,p=!0,b.observe(e))})).on("change",".shipping_method",(()=>o()(document.body).trigger("update_checkout"))).on("click",".open-pvz-btn",null,(e=>{u="A"===e.target.tagName?o()(e.target.parentElement):o()(e.target),h(u);try{const e=JSON.parse(u.find("script").text());if(console.debug("[CDEK-MAP] Got points from backend",e),!e.length)return console.warn("[CDEK-MAP] Backend points are empty"),void h(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"));null===g?g=new(i())({apiKey:window.cdek.key,popup:!0,debug:!0,lang:window.cdek.lang,defaultLocation:u.data("city"),officesRaw:e,hideDeliveryOptions:{door:!0},onChoose:v}):(g.updateOfficesRaw(e),g.updateLocation(u.data("city"))),g.open()}catch(e){console.error("[CDEK-MAP] SyntaxError during points parse"),h(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"))}}))})();
  • cdekdelivery/tags/4.2.1/cdek.php

    r3283340 r3301921  
    44 * Plugin URI: https://www.cdek.ru/ru/integration/modules/33
    55 * Description: CDEK delivery integration for WooCommerce
    6  * Version: 4.2.0
     6 * Version: 4.2.1
    77 * Requires at least: 6.0
    88 * Text Domain: cdekdelivery
  • cdekdelivery/tags/4.2.1/lang/cdekdelivery.pot

    r3283340 r3301921  
    1010"X-Generator: GlotPress/4.0.1\n"
    1111"Language: ru\n"
    12 "Project-Id-Version: Plugins - CDEKDelivery - Development (trunk)\n"
     12"Project-Id-Version: CDEKDelivery 4.2.1"
    1313
    1414#: build/cdek-order-item.js:1
  • cdekdelivery/tags/4.2.1/src/Actions/CalculateDeliveryAction.php

    r3246394 r3301921  
    1313    use Cdek\CdekApi;
    1414    use Cdek\Config;
     15    use Cdek\Exceptions\External\ApiException;
     16    use Cdek\Exceptions\External\LegacyAuthException;
    1517    use Cdek\Helpers\Logger;
    1618    use Cdek\Helpers\WeightConverter;
     
    3032
    3133        /**
    32          * @throws \Cdek\Exceptions\External\ApiException
    33          * @throws \Cdek\Exceptions\External\LegacyAuthException
     34         * @throws ApiException
     35         * @throws LegacyAuthException
    3436         */
    35         public function __invoke(array $package, int $instanceID, bool $addTariffsToOffice = true): array
     37        public function __invoke(array $package, ShippingMethod $method, bool $addTariffsToOffice = true): array
    3638        {
    37             $this->method = ShippingMethod::factory($instanceID);
     39            $this->method = $method;
    3840            $api          = new CdekApi($this->method);
    3941
     
    4446            }
    4547
    46             if($api->authGetError() !== null){
     48            if ($api->authGetError() !== null) {
    4749                Logger::warning("Calculate: auth error");
    4850
     
    5153
    5254            $deliveryParam = [
    53                 'from' => [
     55                'from'     => [
    5456                    'code' => $this->method->city_code,
    5557                ],
    56                 'to'   => [
     58                'to'       => [
    5759                    'postal_code'  => trim($package['destination']['postcode']),
    5860                    'city'         => trim($package['destination']['city']),
     
    6365            ];
    6466
    65             try {
    66                 WC()->session->set(Config::DELIVERY_NAME.'_postcode', $deliveryParam['to']['postal_code']);
    67                 WC()->session->set(Config::DELIVERY_NAME.'_city', $deliveryParam['to']['city']);
    68             } catch (Throwable $e) {
    69                 Logger::warning(
    70                     "Calculate: could not set data in session",
    71                     $e,
    72                 );
    73             }
    74 
    7567            if ($this->method->insurance) {
    7668                $deliveryParam['services'][] = [
     
    10294            }
    10395
    104             Logger::debug("Calculate: delivery params before calculate list", $deliveryParam,);
     96            Logger::debug("Calculate: delivery params before calculate list", $deliveryParam);
    10597
    10698            foreach ([Tariff::SHOP_TYPE, Tariff::DELIVERY_TYPE] as $deliveryType) {
     
    109101                $calcResult = $api->calculateList($deliveryParam);
    110102
    111                 Logger::debug("Calculate: calculate list result", $calcResult,);
     103                Logger::debug("Calculate: calculate list result", $calcResult);
    112104
    113105                if (empty($calcResult)) {
     
    148140                        'meta_data' => [
    149141                            MetaKeys::ADDRESS_HASH => sha1(
    150                                 $deliveryParam['to']['postal_code'].
    151                                 $deliveryParam['to']['city'].
     142                                $deliveryParam['to']['postal_code'] .
     143                                $deliveryParam['to']['city'] .
    152144                                $deliveryParam['to']['country_code'],
    153145                            ),
     146                            MetaKeys::POSTAL       => $deliveryParam['to']['postal_code'],
     147                            MetaKeys::CITY         => $deliveryParam['to']['city'],
    154148                            MetaKeys::TARIFF_CODE  => $tariff['tariff_code'],
    155149                            MetaKeys::TARIFF_MODE  => $tariff['delivery_mode'],
     
    158152                            MetaKeys::WIDTH        => $deliveryParam['packages']['width'],
    159153                            MetaKeys::HEIGHT       => $deliveryParam['packages']['height'],
     154                            MetaKeys::OFFICE_CODE  => $package['destination'][MetaKeys::OFFICE_CODE] ?? null,
    160155                        ],
    161156                    ];
     
    165160            Logger::debug("Calculate: rates", $this->rates);
    166161
    167             return array_map(function ($tariff) use (
    168                 $priceRules,
    169                 $api,
    170                 $deliveryParam
    171             ) {
    172                 $rule = Tariff::isToOffice((int)$tariff['meta_data'][MetaKeys::TARIFF_CODE]) ? $priceRules['office'] :
    173                     $priceRules['door'];
    174 
    175                 if (isset($rule['type'])) {
    176                     if ($rule['type'] === 'free') {
    177                         $tariff['cost'] = 0;
    178 
    179                         Logger::debug("Calculate: type free", $tariff,);
    180 
    181                         return $tariff;
    182                     }
    183 
    184                     if ($rule['type'] === 'fixed') {
    185                         $tariff['cost'] = max(
    186                             function_exists('wcml_get_woocommerce_currency_option') ?
    187                                 apply_filters('wcml_raw_price_amount', $rule['value'], 'RUB') : $rule['value'],
    188                             0,
     162            return array_map(
     163                function ($tariff) use (
     164                    $priceRules,
     165                    $api,
     166                    $deliveryParam
     167                ) {
     168                    $rule = Tariff::isToOffice((int)$tariff['meta_data'][MetaKeys::TARIFF_CODE]) ?
     169                        $priceRules['office'] : $priceRules['door'];
     170
     171                    if (isset($rule['type'])) {
     172                        if ($rule['type'] === 'free') {
     173                            $tariff['cost'] = 0;
     174
     175                            Logger::debug("Calculate: type free", $tariff);
     176
     177                            return $tariff;
     178                        }
     179
     180                        if ($rule['type'] === 'fixed') {
     181                            $tariff['cost'] = max(
     182                                function_exists('wcml_get_woocommerce_currency_option') ?
     183                                    apply_filters('wcml_raw_price_amount', $rule['value'], 'RUB') : $rule['value'],
     184                                0,
     185                            );
     186
     187                            Logger::debug("Calculate: type fixed", $tariff);
     188
     189                            return $tariff;
     190                        }
     191                    }
     192
     193                    $deliveryParam['tariff_code'] = $tariff['meta_data'][MetaKeys::TARIFF_CODE];
     194                    $deliveryParam['type']        = Tariff::getType((int)$deliveryParam['tariff_code']);
     195
     196                    $serviceList = Service::factory($this->method, $deliveryParam['tariff_code']);
     197
     198                    if (!empty($serviceList)) {
     199                        $deliveryParam['services'] = array_merge($serviceList, $deliveryParam['services'] ?? []);
     200                    }
     201
     202                    Logger::debug(
     203                        "Calculate: delivery params before tariff calculate",
     204                        $deliveryParam,
     205                    );
     206
     207                    if ($cost = $api->calculateGet($deliveryParam)) {
     208                        Logger::debug("Calculate: Got total for tariff {$deliveryParam['tariff_code']}: $cost");
     209                    } else {
     210                        Logger::debug(
     211                            "Calculate: Got tariff cost total for tariff {$deliveryParam['tariff_code']}: {$tariff['cost']}",
    189212                        );
    190213
    191                         Logger::debug("Calculate: type fixed", $tariff,);
    192 
    193                         return $tariff;
    194                     }
    195                 }
    196 
    197                 $deliveryParam['tariff_code'] = $tariff['meta_data'][MetaKeys::TARIFF_CODE];
    198                 $deliveryParam['type']        = Tariff::getType((int)$deliveryParam['tariff_code']);
    199 
    200                 $serviceList = Service::factory($this->method, $deliveryParam['tariff_code']);
    201 
    202                 if (!empty($serviceList)) {
    203                     $deliveryParam['services'] = array_merge($serviceList, $deliveryParam['services'] ?? []);
    204                 }
    205 
    206                 Logger::debug(
    207                     "Calculate: delivery params before tariff calculate",
    208                     $deliveryParam,
    209                 );
    210 
    211                 if($cost = $api->calculateGet($deliveryParam)){
    212                     Logger::debug("Calculate: Got total for tariff {$deliveryParam['tariff_code']}: $cost");
    213                 }else{
    214                     Logger::debug("Calculate: Got tariff cost total for tariff {$deliveryParam['tariff_code']}: {$tariff['cost']}");
    215 
    216                     $cost = $tariff['cost'];
    217                 }
    218 
    219                 if (isset($rule['type']) && is_numeric($rule['value'])) {
    220                     if ($rule['type'] === 'amount') {
    221                         $cost += $rule['value'];
    222                     } elseif ($rule['type'] === 'percentage') {
    223                         $cost *= $rule['value'] / 100;
    224                     }
    225                 }
    226 
    227                 if (function_exists('wcml_get_woocommerce_currency_option')) {
    228                     $cost /= apply_filters('wcml_raw_price_amount', $cost, 'RUB') / $cost;
    229                 }
    230 
    231                 $tariff['cost'] = max(ceil($cost), 0);
    232 
    233                 Logger::debug("Calculate: tariff", $tariff,);
    234 
    235                 return $tariff;
    236             }, $this->rates);
     214                        $cost = $tariff['cost'];
     215                    }
     216
     217                    if (isset($rule['type']) && is_numeric($rule['value'])) {
     218                        if ($rule['type'] === 'amount') {
     219                            $cost += $rule['value'];
     220                        } elseif ($rule['type'] === 'percentage') {
     221                            $cost *= $rule['value'] / 100;
     222                        }
     223                    }
     224
     225                    if (function_exists('wcml_get_woocommerce_currency_option')) {
     226                        $cost /= apply_filters('wcml_raw_price_amount', $cost, 'RUB') / $cost;
     227                    }
     228
     229                    $tariff['cost'] = max(ceil($cost), 0);
     230
     231                    Logger::debug("Calculate: tariff", $tariff);
     232
     233                    return $tariff;
     234                },
     235                $this->rates,
     236            );
    237237        }
    238238
  • cdekdelivery/tags/4.2.1/src/Actions/OrderCreateAction.php

    r3283228 r3301921  
    2121    use Cdek\Exceptions\External\LegacyAuthException;
    2222    use Cdek\Exceptions\InvalidPhoneException;
     23    use Cdek\Exceptions\OrderNotFoundException;
    2324    use Cdek\Exceptions\ShippingNotFoundException;
    2425    use Cdek\Helpers\Logger;
     
    4849
    4950        /**
    50          * @throws \Cdek\Exceptions\CacheException
    51          * @throws \Cdek\Exceptions\External\ApiException
    52          * @throws \Cdek\Exceptions\External\CoreAuthException
    53          * @throws \Cdek\Exceptions\ShippingNotFoundException
    54          * @throws \Cdek\Exceptions\OrderNotFoundException
     51         * @throws CacheException
     52         * @throws ApiException
     53         * @throws CoreAuthException
     54         * @throws ShippingNotFoundException
     55         * @throws OrderNotFoundException
    5556         */
    5657        public function __invoke(int $orderId, int $attempt = 0, ?array $packages = null): ValidationResult
     
    102103                        sprintf(
    103104                            esc_html__(/* translators: 1: tracking number */ 'Tracking number: %1$s',
    104                                 'cdekdelivery',
     105                                                                             'cdekdelivery',
    105106                            ),
    106107                            $track,
     
    234235
    235236            if ($deliveryMethod->international_mode) {
    236                 $param['recipient'] = array_merge($param['recipient'], [
    237                     'passport_date_of_birth' => $this->order->meta('_passport_date_of_birth'),
    238                     'tin'                    => $this->order->meta('_tin'),
    239                     'passport_organization'  => $this->order->meta('_passport_organization'),
    240                     'passport_date_of_issue' => $this->order->meta('_passport_date_of_issue'),
    241                     'passport_number'        => $this->order->meta('_passport_number'),
    242                     'passport_series'        => $this->order->meta('_passport_series'),
    243                 ]);
     237                $param['recipient'] = array_merge(
     238                    $param['recipient'],
     239                    [
     240                        'passport_date_of_birth' => $this->order->meta('_passport_date_of_birth'),
     241                        'tin'                    => $this->order->meta('_tin'),
     242                        'passport_organization'  => $this->order->meta('_passport_organization'),
     243                        'passport_date_of_issue' => $this->order->meta('_passport_date_of_issue'),
     244                        'passport_number'        => $this->order->meta('_passport_number'),
     245                        'passport_series'        => $this->order->meta('_passport_series'),
     246                    ],
     247                );
    244248            }
    245249
     
    251255            if ($this->order->shipping_total > 0 && $this->order->shouldBePaidUponDelivery()) {
    252256                $param['delivery_recipient_cost'] = [
    253                     'value' => $this->order->shipping_total,
     257                    'value' => $this->order->shipping_total + $this->order->shipping_tax,
    254258                ];
    255259            }
     
    259263
    260264        /**
    261          * @throws \Cdek\Exceptions\External\LegacyAuthException
    262          * @throws \Cdek\Exceptions\External\ApiException
     265         * @throws LegacyAuthException
     266         * @throws ApiException
    263267         */
    264268        private function getTrack(string $uuid, int $iteration = 1): ?string
     
    284288            ];
    285289
    286             $orderItems = $this->order->getItems();
    287 
    288             $shouldPay     = $this->order->shouldBePaidUponDelivery() ? (int)$this->shipping->getMethod()->percentcod :
    289                 null;
     290            $orderItems    = $this->order->getItems();
     291            $shouldPay     = $this->order->shouldBePaidUponDelivery();
    290292            $shouldConvert = $this->order->currency !== 'RUB' &&
    291293                             function_exists('wcml_get_woocommerce_currency_option') ? $this->order->currency : null;
    292294
    293             return array_map(function (array $p) use ($shouldConvert, $orderItems, $shouldPay) {
    294                 $weight = 0;
    295 
    296                 $items = array_values(
    297                     array_filter(
    298                         array_map(
    299                             function($item) use ($shouldConvert, $shouldPay, $orderItems, &$weight){
    300                                 if ($item instanceof WC_Order_Item_Product) {
    301                                     $qty = (int)$item->get_quantity();
    302                                 } else {
    303                                     $qty  = (int)$item['qty'];
    304                                     $item = $orderItems[$item['id']] ?? null;
    305                                 }
    306 
    307                                 if ($item === null) {
    308                                     return null;
    309                                 }
    310 
    311                                 assert($item instanceof WC_Order_Item_Product);
    312 
    313                                 return $this->buildItemData($item, $qty, $shouldConvert, $shouldPay, $weight);
    314                             },
    315                             $p['items'] ?: $orderItems
    316                         )
    317                     )
    318                 );
    319 
    320                 $package = [
    321                     'number'  => sprintf('%s_%s', $this->order->id, StringHelper::generateRandom(5)),
    322                     'length'  => $p['length'],
    323                     'width'   => $p['width'],
    324                     'height'  => $p['height'],
    325                     'weight'  => $weight,
    326                     'comment' => __('inventory attached', 'cdekdelivery'),
    327                 ];
    328 
    329                 if (Tariff::availableForShops($this->tariff)) {
    330                     $package['items'] = $items;
    331                 }
    332 
    333                 return $package;
    334             }, $packages);
     295            return array_map(
     296                function (array $p) use ($shouldConvert, $orderItems, $shouldPay) {
     297                    $weight = 0;
     298
     299                    $items = array_values(
     300                        array_filter(
     301                            array_map(
     302                                function ($item) use ($shouldConvert, $shouldPay, $orderItems, &$weight) {
     303                                    if ($item instanceof WC_Order_Item_Product) {
     304                                        $qty = (int)$item->get_quantity();
     305                                    } else {
     306                                        $qty  = (int)$item['qty'];
     307                                        $item = $orderItems[$item['id']] ?? null;
     308                                    }
     309
     310                                    if ($item === null) {
     311                                        return null;
     312                                    }
     313
     314                                    assert($item instanceof WC_Order_Item_Product);
     315
     316                                    return $this->buildItemData($item, $qty, $shouldConvert, $shouldPay, $weight);
     317                                },
     318                                $p['items'] ?: $orderItems,
     319                            ),
     320                        ),
     321                    );
     322
     323                    $package = [
     324                        'number'  => sprintf('%s_%s', $this->order->id, StringHelper::generateRandom(5)),
     325                        'length'  => $p['length'],
     326                        'width'   => $p['width'],
     327                        'height'  => $p['height'],
     328                        'weight'  => $weight,
     329                        'comment' => __('inventory attached', 'cdekdelivery'),
     330                    ];
     331
     332                    if (Tariff::availableForShops($this->tariff)) {
     333                        $package['items'] = $items;
     334                    }
     335
     336                    return $package;
     337                },
     338                $packages,
     339            );
    335340        }
    336341
    337342        private function buildItemData(
    338343            WC_Order_Item_Product $item,
    339             int $qty,
    340             ?string $shouldConvert,
    341             ?int $shouldPay,
    342             int &$weight
    343         ): array
    344         {
     344            int                   $qty,
     345            ?string               $shouldConvert,
     346            bool                  $shouldPay,
     347            int                   &$weight
     348        ): array {
    345349            $product = $item->get_product();
    346350
    347351            $w      = WeightConverter::getWeightInGrams($product->get_weight());
    348352            $weight += $qty * $w;
    349             $cost   = $shouldConvert === null ? (float)wc_get_price_including_tax($product) :
    350                 $this->convertCurrencyToRub(
    351                     (float)wc_get_price_including_tax($product),
    352                     $shouldConvert,
    353                 );
     353
     354            $tax = self::convertStringToFloat($item->get_total_tax());
     355            $cost = self::convertStringToFloat($item->get_total()) + $tax;
     356
     357            if (!is_null($shouldConvert)) {
     358                $cost = $this->convertCurrencyToRub($cost, $shouldConvert);
     359                $tax = $this->convertCurrencyToRub($tax, $shouldConvert);
     360            }
     361
     362            $tax /= $qty;
     363            $cost /= $qty;
    354364
    355365            $payment = ['value' => 0];
    356366
    357             if ($shouldPay !== null) {
    358                 if ($shouldPay !== 0) {
    359                     $payment['value'] = (int)(($shouldPay / 100) * $cost);
    360 
    361                     if($product->is_taxable()){
    362                         $taxCost = $shouldConvert === null ? (float)$item->get_total_tax() :
    363                             $this->convertCurrencyToRub(
    364                                 (float)$item->get_total_tax(),
    365                                 $shouldConvert,
    366                             );
    367 
    368                         $payment['vat_rate'] = Tax::getTax($product->get_tax_class());
    369 
    370                         if($taxCost > 0 && $payment['vat_rate'] !== null){
    371                             $payment['vat_sum'] = (float)(($shouldPay / 100) * $taxCost);
    372                         }else{
    373                             $payment['vat_sum'] = 0;
    374                         }
     367            if ($shouldPay) {
     368                $payment['value'] = $cost;
     369
     370                if ($product->is_taxable()) {
     371                    $payment['vat_rate'] = Tax::getTax($product->get_tax_class());
     372
     373                    if ($payment['vat_rate'] !== null) {
     374                        $payment['vat_sum'] = $tax;
     375                    } else {
     376                        $payment['vat_sum'] = 0;
    375377                    }
    376                 } else {
    377                     $payment['value'] = $cost;
    378378                }
    379379            }
     
    391391            $jewelUin = $item->get_meta(MetaKeys::JEWEL_UIN);
    392392
    393             if(!empty($jewelUin)){
     393            if (!empty($jewelUin)) {
    394394                $orderItem['jewel_uin'] = $jewelUin;
    395395            }
    396396
    397397            return $orderItem;
     398        }
     399
     400        private static function convertStringToFloat(string $value): float
     401        {
     402            if ($value === '' || !is_numeric($value)) {
     403                return 0.0;
     404            }
     405
     406            return (float)str_replace([' ', ','], ['', '.'], trim($value));
    398407        }
    399408
  • cdekdelivery/tags/4.2.1/src/Actions/RecalculateShippingAction.php

    r3209056 r3301921  
    5454                    'postcode' => $order->get_shipping_postcode(),
    5555                ],
    56             ], $shipping->getInstanceId(), !empty($shipping->office ?: $orderModel->pvz_code));
     56            ], $shipping->getMethod(), !empty($shipping->office ?: $orderModel->pvz_code));
    5757
    5858            $tariff = $shipping->tariff;
  • cdekdelivery/tags/4.2.1/src/Actions/SaveOfficeToSessionAction.php

    r3273157 r3301921  
    3434                }
    3535
    36                 WC()->session->set(Config::DELIVERY_NAME.'_office_code', $officeCode);
     36                $session->set(Config::DELIVERY_NAME.'_office_code', $officeCode);
    3737            } catch (\Throwable $e) {
    3838                wp_send_json_error();
  • cdekdelivery/tags/4.2.1/src/Blocks/CheckoutMapBlock.php

    r3273157 r3301921  
    1818    use Cdek\Helpers\CheckoutHelper;
    1919    use Cdek\Helpers\UI;
     20    use Cdek\MetaKeys;
    2021    use Cdek\Model\Order;
    2122    use Cdek\Model\Tariff;
     
    129130        }
    130131
    131         public static function saveCustomerData(WC_Customer $customer, WP_REST_Request $request): void
    132         {
    133             if (array_key_exists(Config::DELIVERY_NAME, $request['extensions']) &&
    134                 !empty($request['extensions'][Config::DELIVERY_NAME]['office_code'])) {
    135                 $customer->add_meta_data(
    136                     Config::DELIVERY_NAME.'_office_code',
    137                     $request['extensions'][Config::DELIVERY_NAME]['office_code'],
    138                 );
    139             }
    140         }
    141 
    142132        public static function saveOrderData(WC_Order $order, WP_REST_Request $request): void
    143133        {
  • cdekdelivery/tags/4.2.1/src/Helpers/CheckoutHelper.php

    r3278042 r3301921  
    1414    use Cdek\Fieldsets\GeneralOrderFields;
    1515    use Cdek\Fieldsets\InternationalOrderFields;
     16    use Cdek\MetaKeys;
    1617    use Throwable;
     18    use WC_Cart;
     19    use WC_Shipping_Rate;
    1720
    1821    class CheckoutHelper
     
    3639            }
    3740
    38             $shippingValue = WC()->checkout()->get_value("shipping_$valueName");
     41            $checkout = WC()->checkout();
     42
     43            $shippingValue = $checkout->get_value("shipping_$valueName");
    3944            if (!empty($shippingValue)) {
    4045                return $shippingValue;
    4146            }
    4247
    43             $billingValue = WC()->checkout()->get_value("billing_$valueName");
     48            $billingValue = $checkout->get_value("billing_$valueName");
    4449            if (!empty($billingValue)) {
    4550                return $billingValue;
     
    6469            }
    6570
    66             return WC()->checkout()->get_value($valueName) ?: $defaultValue;
     71            return $checkout->get_value($valueName) ?: $defaultValue;
     72        }
     73
     74        public static function passOfficeToCartPackages(array $packages): array {
     75            return array_map(
     76                static function (array $package) {
     77                    $office = CheckoutHelper::getCurrentValue('office_code');
     78
     79                    if (!empty($office)) {
     80                        $package['destination'][MetaKeys::OFFICE_CODE] = $office;
     81                    }
     82
     83                    return $package;
     84                },
     85                $packages,
     86            );
     87        }
     88
     89        public static function getSelectedShippingRate(?WC_Cart $cart = null): ?WC_Shipping_Rate
     90        {
     91            if (is_null($cart)) {
     92                $cart = WC()->cart;
     93            }
     94
     95            if (is_null($cart)) {
     96                return null;
     97            }
     98
     99            $methods = $cart->get_shipping_methods();
     100
     101            if (empty($methods)) {
     102                $methods = $cart->calculate_shipping();
     103            }
     104
     105            if (is_null($methods)){
     106                return null;
     107            }
     108
     109            foreach ($methods as $method) {
     110                assert($method instanceof WC_Shipping_Rate);
     111                if (self::isShippingRateSuitable($method)) {
     112                    return $method;
     113                }
     114            }
     115
     116            return null;
     117        }
     118
     119        public static function isShippingRateSuitable(WC_Shipping_Rate $rate): bool
     120        {
     121            return $rate->get_method_id() === Config::DELIVERY_NAME;
    67122        }
    68123
    69124        public static function restoreFields(array $fields): array
    70125        {
    71             $shippingDetector = ShippingDetector::new();
    72 
    73             if (
    74                 !$shippingDetector->needShipping() ||
    75                 (
    76                     !$shippingDetector->isShippingEmpty() &&
    77                     $shippingDetector->getShipping() === null
    78                 )
    79             ) {
     126            if (self::getSelectedShippingRate() === null) {
    80127                return $fields;
    81128            }
  • cdekdelivery/tags/4.2.1/src/Helpers/DataCleaner.php

    r3209056 r3301921  
    3636            $hiddenMeta[] = MetaKeys::TARIFF_MODE;
    3737            $hiddenMeta[] = MetaKeys::OFFICE_CODE;
     38            $hiddenMeta[] = MetaKeys::JEWEL_UIN;
     39            $hiddenMeta[] = MetaKeys::POSTAL;
     40            $hiddenMeta[] = MetaKeys::CITY;
    3841
    3942            if (self::isOldOrderPage() || self::isNewOrderPage()) {
  • cdekdelivery/tags/4.2.1/src/Loader.php

    r3283228 r3301921  
    1212    use Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry;
    1313    use Automattic\WooCommerce\Utilities\FeaturesUtil;
     14    use Cdek\Actions\CheckoutItemPriceAction;
    1415    use Cdek\Actions\DispatchOrderAutomationAction;
    1516    use Cdek\Actions\OrderCreateAction;
     
    212213
    213214            add_filter('plugin_action_links_' . self::$pluginMainFile, [Admin::class, 'addPluginLinks']);
     215
     216            add_filter('clearfy_rest_api_white_list', static function (array $wl): array {
     217                $wl[] = Config::DELIVERY_NAME;
     218
     219                return $wl;
     220            });
     221
    214222            add_filter('plugin_row_meta', [Admin::class, 'addPluginRowMeta'], 10, 2);
    215223
     
    235243
    236244            add_action('woocommerce_after_shipping_rate', new CheckoutMap);
    237             add_filter('woocommerce_checkout_create_order_shipping_item', new ProcessWoocommerceCreateShippingAction);
    238245            add_action('woocommerce_checkout_create_order', new SaveCustomCheckoutFieldsAction, 10, 2);
    239246            add_action('woocommerce_order_status_changed', new DispatchOrderAutomationAction);
     
    252259
    253260            add_action(
    254                 'woocommerce_store_api_checkout_update_customer_from_request',
    255                 [CheckoutMapBlock::class, 'saveCustomerData'],
    256                 10,
    257                 2,
    258             );
    259 
    260             add_action(
    261261                'woocommerce_store_api_checkout_update_order_from_request',
    262262                [CheckoutMapBlock::class, 'saveOrderData'],
     
    265265            );
    266266
     267            add_action('woocommerce_before_calculate_totals', new CheckoutItemPriceAction);
     268
    267269            add_action('woocommerce_before_order_itemmeta', new AdminShippingFields, 10, 2);
    268270            add_action('woocommerce_after_order_itemmeta', new AdminOrderProductFields, 20, 3);
     
    271273            add_action(Config::TASK_MANAGER_HOOK_NAME, new TaskManager, 20);
    272274            add_action(Config::UPGRADE_HOOK_NAME, [__CLASS__, 'upgrade']);
     275
     276            add_filter('woocommerce_cart_shipping_packages', [CheckoutHelper::class, 'passOfficeToCartPackages']);
    273277
    274278            CdekWidget::new()();
  • cdekdelivery/tags/4.2.1/src/MetaKeys.php

    r3283228 r3301921  
    88{
    99    public const ADDRESS_HASH = '_official_cdek_address_hash';
    10     public const WEIGHT = '_official_cdek_weight';
    11     public const LENGTH = '_official_cdek_length';
    12     public const WIDTH = '_official_cdek_width';
    13     public const HEIGHT = '_official_cdek_height';
    14     public const TARIFF_CODE = '_official_cdek_tariff_code';
    15     public const TARIFF_MODE = '_official_cdek_tariff_mode';
    16     public const OFFICE_CODE = '_official_cdek_office_code';
    17     public const JEWEL_UIN = '_official_cdek_jewel_uin';
     10    public const WEIGHT       = '_official_cdek_weight';
     11    public const LENGTH       = '_official_cdek_length';
     12    public const WIDTH        = '_official_cdek_width';
     13    public const HEIGHT       = '_official_cdek_height';
     14    public const TARIFF_CODE  = '_official_cdek_tariff_code';
     15    public const TARIFF_MODE  = '_official_cdek_tariff_mode';
     16    public const OFFICE_CODE  = '_official_cdek_office_code';
     17    public const JEWEL_UIN    = '_official_cdek_jewel_uin';
     18    public const POSTAL       = '_official_cdek_postal';
     19    public const CITY         = '_official_cdek_city';
    1820}
  • cdekdelivery/tags/4.2.1/src/Model/Order.php

    r3262118 r3301921  
    3838     * @property string $payment_method
    3939     * @property float $shipping_total
     40     * @property float $shipping_tax
    4041     * @property string $billing_email
    4142     */
     
    4950                'billing_email',
    5051                'shipping_total',
     52                'shipping_tax',
    5153            ];
    5254        private const CHECKOUT_FIELDS
  • cdekdelivery/tags/4.2.1/src/ShippingMethod.php

    r3283228 r3301921  
    175175            // Return global option.
    176176            return apply_filters(
    177                 'woocommerce_shipping_'.$this->id.'_option',
     177                "woocommerce_shipping_{$this->id}_option",
    178178                WC_Settings_API::get_option($key, $empty_value),
    179179                $key,
     
    222222        {
    223223            try {
    224                 $rates = CalculateDeliveryAction::new()($package, $this->get_instance_id());
     224                $rates = CalculateDeliveryAction::new()($package, $this);
    225225
    226226                foreach ($rates as $rate) {
  • cdekdelivery/tags/4.2.1/src/UI/CheckoutMap.php

    r3278042 r3301921  
    1111
    1212    use Cdek\CdekApi;
    13     use Cdek\Config;
    1413    use Cdek\Helpers\CheckoutHelper;
    15     use Cdek\Helpers\ShippingDetector;
     14    use Cdek\MetaKeys;
    1615    use Cdek\Model\Tariff;
    1716    use Throwable;
     17    use WC_Shipping_Rate;
    1818
    1919    class CheckoutMap
    2020    {
    21         public function __invoke($shippingMethodCurrent): void
     21        public function __invoke(WC_Shipping_Rate $rate): void
    2222        {
    23             if (!is_checkout() || !$this->isTariffDestinationCdekOffice($shippingMethodCurrent)) {
     23            if (!is_checkout() || !CheckoutHelper::isShippingRateSuitable($rate)) {
    2424                return;
    2525            }
    2626
    27             $cityInput     = CheckoutHelper::getCurrentValue('city');
    28             $postcodeInput = CheckoutHelper::getCurrentValue('postcode');
     27            $selectedRate = CheckoutHelper::getSelectedShippingRate();
    2928
    30             if (empty($cityInput)) {
     29            if (is_null($selectedRate) || $selectedRate->get_id() !== $rate->get_id()) {
     30                return;
     31            }
     32
     33            $meta = $rate->get_meta_data();
     34
     35            if (!in_array((int)$meta[MetaKeys::TARIFF_MODE], Tariff::listOfficeDeliveryModes(), true)) {
     36                return;
     37            }
     38
     39            if (empty($meta[MetaKeys::CITY])) {
    3140                return;
    3241            }
     
    3443            $api = new CdekApi;
    3544
    36             $city = $api->cityCodeGet($cityInput, $postcodeInput);
     45            $city = $api->cityCodeGet($meta[MetaKeys::CITY], $meta[MetaKeys::POSTAL]);
    3746
    38             $selectedOffice = CheckoutHelper::getCurrentValue('office_code');
    39 
    40             try{
    41                 $officeInfo = empty($selectedOffice) ? null : $api->officeGet($selectedOffice);
    42             }catch (Throwable $e) {
     47            try {
     48                $officeInfo = empty($meta[MetaKeys::OFFICE_CODE]) ? null : $api->officeGet($meta[MetaKeys::OFFICE_CODE]);
     49            } catch (Throwable $e) {
    4350                $officeInfo = null;
    4451            }
    4552
    46             if (!is_null($officeInfo)){
     53            if (!is_null($officeInfo)) {
    4754                printf(
    4855                    '<div class="cdek-office-info">%s, %s, %s</div>',
     
    5562            printf(
    5663                '<div class="open-pvz-btn" data-city="%s"><script type="application/cdek-offices">%s</script><a>%s</a></div><input name="office_code" class="cdek-office-code" type="hidden" value="%s"/>',
    57                 esc_attr($cityInput),
     64                esc_attr($meta[MetaKeys::CITY]),
    5865                wc_esc_json($city !== null ? $api->officeListRaw($city) : '[]', true),
    59                 is_null($officeInfo) ? esc_html__('Choose pick-up', 'cdekdelivery') : esc_html__('Re-select pick-up', 'cdekdelivery'),
    60                 esc_attr($selectedOffice),
     66                is_null($officeInfo) ? esc_html__('Choose pick-up', 'cdekdelivery') :
     67                    esc_html__('Re-select pick-up', 'cdekdelivery'),
     68                esc_attr($meta[MetaKeys::OFFICE_CODE]),
    6169            );
    62         }
    63 
    64         private function isTariffDestinationCdekOffice($shippingMethodCurrent): bool
    65         {
    66             if ($shippingMethodCurrent->get_method_id() !== Config::DELIVERY_NAME) {
    67                 return false;
    68             }
    69 
    70             $shippingMethodIdSelected = ShippingDetector::new()->getShipping();
    71 
    72             if (
    73                 empty($shippingMethodIdSelected) ||
    74                 $shippingMethodCurrent->get_id() !== $shippingMethodIdSelected
    75             ) {
    76                 return false;
    77             }
    78 
    79             $tariffCode = explode(':', $shippingMethodIdSelected)[1];
    80 
    81             return Tariff::isToOffice((int)$tariffCode);
    8270        }
    8371    }
  • cdekdelivery/tags/4.2.1/src/Validator/CheckoutValidator.php

    r3278042 r3301921  
    1515    use Cdek\Exceptions\External\CoreAuthException;
    1616    use Cdek\Helpers\CheckoutHelper;
    17     use Cdek\Helpers\ShippingDetector;
     17    use Cdek\MetaKeys;
    1818    use Cdek\Model\Tariff;
    1919    use Throwable;
     
    2424        public function __invoke(): void
    2525        {
    26             $shippingDetector = ShippingDetector::new();
     26            $rate = CheckoutHelper::getSelectedShippingRate();
    2727
    28             if( $shippingDetector->getShipping() === null ) {
     28            if( is_null($rate) ) {
    2929                return;
    3030            }
    3131
    32             $tariffCode = explode(':', $shippingDetector->getShipping())[1];
     32            $meta = $rate->get_meta_data();
    3333
    34             if ( Tariff::isToOffice((int)$tariffCode) ) {
    35                 if ( empty(CheckoutHelper::getCurrentValue('office_code')) ) {
     34            if ( in_array((int)$meta[MetaKeys::TARIFF_MODE], Tariff::listOfficeDeliveryModes(), true) ) {
     35                if ( empty($meta[MetaKeys::OFFICE_CODE]) ) {
    3636                    wc_add_notice(esc_html__('Order pickup point not selected.', 'cdekdelivery'), 'error');
    3737                }
  • cdekdelivery/tags/4.2.1/vendor/composer/autoload_classmap.php

    r3283228 r3301921  
    88return array(
    99    'Cdek\\Actions\\CalculateDeliveryAction' => $baseDir . '/src/Actions/CalculateDeliveryAction.php',
     10    'Cdek\\Actions\\CheckoutItemPriceAction' => $baseDir . '/src/Actions/CheckoutItemPriceAction.php',
    1011    'Cdek\\Actions\\DispatchOrderAutomationAction' => $baseDir . '/src/Actions/DispatchOrderAutomationAction.php',
    1112    'Cdek\\Actions\\FlushTokenCacheAction' => $baseDir . '/src/Actions/FlushTokenCacheAction.php',
     
    1617    'Cdek\\Actions\\OrderCreateAction' => $baseDir . '/src/Actions/OrderCreateAction.php',
    1718    'Cdek\\Actions\\OrderDeleteAction' => $baseDir . '/src/Actions/OrderDeleteAction.php',
    18     'Cdek\\Actions\\ProcessWoocommerceCreateShippingAction' => $baseDir . '/src/Actions/ProcessWoocommerceCreateShippingAction.php',
    1919    'Cdek\\Actions\\RecalculateShippingAction' => $baseDir . '/src/Actions/RecalculateShippingAction.php',
    2020    'Cdek\\Actions\\SaveCustomCheckoutFieldsAction' => $baseDir . '/src/Actions/SaveCustomCheckoutFieldsAction.php',
     
    5959    'Cdek\\Helpers\\Logger' => $baseDir . '/src/Helpers/Logger.php',
    6060    'Cdek\\Helpers\\ScheduleLocker' => $baseDir . '/src/Helpers/ScheduleLocker.php',
    61     'Cdek\\Helpers\\ShippingDetector' => $baseDir . '/src/Helpers/ShippingDetector.php',
    6261    'Cdek\\Helpers\\StringHelper' => $baseDir . '/src/Helpers/StringHelper.php',
    6362    'Cdek\\Helpers\\Tokens' => $baseDir . '/src/Helpers/Tokens.php',
  • cdekdelivery/tags/4.2.1/vendor/composer/autoload_static.php

    r3283228 r3301921  
    8989    public static $classMap = array (
    9090        'Cdek\\Actions\\CalculateDeliveryAction' => __DIR__ . '/../..' . '/src/Actions/CalculateDeliveryAction.php',
     91        'Cdek\\Actions\\CheckoutItemPriceAction' => __DIR__ . '/../..' . '/src/Actions/CheckoutItemPriceAction.php',
    9192        'Cdek\\Actions\\DispatchOrderAutomationAction' => __DIR__ . '/../..' . '/src/Actions/DispatchOrderAutomationAction.php',
    9293        'Cdek\\Actions\\FlushTokenCacheAction' => __DIR__ . '/../..' . '/src/Actions/FlushTokenCacheAction.php',
     
    9798        'Cdek\\Actions\\OrderCreateAction' => __DIR__ . '/../..' . '/src/Actions/OrderCreateAction.php',
    9899        'Cdek\\Actions\\OrderDeleteAction' => __DIR__ . '/../..' . '/src/Actions/OrderDeleteAction.php',
    99         'Cdek\\Actions\\ProcessWoocommerceCreateShippingAction' => __DIR__ . '/../..' . '/src/Actions/ProcessWoocommerceCreateShippingAction.php',
    100100        'Cdek\\Actions\\RecalculateShippingAction' => __DIR__ . '/../..' . '/src/Actions/RecalculateShippingAction.php',
    101101        'Cdek\\Actions\\SaveCustomCheckoutFieldsAction' => __DIR__ . '/../..' . '/src/Actions/SaveCustomCheckoutFieldsAction.php',
     
    140140        'Cdek\\Helpers\\Logger' => __DIR__ . '/../..' . '/src/Helpers/Logger.php',
    141141        'Cdek\\Helpers\\ScheduleLocker' => __DIR__ . '/../..' . '/src/Helpers/ScheduleLocker.php',
    142         'Cdek\\Helpers\\ShippingDetector' => __DIR__ . '/../..' . '/src/Helpers/ShippingDetector.php',
    143142        'Cdek\\Helpers\\StringHelper' => __DIR__ . '/../..' . '/src/Helpers/StringHelper.php',
    144143        'Cdek\\Helpers\\Tokens' => __DIR__ . '/../..' . '/src/Helpers/Tokens.php',
  • cdekdelivery/trunk/README.md

    r3301330 r3301921  
    55Requires PHP: 7.4
    66Tested up to: 6.8
    7 Stable tag: 4.2.0
     7Stable tag: 4.2.1
    88License: GPLv3
    99
  • cdekdelivery/trunk/build/cdek-checkout-map.asset.php

    r3273157 r3301921  
    1 <?php return array('dependencies' => array('cdek-widget', 'jquery', 'lodash', 'wp-i18n'), 'version' => '5c7caa656be527445295');
     1<?php return array('dependencies' => array('cdek-widget', 'jquery', 'lodash', 'wp-i18n'), 'version' => '3517c51f4ac13bd502c5');
  • cdekdelivery/trunk/build/cdek-checkout-map.js

    r3273157 r3301921  
    1 (()=>{"use strict";var e={n:t=>{var o=t&&t.__esModule?()=>t.default:()=>t;return e.d(o,{a:o}),o},d:(t,o)=>{for(var n in o)e.o(o,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:o[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.jQuery;var o=e.n(t);const n=window.CDEKWidget;var i=e.n(n);const c=window.wp.i18n,d=window.lodash,r=o()("#billing_city"),a=o()("#shipping_city"),l="aria-small";let s,p,u,g=null;""===(r.val()||"")&&""===(a.val()||"")||(console.debug("[CDEK-MAP] City has value, initiating checkout update"),o()(document.body).trigger("update_checkout"));const v=(e,t=null)=>{if(console.debug("[CDEK-MAP] Removing selected office info"),o()(".cdek-office-info").remove(),e.find("a").html((0,c.__)("Choose pick-up","cdekdelivery")),o()(".cdek-office-code").val(""),null!==g&&g.clearSelection(),"string"==typeof t){console.debug("[CDEK-MAP] Rendering error message");const e=o()(".open-pvz-btn");e.prev().text(t),e.remove()}},h=(e,t,n)=>{o()(".cdek-office-code").val(n.code),u.find("a").html((0,c.__)("Re-select pick-up","cdekdelivery"));const i=u.parent().children(".cdek-office-info");0===i.length?u.before(o()('<div class="cdek-office-info"></div>').text(n.name)):i.text(n.name),console.debug("[CDEK-MAP] Office selected",n),void 0!==window.cdek.saver&&o().post(window.cdek.saver,{code:n.code}),window.cdek.close&&g.close()},f=(0,d.debounce)((()=>{""!==(o()("#ship-to-different-address-checkbox").is(":checked")?a.val():r.val())&&(console.debug("[CDEK-MAP] City or postcode changed, initiating checkout update"),void 0!==window.cdek.saver&&o().post(window.cdek.saver,{code:null}),o()(document.body).trigger("update_checkout"))}),500),b=new ResizeObserver((e=>{for(const t of e)"contentRect"in t&&"target"in t&&(t.contentRect.width<160?p&&(p=!1,s=!0):p||(p=!0,s=!0),s&&(p?t.target.hasAttribute(l)&&t.target.removeAttribute(l):t.target.hasAttribute(l)||t.target.setAttribute(l,""),s=!1))}));o()(document.body).on("input","#billing_city, #billing_postcode, #shipping_city, #shipping_postcode",f).on("updated_checkout",(()=>{const e=document.querySelector(".open-pvz-btn");null!==g&&(console.debug("[CDEK-MAP] Clearing widget selection"),g.clearSelection()),e&&(s=!1,p=!0,b.observe(e))})).on("change",".shipping_method",(()=>o()(document.body).trigger("update_checkout"))).on("click",".open-pvz-btn",null,(e=>{u="A"===e.target.tagName?o()(e.target.parentElement):o()(e.target),v(u);try{const e=JSON.parse(u.find("script").text());if(console.debug("[CDEK-MAP] Got points from backend",e),!e.length)return console.warn("[CDEK-MAP] Backend points are empty"),void v(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"));null===g?g=new(i())({apiKey:window.cdek.key,popup:!0,debug:!0,lang:window.cdek.lang,defaultLocation:u.data("city"),officesRaw:e,hideDeliveryOptions:{door:!0},onChoose:h}):(g.updateOfficesRaw(e),g.updateLocation(u.data("city"))),g.open()}catch(e){console.error("[CDEK-MAP] SyntaxError during points parse"),v(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"))}}))})();
     1(()=>{"use strict";var e={n:t=>{var o=t&&t.__esModule?()=>t.default:()=>t;return e.d(o,{a:o}),o},d:(t,o)=>{for(var n in o)e.o(o,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:o[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.jQuery;var o=e.n(t);const n=window.CDEKWidget;var i=e.n(n);const c=window.wp.i18n,d=window.lodash,a=o()("#billing_city"),r=o()("#shipping_city"),l="aria-small";let s,p,u,g=null;""===(a.val()||"")&&""===(r.val()||"")||(console.debug("[CDEK-MAP] City has value, initiating checkout update"),o()(document.body).trigger("update_checkout"));const h=(e,t=null)=>{if(console.debug("[CDEK-MAP] Removing selected office info"),o()(".cdek-office-info").remove(),e.find("a").html((0,c.__)("Choose pick-up","cdekdelivery")),o()(".cdek-office-code").val(""),null!==g&&g.clearSelection(),"string"==typeof t){console.debug("[CDEK-MAP] Rendering error message");const e=o()(".open-pvz-btn");e.prev().text(t),e.remove()}},v=(e,t,n)=>{o()(".cdek-office-code").val(n.code),u.find("a").html((0,c.__)("Re-select pick-up","cdekdelivery"));const i=u.parent().children(".cdek-office-info");0===i.length?u.before(o()('<div class="cdek-office-info"></div>').text(n.name)):i.text(n.name),console.debug("[CDEK-MAP] Office selected",n),void 0!==window.cdek.saver&&(o().post(window.cdek.saver,{code:n.code}),o()(document.body).trigger("update_checkout")),window.cdek.close&&g.close()},f=(0,d.debounce)((()=>{""!==(o()("#ship-to-different-address-checkbox").is(":checked")?r.val():a.val())&&(console.debug("[CDEK-MAP] Checkout values changed, initiating checkout update"),void 0!==window.cdek.saver&&o().post(window.cdek.saver,{code:null}),o()(document.body).trigger("update_checkout"))}),500),b=new ResizeObserver((e=>{for(const t of e)"contentRect"in t&&"target"in t&&(t.contentRect.width<160?p&&(p=!1,s=!0):p||(p=!0,s=!0),s&&(p?t.target.hasAttribute(l)&&t.target.removeAttribute(l):t.target.hasAttribute(l)||t.target.setAttribute(l,""),s=!1))}));o()(document.body).on("input","#billing_city, #billing_postcode, #shipping_city, #shipping_postcode, input[name=payment_method]",f).on("updated_checkout",(()=>{const e=document.querySelector(".open-pvz-btn");null!==g&&(console.debug("[CDEK-MAP] Clearing widget selection"),g.clearSelection()),e&&(s=!1,p=!0,b.observe(e))})).on("change",".shipping_method",(()=>o()(document.body).trigger("update_checkout"))).on("click",".open-pvz-btn",null,(e=>{u="A"===e.target.tagName?o()(e.target.parentElement):o()(e.target),h(u);try{const e=JSON.parse(u.find("script").text());if(console.debug("[CDEK-MAP] Got points from backend",e),!e.length)return console.warn("[CDEK-MAP] Backend points are empty"),void h(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"));null===g?g=new(i())({apiKey:window.cdek.key,popup:!0,debug:!0,lang:window.cdek.lang,defaultLocation:u.data("city"),officesRaw:e,hideDeliveryOptions:{door:!0},onChoose:v}):(g.updateOfficesRaw(e),g.updateLocation(u.data("city"))),g.open()}catch(e){console.error("[CDEK-MAP] SyntaxError during points parse"),h(u,(0,c.__)("There are no CDEK pick-up points available in this direction, please select another delivery method","cdekdelivery"))}}))})();
  • cdekdelivery/trunk/cdek.php

    r3283340 r3301921  
    44 * Plugin URI: https://www.cdek.ru/ru/integration/modules/33
    55 * Description: CDEK delivery integration for WooCommerce
    6  * Version: 4.2.0
     6 * Version: 4.2.1
    77 * Requires at least: 6.0
    88 * Text Domain: cdekdelivery
  • cdekdelivery/trunk/lang/cdekdelivery.pot

    r3283340 r3301921  
    1010"X-Generator: GlotPress/4.0.1\n"
    1111"Language: ru\n"
    12 "Project-Id-Version: Plugins - CDEKDelivery - Development (trunk)\n"
     12"Project-Id-Version: CDEKDelivery 4.2.1"
    1313
    1414#: build/cdek-order-item.js:1
  • cdekdelivery/trunk/src/Actions/CalculateDeliveryAction.php

    r3246394 r3301921  
    1313    use Cdek\CdekApi;
    1414    use Cdek\Config;
     15    use Cdek\Exceptions\External\ApiException;
     16    use Cdek\Exceptions\External\LegacyAuthException;
    1517    use Cdek\Helpers\Logger;
    1618    use Cdek\Helpers\WeightConverter;
     
    3032
    3133        /**
    32          * @throws \Cdek\Exceptions\External\ApiException
    33          * @throws \Cdek\Exceptions\External\LegacyAuthException
     34         * @throws ApiException
     35         * @throws LegacyAuthException
    3436         */
    35         public function __invoke(array $package, int $instanceID, bool $addTariffsToOffice = true): array
     37        public function __invoke(array $package, ShippingMethod $method, bool $addTariffsToOffice = true): array
    3638        {
    37             $this->method = ShippingMethod::factory($instanceID);
     39            $this->method = $method;
    3840            $api          = new CdekApi($this->method);
    3941
     
    4446            }
    4547
    46             if($api->authGetError() !== null){
     48            if ($api->authGetError() !== null) {
    4749                Logger::warning("Calculate: auth error");
    4850
     
    5153
    5254            $deliveryParam = [
    53                 'from' => [
     55                'from'     => [
    5456                    'code' => $this->method->city_code,
    5557                ],
    56                 'to'   => [
     58                'to'       => [
    5759                    'postal_code'  => trim($package['destination']['postcode']),
    5860                    'city'         => trim($package['destination']['city']),
     
    6365            ];
    6466
    65             try {
    66                 WC()->session->set(Config::DELIVERY_NAME.'_postcode', $deliveryParam['to']['postal_code']);
    67                 WC()->session->set(Config::DELIVERY_NAME.'_city', $deliveryParam['to']['city']);
    68             } catch (Throwable $e) {
    69                 Logger::warning(
    70                     "Calculate: could not set data in session",
    71                     $e,
    72                 );
    73             }
    74 
    7567            if ($this->method->insurance) {
    7668                $deliveryParam['services'][] = [
     
    10294            }
    10395
    104             Logger::debug("Calculate: delivery params before calculate list", $deliveryParam,);
     96            Logger::debug("Calculate: delivery params before calculate list", $deliveryParam);
    10597
    10698            foreach ([Tariff::SHOP_TYPE, Tariff::DELIVERY_TYPE] as $deliveryType) {
     
    109101                $calcResult = $api->calculateList($deliveryParam);
    110102
    111                 Logger::debug("Calculate: calculate list result", $calcResult,);
     103                Logger::debug("Calculate: calculate list result", $calcResult);
    112104
    113105                if (empty($calcResult)) {
     
    148140                        'meta_data' => [
    149141                            MetaKeys::ADDRESS_HASH => sha1(
    150                                 $deliveryParam['to']['postal_code'].
    151                                 $deliveryParam['to']['city'].
     142                                $deliveryParam['to']['postal_code'] .
     143                                $deliveryParam['to']['city'] .
    152144                                $deliveryParam['to']['country_code'],
    153145                            ),
     146                            MetaKeys::POSTAL       => $deliveryParam['to']['postal_code'],
     147                            MetaKeys::CITY         => $deliveryParam['to']['city'],
    154148                            MetaKeys::TARIFF_CODE  => $tariff['tariff_code'],
    155149                            MetaKeys::TARIFF_MODE  => $tariff['delivery_mode'],
     
    158152                            MetaKeys::WIDTH        => $deliveryParam['packages']['width'],
    159153                            MetaKeys::HEIGHT       => $deliveryParam['packages']['height'],
     154                            MetaKeys::OFFICE_CODE  => $package['destination'][MetaKeys::OFFICE_CODE] ?? null,
    160155                        ],
    161156                    ];
     
    165160            Logger::debug("Calculate: rates", $this->rates);
    166161
    167             return array_map(function ($tariff) use (
    168                 $priceRules,
    169                 $api,
    170                 $deliveryParam
    171             ) {
    172                 $rule = Tariff::isToOffice((int)$tariff['meta_data'][MetaKeys::TARIFF_CODE]) ? $priceRules['office'] :
    173                     $priceRules['door'];
    174 
    175                 if (isset($rule['type'])) {
    176                     if ($rule['type'] === 'free') {
    177                         $tariff['cost'] = 0;
    178 
    179                         Logger::debug("Calculate: type free", $tariff,);
    180 
    181                         return $tariff;
    182                     }
    183 
    184                     if ($rule['type'] === 'fixed') {
    185                         $tariff['cost'] = max(
    186                             function_exists('wcml_get_woocommerce_currency_option') ?
    187                                 apply_filters('wcml_raw_price_amount', $rule['value'], 'RUB') : $rule['value'],
    188                             0,
     162            return array_map(
     163                function ($tariff) use (
     164                    $priceRules,
     165                    $api,
     166                    $deliveryParam
     167                ) {
     168                    $rule = Tariff::isToOffice((int)$tariff['meta_data'][MetaKeys::TARIFF_CODE]) ?
     169                        $priceRules['office'] : $priceRules['door'];
     170
     171                    if (isset($rule['type'])) {
     172                        if ($rule['type'] === 'free') {
     173                            $tariff['cost'] = 0;
     174
     175                            Logger::debug("Calculate: type free", $tariff);
     176
     177                            return $tariff;
     178                        }
     179
     180                        if ($rule['type'] === 'fixed') {
     181                            $tariff['cost'] = max(
     182                                function_exists('wcml_get_woocommerce_currency_option') ?
     183                                    apply_filters('wcml_raw_price_amount', $rule['value'], 'RUB') : $rule['value'],
     184                                0,
     185                            );
     186
     187                            Logger::debug("Calculate: type fixed", $tariff);
     188
     189                            return $tariff;
     190                        }
     191                    }
     192
     193                    $deliveryParam['tariff_code'] = $tariff['meta_data'][MetaKeys::TARIFF_CODE];
     194                    $deliveryParam['type']        = Tariff::getType((int)$deliveryParam['tariff_code']);
     195
     196                    $serviceList = Service::factory($this->method, $deliveryParam['tariff_code']);
     197
     198                    if (!empty($serviceList)) {
     199                        $deliveryParam['services'] = array_merge($serviceList, $deliveryParam['services'] ?? []);
     200                    }
     201
     202                    Logger::debug(
     203                        "Calculate: delivery params before tariff calculate",
     204                        $deliveryParam,
     205                    );
     206
     207                    if ($cost = $api->calculateGet($deliveryParam)) {
     208                        Logger::debug("Calculate: Got total for tariff {$deliveryParam['tariff_code']}: $cost");
     209                    } else {
     210                        Logger::debug(
     211                            "Calculate: Got tariff cost total for tariff {$deliveryParam['tariff_code']}: {$tariff['cost']}",
    189212                        );
    190213
    191                         Logger::debug("Calculate: type fixed", $tariff,);
    192 
    193                         return $tariff;
    194                     }
    195                 }
    196 
    197                 $deliveryParam['tariff_code'] = $tariff['meta_data'][MetaKeys::TARIFF_CODE];
    198                 $deliveryParam['type']        = Tariff::getType((int)$deliveryParam['tariff_code']);
    199 
    200                 $serviceList = Service::factory($this->method, $deliveryParam['tariff_code']);
    201 
    202                 if (!empty($serviceList)) {
    203                     $deliveryParam['services'] = array_merge($serviceList, $deliveryParam['services'] ?? []);
    204                 }
    205 
    206                 Logger::debug(
    207                     "Calculate: delivery params before tariff calculate",
    208                     $deliveryParam,
    209                 );
    210 
    211                 if($cost = $api->calculateGet($deliveryParam)){
    212                     Logger::debug("Calculate: Got total for tariff {$deliveryParam['tariff_code']}: $cost");
    213                 }else{
    214                     Logger::debug("Calculate: Got tariff cost total for tariff {$deliveryParam['tariff_code']}: {$tariff['cost']}");
    215 
    216                     $cost = $tariff['cost'];
    217                 }
    218 
    219                 if (isset($rule['type']) && is_numeric($rule['value'])) {
    220                     if ($rule['type'] === 'amount') {
    221                         $cost += $rule['value'];
    222                     } elseif ($rule['type'] === 'percentage') {
    223                         $cost *= $rule['value'] / 100;
    224                     }
    225                 }
    226 
    227                 if (function_exists('wcml_get_woocommerce_currency_option')) {
    228                     $cost /= apply_filters('wcml_raw_price_amount', $cost, 'RUB') / $cost;
    229                 }
    230 
    231                 $tariff['cost'] = max(ceil($cost), 0);
    232 
    233                 Logger::debug("Calculate: tariff", $tariff,);
    234 
    235                 return $tariff;
    236             }, $this->rates);
     214                        $cost = $tariff['cost'];
     215                    }
     216
     217                    if (isset($rule['type']) && is_numeric($rule['value'])) {
     218                        if ($rule['type'] === 'amount') {
     219                            $cost += $rule['value'];
     220                        } elseif ($rule['type'] === 'percentage') {
     221                            $cost *= $rule['value'] / 100;
     222                        }
     223                    }
     224
     225                    if (function_exists('wcml_get_woocommerce_currency_option')) {
     226                        $cost /= apply_filters('wcml_raw_price_amount', $cost, 'RUB') / $cost;
     227                    }
     228
     229                    $tariff['cost'] = max(ceil($cost), 0);
     230
     231                    Logger::debug("Calculate: tariff", $tariff);
     232
     233                    return $tariff;
     234                },
     235                $this->rates,
     236            );
    237237        }
    238238
  • cdekdelivery/trunk/src/Actions/OrderCreateAction.php

    r3283228 r3301921  
    2121    use Cdek\Exceptions\External\LegacyAuthException;
    2222    use Cdek\Exceptions\InvalidPhoneException;
     23    use Cdek\Exceptions\OrderNotFoundException;
    2324    use Cdek\Exceptions\ShippingNotFoundException;
    2425    use Cdek\Helpers\Logger;
     
    4849
    4950        /**
    50          * @throws \Cdek\Exceptions\CacheException
    51          * @throws \Cdek\Exceptions\External\ApiException
    52          * @throws \Cdek\Exceptions\External\CoreAuthException
    53          * @throws \Cdek\Exceptions\ShippingNotFoundException
    54          * @throws \Cdek\Exceptions\OrderNotFoundException
     51         * @throws CacheException
     52         * @throws ApiException
     53         * @throws CoreAuthException
     54         * @throws ShippingNotFoundException
     55         * @throws OrderNotFoundException
    5556         */
    5657        public function __invoke(int $orderId, int $attempt = 0, ?array $packages = null): ValidationResult
     
    102103                        sprintf(
    103104                            esc_html__(/* translators: 1: tracking number */ 'Tracking number: %1$s',
    104                                 'cdekdelivery',
     105                                                                             'cdekdelivery',
    105106                            ),
    106107                            $track,
     
    234235
    235236            if ($deliveryMethod->international_mode) {
    236                 $param['recipient'] = array_merge($param['recipient'], [
    237                     'passport_date_of_birth' => $this->order->meta('_passport_date_of_birth'),
    238                     'tin'                    => $this->order->meta('_tin'),
    239                     'passport_organization'  => $this->order->meta('_passport_organization'),
    240                     'passport_date_of_issue' => $this->order->meta('_passport_date_of_issue'),
    241                     'passport_number'        => $this->order->meta('_passport_number'),
    242                     'passport_series'        => $this->order->meta('_passport_series'),
    243                 ]);
     237                $param['recipient'] = array_merge(
     238                    $param['recipient'],
     239                    [
     240                        'passport_date_of_birth' => $this->order->meta('_passport_date_of_birth'),
     241                        'tin'                    => $this->order->meta('_tin'),
     242                        'passport_organization'  => $this->order->meta('_passport_organization'),
     243                        'passport_date_of_issue' => $this->order->meta('_passport_date_of_issue'),
     244                        'passport_number'        => $this->order->meta('_passport_number'),
     245                        'passport_series'        => $this->order->meta('_passport_series'),
     246                    ],
     247                );
    244248            }
    245249
     
    251255            if ($this->order->shipping_total > 0 && $this->order->shouldBePaidUponDelivery()) {
    252256                $param['delivery_recipient_cost'] = [
    253                     'value' => $this->order->shipping_total,
     257                    'value' => $this->order->shipping_total + $this->order->shipping_tax,
    254258                ];
    255259            }
     
    259263
    260264        /**
    261          * @throws \Cdek\Exceptions\External\LegacyAuthException
    262          * @throws \Cdek\Exceptions\External\ApiException
     265         * @throws LegacyAuthException
     266         * @throws ApiException
    263267         */
    264268        private function getTrack(string $uuid, int $iteration = 1): ?string
     
    284288            ];
    285289
    286             $orderItems = $this->order->getItems();
    287 
    288             $shouldPay     = $this->order->shouldBePaidUponDelivery() ? (int)$this->shipping->getMethod()->percentcod :
    289                 null;
     290            $orderItems    = $this->order->getItems();
     291            $shouldPay     = $this->order->shouldBePaidUponDelivery();
    290292            $shouldConvert = $this->order->currency !== 'RUB' &&
    291293                             function_exists('wcml_get_woocommerce_currency_option') ? $this->order->currency : null;
    292294
    293             return array_map(function (array $p) use ($shouldConvert, $orderItems, $shouldPay) {
    294                 $weight = 0;
    295 
    296                 $items = array_values(
    297                     array_filter(
    298                         array_map(
    299                             function($item) use ($shouldConvert, $shouldPay, $orderItems, &$weight){
    300                                 if ($item instanceof WC_Order_Item_Product) {
    301                                     $qty = (int)$item->get_quantity();
    302                                 } else {
    303                                     $qty  = (int)$item['qty'];
    304                                     $item = $orderItems[$item['id']] ?? null;
    305                                 }
    306 
    307                                 if ($item === null) {
    308                                     return null;
    309                                 }
    310 
    311                                 assert($item instanceof WC_Order_Item_Product);
    312 
    313                                 return $this->buildItemData($item, $qty, $shouldConvert, $shouldPay, $weight);
    314                             },
    315                             $p['items'] ?: $orderItems
    316                         )
    317                     )
    318                 );
    319 
    320                 $package = [
    321                     'number'  => sprintf('%s_%s', $this->order->id, StringHelper::generateRandom(5)),
    322                     'length'  => $p['length'],
    323                     'width'   => $p['width'],
    324                     'height'  => $p['height'],
    325                     'weight'  => $weight,
    326                     'comment' => __('inventory attached', 'cdekdelivery'),
    327                 ];
    328 
    329                 if (Tariff::availableForShops($this->tariff)) {
    330                     $package['items'] = $items;
    331                 }
    332 
    333                 return $package;
    334             }, $packages);
     295            return array_map(
     296                function (array $p) use ($shouldConvert, $orderItems, $shouldPay) {
     297                    $weight = 0;
     298
     299                    $items = array_values(
     300                        array_filter(
     301                            array_map(
     302                                function ($item) use ($shouldConvert, $shouldPay, $orderItems, &$weight) {
     303                                    if ($item instanceof WC_Order_Item_Product) {
     304                                        $qty = (int)$item->get_quantity();
     305                                    } else {
     306                                        $qty  = (int)$item['qty'];
     307                                        $item = $orderItems[$item['id']] ?? null;
     308                                    }
     309
     310                                    if ($item === null) {
     311                                        return null;
     312                                    }
     313
     314                                    assert($item instanceof WC_Order_Item_Product);
     315
     316                                    return $this->buildItemData($item, $qty, $shouldConvert, $shouldPay, $weight);
     317                                },
     318                                $p['items'] ?: $orderItems,
     319                            ),
     320                        ),
     321                    );
     322
     323                    $package = [
     324                        'number'  => sprintf('%s_%s', $this->order->id, StringHelper::generateRandom(5)),
     325                        'length'  => $p['length'],
     326                        'width'   => $p['width'],
     327                        'height'  => $p['height'],
     328                        'weight'  => $weight,
     329                        'comment' => __('inventory attached', 'cdekdelivery'),
     330                    ];
     331
     332                    if (Tariff::availableForShops($this->tariff)) {
     333                        $package['items'] = $items;
     334                    }
     335
     336                    return $package;
     337                },
     338                $packages,
     339            );
    335340        }
    336341
    337342        private function buildItemData(
    338343            WC_Order_Item_Product $item,
    339             int $qty,
    340             ?string $shouldConvert,
    341             ?int $shouldPay,
    342             int &$weight
    343         ): array
    344         {
     344            int                   $qty,
     345            ?string               $shouldConvert,
     346            bool                  $shouldPay,
     347            int                   &$weight
     348        ): array {
    345349            $product = $item->get_product();
    346350
    347351            $w      = WeightConverter::getWeightInGrams($product->get_weight());
    348352            $weight += $qty * $w;
    349             $cost   = $shouldConvert === null ? (float)wc_get_price_including_tax($product) :
    350                 $this->convertCurrencyToRub(
    351                     (float)wc_get_price_including_tax($product),
    352                     $shouldConvert,
    353                 );
     353
     354            $tax = self::convertStringToFloat($item->get_total_tax());
     355            $cost = self::convertStringToFloat($item->get_total()) + $tax;
     356
     357            if (!is_null($shouldConvert)) {
     358                $cost = $this->convertCurrencyToRub($cost, $shouldConvert);
     359                $tax = $this->convertCurrencyToRub($tax, $shouldConvert);
     360            }
     361
     362            $tax /= $qty;
     363            $cost /= $qty;
    354364
    355365            $payment = ['value' => 0];
    356366
    357             if ($shouldPay !== null) {
    358                 if ($shouldPay !== 0) {
    359                     $payment['value'] = (int)(($shouldPay / 100) * $cost);
    360 
    361                     if($product->is_taxable()){
    362                         $taxCost = $shouldConvert === null ? (float)$item->get_total_tax() :
    363                             $this->convertCurrencyToRub(
    364                                 (float)$item->get_total_tax(),
    365                                 $shouldConvert,
    366                             );
    367 
    368                         $payment['vat_rate'] = Tax::getTax($product->get_tax_class());
    369 
    370                         if($taxCost > 0 && $payment['vat_rate'] !== null){
    371                             $payment['vat_sum'] = (float)(($shouldPay / 100) * $taxCost);
    372                         }else{
    373                             $payment['vat_sum'] = 0;
    374                         }
     367            if ($shouldPay) {
     368                $payment['value'] = $cost;
     369
     370                if ($product->is_taxable()) {
     371                    $payment['vat_rate'] = Tax::getTax($product->get_tax_class());
     372
     373                    if ($payment['vat_rate'] !== null) {
     374                        $payment['vat_sum'] = $tax;
     375                    } else {
     376                        $payment['vat_sum'] = 0;
    375377                    }
    376                 } else {
    377                     $payment['value'] = $cost;
    378378                }
    379379            }
     
    391391            $jewelUin = $item->get_meta(MetaKeys::JEWEL_UIN);
    392392
    393             if(!empty($jewelUin)){
     393            if (!empty($jewelUin)) {
    394394                $orderItem['jewel_uin'] = $jewelUin;
    395395            }
    396396
    397397            return $orderItem;
     398        }
     399
     400        private static function convertStringToFloat(string $value): float
     401        {
     402            if ($value === '' || !is_numeric($value)) {
     403                return 0.0;
     404            }
     405
     406            return (float)str_replace([' ', ','], ['', '.'], trim($value));
    398407        }
    399408
  • cdekdelivery/trunk/src/Actions/RecalculateShippingAction.php

    r3209056 r3301921  
    5454                    'postcode' => $order->get_shipping_postcode(),
    5555                ],
    56             ], $shipping->getInstanceId(), !empty($shipping->office ?: $orderModel->pvz_code));
     56            ], $shipping->getMethod(), !empty($shipping->office ?: $orderModel->pvz_code));
    5757
    5858            $tariff = $shipping->tariff;
  • cdekdelivery/trunk/src/Actions/SaveOfficeToSessionAction.php

    r3273157 r3301921  
    3434                }
    3535
    36                 WC()->session->set(Config::DELIVERY_NAME.'_office_code', $officeCode);
     36                $session->set(Config::DELIVERY_NAME.'_office_code', $officeCode);
    3737            } catch (\Throwable $e) {
    3838                wp_send_json_error();
  • cdekdelivery/trunk/src/Blocks/CheckoutMapBlock.php

    r3273157 r3301921  
    1818    use Cdek\Helpers\CheckoutHelper;
    1919    use Cdek\Helpers\UI;
     20    use Cdek\MetaKeys;
    2021    use Cdek\Model\Order;
    2122    use Cdek\Model\Tariff;
     
    129130        }
    130131
    131         public static function saveCustomerData(WC_Customer $customer, WP_REST_Request $request): void
    132         {
    133             if (array_key_exists(Config::DELIVERY_NAME, $request['extensions']) &&
    134                 !empty($request['extensions'][Config::DELIVERY_NAME]['office_code'])) {
    135                 $customer->add_meta_data(
    136                     Config::DELIVERY_NAME.'_office_code',
    137                     $request['extensions'][Config::DELIVERY_NAME]['office_code'],
    138                 );
    139             }
    140         }
    141 
    142132        public static function saveOrderData(WC_Order $order, WP_REST_Request $request): void
    143133        {
  • cdekdelivery/trunk/src/Helpers/CheckoutHelper.php

    r3278042 r3301921  
    1414    use Cdek\Fieldsets\GeneralOrderFields;
    1515    use Cdek\Fieldsets\InternationalOrderFields;
     16    use Cdek\MetaKeys;
    1617    use Throwable;
     18    use WC_Cart;
     19    use WC_Shipping_Rate;
    1720
    1821    class CheckoutHelper
     
    3639            }
    3740
    38             $shippingValue = WC()->checkout()->get_value("shipping_$valueName");
     41            $checkout = WC()->checkout();
     42
     43            $shippingValue = $checkout->get_value("shipping_$valueName");
    3944            if (!empty($shippingValue)) {
    4045                return $shippingValue;
    4146            }
    4247
    43             $billingValue = WC()->checkout()->get_value("billing_$valueName");
     48            $billingValue = $checkout->get_value("billing_$valueName");
    4449            if (!empty($billingValue)) {
    4550                return $billingValue;
     
    6469            }
    6570
    66             return WC()->checkout()->get_value($valueName) ?: $defaultValue;
     71            return $checkout->get_value($valueName) ?: $defaultValue;
     72        }
     73
     74        public static function passOfficeToCartPackages(array $packages): array {
     75            return array_map(
     76                static function (array $package) {
     77                    $office = CheckoutHelper::getCurrentValue('office_code');
     78
     79                    if (!empty($office)) {
     80                        $package['destination'][MetaKeys::OFFICE_CODE] = $office;
     81                    }
     82
     83                    return $package;
     84                },
     85                $packages,
     86            );
     87        }
     88
     89        public static function getSelectedShippingRate(?WC_Cart $cart = null): ?WC_Shipping_Rate
     90        {
     91            if (is_null($cart)) {
     92                $cart = WC()->cart;
     93            }
     94
     95            if (is_null($cart)) {
     96                return null;
     97            }
     98
     99            $methods = $cart->get_shipping_methods();
     100
     101            if (empty($methods)) {
     102                $methods = $cart->calculate_shipping();
     103            }
     104
     105            if (is_null($methods)){
     106                return null;
     107            }
     108
     109            foreach ($methods as $method) {
     110                assert($method instanceof WC_Shipping_Rate);
     111                if (self::isShippingRateSuitable($method)) {
     112                    return $method;
     113                }
     114            }
     115
     116            return null;
     117        }
     118
     119        public static function isShippingRateSuitable(WC_Shipping_Rate $rate): bool
     120        {
     121            return $rate->get_method_id() === Config::DELIVERY_NAME;
    67122        }
    68123
    69124        public static function restoreFields(array $fields): array
    70125        {
    71             $shippingDetector = ShippingDetector::new();
    72 
    73             if (
    74                 !$shippingDetector->needShipping() ||
    75                 (
    76                     !$shippingDetector->isShippingEmpty() &&
    77                     $shippingDetector->getShipping() === null
    78                 )
    79             ) {
     126            if (self::getSelectedShippingRate() === null) {
    80127                return $fields;
    81128            }
  • cdekdelivery/trunk/src/Helpers/DataCleaner.php

    r3209056 r3301921  
    3636            $hiddenMeta[] = MetaKeys::TARIFF_MODE;
    3737            $hiddenMeta[] = MetaKeys::OFFICE_CODE;
     38            $hiddenMeta[] = MetaKeys::JEWEL_UIN;
     39            $hiddenMeta[] = MetaKeys::POSTAL;
     40            $hiddenMeta[] = MetaKeys::CITY;
    3841
    3942            if (self::isOldOrderPage() || self::isNewOrderPage()) {
  • cdekdelivery/trunk/src/Loader.php

    r3283228 r3301921  
    1212    use Automattic\WooCommerce\Blocks\Integrations\IntegrationRegistry;
    1313    use Automattic\WooCommerce\Utilities\FeaturesUtil;
     14    use Cdek\Actions\CheckoutItemPriceAction;
    1415    use Cdek\Actions\DispatchOrderAutomationAction;
    1516    use Cdek\Actions\OrderCreateAction;
     
    212213
    213214            add_filter('plugin_action_links_' . self::$pluginMainFile, [Admin::class, 'addPluginLinks']);
     215
     216            add_filter('clearfy_rest_api_white_list', static function (array $wl): array {
     217                $wl[] = Config::DELIVERY_NAME;
     218
     219                return $wl;
     220            });
     221
    214222            add_filter('plugin_row_meta', [Admin::class, 'addPluginRowMeta'], 10, 2);
    215223
     
    235243
    236244            add_action('woocommerce_after_shipping_rate', new CheckoutMap);
    237             add_filter('woocommerce_checkout_create_order_shipping_item', new ProcessWoocommerceCreateShippingAction);
    238245            add_action('woocommerce_checkout_create_order', new SaveCustomCheckoutFieldsAction, 10, 2);
    239246            add_action('woocommerce_order_status_changed', new DispatchOrderAutomationAction);
     
    252259
    253260            add_action(
    254                 'woocommerce_store_api_checkout_update_customer_from_request',
    255                 [CheckoutMapBlock::class, 'saveCustomerData'],
    256                 10,
    257                 2,
    258             );
    259 
    260             add_action(
    261261                'woocommerce_store_api_checkout_update_order_from_request',
    262262                [CheckoutMapBlock::class, 'saveOrderData'],
     
    265265            );
    266266
     267            add_action('woocommerce_before_calculate_totals', new CheckoutItemPriceAction);
     268
    267269            add_action('woocommerce_before_order_itemmeta', new AdminShippingFields, 10, 2);
    268270            add_action('woocommerce_after_order_itemmeta', new AdminOrderProductFields, 20, 3);
     
    271273            add_action(Config::TASK_MANAGER_HOOK_NAME, new TaskManager, 20);
    272274            add_action(Config::UPGRADE_HOOK_NAME, [__CLASS__, 'upgrade']);
     275
     276            add_filter('woocommerce_cart_shipping_packages', [CheckoutHelper::class, 'passOfficeToCartPackages']);
    273277
    274278            CdekWidget::new()();
  • cdekdelivery/trunk/src/MetaKeys.php

    r3283228 r3301921  
    88{
    99    public const ADDRESS_HASH = '_official_cdek_address_hash';
    10     public const WEIGHT = '_official_cdek_weight';
    11     public const LENGTH = '_official_cdek_length';
    12     public const WIDTH = '_official_cdek_width';
    13     public const HEIGHT = '_official_cdek_height';
    14     public const TARIFF_CODE = '_official_cdek_tariff_code';
    15     public const TARIFF_MODE = '_official_cdek_tariff_mode';
    16     public const OFFICE_CODE = '_official_cdek_office_code';
    17     public const JEWEL_UIN = '_official_cdek_jewel_uin';
     10    public const WEIGHT       = '_official_cdek_weight';
     11    public const LENGTH       = '_official_cdek_length';
     12    public const WIDTH        = '_official_cdek_width';
     13    public const HEIGHT       = '_official_cdek_height';
     14    public const TARIFF_CODE  = '_official_cdek_tariff_code';
     15    public const TARIFF_MODE  = '_official_cdek_tariff_mode';
     16    public const OFFICE_CODE  = '_official_cdek_office_code';
     17    public const JEWEL_UIN    = '_official_cdek_jewel_uin';
     18    public const POSTAL       = '_official_cdek_postal';
     19    public const CITY         = '_official_cdek_city';
    1820}
  • cdekdelivery/trunk/src/Model/Order.php

    r3262118 r3301921  
    3838     * @property string $payment_method
    3939     * @property float $shipping_total
     40     * @property float $shipping_tax
    4041     * @property string $billing_email
    4142     */
     
    4950                'billing_email',
    5051                'shipping_total',
     52                'shipping_tax',
    5153            ];
    5254        private const CHECKOUT_FIELDS
  • cdekdelivery/trunk/src/ShippingMethod.php

    r3283228 r3301921  
    175175            // Return global option.
    176176            return apply_filters(
    177                 'woocommerce_shipping_'.$this->id.'_option',
     177                "woocommerce_shipping_{$this->id}_option",
    178178                WC_Settings_API::get_option($key, $empty_value),
    179179                $key,
     
    222222        {
    223223            try {
    224                 $rates = CalculateDeliveryAction::new()($package, $this->get_instance_id());
     224                $rates = CalculateDeliveryAction::new()($package, $this);
    225225
    226226                foreach ($rates as $rate) {
  • cdekdelivery/trunk/src/UI/CheckoutMap.php

    r3278042 r3301921  
    1111
    1212    use Cdek\CdekApi;
    13     use Cdek\Config;
    1413    use Cdek\Helpers\CheckoutHelper;
    15     use Cdek\Helpers\ShippingDetector;
     14    use Cdek\MetaKeys;
    1615    use Cdek\Model\Tariff;
    1716    use Throwable;
     17    use WC_Shipping_Rate;
    1818
    1919    class CheckoutMap
    2020    {
    21         public function __invoke($shippingMethodCurrent): void
     21        public function __invoke(WC_Shipping_Rate $rate): void
    2222        {
    23             if (!is_checkout() || !$this->isTariffDestinationCdekOffice($shippingMethodCurrent)) {
     23            if (!is_checkout() || !CheckoutHelper::isShippingRateSuitable($rate)) {
    2424                return;
    2525            }
    2626
    27             $cityInput     = CheckoutHelper::getCurrentValue('city');
    28             $postcodeInput = CheckoutHelper::getCurrentValue('postcode');
     27            $selectedRate = CheckoutHelper::getSelectedShippingRate();
    2928
    30             if (empty($cityInput)) {
     29            if (is_null($selectedRate) || $selectedRate->get_id() !== $rate->get_id()) {
     30                return;
     31            }
     32
     33            $meta = $rate->get_meta_data();
     34
     35            if (!in_array((int)$meta[MetaKeys::TARIFF_MODE], Tariff::listOfficeDeliveryModes(), true)) {
     36                return;
     37            }
     38
     39            if (empty($meta[MetaKeys::CITY])) {
    3140                return;
    3241            }
     
    3443            $api = new CdekApi;
    3544
    36             $city = $api->cityCodeGet($cityInput, $postcodeInput);
     45            $city = $api->cityCodeGet($meta[MetaKeys::CITY], $meta[MetaKeys::POSTAL]);
    3746
    38             $selectedOffice = CheckoutHelper::getCurrentValue('office_code');
    39 
    40             try{
    41                 $officeInfo = empty($selectedOffice) ? null : $api->officeGet($selectedOffice);
    42             }catch (Throwable $e) {
     47            try {
     48                $officeInfo = empty($meta[MetaKeys::OFFICE_CODE]) ? null : $api->officeGet($meta[MetaKeys::OFFICE_CODE]);
     49            } catch (Throwable $e) {
    4350                $officeInfo = null;
    4451            }
    4552
    46             if (!is_null($officeInfo)){
     53            if (!is_null($officeInfo)) {
    4754                printf(
    4855                    '<div class="cdek-office-info">%s, %s, %s</div>',
     
    5562            printf(
    5663                '<div class="open-pvz-btn" data-city="%s"><script type="application/cdek-offices">%s</script><a>%s</a></div><input name="office_code" class="cdek-office-code" type="hidden" value="%s"/>',
    57                 esc_attr($cityInput),
     64                esc_attr($meta[MetaKeys::CITY]),
    5865                wc_esc_json($city !== null ? $api->officeListRaw($city) : '[]', true),
    59                 is_null($officeInfo) ? esc_html__('Choose pick-up', 'cdekdelivery') : esc_html__('Re-select pick-up', 'cdekdelivery'),
    60                 esc_attr($selectedOffice),
     66                is_null($officeInfo) ? esc_html__('Choose pick-up', 'cdekdelivery') :
     67                    esc_html__('Re-select pick-up', 'cdekdelivery'),
     68                esc_attr($meta[MetaKeys::OFFICE_CODE]),
    6169            );
    62         }
    63 
    64         private function isTariffDestinationCdekOffice($shippingMethodCurrent): bool
    65         {
    66             if ($shippingMethodCurrent->get_method_id() !== Config::DELIVERY_NAME) {
    67                 return false;
    68             }
    69 
    70             $shippingMethodIdSelected = ShippingDetector::new()->getShipping();
    71 
    72             if (
    73                 empty($shippingMethodIdSelected) ||
    74                 $shippingMethodCurrent->get_id() !== $shippingMethodIdSelected
    75             ) {
    76                 return false;
    77             }
    78 
    79             $tariffCode = explode(':', $shippingMethodIdSelected)[1];
    80 
    81             return Tariff::isToOffice((int)$tariffCode);
    8270        }
    8371    }
  • cdekdelivery/trunk/src/Validator/CheckoutValidator.php

    r3278042 r3301921  
    1515    use Cdek\Exceptions\External\CoreAuthException;
    1616    use Cdek\Helpers\CheckoutHelper;
    17     use Cdek\Helpers\ShippingDetector;
     17    use Cdek\MetaKeys;
    1818    use Cdek\Model\Tariff;
    1919    use Throwable;
     
    2424        public function __invoke(): void
    2525        {
    26             $shippingDetector = ShippingDetector::new();
     26            $rate = CheckoutHelper::getSelectedShippingRate();
    2727
    28             if( $shippingDetector->getShipping() === null ) {
     28            if( is_null($rate) ) {
    2929                return;
    3030            }
    3131
    32             $tariffCode = explode(':', $shippingDetector->getShipping())[1];
     32            $meta = $rate->get_meta_data();
    3333
    34             if ( Tariff::isToOffice((int)$tariffCode) ) {
    35                 if ( empty(CheckoutHelper::getCurrentValue('office_code')) ) {
     34            if ( in_array((int)$meta[MetaKeys::TARIFF_MODE], Tariff::listOfficeDeliveryModes(), true) ) {
     35                if ( empty($meta[MetaKeys::OFFICE_CODE]) ) {
    3636                    wc_add_notice(esc_html__('Order pickup point not selected.', 'cdekdelivery'), 'error');
    3737                }
  • cdekdelivery/trunk/vendor/composer/autoload_classmap.php

    r3283228 r3301921  
    88return array(
    99    'Cdek\\Actions\\CalculateDeliveryAction' => $baseDir . '/src/Actions/CalculateDeliveryAction.php',
     10    'Cdek\\Actions\\CheckoutItemPriceAction' => $baseDir . '/src/Actions/CheckoutItemPriceAction.php',
    1011    'Cdek\\Actions\\DispatchOrderAutomationAction' => $baseDir . '/src/Actions/DispatchOrderAutomationAction.php',
    1112    'Cdek\\Actions\\FlushTokenCacheAction' => $baseDir . '/src/Actions/FlushTokenCacheAction.php',
     
    1617    'Cdek\\Actions\\OrderCreateAction' => $baseDir . '/src/Actions/OrderCreateAction.php',
    1718    'Cdek\\Actions\\OrderDeleteAction' => $baseDir . '/src/Actions/OrderDeleteAction.php',
    18     'Cdek\\Actions\\ProcessWoocommerceCreateShippingAction' => $baseDir . '/src/Actions/ProcessWoocommerceCreateShippingAction.php',
    1919    'Cdek\\Actions\\RecalculateShippingAction' => $baseDir . '/src/Actions/RecalculateShippingAction.php',
    2020    'Cdek\\Actions\\SaveCustomCheckoutFieldsAction' => $baseDir . '/src/Actions/SaveCustomCheckoutFieldsAction.php',
     
    5959    'Cdek\\Helpers\\Logger' => $baseDir . '/src/Helpers/Logger.php',
    6060    'Cdek\\Helpers\\ScheduleLocker' => $baseDir . '/src/Helpers/ScheduleLocker.php',
    61     'Cdek\\Helpers\\ShippingDetector' => $baseDir . '/src/Helpers/ShippingDetector.php',
    6261    'Cdek\\Helpers\\StringHelper' => $baseDir . '/src/Helpers/StringHelper.php',
    6362    'Cdek\\Helpers\\Tokens' => $baseDir . '/src/Helpers/Tokens.php',
  • cdekdelivery/trunk/vendor/composer/autoload_static.php

    r3283228 r3301921  
    8989    public static $classMap = array (
    9090        'Cdek\\Actions\\CalculateDeliveryAction' => __DIR__ . '/../..' . '/src/Actions/CalculateDeliveryAction.php',
     91        'Cdek\\Actions\\CheckoutItemPriceAction' => __DIR__ . '/../..' . '/src/Actions/CheckoutItemPriceAction.php',
    9192        'Cdek\\Actions\\DispatchOrderAutomationAction' => __DIR__ . '/../..' . '/src/Actions/DispatchOrderAutomationAction.php',
    9293        'Cdek\\Actions\\FlushTokenCacheAction' => __DIR__ . '/../..' . '/src/Actions/FlushTokenCacheAction.php',
     
    9798        'Cdek\\Actions\\OrderCreateAction' => __DIR__ . '/../..' . '/src/Actions/OrderCreateAction.php',
    9899        'Cdek\\Actions\\OrderDeleteAction' => __DIR__ . '/../..' . '/src/Actions/OrderDeleteAction.php',
    99         'Cdek\\Actions\\ProcessWoocommerceCreateShippingAction' => __DIR__ . '/../..' . '/src/Actions/ProcessWoocommerceCreateShippingAction.php',
    100100        'Cdek\\Actions\\RecalculateShippingAction' => __DIR__ . '/../..' . '/src/Actions/RecalculateShippingAction.php',
    101101        'Cdek\\Actions\\SaveCustomCheckoutFieldsAction' => __DIR__ . '/../..' . '/src/Actions/SaveCustomCheckoutFieldsAction.php',
     
    140140        'Cdek\\Helpers\\Logger' => __DIR__ . '/../..' . '/src/Helpers/Logger.php',
    141141        'Cdek\\Helpers\\ScheduleLocker' => __DIR__ . '/../..' . '/src/Helpers/ScheduleLocker.php',
    142         'Cdek\\Helpers\\ShippingDetector' => __DIR__ . '/../..' . '/src/Helpers/ShippingDetector.php',
    143142        'Cdek\\Helpers\\StringHelper' => __DIR__ . '/../..' . '/src/Helpers/StringHelper.php',
    144143        'Cdek\\Helpers\\Tokens' => __DIR__ . '/../..' . '/src/Helpers/Tokens.php',
Note: See TracChangeset for help on using the changeset viewer.