Question

I'm trying to build a custom carrier-class (shipping method) that display shipping methods based on time/date related third party API, I tried to find out a solution to sort the below options but I failed

Has anyone faced such an issue? How does Magento sort these options?

Any help is really appreciated!

Thanks

Shipping carrier - custom class - time related shipping

adding code sample :

    /**
     * {@inheritdoc}
     */
    public function collectRates(RateRequest $request)
    {
        if (!$this->getConfigFlag('active')) {
            return false;
        }
        try {
            // get current quote id
            $quoteId = false;
            $items = $request->getAllItems();
            foreach ($items  as $item) {
                $quoteId = $item->getQuoteId();
                break;
            }
            /**  Quote $quote */
            $quote = $this->quoteFactory->create()->load($quoteId);
            $shippingAddress = $quote->getShippingAddress();
            $lat = (float) $shippingAddress->getData('latitude');
            $lng = (float) $shippingAddress->getData('longitude');
            if (!$lat || !$lng) {
                return false;
            }

            $isIn = $this->descartes->IsIn($lat, $lng);
            if (!$isIn) {
                // @todo handle logging here
                return false;
            }


            $shippingPrice = 10 ;
            $result = $this->_rateResultFactory->create();
            $slotsData = $this->descartes->getAvailableSlots();
            $lockBelow = (int) $this->getConfigData('capacitylock');
            $i = 1;

            foreach ($slotsData as $date => $slots) {
                foreach ($slots as $time => $slot_info) {
                    $capacity = (int) $slot_info['available_capacity'];
                    $id = (int) $slot_info['id'];
                    if ($capacity <= 0) {
                        continue;
                    }
                    switch ($capacity) {

                        case $capacity > $lockBelow:
                            $i = sprintf('%02d', $i);
                            /** @var Method $rate */
                            $rate = $this->_rateMethodFactory->create();
                            $rate->setCarrier($this->_code);
                            $rate->setCarrierTitle($this->getConfigData('title'));
                            $rate->setMethod($id);
                            $rate->setMethodTitle($date . "_" . $time);
                            $rate->setPrice($shippingPrice);
                            $rate->setCost($shippingPrice);
                            $rate->setSortOrder($i);
                            $result->append($rate);
                            break;
                    }
                    $i++;
                }
            }
            return $result;
        } catch (\Exception $e) {
            $this->manager->addErrorMessage($e->getMessage());
            return false;
        }
    }

sample slots API response :

array(2) {
  ["2020-05-13"]=>
  array(7) {
    ["2:00 PM-4:00 PM"]=>
    array(2) {
      ["id"]=>
      int(568)
      ["available_capacity"]=>
      int(-1)
    }
    ["4:00 PM-6:00 PM"]=>
    array(2) {
      ["id"]=>
      int(570)
      ["available_capacity"]=>
      int(24)
    }
    ["6:00 PM-8:00 PM"]=>
    array(2) {
      ["id"]=>
      int(555)
      ["available_capacity"]=>
      int(25)
    }
    ["8:00 PM-10:00 PM"]=>
    array(2) {
      ["id"]=>
      int(566)
      ["available_capacity"]=>
      int(25)
    }
    ["10:00 AM-11:59 AM"]=>
    array(2) {
      ["id"]=>
      int(482)
      ["available_capacity"]=>
      int(25)
    }
    ["10:00 PM-11:59 PM"]=>
    array(2) {
      ["id"]=>
      int(671)
      ["available_capacity"]=>
      int(25)
    }
    ["12:00 PM-2:00 PM"]=>
    array(2) {
      ["id"]=>
      int(678)
      ["available_capacity"]=>
      int(25)
    }
  }
  ["2020-05-14"]=>
  array(7) {
    ["2:00 PM-4:00 PM"]=>
    array(2) {
      ["id"]=>
      int(568)
      ["available_capacity"]=>
      int(25)
    }
    ["4:00 PM-6:00 PM"]=>
    array(2) {
      ["id"]=>
      int(570)
      ["available_capacity"]=>
      int(25)
    }
    ["6:00 PM-8:00 PM"]=>
    array(2) {
      ["id"]=>
      int(555)
      ["available_capacity"]=>
      int(25)
    }
    ["8:00 PM-10:00 PM"]=>
    array(2) {
      ["id"]=>
      int(566)
      ["available_capacity"]=>
      int(25)
    }
    ["10:00 AM-11:59 AM"]=>
    array(2) {
      ["id"]=>
      int(482)
      ["available_capacity"]=>
      int(25)
    }
    ["10:00 PM-11:59 PM"]=>
    array(2) {
      ["id"]=>
      int(671)
      ["available_capacity"]=>
      int(25)
    }
    ["12:00 PM-2:00 PM"]=>
    array(2) {
      ["id"]=>
      int(678)
      ["available_capacity"]=>
      int(25)
    }
  }
}

No correct solution

OTHER TIPS

Ok, take a look here:

vendor/magento/module-shipping/Model/Rate/Result.php

There is function sortRatesByPrice(); This foreach puts all in array for sorting:

foreach ($this->_rates as $i => $rate) {
        $tmp[$i] = $rate->getPrice();
    }

If you change this $rate->getPrice() to $rate->getMethodTitle() it will sort by method title, that in your case is date and time. I haven't looked deeper, but you can try to do plugin here or overwrite with preference. Just try and see. I think you will manage how to sort now. That sortRatesByPrice() is called here vendor/magento/module-shipping/Model/Rate/CarrierResult.php, function public function getAllRates().

I think you can simply sort first the array before your foreach using at least asort()

asort() - sort associative arrays in ascending order:

asort($slotsData)  
foreach ($slotsData......){}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top