. */ /* */ /*************************************************************************************/ namespace SoColissimo; use PDO; use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\Exception\PropelException; use Propel\Runtime\Propel; use SoColissimo\Model\SocolissimoAreaFreeshippingDomQuery; use SoColissimo\Model\SocolissimoAreaFreeshippingPrQuery; use SoColissimo\Model\SocolissimoDeliveryMode; use SoColissimo\Model\SocolissimoDeliveryModeQuery; use SoColissimo\Model\SocolissimoPrice; use SoColissimo\Model\SocolissimoPriceQuery; use Symfony\Component\Config\Definition\Exception\Exception; use Symfony\Component\Finder\Finder; use Thelia\Model\AreaQuery; use Thelia\Model\ConfigQuery; use Thelia\Model\Country; use Thelia\Model\ModuleImageQuery; use Thelia\Model\ModuleQuery; use Propel\Runtime\Connection\ConnectionInterface; use Thelia\Install\Database; use Thelia\Module\AbstractDeliveryModule; use Thelia\Module\Exception\DeliveryException; class SoColissimo extends AbstractDeliveryModule { protected $request; protected $dispatcher; private static $prices = null; const DOMAIN = 'socolissimo'; const JSON_PRICE_RESOURCE = "/Config/prices.json"; const JSON_CONFIG_PATH = "/Config/config.json"; /** * These constants refer to the imported CSV file. * IMPORT_NB_COLS: file's number of columns (begin at 1) * IMPORT_DELIVERY_REF_COL: file's column where delivery reference is set (begin at 0) * IMPORT_ORDER_REF_COL: file's column where order reference is set (begin at 0) */ const IMPORT_NB_COLS = 2; const IMPORT_DELIVERY_REF_COL = 0; const IMPORT_ORDER_REF_COL = 1; /** * This method is called by the Delivery loop, to check if the current module has to be displayed to the customer. * Override it to implements your delivery rules/ * * If you return true, the delivery method will de displayed to the customer * If you return false, the delivery method will not be displayed * * @param Country $country the country to deliver to. * * @return boolean */ public function isValidDelivery(Country $country) { $cartWeight = $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getWeight(); $areaId = $country->getAreaId(); $prices = SocolissimoPriceQuery::create() ->filterByAreaId($areaId) ->findOne(); $freeShipping = SocolissimoDeliveryModeQuery::create() ->findOneByFreeshippingActive(1); /* check if Colissimo delivers the asked area*/ if (null !== $prices || null !== $freeShipping) { return true; } return false; } /** * @param $areaId * @param $weight * @param $cartAmount * @param $deliverModeCode * * @return mixed * @throws DeliveryException */ public static function getPostageAmount($areaId, $weight, $cartAmount = 0, $deliverModeCode = null) { if (null === $deliverModeCode) { $deliveryMode = SocolissimoDeliveryModeQuery::create()->find()->getFirst(); } else { $deliveryMode = SocolissimoDeliveryModeQuery::create()->findOneByCode($deliverModeCode); } $freeshipping = $deliveryMode->getFreeshippingActive(); $freeshippingFrom = $deliveryMode->getFreeshippingFrom(); $deliveryModeQuery = $deliveryMode->getCode(); $postage = 0; if (!$freeshipping) { $areaPrices = SocolissimoPriceQuery::create() ->filterByDeliveryModeId($deliveryMode->getId()) ->filterByAreaId($areaId) ->filterByWeightMax($weight, Criteria::GREATER_EQUAL) ->_or() ->filterByWeightMax(null) ->filterByPriceMax($cartAmount, Criteria::GREATER_EQUAL) ->_or() ->filterByPriceMax(null) ->orderByWeightMax() ->orderByPriceMax(); $firstPrice = $areaPrices->find() ->getFirst(); if (null === $firstPrice) { throw new DeliveryException("Colissimo delivery unavailable for your cart weight or delivery country"); } //If a min price for freeshipping is define and the amount of cart reach this montant return 0 if (null !== $freeshippingFrom && $freeshippingFrom <= $cartAmount) { $postage = 0; return $postage; } if ($deliveryModeQuery === 'dom') { $cartAmountDom = SocolissimoAreaFreeshippingDomQuery::create() ->filterByAreaId($areaId) ->findOne(); if ($cartAmountDom) { $cartAmountDom = $cartAmountDom->getCartAmount(); } if (null !== $cartAmountDom && $cartAmountDom <= $cartAmount) { $postage = 0; return $postage; } } elseif ($deliveryModeQuery === 'pr') { $cartAmountPr = SocolissimoAreaFreeshippingPrQuery::create() ->filterByAreaId($areaId) ->findOne(); if ($cartAmountPr) { $cartAmountPr = $cartAmountPr->getCartAmount(); } if (null !== $cartAmountPr && $cartAmountPr <= $cartAmount) { $postage = 0; return $postage; } } $postage = $firstPrice->getPrice(); } return $postage; } /** * * calculate and return delivery price * * @param Country $country * @return mixed * @throws DeliveryException */ public function getPostage(Country $country) { $request = $this->getRequest(); $cartWeight = $request->getSession()->getSessionCart($this->getDispatcher())->getWeight(); $cartAmount = $request->getSession()->getSessionCart($this->getDispatcher())->getTaxedAmount($country); $dom = $request->get('socolissimo-home'); $pr_code = $request->get('socolissimo_code'); $deliveryModeCode = null; if ($dom) { $deliveryModeCode = "dom"; } elseif (!empty($pr_code)) { $deliveryModeCode = "pr"; } if (null == $deliveryModeCode) { $session = $request->getSession(); $dom = $session->get('SoColissimoDomicile'); $pr_code = $session->get('SoColissimoDeliveryId'); if ($dom) { $deliveryModeCode = "dom"; } elseif (!empty($pr_code)) { $deliveryModeCode = "pr"; } } $areaIdArray = $this->getAllAreasForCountry($country); if (empty($areaIdArray)) { throw new DeliveryException("Your delivery country is not covered by Colissimo."); } $postage = null; if (null === $postage = self::getMinPostage($areaIdArray, $cartWeight, $cartAmount, $deliveryModeCode)) { $postage = self::getMinPostage($areaIdArray, $cartWeight, $cartAmount, 'dom'); if (null === $postage) { throw new DeliveryException("Colissimo delivery unavailable for your cart weight or delivery country"); } } return $postage; } private function getMinPostage($areaIdArray, $cartWeight, $cartAmount, $deliveryModeCode) { $minPostage = null; foreach ($areaIdArray as $areaId) { try { $postage = self::getPostageAmount($areaId, $cartWeight, $cartAmount, $deliveryModeCode); if ($minPostage === null || $postage < $minPostage) { $minPostage = $postage; if ($minPostage == 0) { break; } } } catch (\Exception $ex) { } } return $minPostage; } /** * Returns ids of area containing this country and covers by this module * @param Country $country * @return array Area ids */ private function getAllAreasForCountry(Country $country) { $areaArray = []; $sql = "SELECT ca.area_id as area_id FROM country_area ca INNER JOIN area_delivery_module adm ON (ca.area_id = adm.area_id AND adm.delivery_module_id = :p0) WHERE ca.country_id = :p1"; $con = Propel::getConnection(); $stmt = $con->prepare($sql); $stmt->bindValue(':p0', $this->getModuleModel()->getId(), PDO::PARAM_INT); $stmt->bindValue(':p1', $country->getId(), PDO::PARAM_INT); $stmt->execute(); while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { $areaArray[] = $row['area_id']; } return $areaArray; } public function getCode() { return 'SoColissimo'; } public static function getPrices(SocolissimoDeliveryMode $deliveryMode) { self::$prices = null; $fileName = sprintf('%s%s', __DIR__, "/Config/prices_".$deliveryMode->getCode().".json"); // If delivery mode file doesn't exist take global price if (!file_exists($fileName)) { $fileName = sprintf('%s%s', __DIR__, self::JSON_PRICE_RESOURCE); // If global price doesn't exist throw exception if (!file_exists($fileName)) { throw new Exception("Prices configuration not found."); } } if (null === self::$prices) { self::$prices = json_decode(file_get_contents($fileName), true); } return self::$prices; } public static function importJsonPrice(SocolissimoDeliveryMode $deliveryMode, ConnectionInterface $con) { $areaPrices = self::getPrices($deliveryMode); $priceExist = SocolissimoPriceQuery::create() ->filterByDeliveryModeId($deliveryMode->getId()) ->findOne(); //If at least one price exist doesn't import the xml (or it will erase the user price) if (null !== $priceExist) { return; } $con->beginTransaction(); try { foreach ($areaPrices as $areaId => $area) { // Check if the area exists if (null !== AreaQuery::create()->findPk($areaId)) { foreach ($area['slices'] as $weight => $price) { $slice = (new SocolissimoPrice()) ->setAreaId($areaId) ->setWeightMax($weight) ->setPrice($price) ->setDeliveryModeId($deliveryMode->getId()); $slice->save(); } $con->commit(); } } } catch (PropelException $e) { $con->rollback(); throw $e; } } public function postActivation(ConnectionInterface $con = null) { try { // Security to not erase user config on reactivation SocolissimoDeliveryModeQuery::create()->findOne(); SocolissimoAreaFreeshippingDomQuery::create()->findOne(); SocolissimoAreaFreeshippingPrQuery::create()->findOne(); } catch (\Exception $e) { $database = new Database($con->getWrappedConnection()); $database->insertSql(null, [__DIR__ . '/Config/thelia.sql', __DIR__ . '/Config/insert.sql']); } try { $deliveryModes = SocolissimoDeliveryModeQuery::create() ->find(); foreach ($deliveryModes as $deliveryMode) { self::importJsonPrice($deliveryMode, $con); } } catch (\Exception $e) { throw $e; } ConfigQuery::write( 'socolissimo_login', ConfigQuery::read('socolissimo_login', null), 1, 1 ); ConfigQuery::write( 'socolissimo_pwd', ConfigQuery::read('socolissimo_pwd', null), 1, 1 ); ConfigQuery::write( 'socolissimo_pwd', ConfigQuery::read('socolissimo_pwd', null), 1, 1 ); ConfigQuery::write( 'socolissimo_google_map_key', ConfigQuery::read('socolissimo_google_map_key', null), 1, 1 ); ConfigQuery::write( 'socolissimo_url_prod', ConfigQuery::read('socolissimo_url_prod', 'https://ws.colissimo.fr/pointretrait-ws-cxf/PointRetraitServiceWS/2.0?wsdl'), 1, 1 ); ConfigQuery::write( 'socolissimo_url_test', ConfigQuery::read('socolissimo_url_test', 'https://pfi.telintrans.fr/pointretrait-ws-cxf/PointRetraitServiceWS/2.0?wsdl'), 1, 1 ); /* insert the images from image folder if first module activation */ $module = $this->getModuleModel(); if (ModuleImageQuery::create()->filterByModule($module)->count() == 0) { $this->deployImageFolder($module, sprintf('%s/images', __DIR__), $con); } } public static function getModCode() { return ModuleQuery::create()->findOneByCode("SoColissimo")->getId(); } /** * @inheritDoc */ public function update($currentVersion, $newVersion, ConnectionInterface $con = null) { $finder = (new Finder) ->files() ->name('#.*?\.sql#') ->sortByName() ->in(__DIR__ . DS . 'Config' . DS . 'update' . DS . 'sql'); $database = new Database($con); /** @var \Symfony\Component\Finder\SplFileInfo $updateSQLFile */ foreach ($finder as $updateSQLFile) { if (version_compare($currentVersion, str_replace('.sql', '', $updateSQLFile->getFilename()), '<')) { $database->insertSql( null, [ $updateSQLFile->getPathname() ] ); } } } }