292 lines
8.7 KiB
PHP
292 lines
8.7 KiB
PHP
<?php
|
|
|
|
namespace KupShop\FeedsBundle\Utils;
|
|
|
|
use KupShop\FeedGeneratorBundle\Expressions\ExpressionObjectTrait;
|
|
use KupShop\FeedGeneratorBundle\Expressions\IExpressionObject;
|
|
use KupShop\FeedGeneratorBundle\Utils\IObjectInfo;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
use KupShop\KupShopBundle\Util\Price\Price;
|
|
use KupShop\KupShopBundle\Util\Price\PriceCalculator;
|
|
use KupShop\KupShopBundle\Wrapper\PriceWrapper;
|
|
use KupShop\OrderingBundle\Entity\Purchase\ProductPurchaseItem;
|
|
use KupShop\OrderingBundle\Entity\Purchase\PurchaseState;
|
|
use KupShop\OrderingBundle\Exception\DeliveryException;
|
|
use KupShop\OrderingBundle\Util\Purchase\PurchaseUtil;
|
|
|
|
class DeliveryWrapper implements IExpressionObject, IObjectInfo, \ArrayAccess
|
|
{
|
|
use ExpressionObjectTrait;
|
|
|
|
/** @var \Delivery */
|
|
private $delivery;
|
|
|
|
/** @var PriceWrapper */
|
|
private $price;
|
|
|
|
/** @var PriceWrapper */
|
|
private $priceWithCOD;
|
|
|
|
/** @var PriceWrapper */
|
|
private $freeDeliveryPriceWithCOD;
|
|
|
|
/** @var Price */
|
|
private $dtPriceDontCountinFrom;
|
|
|
|
/** @var Price */
|
|
private $dtPriceDontCountinFromCOD;
|
|
|
|
/** @var \Product */
|
|
private $product;
|
|
|
|
private static ?PurchaseUtil $purchaseUtil = null;
|
|
|
|
public function __construct(\Delivery $delivery)
|
|
{
|
|
$this->delivery = $delivery;
|
|
}
|
|
|
|
/**
|
|
* This method should only be used from \KupShop\FeedsBundle\Wrapper\DeliveryWrapper.
|
|
*
|
|
* @private
|
|
*/
|
|
public function setProduct(\Product $product)
|
|
{
|
|
$this->product = $product;
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
public function processDeliveryType(\DeliveryType $deliveryType)
|
|
{
|
|
$payment = $deliveryType->getPayment();
|
|
|
|
if (isset($payment) && $payment->getPayMethod() === \Payment::METHOD_COD) {
|
|
$this->setMinimalPrice($this->priceWithCOD, $deliveryType->getPrice());
|
|
// minimal payment price (COD only)
|
|
$this->setMinimalPrice($this->freeDeliveryPriceWithCOD, $deliveryType->price_payment);
|
|
}
|
|
|
|
if (isset($payment) && in_array($payment->getPayMethod(), [\Payment::METHOD_TRANSFER, \Payment::METHOD_ONLINE])) {
|
|
$this->setMinimalPrice($this->price, $deliveryType->getPrice());
|
|
}
|
|
|
|
// set minimal priceDontCountinFrom from delivery type
|
|
if ($dtPriceDontCountinFrom = $deliveryType->getPriceDontCountinFrom()) {
|
|
if (isset($payment) && $payment->getPayMethod() === \Payment::METHOD_COD) {
|
|
if (!isset($this->dtPriceDontCountinFromCOD)
|
|
|| $dtPriceDontCountinFrom->getPriceWithVat()->lowerThan($this->dtPriceDontCountinFromCOD->getPriceWithVat())) {
|
|
$this->dtPriceDontCountinFromCOD = $dtPriceDontCountinFrom;
|
|
}
|
|
} else {
|
|
if (!isset($this->dtPriceDontCountinFrom)
|
|
|| $dtPriceDontCountinFrom->getPriceWithVat()->lowerThan($this->dtPriceDontCountinFrom->getPriceWithVat())) {
|
|
$this->dtPriceDontCountinFrom = $dtPriceDontCountinFrom;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function setMinimalPrice(?PriceWrapper &$currentPrice = null, ?Price $newPrice = null)
|
|
{
|
|
if (!isset($newPrice)) {
|
|
return;
|
|
}
|
|
if (!isset($currentPrice) || $newPrice->getPriceWithVat()->lowerThan($currentPrice->field_value_with_vat())) {
|
|
$currentPrice = PriceWrapper::wrap($newPrice);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
public function getDelivery(): \Delivery
|
|
{
|
|
return $this->delivery;
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
public function getFinalPrice(\Product $product): ?\Decimal
|
|
{
|
|
if (isset($this->dtPriceDontCountinFrom)
|
|
&& PriceCalculator::firstLower($this->dtPriceDontCountinFrom, $product->getProductPrice())
|
|
) {
|
|
return \Decimal::fromInteger(0);
|
|
}
|
|
|
|
$hasFreeDelivery = isset($product->campaign_codes['Z']) || (
|
|
$this->delivery->getPriceDontCountinFromDelivery()
|
|
&& PriceCalculator::firstLower($this->delivery->getPriceDontCountinFromDelivery(), $product->getProductPrice())
|
|
);
|
|
|
|
if ($hasFreeDelivery) {
|
|
return \Decimal::fromInteger(0);
|
|
} elseif (isset($this->price)) {
|
|
return $this->price->field_value_with_vat();
|
|
} elseif ($this->priceWithCOD) {
|
|
return $this->priceWithCOD->field_value_with_vat();
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
public function hasCOD(): bool
|
|
{
|
|
return isset($this->priceWithCOD);
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
public function getFinalPriceWithCOD(\Product $product): ?\Decimal
|
|
{
|
|
if (isset($this->dtPriceDontCountinFromCOD)
|
|
&& PriceCalculator::firstLower($this->dtPriceDontCountinFromCOD, $product->getProductPrice())
|
|
) {
|
|
return \Decimal::fromInteger(0);
|
|
}
|
|
|
|
$hasFreeDelivery = isset($product->campaign_codes['Z']) || (
|
|
$this->delivery->getPriceDontCountinFromDelivery()
|
|
&& PriceCalculator::firstLower($this->delivery->getPriceDontCountinFromDelivery(), $product->getProductPrice())
|
|
);
|
|
|
|
if ($hasFreeDelivery) {
|
|
return isset($this->freeDeliveryPriceWithCOD) ? $this->freeDeliveryPriceWithCOD->field_value_with_vat() : \Decimal::fromInteger(0);
|
|
} elseif (isset($this->priceWithCOD)) {
|
|
return $this->priceWithCOD->field_value_with_vat();
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return \Decimal|null
|
|
*
|
|
* @private
|
|
*/
|
|
public function getPriceDontCountinFrom()
|
|
{
|
|
if ($this->dtPriceDontCountinFrom) {
|
|
return $this->dtPriceDontCountinFrom->getPriceWithVat();
|
|
}
|
|
|
|
if ($this->delivery->getPriceDontCountinFromDelivery()) {
|
|
return $this->delivery->getPriceDontCountinFromDelivery()->getPriceWithVat();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Spustí kontrolu restrikcí pro aktuální produkt a vrací `true` / `false`. Pokud vrátí `true`, tak byla
|
|
* kontrola restrikcí úspěšná a produkt je možné danou dopravou poslat.
|
|
*/
|
|
public function checkRestrictions(): bool
|
|
{
|
|
try {
|
|
$this->delivery->checkSoftRestrictions(
|
|
$this->getProductPurchaseState()
|
|
);
|
|
} catch (DeliveryException $e) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/** Název dopravy.
|
|
*/
|
|
public function field_name(): string
|
|
{
|
|
return $this->delivery->name ?? '';
|
|
}
|
|
|
|
/** Umožnuje doprava dobírku.
|
|
*/
|
|
public function field_cod(): bool
|
|
{
|
|
return $this->hasCOD();
|
|
}
|
|
|
|
/** Cena dopravy.
|
|
*/
|
|
public function field_final_price(): ?float
|
|
{
|
|
$price = $this->getFinalPrice($this->product);
|
|
|
|
return isset($price) ? $price->asFloat() : null;
|
|
}
|
|
|
|
/** Cena dopravy včetně dobírky.
|
|
*/
|
|
public function field_final_price_with_cod(): ?float
|
|
{
|
|
if ($this->hasCOD()) {
|
|
$price = $this->getFinalPriceWithCOD($this->product);
|
|
} else {
|
|
$price = $this->getFinalPrice($this->product);
|
|
}
|
|
|
|
return isset($price) ? $price->asFloat() : null;
|
|
}
|
|
|
|
/**
|
|
* Částka od které se nemá započítávat cena dopravy.
|
|
*
|
|
* Nemusí být definována.
|
|
*
|
|
* @return float|null
|
|
*/
|
|
public function field_price_dont_countin_from()
|
|
{
|
|
return $this->getPriceDontCountinFrom() ? $this->getPriceDontCountinFrom()->asFloat() : $this->getPriceDontCountinFrom();
|
|
}
|
|
|
|
/** Heureka DELIVERY_ID */
|
|
public function field_heureka_id(): string
|
|
{
|
|
return $this->delivery->getHeurekaDeliveryID() ?? '';
|
|
}
|
|
|
|
/** Zbozi DELIVERY_ID */
|
|
public function field_zbozi_id(): string
|
|
{
|
|
return $this->delivery->getZboziDeliveryID() ?? '';
|
|
}
|
|
|
|
/** Státy, pro které je doprava povolena */
|
|
public function field_countries(): array
|
|
{
|
|
return $this->delivery->getSupportedCountries();
|
|
}
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
private function getProductPurchaseState(): PurchaseState
|
|
{
|
|
if (!static::$purchaseUtil) {
|
|
static::$purchaseUtil = ServiceContainer::getService(PurchaseUtil::class);
|
|
}
|
|
|
|
if (!isset($this->product->feedPurchaseState)) {
|
|
$productPurchaseItem = new ProductPurchaseItem($this->product->id, $this->product->variationId ?? null, 1, $this->product->getProductPrice(), null);
|
|
$productPurchaseItem->setProduct($this->product);
|
|
|
|
$purchaseState = new PurchaseState([$productPurchaseItem]);
|
|
|
|
$this->product->feedPurchaseState = static::$purchaseUtil->recalculateTotalPrices($purchaseState);
|
|
}
|
|
|
|
return $this->product->feedPurchaseState;
|
|
}
|
|
}
|