116 lines
4.0 KiB
PHP
116 lines
4.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KupShop\UnitsBundle\Utils;
|
|
|
|
use KupShop\CatalogBundle\ProductList\ProductCollection;
|
|
use KupShop\ContentBundle\Entity\ProductUnified;
|
|
use KupShop\ContentBundle\Entity\Wrapper\ProductUnifiedWrapper;
|
|
use KupShop\I18nBundle\Translations\ProductsUnitsTranslation;
|
|
use KupShop\I18nBundle\Util\PriceConverter;
|
|
use KupShop\KupShopBundle\Context\CurrencyContext;
|
|
use KupShop\KupShopBundle\Util\Price\Price;
|
|
use KupShop\KupShopBundle\Util\Price\ProductPrice;
|
|
use KupShop\KupShopBundle\Wrapper\PriceWrapper;
|
|
use Query\Operator;
|
|
use Query\Translation;
|
|
use Symfony\Contracts\Service\Attribute\Required;
|
|
|
|
class MeasureUnitUtil
|
|
{
|
|
protected ?PriceConverter $priceConverter;
|
|
protected CurrencyContext $currencyContext;
|
|
|
|
public function getUnitPrice(ProductUnified|ProductUnifiedWrapper $product, bool $round = false): ?array
|
|
{
|
|
$productCollection = new ProductCollection([$product->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;
|
|
}
|
|
}
|