/** * Update PSE for a given product * * @param array $pseList an array of priduct sale elements * @param bool $promoStatus true if the PSEs are on sale, false otherwise * @param int $offsetType the offset type, see SaleModel::OFFSET_* constants * @param Calculator $taxCalculator the tax calculator * @param array $saleOffsetByCurrency an array of price offset for each currency (currency ID => offset_amount) * @param ConnectionInterface $con */ protected function updateProductSaleElementsPrices($pseList, $promoStatus, $offsetType, Calculator $taxCalculator, $saleOffsetByCurrency, ConnectionInterface $con) { /** @var ProductSaleElements $pse */ foreach ($pseList as $pse) { if ($pse->getPromo() != $promoStatus) { $pse->setPromo($promoStatus)->save($con); } /** @var SaleOffsetCurrency $offsetByCurrency */ foreach ($saleOffsetByCurrency as $currencyId => $offset) { $productPrice = ProductPriceQuery::create()->filterByProductSaleElementsId($pse->getId())->filterByCurrencyId($currencyId)->findOne($con); if (null !== $productPrice) { // Get the taxed price $priceWithTax = $taxCalculator->getTaxedPrice($productPrice->getPrice()); // Remove the price offset to get the taxed promo price switch ($offsetType) { case SaleModel::OFFSET_TYPE_AMOUNT: $promoPrice = max(0, $priceWithTax - $offset); break; case SaleModel::OFFSET_TYPE_PERCENTAGE: $promoPrice = $priceWithTax * (1 - $offset / 100); break; default: $promoPrice = $priceWithTax; } // and then get the untaxed promo price. $promoPrice = $taxCalculator->getUntaxedPrice($promoPrice); $productPrice->setPromoPrice($promoPrice)->save($con); } } } }
/** * @param array $data * @return array * * Return the untaxed prices to store */ protected function extractPrices(array $data) { $calculator = new Calculator(); $calculator->loadTaxRuleWithoutProduct(TaxRuleQuery::create()->findPk($data["tax_rule_id"]), Country::getShopLocation()); $price = null === $data["price_with_tax"] ? $data["price"] : $calculator->getUntaxedPrice($data["price_with_tax"]); $salePrice = null === $data["sale_price_with_tax"] ? $data["sale_price"] : $calculator->getUntaxedPrice($data["sale_price_with_tax"]); return [$price, $salePrice]; }
/** * Calculate taxed/untexted price for a product * * @param $price * @param $price_type * @param Product $product * @param bool $convert * @return string */ protected function computePrice($price, $price_type, Product $product, $convert = false) { $calc = new Calculator(); $calc->load($product, Country::getShopLocation()); if ($price_type == 'without_tax') { $return_price = $calc->getTaxedPrice($price); } elseif ($price_type == 'with_tax') { $return_price = $calc->getUntaxedPrice($price); } else { $return_price = $price; } if ($convert != 0) { $return_price = $price * Currency::getDefaultCurrency()->getRate(); } return floatval($return_price); }
/** * Calculate taxed/untexted price for a product * * @param $price * @param $price_type * @param Product $product * @param bool $convert * @return string */ protected function computePrice($price, $price_type, Product $product, $convert = false) { $calc = new Calculator(); $calc->load($product, Country::getShopLocation()); if ($price_type == 'without_tax') { $return_price = $calc->getTaxedPrice($price); } elseif ($price_type == 'with_tax') { $return_price = $calc->getUntaxedPrice($price); } else { $return_price = $price; } if ($convert != 0) { $return_price = $price * Currency::getDefaultCurrency()->getRate(); } // Format the number using '.', to perform further calculation return NumberFormat::getInstance($this->getRequest())->formatStandardNumber($return_price); }
public function processGetOrders(ApiCallEvent $event) { $api = $event->getApi(); $response = $api->getResponse(); if ($response->isInError()) { $this->logger->error($response->getFormattedError()); throw new BadResponseException($response->getFormattedError()); } $dispatcher = $event->getDispatcher(); $orders = $response->getGroup("Orders"); $validOrders = []; /** @var \Thelia\Model\Country $country */ $shopCountry = CountryQuery::create()->findOneByShopCountry(true); $calculator = new Calculator(); /** * Check if there is only one order: reformat the array in that case */ if (array_key_exists("IdOrder", $orders["Order"])) { $orders = array("Order" => [$orders["Order"]]); } $notImportedOrders = []; /** * Then treat the orders */ foreach ($orders["Order"] as $orderArray) { /** * I) create the addresses */ /** * Get delivery address, and format empty fields */ $deliveryAddressArray =& $orderArray["ShippingAddress"]; $deliveryCountryId = CountryQuery::create()->findOneByIsoalpha2(strtolower($deliveryAddressArray["Country"]))->getId(); foreach ($deliveryAddressArray as &$value) { if (is_array($value)) { $value = ""; } } /** * Same for invoice address */ $invoiceAddressArray =& $orderArray["BillingAddress"]; $invoiceCountry = CountryQuery::create()->findOneByIsoalpha2(strtolower($invoiceAddressArray["Country"])); $invoiceCountryId = $invoiceCountry->getId(); foreach ($invoiceAddressArray as &$value) { if (is_array($value)) { $value = ""; } } $title = CustomerTitleQuery::create()->findOne()->getId(); /** * Create the order addresses */ $deliveryAddressEvent = new AddressCreateOrUpdateEvent("Delivery address", $title, $deliveryAddressArray["FirstName"], $deliveryAddressArray["LastName"], $deliveryAddressArray["Street"], $deliveryAddressArray["Street1"], $deliveryAddressArray["Street2"], $deliveryAddressArray["PostalCode"], $deliveryAddressArray["Town"], $deliveryCountryId, $deliveryAddressArray["PhoneMobile"], $deliveryAddressArray["Phone"], $deliveryAddressArray["Company"]); $deliveryAddressEvent->setCustomer($this->shoppingFluxCustomer); $dispatcher->dispatch(TheliaEvents::ADDRESS_CREATE, $deliveryAddressEvent); $invoiceAddressEvent = new AddressCreateOrUpdateEvent("Invoice address", $title, $invoiceAddressArray["FirstName"], $invoiceAddressArray["LastName"], $invoiceAddressArray["Street"], $invoiceAddressArray["Street1"], $invoiceAddressArray["Street2"], $invoiceAddressArray["PostalCode"], $invoiceAddressArray["Town"], $deliveryCountryId, $invoiceAddressArray["PhoneMobile"], $invoiceAddressArray["Phone"], $invoiceAddressArray["Company"]); $invoiceAddressEvent->setCustomer($this->shoppingFluxCustomer); $dispatcher->dispatch(TheliaEvents::ADDRESS_CREATE, $invoiceAddressEvent); /** * II) Add the products to a cart */ /** * Format the products array */ if ($orderArray["NumberOfProducts"] == "1") { $orderArray["Products"] = array("Product" => [$orderArray["Products"]["Product"]]); } $productsArray =& $orderArray["Products"]["Product"]; /** * Create a fake cart */ $cart = new Cart(); /** * And fulfil it with the products */ foreach ($productsArray as &$productArray) { $ids = explode("_", $productArray["SKU"]); $cartPse = ProductSaleElementsQuery::create()->findPk($ids[1]); $calculator->load($cartPse->getProduct(), $shopCountry); $price = $calculator->getUntaxedPrice((double) $productArray["Price"]); $cart->addCartItem((new CartItem())->setProductSaleElements($cartPse)->setProduct($cartPse->getProduct())->setQuantity($productArray["Quantity"])->setPrice($price)->setPromoPrice(0)->setPromo(0)); } /** * III) Create/Save the order */ /** * Construct order model */ $lang = LangQuery::create()->findOneByLocale($invoiceCountry->getLocale()); $currency = CurrencyQuery::create()->findOneByCode("EUR"); $order = OrderQuery::create()->findOneByRef($orderArray["IdOrder"]); if ($order !== null) { $order->delete(); } $order = new Order(); $order->setPostage($orderArray["TotalShipping"])->setChoosenDeliveryAddress($deliveryAddressEvent->getAddress()->getId())->setChoosenInvoiceAddress($invoiceAddressEvent->getAddress()->getId())->setDeliveryModuleId(ShoppingFluxConfigQuery::getDeliveryModuleId())->setPaymentModuleId($this->shoppingFluxPaymentModuleId)->setTransactionRef($orderArray["Marketplace"]); /** * Construct event */ $orderEvent = new OrderManualEvent($order, $currency, $lang, $cart, $this->shoppingFluxCustomer); $orderEvent->setDispatcher($dispatcher); $dispatcher->dispatch(TheliaEvents::ORDER_CREATE_MANUAL, $orderEvent); $placedOrder = $orderEvent->getPlacedOrder(); $placedOrder->setRef($orderArray["IdOrder"])->setPaid(); $validOrders[] = ["IdOrder" => $placedOrder->getRef(), "Marketplace" => $placedOrder->getTransactionRef()]; } /** * IV) Valid the orders to Shopping Flux */ $request = new Request("ValidOrders"); foreach ($validOrders as $validOrder) { $request->addOrder($validOrder); } $validOrdersApi = new ValidOrders($response->getToken(), $response->getMode()); $validOrdersApi->setRequest($request); $validOrdersResponse = $validOrdersApi->getResponse(); if ($validOrdersResponse->isInError()) { $this->logger->error($response->getFormattedError()); } }
/** * Copy of default product loop price filter but with tax applied to asked price * @param $search * @param $minPriceTTC * @param $maxPriceTTC * @throws \Propel\Runtime\Exception\PropelException */ protected function managePriceFilter(&$search, $minPriceTTC, $maxPriceTTC) { $categoryId = $this->getCategoryId(); $taxeRuleQuery = TaxRuleQuery::create(); $categoryJoin = new Join(); $categoryJoin->addExplicitCondition(TaxRuleTableMap::TABLE_NAME, 'ID', null, CriteriaSearchCategoryTaxRuleTableMap::TABLE_NAME, 'TAX_RULE_ID', null); $categoryJoin->setJoinType(Criteria::LEFT_JOIN); $taxeRuleQuery->addJoinObject($categoryJoin, 'category_join')->addJoinCondition('category_join', CriteriaSearchCategoryTaxRuleTableMap::CATEGORY_ID . ' = ' . $categoryId); $taxeRule = $taxeRuleQuery->findOne(); $taxCountry = $this->container->get('thelia.taxEngine')->getDeliveryCountry(); $calculator = new Calculator(); $calculator->loadTaxRuleWithoutProduct($taxeRule, $taxCountry); $currencyId = $this->getCurrency(); if (null !== $currencyId) { $currency = CurrencyQuery::create()->findOneById($currencyId); if (null === $currency) { throw new \InvalidArgumentException('Cannot found currency id: `' . $currency . '` in product_sale_elements loop'); } } else { $currency = $this->request->getSession()->getCurrency(); } $defaultCurrency = CurrencyQuery::create()->findOneByByDefault(1); $defaultCurrencySuffix = '_default_currency'; if (null !== $minPriceTTC) { $minPriceHt = round($calculator->getUntaxedPrice($minPriceTTC), 2); $isPSELeftJoinList[] = 'is_min_price'; $minPriceJoin = new Join(); $minPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price_ttc', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_ttc_data'); $minPriceJoin->setJoinType(Criteria::LEFT_JOIN); $search->joinProductSaleElements('is_min_price_ttc', Criteria::LEFT_JOIN)->addJoinObject($minPriceJoin, 'is_min_price_ttc_join')->addJoinCondition('is_min_price_ttc_join', '`min_price_ttc_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); if ($defaultCurrency->getId() != $currency->getId()) { $minPriceJoinDefaultCurrency = new Join(); $minPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_min_price_ttc', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'min_price_ttc_data' . $defaultCurrencySuffix); $minPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); $search->addJoinObject($minPriceJoinDefaultCurrency, 'is_min_price_ttc_join' . $defaultCurrencySuffix)->addJoinCondition('is_min_price_ttc_join' . $defaultCurrencySuffix, '`min_price_ttc_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); /** * In propel we trust : $currency->getRate() always returns a float. * Or maybe not : rate value is checked as a float in overloaded getRate method. */ $MinPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_min_price_ttc`.PROMO=1 THEN `min_price_ttc_data`.PROMO_PRICE ELSE `min_price_ttc_data`.PRICE END) OR `min_price_ttc_data`.FROM_DEFAULT_CURRENCY = 1 THEN CASE WHEN `is_min_price_ttc`.PROMO=1 THEN `min_price_ttc_data' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `min_price_ttc_data' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' ELSE CASE WHEN `is_min_price_ttc`.PROMO=1 THEN `min_price_ttc_data`.PROMO_PRICE ELSE `min_price_ttc_data`.PRICE END END'; } else { $MinPriceToCompareAsSQL = 'CASE WHEN `is_min_price_ttc`.PROMO=1 THEN `min_price_ttc_data`.PROMO_PRICE ELSE `min_price_ttc_data`.PRICE END'; } $search->where('ROUND(' . $MinPriceToCompareAsSQL . ', 2)>=?', $minPriceHt, \PDO::PARAM_STR); } if (null !== $maxPriceTTC) { $maxPriceHt = round($calculator->getUntaxedPrice($maxPriceTTC), 2); $isPSELeftJoinList[] = 'is_max_price_ttc'; $maxPriceJoin = new Join(); $maxPriceJoin->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price_ttc', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_ttc_data'); $maxPriceJoin->setJoinType(Criteria::LEFT_JOIN); $search->joinProductSaleElements('is_max_price_ttc', Criteria::LEFT_JOIN)->addJoinObject($maxPriceJoin, 'is_max_price_ttc_join')->addJoinCondition('is_max_price_ttc_join', '`max_price_ttc_data`.`currency_id` = ?', $currency->getId(), null, \PDO::PARAM_INT); if ($defaultCurrency->getId() != $currency->getId()) { $maxPriceJoinDefaultCurrency = new Join(); $maxPriceJoinDefaultCurrency->addExplicitCondition(ProductSaleElementsTableMap::TABLE_NAME, 'ID', 'is_max_price_ttc', ProductPriceTableMap::TABLE_NAME, 'PRODUCT_SALE_ELEMENTS_ID', 'max_price_ttc_data' . $defaultCurrencySuffix); $maxPriceJoinDefaultCurrency->setJoinType(Criteria::LEFT_JOIN); $search->addJoinObject($maxPriceJoinDefaultCurrency, 'is_max_price_ttc_join' . $defaultCurrencySuffix)->addJoinCondition('is_max_price_ttc_join' . $defaultCurrencySuffix, '`max_price_ttc_data' . $defaultCurrencySuffix . '`.`currency_id` = ?', $defaultCurrency->getId(), null, \PDO::PARAM_INT); /** * In propel we trust : $currency->getRate() always returns a float. * Or maybe not : rate value is checked as a float in overloaded getRate method. */ $MaxPriceToCompareAsSQL = 'CASE WHEN ISNULL(CASE WHEN `is_max_price_ttc`.PROMO=1 THEN `max_price_ttc_data`.PROMO_PRICE ELSE `max_price_ttc_data`.PRICE END) OR `min_price_data`.FROM_DEFAULT_CURRENCY = 1 THEN CASE WHEN `is_max_price_ttc`.PROMO=1 THEN `max_price_ttc_data' . $defaultCurrencySuffix . '`.PROMO_PRICE ELSE `max_price_ttc_data' . $defaultCurrencySuffix . '`.PRICE END * ' . $currency->getRate() . ' ELSE CASE WHEN `is_max_price_ttc`.PROMO=1 THEN `max_price_ttc_data`.PROMO_PRICE ELSE `max_price_ttc_data`.PRICE END END'; } else { $MaxPriceToCompareAsSQL = 'CASE WHEN `is_max_price_ttc`.PROMO=1 THEN `max_price_ttc_data`.PROMO_PRICE ELSE `max_price_ttc_data`.PRICE END'; } $search->where('ROUND(' . $MaxPriceToCompareAsSQL . ', 2)<=?', $maxPriceHt, \PDO::PARAM_STR); } }