Adjust an original price according to applied price rules
@param array $item
@param \gplcart\core\models\Product $product_model
348350
public function setItemPriceCalculated(array &$item, $product_model)
    {
        $calculated = $product_model->calculate($item);

        if ($item['price'] != $calculated) {
            $item['original_price'] = $item['price'];
        }

        $item['price'] = $calculated;
    }
709685
public function addItem(Item $item) {
        if(empty($item->title) && empty($item->description)) {
            throw new Exception('At least one of title or description must be defined.');
        }

        $this->items[] = $item;
    }
415850
public function addItem(Item $item)
    {
        if (!$this->items->contains($item)) {
            $this->items->add($item);
            $item->setStudio($this);
        }

        return $this;
    }
754200
public function set($item, $value = null)
    {
        if (is_array($item)) {
            foreach($item as $key => $val){
                $this->custom[$key] = $val;
            }
        } else {
            $this->custom[$item] = $value;
        }
        return $this;
    }
582266
protected function setItems()
    {
        foreach ($this->sgBase->getItems() as $item) {
            if ($item->isSgCoupon()) {
                continue;
            }

            $info        = $item->getInternalOrderInfo();
            $amountNet   = $item->getUnitAmount();
            $amountGross = $item->getUnitAmountWithTax();

            try {
                $product = $this->productHelper->loadById($info->getProductId());
            } catch (\Exception $e) {
                $product = null;
            }

            if (!is_object($product) || !$product->getId() || $product->getStatus() != MageStatus::STATUS_ENABLED) {
                $this->log->error('Product with ID ' . $info->getProductId() . ' could not be loaded.');
                $this->log->error('SG item number: ' . $item->getItemNumber());
                $item->setUnhandledError(\ShopgateLibraryException::CART_ITEM_PRODUCT_NOT_FOUND, 'product not found');
                continue;
            }

            try {
                $quoteItem = $this->getQuoteItem($item, $product);
                if ($this->useShopgatePrices()) {
                    if ($this->taxData->priceIncludesTax($this->storeManager->getStore())) {
                        $quoteItem->setCustomPrice($amountGross);
                        $quoteItem->setOriginalCustomPrice($amountGross);
                    } else {
                        $quoteItem->setCustomPrice($amountNet);
                        $quoteItem->setOriginalCustomPrice($amountNet);
                    }
                }
                $quoteItem->setTaxPercent($item->getTaxPercent());

                if (!$item->isSimple()) {
                    $productWeight = $product->getTypeInstance()->getWeight($product);
                    $quoteItem->setWeight($productWeight);
                }

                $quoteItem->setRowWeight($quoteItem->getWeight() * $quoteItem->getQty());
                $this->quote->setItemsCount($this->quote->getItemsCount() + 1);
            } catch (\Exception $e) {
                $this->log->error(
                    "Error importing product to quote by id: {$product->getId()}, error: {$e->getMessage()}"
                );
                $this->log->error('SG item number: ' . $item->getItemNumber());
                $item->setMagentoError($e->getMessage());
            }
        }

        /**
         * Magento's flow is to save Quote on addItem, then on saveOrder load quote again. We mimic this here.
         */
        $this->quoteRepository->save($this->quote);
        $this->quote = $this->quoteRepository->get($this->quote->getId());
    }
1276120
public function setItem(Item $item)
    {
        $this->childOf = $item->id;
        $this->_item = $item;
        
        return $this;
    }
615823
public function calculateItemNetPrice($item, $currency = null, $useProductsPrice = null, $isGrossPrice = false)
    {
        $currency = $this->getCurrency($currency);

        if ($useProductsPrice === null) {
            $useProductsPrice = $item->getUseProductsPrice();
        }

        // Validate item
        $this->validateItem($item);

        $priceValue = $item->getPrice();

        if ($useProductsPrice && ($item->getCalcProduct() || $item->getAddon())) {
            $priceValue = $this->getValidProductNetPriceForItem($item, $currency);
        } elseif ($isGrossPrice) {
            // Handle gross prices.
            $tax = $item->getTax();
            if ($tax > 0) {
                $priceValue = ($priceValue / (100 + $tax)) * 100;
            }
        }

        return $priceValue;
    }
311040
public function setItemModel(core_kernel_classes_Resource $item, core_kernel_classes_Resource $model)
    {
        return $item->editPropertyValues($this->getProperty(self::PROPERTY_ITEM_MODEL), $model);
    }
1039153
protected function setPriceRules(array $order)
    {
        foreach (array_keys($order['data']['components']) as $component_id) {
            if (is_numeric($component_id)) {
                $rule = $this->price_rule->get($component_id);
                if (isset($rule['code']) && $rule['code'] !== '') {
                    $this->price_rule->setUsed($rule['price_rule_id']);
                }
            }
        }
    }
959157
protected function getItemLineOrder($item)
    {
        $result = array();

        $this->addPropertySource('item', $item);

        $this->addProductInfo($result);

        // For higher precision of the unit price, we will recalculate the price
        // ex vat if product prices are entered inc vat by the admin.
        $productPriceEx = (float) $item->getBasePrice();
        $productPriceInc = (float) $item->getBasePriceInclTax();

        // Check for cost price and margin scheme.
        if (!empty($line['costPrice']) && $this->allowMarginScheme()) {
            // Margin scheme:
            // - Do not put VAT on invoice: send price incl VAT as unitprice.
            // - But still send the VAT rate to Acumulus.
            $result[Tag::UnitPrice] = $productPriceInc;
        } else {
            $result += array(
                Tag::UnitPrice => $productPriceEx,
                Meta::UnitPriceInc => $productPriceInc,
                Meta::RecalculatePrice => $this->productPricesIncludeTax() ? Tag::UnitPrice : Meta::UnitPriceInc,
            );
        }
        $result[Tag::Quantity] = $item->getQtyOrdered();

        // Tax amount = VAT over discounted product price.
        // Hidden tax amount = VAT over discount.
        // Tax percent = VAT % as specified in product settings, for the parent
        // of bundled products this may be 0 and incorrect.
        // But as discounts get their own lines and the product lines are
        // showing the normal (not discounted) price we add these 2.
        $vatRate = (float) $item->getTaxPercent();
        $lineVat = (float) $item->getBaseTaxAmount() + (float) $item->getBaseDiscountTaxCompensationAmount();

        // Add VAT related info.
        $childrenItems = $item->getChildrenItems();
        if (Number::isZero($vatRate) && !empty($childrenItems)) {
            // 0 VAT rate on parent: this is (very very) probably not correct.
            $result += array(
                Tag::VatRate => null,
                Meta::VatRateSource => Creator::VatRateSource_Completor,
                Meta::VatRateLookup => $vatRate,
                Meta::VatRateLookupSource => '$item->getTaxPercent()',
            );
        } else {
            // No 0 VAT or not a parent product: the vat rate is real.
            $result += array(
                Tag::VatRate => $vatRate,
                Meta::VatRateSource => Number::isZero($vatRate) ? Creator::VatRateSource_Exact0 : Creator::VatRateSource_Exact,
            );
        }
        $result += array(
            Meta::LineVatAmount => $lineVat,
        );

        // Add vat meta data.
        $product = $item->getProduct();
        if ($product) {
            /** @noinspection PhpUndefinedMethodInspection */
            $result += $this->getVatClassMetaData((int) $product->getTaxClassId());
        }

        // Add discount related info.
        if (!Number::isZero($item->getBaseDiscountAmount())) {
            // Store discount on this item to be able to get correct discount
            // lines later on in the completion phase.
            $result[Meta::LineDiscountAmountInc] = -$item->getBaseDiscountAmount();
        }

        // Add children lines for composed products.
        if (!empty($childrenItems)) {
            $result[Meta::ChildrenLines] = array();
            foreach ($childrenItems as $child) {
                $result[Meta::ChildrenLines][] = $this->getItemLineOrder($child);
            }
        }

        $this->removePropertySource('item');

        return $result;
    }
298299
protected function getItemLine(stdClass $item)
    {
        $result = array();
        $this->addPropertySource('item', $item);

        $this->addProductInfo($result);

        $productPriceEx = (float) $item->product_discountedPriceWithoutTax;
        $productPriceInc = (float) $item->product_final_price;
        $productVat = (float) $item->product_tax;

        $calcRule = $this->getCalcRule('VatTax', $item->virtuemart_order_item_id);
        if (!empty($calcRule->calc_value)) {
            $vatInfo = array(
                Tag::VatRate => (float) $calcRule->calc_value,
                Meta::VatRateSource => static::VatRateSource_Exact,
                Meta::VatClassId => $calcRule->virtuemart_calc_id,
                Meta::VatClassName => $calcRule->calc_rule_name,
            );
        } else {
            $vatInfo = $this->getVatRangeTags($productVat, $productPriceEx, $this->precision, $this->precision);
        }

        // Check for cost price and margin scheme.
        if (!empty($line['costPrice']) && $this->allowMarginScheme()) {
            // Margin scheme:
            // - Do not put VAT on invoice: send price incl VAT as unitprice.
            // - But still send the VAT rate to Acumulus.
            $result[Tag::UnitPrice] = $productPriceInc;
        } else {
            $result += array(
                Tag::UnitPrice => $productPriceEx,
                Meta::UnitPriceInc => $productPriceInc,
                Meta::VatAmount => $productVat,
            );
        }
        $result[Tag::Quantity] = $item->product_quantity;
        $result += $vatInfo;

        // Add variant info.
        $children = $this->getVariantLines($item, $result[Tag::Quantity], $vatInfo);
        if (!empty($children)) {
            $result[Meta::ChildrenLines] = $children;
        }

        $this->removePropertySource('item');

        return $result;
    }
1353393
public function addItem(Item $item)
    {
        if (!$this->items->contains($item)) {
            $this->items->add($item);
            $item->setType($this);
        }

        return $this;
    }
157833
protected function validateItem($item)
    {
        // validate not null
        $this->validateNotNull('quantity', $item->getCalcQuantity());

        // validate discount
        $discountPercent = $item->getCalcDiscount();
        if ($discountPercent < 0 || $discountPercent > 100) {
            throw new PriceCalculationException('Discount must be within 0 and 100 percent');
        }
    }
216869
private function getValidProductPriceForItem($item, $currency)
    {
        $product = $item->getCalcProduct();
        $specialPriceValue = null;
        $bulkPriceValue = null;

        //get special price
        $specialPrice = $this->priceManager->getSpecialPriceForCurrency($product, $currency);
        if ($specialPrice) {
            $specialPriceValue = $specialPrice->getPrice();
        }

        //get bulk price
        $bulkPrice = $this->priceManager->getBulkPriceForCurrency($product, $item->getCalcQuantity(), $currency);
        if ($bulkPrice) {
            $bulkPriceValue = $bulkPrice->getPrice();
        }

        //take the smallest
        if(!empty($specialPriceValue) && !empty($bulkPriceValue)) {
            $priceValue = $specialPriceValue;
            if ($specialPriceValue > $bulkPriceValue) {
                $priceValue = $bulkPriceValue;
            }
        } elseif (!empty($specialPriceValue)) {
            $priceValue = $specialPriceValue;
        } else {
            $priceValue = $bulkPriceValue;
        }

        // no price set - return 0
        if (empty($priceValue)) {
            return 0;
        }

        return $priceValue;
    }
1264634
public function setItem(Item $item)
    {
        if ($this->item !== $item) {
            $this->item = $item->setType($this);
        }

        return $this;
    }
1048070
protected function processSingleProductSaleElementUpdate($data)
    {
        $event = new ProductSaleElementUpdateEvent(
            $this->getExistingObject(),
            $data['product_sale_element_id']
        );

        $event
            ->setReference($data['reference'])
            ->setPrice($data['price'])
            ->setCurrencyId($data['currency'])
            ->setWeight($data['weight'])
            ->setQuantity($data['quantity'])
            ->setSalePrice($data['sale_price'])
            ->setOnsale($data['onsale'])
            ->setIsnew($data['isnew'])
            ->setIsdefault($data['isdefault'])
            ->setEanCode($data['ean_code'])
            ->setTaxRuleId($data['tax_rule'])
            ->setFromDefaultCurrency($data['use_exchange_rate'])
        ;

        $this->dispatch(TheliaEvents::PRODUCT_UPDATE_PRODUCT_SALE_ELEMENT, $event);

        // Log object modification
        if (null !== $changedObject = $event->getProductSaleElement()) {
            $this->adminLogAppend(
                $this->resourceCode,
                AccessManager::UPDATE,
                sprintf(
                    "Product Sale Element (ID %s) for product reference %s modified",
                    $changedObject->getId(),
                    $event->getProduct()->getRef()
                ),
                $changedObject->getId()
            );
        }
    }
1327395
public function calculateItemTotalNetPrice($item, $currency = null, $useProductsPrice = true, $isGrossPrice = false)
    {
        $priceValue = $this->calculateItemNetPrice($item, $currency, $useProductsPrice, $isGrossPrice);

        if ($priceValue === null) {
            $priceValue = 0;
        }

        if ($item->getPrice() && $item->getPrice() !== $priceValue) {
            $item->setPriceChange($item->getPrice(), $priceValue);
        }

        $itemPrice = $priceValue * $item->getCalcQuantity();

        // Calculate items discount.
        $discount = ($itemPrice / 100) * $item->getCalcDiscount();

        // Calculate total item price.
        $totalPrice = $itemPrice - $discount;

        return $totalPrice;
    }