getId() => $product]); $productCollection->fetchMeasureUnits(); if ($product instanceof ProductUnifiedWrapper) { $product = $product->getObject(); } if (empty($product->measureUnits)) { return null; } // Select first variation by default or get data for product $data = $product->measureUnits[array_key_first($product->measureUnits)] ?? null; if ($product->getVariationId()) { $data = $product->measureUnits[$product->getVariationId()] ?? null; } if (!$data) { return null; } return $this->calculatePriceUnit($product->getProductPrice(), $data); } public function calculatePriceUnit(ProductPrice $productPrice, array $data): ?array { $measureQuantity = toDecimal($data['measure_quantity'] ?? null); $measureUnit = toDecimal($data['recalculate_to'] ?? null); if (!$measureQuantity->isPositive()) { return null; } if (!$measureUnit->isPositive()) { return null; } $wrapped = PriceWrapper::wrap($productPrice); $price = $wrapped->field_value_without_vat_no_rounding(); $priceWithoutDiscount = $wrapped->field_value_without_vat_without_discount(); $pricePerUnit = $price->div($measureQuantity->div($measureUnit, 4), 4); $priceWithoutDiscountPerUnit = $priceWithoutDiscount->div($measureQuantity->div($measureUnit, 4), 4); $result = [ 'price' => new Price($pricePerUnit, $this->currencyContext->getActive(), $productPrice->getVat()), 'recalculate_to' => $data['recalculate_to'], 'unit_name' => $data['short_name'], ]; if ($priceWithoutDiscountPerUnit->comp($pricePerUnit)) { $result['price_without_discount'] = new Price($priceWithoutDiscountPerUnit, $this->currencyContext->getActive(), $productPrice->getVat()); } return $result; } public function getUnitPriceQueryBuilder(?array $ids = null): \Query\QueryBuilder { $qb = sqlQueryBuilder()->select('p.id id_product, pv.id id_variation, COALESCE(pv.measure_quantity, p.measure_quantity) measure_quantity, pu.recalculate_to, pu.id as id') ->fromProducts() ->joinVariationsOnProducts() ->innerJoin('p', 'products_units', 'pu', 'pu.id = p.measure_unit') ->andWhere(Translation::coalesceTranslatedFields(ProductsUnitsTranslation::class, ['short_name', 'long_name'])); if (findModule(\Modules::PRODUCTS, \Modules::SUB_UNITS_FLOAT)) { $qb->addSelect('pu.pieces_precision as pieces_precision'); } if ($ids) { $qb->andWhere(Operator::inIntArray($ids, 'p.id')); } return $qb; } #[Required] public function setPriceConverter(?PriceConverter $priceConverter): void { $this->priceConverter = $priceConverter; } #[Required] public function setCurrencyContext(CurrencyContext $currencyContext): void { $this->currencyContext = $currencyContext; } }