/** * Apply percentage discount * * @param Product $product * @param float|null $value * @return float|null */ public function calculateDiscount(Product $product, $value = null) { if ($value === null) { $value = $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue(); } $discount = null; foreach ($product->getPriceInfo()->getPrices() as $price) { if ($price instanceof DiscountProviderInterface && $price->getDiscountPercent()) { $discount = min($price->getDiscountPercent(), $discount ?: $price->getDiscountPercent()); } } return null !== $discount ? $discount / 100 * $value : $value; }
/** * Get the price value for one of selection product * * @return bool|float */ public function getValue() { if (null !== $this->value) { return $this->value; } $priceCode = $this->useRegularPrice ? BundleRegularPrice::PRICE_CODE : FinalPrice::PRICE_CODE; if ($this->bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC) { // just return whatever the product's value is $value = $this->priceInfo->getPrice($priceCode)->getValue(); } else { // don't multiply by quantity. Instead just keep as quantity = 1 $selectionPriceValue = $this->selection->getSelectionPriceValue(); if ($this->product->getSelectionPriceType()) { // calculate price for selection type percent $price = $this->bundleProduct->getPriceInfo()->getPrice(CatalogPrice\RegularPrice::PRICE_CODE)->getValue(); $product = clone $this->bundleProduct; $product->setFinalPrice($price); $this->eventManager->dispatch('catalog_product_get_final_price', ['product' => $product, 'qty' => $this->bundleProduct->getQty()]); $value = $product->getData('final_price') * ($selectionPriceValue / 100); } else { // calculate price for selection type fixed $value = $this->priceCurrency->convert($selectionPriceValue) * $this->quantity; } } if (!$this->useRegularPrice) { $value = $this->discountCalculator->calculateDiscount($this->bundleProduct, $value); } $this->value = $this->priceCurrency->round($value); return $this->value; }
/** * Get product final price * * @param float $qty * @param \Magento\Catalog\Model\Product $product * @return float */ public function getFinalPrice($qty, $product) { if ($qty === null && $product->getCalculatedFinalPrice() !== null) { return $product->getCalculatedFinalPrice(); } if ($product->getCustomOption('simple_product')) { $product->setSelectedConfigurableOption($product->getCustomOption('simple_product')->getProduct()); } //TODO: MAGETWO-23739 catalogrule price must get from simple product. $finalPrice = $product->getPriceInfo()->getPrice('final_price')->getAmount()->getValue(); $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice); $finalPrice = max(0, $finalPrice); $product->setFinalPrice($finalPrice); return $finalPrice; }
/** * Get product final price * * @param float $qty * @param \Magento\Catalog\Model\Product $product * @return float */ public function getFinalPrice($qty, $product) { if ($qty === null && $product->getCalculatedFinalPrice() !== null) { return $product->getCalculatedFinalPrice(); } if ($product->getCustomOption('simple_product') && $product->getCustomOption('simple_product')->getProduct()) { $finalPrice = parent::getFinalPrice($qty, $product->getCustomOption('simple_product')->getProduct()); } else { $priceInfo = $product->getPriceInfo(); $finalPrice = $priceInfo->getPrice('final_price')->getAmount()->getValue(); } $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice); $finalPrice = max(0, $finalPrice); $product->setFinalPrice($finalPrice); return $finalPrice; }
/** * Get the price value for one of selection product * * @return bool|float */ public function getValue() { if (null !== $this->value) { return $this->value; } if ($this->bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC) { $value = $this->priceInfo->getPrice(FinalPrice::PRICE_CODE)->getValue(); } else { if ($this->product->getSelectionPriceType()) { // calculate price for selection type percent $price = $this->bundleProduct->getPriceInfo()->getPrice(CatalogPrice\RegularPrice::PRICE_CODE)->getValue(); $product = clone $this->bundleProduct; $product->setFinalPrice($price); $this->eventManager->dispatch('catalog_product_get_final_price', array('product' => $product, 'qty' => $this->bundleProduct->getQty())); $value = $product->getData('final_price') * ($this->product->getSelectionPriceValue() / 100); } else { // calculate price for selection type fixed $value = $this->product->getSelectionPriceValue() * $this->quantity; } } $this->value = $this->discountCalculator->calculateDiscount($this->bundleProduct, $value); return $this->value; }
/** * Test reload PriceInfo */ public function testReloadPriceInfo() { $this->productTypeInstanceMock->expects($this->exactly(2))->method('getPriceInfo')->with($this->equalTo($this->model))->will($this->returnValue($this->_priceInfoMock)); $this->assertEquals($this->_priceInfoMock, $this->model->getPriceInfo()); $this->assertEquals($this->_priceInfoMock, $this->model->reloadPriceInfo()); }
/** * Get bundle options * * @param Product $saleableItem * @return \Magento\Bundle\Model\Resource\Option\Collection */ protected function getBundleOptions(Product $saleableItem) { /** @var BundleOptionPrice $bundlePrice */ $bundlePrice = $saleableItem->getPriceInfo()->getPrice(BundleOptionPrice::PRICE_CODE); return $bundlePrice->getOptions(); }
/** * Set current attribute to entry (for specified product) * * @param \Magento\Catalog\Model\Product $product * @param \Magento\Framework\Gdata\Gshopping\Entry $entry * @return \Magento\Framework\Gdata\Gshopping\Entry * @throws \Magento\Framework\Exception\LocalizedException */ public function convertAttribute($product, $entry) { $entry->cleanTaxes(); if ($this->_taxData->getConfig()->priceIncludesTax()) { return $entry; } $defaultCustomerTaxClassId = $this->_getDefaultCustomerTaxClassId($product->getStoreId()); $rates = $this->_taxRateManagement->getRatesByCustomerAndProductTaxClassId($defaultCustomerTaxClassId, $product->getTaxClassId()); $targetCountry = $this->_config->getTargetCountry($product->getStoreId()); $ratesTotal = 0; foreach ($rates as $rate) { $countryId = $rate->getTaxCountryId(); $postcode = $rate->getTaxPostcode(); if ($targetCountry == $countryId) { $regions = $this->_getRegionsByRegionId($rate->getTaxRegionId(), $postcode); $ratesTotal += count($regions); if ($ratesTotal > self::RATES_MAX) { throw new \Magento\Framework\Exception\LocalizedException(__('Google shopping only supports %1 tax rates per product', self::RATES_MAX)); } foreach ($regions as $region) { $adjustments = $product->getPriceInfo()->getAdjustments(); if (array_key_exists('tax', $adjustments)) { $taxIncluded = true; } else { $taxIncluded = false; } $quoteDetailsItemDataArray = ['code' => $product->getSku(), 'type' => 'product', 'tax_class_key' => [TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, TaxClassKeyInterface::KEY_VALUE => $product->getTaxClassId()], 'unit_price' => $product->getPrice(), 'quantity' => 1, 'tax_included' => $taxIncluded, 'short_description' => $product->getName()]; $billingAddressDataArray = ['country_id' => $countryId, 'region' => ['region_id' => $rate->getTaxRegionId()], 'postcode' => $postcode]; $shippingAddressDataArray = ['country_id' => $countryId, 'region' => ['region_id' => $rate->getTaxRegionId()], 'postcode' => $postcode]; $quoteDetailsDataArray = ['billing_address' => $billingAddressDataArray, 'shipping_address' => $shippingAddressDataArray, 'customer_tax_class_key' => [TaxClassKeyInterface::KEY_TYPE => TaxClassKeyInterface::TYPE_ID, TaxClassKeyInterface::KEY_VALUE => $defaultCustomerTaxClassId], 'items' => [$quoteDetailsItemDataArray]]; $quoteDetailsObject = $this->_quoteDetailsFactory->create(); $this->dataObjectHelper->populateWithArray($quoteDetailsObject, $quoteDetailsDataArray, '\\Magento\\Tax\\Api\\Data\\QuoteDetailsInterface'); $taxDetails = $this->_taxCalculationService->calculateTax($quoteDetailsObject, $product->getStoreId()); $taxRate = $taxDetails->getTaxAmount() / $taxDetails->getSubtotal() * 100; $entry->addTax(['tax_rate' => $taxRate, 'tax_country' => $countryId, 'tax_region' => $region]); } } } return $entry; }
/** * {@inheritdoc} */ public function getPriceInfo() { $pluginInfo = $this->pluginList->getNext($this->subjectType, 'getPriceInfo'); if (!$pluginInfo) { return parent::getPriceInfo(); } else { return $this->___callPlugins('getPriceInfo', func_get_args(), $pluginInfo); } }
/** * Get formed config data from calculated options data * * @param Product $product * @param array $options * @return array */ private function getConfigData(Product $product, array $options) { $isFixedPrice = $this->getProduct()->getPriceType() == \Magento\Bundle\Model\Product\Price::PRICE_TYPE_FIXED; $productAmount = $product->getPriceInfo()->getPrice(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE)->getPriceWithoutOption(); $baseProductAmount = $product->getPriceInfo()->getPrice(\Magento\Catalog\Pricing\Price\RegularPrice::PRICE_CODE)->getAmount(); $config = ['options' => $options, 'selected' => $this->selectedOptions, 'bundleId' => $product->getId(), 'priceFormat' => $this->localeFormat->getPriceFormat(), 'prices' => ['oldPrice' => ['amount' => $isFixedPrice ? $baseProductAmount->getValue() : 0], 'basePrice' => ['amount' => $isFixedPrice ? $productAmount->getBaseAmount() : 0], 'finalPrice' => ['amount' => $isFixedPrice ? $productAmount->getValue() : 0]], 'priceType' => $product->getPriceType(), 'isFixedPrice' => $isFixedPrice]; return $config; }