141 lines
4.5 KiB
PHP
141 lines
4.5 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Created by PhpStorm.
|
|
* User: ondra
|
|
* Date: 23.11.17
|
|
* Time: 8:01.
|
|
*/
|
|
|
|
namespace KupShop\QuantityDiscountBundle\Util;
|
|
|
|
use KupShop\I18nBundle\Util\PriceConverter;
|
|
use KupShop\KupShopBundle\Context\CurrencyContext;
|
|
use KupShop\KupShopBundle\Util\Contexts;
|
|
use KupShop\KupShopBundle\Util\Price\Price;
|
|
use KupShop\KupShopBundle\Util\Price\ProductPrice;
|
|
use KupShop\QuantityDiscountBundle\Context\QuantityDiscountContext;
|
|
use KupShop\QuantityDiscountBundle\Query\QuantityDiscount;
|
|
use Query\Operator;
|
|
use Query\QueryBuilder;
|
|
|
|
class QuantityDiscountPrice
|
|
{
|
|
public function __construct(
|
|
private QuantityDiscountContext $quantityDiscountContext,
|
|
protected ?PriceConverter $priceConverter = null,
|
|
) {
|
|
}
|
|
|
|
public function getPrice($idProduct, $pieces, $idVariation = null): Price
|
|
{
|
|
if ($productPrice = $this->getProductPrice($idProduct, $idVariation)) {
|
|
return $this->applyDiscount($productPrice, $idProduct, $pieces, $idVariation);
|
|
}
|
|
|
|
return new Price(toDecimal(0), Contexts::get(CurrencyContext::class)->getDefault(), getVat());
|
|
}
|
|
|
|
public function applyDiscount(ProductPrice $productPrice, $idProduct, $pieces, $idVariation): Price
|
|
{
|
|
$discountedValue = $this->calculateQuantityDiscountForProductPrice(
|
|
$productPrice,
|
|
$this->getDiscount($idProduct, toDecimal($pieces), $idVariation)
|
|
);
|
|
|
|
return new Price($discountedValue, $productPrice->getCurrency(), $productPrice->getVat());
|
|
}
|
|
|
|
public function calculateQuantityDiscountPriceForProductPrice(ProductPrice $productPrice, array $discount): Price
|
|
{
|
|
return new Price(
|
|
$this->calculateQuantityDiscountForProductPrice($productPrice, $discount),
|
|
$productPrice->getCurrency(),
|
|
$productPrice->getVat()
|
|
);
|
|
}
|
|
|
|
private function calculateQuantityDiscountForProductPrice(ProductPrice $productPrice, ?array $discount): \Decimal
|
|
{
|
|
$value = $productPrice->getPriceWithVat(false)
|
|
->removeVat($productPrice->getVat());
|
|
|
|
if (!$discount) {
|
|
return $value;
|
|
}
|
|
|
|
if ($discount['discount_type'] == QuantityDiscountUtil::DISCOUNT_TYPE_PERC) {
|
|
$value = $value->addDiscount($discount['discount']);
|
|
} else {
|
|
$discountValue = $this->priceConverter?->convert($discount['discount_type'], $productPrice->getCurrency(), $discount['discount']) ?: toDecimal($discount['discount']);
|
|
$value = \Decimal::max($value->sub($discountValue), \DecimalConstants::zero());
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
private function getProductPrice($idProduct, $idVariation = null): ?ProductPrice
|
|
{
|
|
if ($product = $this->getProduct($idProduct, $idVariation)) {
|
|
return $product->getProductPrice();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function getDiscount(
|
|
int $idProduct,
|
|
\Decimal $pieces,
|
|
?int $variationId = null,
|
|
): ?array {
|
|
$active = $this->quantityDiscountContext->getActive();
|
|
if (!$active) {
|
|
return null;
|
|
}
|
|
|
|
$specs = [
|
|
Operator::equals(['id_product' => $idProduct]),
|
|
QuantityDiscount::byGroup($active),
|
|
];
|
|
|
|
if ($variationId) {
|
|
if ($quantityDiscount = $this->getDiscountQueryBuilder($specs,
|
|
$pieces)->andWhere(Operator::equals(['id_variation' => $variationId]))->execute()->fetchAssociative()) {
|
|
return $quantityDiscount;
|
|
}
|
|
}
|
|
|
|
$quantityDiscount = $this->getDiscountQueryBuilder($specs,
|
|
$pieces, )->andWhere('id_variation IS NULL')->execute()->fetchAssociative();
|
|
|
|
return $quantityDiscount ?: null;
|
|
}
|
|
|
|
private function getDiscountQueryBuilder($specs, $pieces): QueryBuilder
|
|
{
|
|
return sqlQueryBuilder()
|
|
->select('discount, discount_type')
|
|
->from('products_quantity_discounts')
|
|
->where('pieces <= :pieces')
|
|
->andWhere(Operator::andX($specs))
|
|
->orderBy('pieces', 'DESC')
|
|
->setParameter('pieces', $pieces)
|
|
->setMaxResults(1);
|
|
}
|
|
|
|
private function getProduct($idProduct, $idVariation = null): ?\Product
|
|
{
|
|
if ($idVariation !== null) {
|
|
$product = new \Variation($idProduct, $idVariation);
|
|
} else {
|
|
$product = new \Product($idProduct);
|
|
}
|
|
|
|
if (!$product->createFromDB()) {
|
|
return null;
|
|
}
|
|
|
|
return $product;
|
|
}
|
|
}
|