/** * Builds the tax cases for the price selection query * @param Struct\ProductContextInterface $context * @return string */ private function buildTaxCase(Struct\ProductContextInterface $context) { $cases = []; foreach ($context->getTaxRules() as $rule) { $cases[] = ' WHEN ' . $rule->getId() . ' THEN ' . $rule->getTax(); } return '(CASE tax.id ' . implode(' ', $cases) . ' END)'; }
private function searchBlog(Criteria $criteria, Struct\ProductContextInterface $context) { /**@var $condition SearchTermCondition*/ $condition = $criteria->getCondition('search'); $query = $this->createMultiMatchQuery($condition); $search = new Search(); $search->addQuery($query); $search->setFrom(0)->setSize(5); $index = $this->indexFactory->createShopIndex($context->getShop()); $params = ['index' => $index->getName(), 'type' => 'blog', 'body' => $search->toArray()]; $raw = $this->client->search($params); return $this->createBlogStructs($raw); }
/** * @inheritdoc */ public function getList($products, Struct\ProductContextInterface $context) { $group = $context->getCurrentCustomerGroup(); $specify = $this->graduatedPricesGateway->getList($products, $group); //iterates the passed prices and products and assign the product unit to the prices and the passed customer group $prices = $this->buildPrices($products, $specify, $group); //check if one of the products have no assigned price within the prices variable. $fallbackProducts = array_filter($products, function (Struct\ListProduct $product) use($prices) { return !array_key_exists($product->getNumber(), $prices); }); if (!empty($fallbackProducts)) { //if some product has no price, we have to load the fallback customer group prices for the fallbackProducts. $fallbackPrices = $this->graduatedPricesGateway->getList($fallbackProducts, $context->getFallbackCustomerGroup()); $fallbackPrices = $this->buildPrices($fallbackProducts, $fallbackPrices, $context->getFallbackCustomerGroup()); $prices = $prices + $fallbackPrices; } $priceGroups = $context->getPriceGroups(); /** * If one of the products has a configured price group, * the graduated prices has to be build over the defined price group graduations. * * The price group discounts are defined with a percentage discount, which calculated * on the first graduated price of the product. */ foreach ($products as $product) { if (!$product->isPriceGroupActive() || !$product->getPriceGroup()) { continue; } if (!isset($prices[$product->getNumber()])) { continue; } $priceGroupId = $product->getPriceGroup()->getId(); if (!isset($priceGroups[$priceGroupId])) { continue; } $priceGroup = $priceGroups[$priceGroupId]; $firstGraduation = array_shift($prices[$product->getNumber()]); $prices[$product->getNumber()] = $this->buildDiscountGraduations($firstGraduation, $context->getCurrentCustomerGroup(), $priceGroup->getDiscounts()); } return $prices; }
/** * Checks if the provided product is allowed to display in the store front for * the provided context. * * @param Struct\ListProduct $product * @param Struct\ProductContextInterface $context * @return bool */ private function isProductValid(Struct\ListProduct $product, Struct\ProductContextInterface $context) { if (in_array($context->getCurrentCustomerGroup()->getId(), $product->getBlockedCustomerGroupIds())) { return false; } $prices = $product->getPrices(); if (empty($prices)) { return false; } if (!$product->hasAvailableVariant()) { return false; } return true; }
/** * Returns the highest price group discount for the provided product. * * The price groups are stored in the provided context object. * If the product has no configured price group or the price group has no discount defined for the * current customer group, the function returns null. * * @param Struct\ListProduct $product * @param Struct\ProductContextInterface $context * @param $quantity * @return null|Struct\Product\PriceDiscount */ private function getHighestQuantityDiscount(Struct\ListProduct $product, Struct\ProductContextInterface $context, $quantity) { $priceGroups = $context->getPriceGroups(); if (empty($priceGroups)) { return null; } $id = $product->getPriceGroup()->getId(); if (!isset($priceGroups[$id])) { return null; } $priceGroup = $priceGroups[$id]; /**@var $highest Struct\Product\PriceDiscount*/ $highest = null; foreach ($priceGroup->getDiscounts() as $discount) { if ($discount->getQuantity() > $quantity) { continue; } if (!$highest) { $highest = $discount; continue; } if ($highest->getPercent() < $discount->getPercent()) { $highest = $discount; } } return $highest; }
/** * Helper function which calculates a single price value. * The function subtracts the percentage customer group discount if * it should be considered and decides over the global state if the * price should be calculated gross or net. * The function is used for the original price value of a price struct * and the pseudo price of a price struct. * * @param $price * @param Struct\Tax $tax * @param Struct\ProductContextInterface $context * @return float */ private function calculatePrice($price, Struct\Tax $tax, Struct\ProductContextInterface $context) { /** * Important: * We have to use the current customer group of the current user * and not the customer group of the price. * * The price could be a price of the fallback customer group * but the discounts and gross calculation should be used from * the current customer group! */ $customerGroup = $context->getCurrentCustomerGroup(); /** * Basket discount calculation: * * Check if a global basket discount is configured and reduce the price * by the percentage discount value of the current customer group. */ if ($customerGroup->useDiscount() && $customerGroup->getPercentageDiscount()) { if ($customerGroup->getPercentageDiscount() != 0) { $price = $price - $price / 100 * $customerGroup->getPercentageDiscount(); } else { $price = 0; } } /** * Currency calculation: * If the customer is currently in a sub shop with another currency, like dollar, * we have to calculate the the price for the other currency. */ $price = $price * $context->getCurrency()->getFactor(); /** * check if the customer group should see gross prices. */ if (!$customerGroup->displayGrossPrices()) { return round($price, 3); } /** * Gross calculation: * * This line contains the gross price calculation within the store front. * * The passed $context object contains a calculated Struct\Tax object which * defines which tax rules should be used for the tax calculation. * * The tax rules can be defined individual for each customer group and * individual for each area, country and state. * * For example: * - The EK customer group has different configured HIGH-TAX rules. * - In area Europe, in country Germany the global tax value are set to 19% * - But in area Europe, in country Germany, in state Bayern, the tax value are set to 20% * - But in area Europe, in country Germany, in state Berlin, the tax value are set to 18% */ $price = $price * (100 + $tax->getTax()) / 100; return round($price, 3); }
/** * Checks if the provided product is allowed to display in the store front for * the provided context. * * @param Struct\ListProduct $product * @param Struct\ProductContextInterface $context * @return bool */ private function isProductValid(Struct\ListProduct $product, Struct\ProductContextInterface $context) { if (in_array($context->getCurrentCustomerGroup()->getId(), $product->getBlockedCustomerGroupIds())) { return false; } $prices = $product->getPrices(); if (empty($prices)) { return false; } if (!$product->hasAvailableVariant()) { return false; } $ids = array_map(function (Struct\Category $category) { return $category->getId(); }, $product->getCategories()); return in_array($context->getShop()->getCategory()->getId(), $ids); }