<?php
namespace App\Ecommerce\PriceSystem;
use App\Ecommerce\PriceSystem\PriceSystemRule\HasPriceSystemRuleContract;
use App\Ecommerce\PriceSystem\PriceSystemRule\Processor as PriceSystemRuleProcessor;
use App\Model\Customer;
use Factory\CheckoutBundle\Repository\TaxRepository;
use Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException;
use Pimcore\Bundle\EcommerceFrameworkBundle\Model\CheckoutableInterface;
use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\AbstractPriceSystem;
use Pimcore\Bundle\EcommerceFrameworkBundle\Model\Currency;
use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\AttributePriceInfo;
use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\PriceInterface;
use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\TaxManagement\TaxEntry;
use Pimcore\Bundle\EcommerceFrameworkBundle\Type\Decimal;
use Pimcore\Bundle\EcommerceFrameworkBundle\EnvironmentInterface;
use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
use Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\PricingManagerLocatorInterface;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\Data\QuantityValue;
use Pimcore\Model\DataObject\OnlineShopTaxClass;
use Pimcore\Model\DataObject\PriceSystemRule;
class StoeltingPriceSystem extends AbstractPriceSystem
{
/**
* @var Customer
*/
protected $customer;
/**
* @var EnvironmentInterface
*/
protected $environment;
/**
* @var string
*/
protected $attributeName;
/**
* @var string
*/
protected $priceType;
/**
* @var string
*/
protected $priceClass;
/**
* @var TaxRepository
*/
protected $taxRepository;
public function __construct(PricingManagerLocatorInterface $pricingManagers, EnvironmentInterface $environment, TaxRepository $taxRepository, array $options = [])
{
parent::__construct($pricingManagers);
$this->environment = $environment;
$this->taxRepository = $taxRepository;
$this->attributeName = $options['attribute_name'];
$this->priceType = $options['price_type'];
$this->priceClass = $options['price_class'];
}
/**
* Undocumented function
*
* @param int $quantityScale
* @param CheckoutableInterface|HasPriceSystemRuleContract $product
* @param mix $products
*/
public function createPriceInfoInstance($quantityScale, $product, $products)
{
$taxClass = $this->getTaxClassForProduct($product);
$amount = $this->calculateAmount($product, $products);
$priceSystemRule = $this->getPriceSystemRule($product, $products);
$priceSystemRuleProcessor = new PriceSystemRuleProcessor($this->environment);
$action = $priceSystemRuleProcessor->getMatchingAction(
$priceSystemRule
);
$action->setDefaultCurrency($this->getDefaultCurrency());
$price = $action->getPriceObject($amount);
$totalPrice = $action->getPriceObject($amount->mul($quantityScale));
// $price = $this->getPriceClassInstance($amount);
// $totalPrice = $this->getPriceClassInstance($amount->mul($quantityScale));
if ($taxClass) {
// Move this into OnlineShopTaxClass
$inheritanceBackup = AbstractObject::getGetInheritedValues();
AbstractObject::setGetInheritedValues(true);
$mode = $taxClass->getTaxEntryCombinationType();
AbstractObject::setGetInheritedValues($inheritanceBackup);
$price->setTaxEntryCombinationMode($mode);
$price->setTaxEntries(TaxEntry::convertTaxEntries($taxClass));
$totalPrice->setTaxEntryCombinationMode($mode);
$totalPrice->setTaxEntries(TaxEntry::convertTaxEntries($taxClass));
}
$taxCalculationService = $this->getTaxCalculationService();
$taxCalculationService->updateTaxes($price, $this->priceType);
$taxCalculationService->updateTaxes($totalPrice, $this->priceType);
$priceVisibility = $this->isPriceVisible($priceSystemRule);
$price->setIsVisible($priceVisibility);
return new StoeltingPriceInfo($price, $quantityScale, $totalPrice, $priceVisibility);
}
protected function isPriceVisible(PriceSystemRuleContract $priceSystemRule)
{
if ($this->environment->getCurrentUserId() > 0) {
return true;
}
if ($priceSystemRule->getGuestCustomerSee() == 'not-price') {
return false;
}
return true;
}
public function filterProductIds($productIds, $fromPrice, $toPrice, $order, $offset, $limit)
{
throw new UnsupportedException(__METHOD__ . ' is not supported for ' . get_class($this));
}
/**
* Calculates prices from product
*
* @param CheckoutableInterface $product
* @param CheckoutableInterface[] $products
*
* @return Decimal
*/
protected function calculateAmount(CheckoutableInterface $product, $products): Decimal
{
$getter = 'get'.$this->attributeName;
$quantityValue = $product->{$getter}();
if (!$quantityValue) {
return Decimal::zero();
}
if (!$quantityValue instanceof QuantityValue) {
return Decimal::fromNumeric($quantityValue);
}
return Decimal::create($quantityValue->getValue());
}
/**
* Returns default currency based on environment settings
*
* @return Currency
*/
protected function getDefaultCurrency(): Currency
{
return $this->environment->getDefaultCurrency();
}
protected function getPriceSystemRule(HasPriceSystemRuleContract $product, $products)
{
$priceSysRule = $product->getPriceSystemRule();
if ($priceSysRule) {
return $priceSysRule;
}
return new PriceSystemRule();
}
protected function getCustomer()
{
$env = Factory::getInstance()->getEnvironment();
if (!$this->customer && $env->getCurrentUserId() > 0) {
$this->customer = Customer::getById($env->getCurrentUserId());
}
return $this->customer;
}
/** @inheritDoc */
public function getDefaultTaxClass()
{
if ($this->getCustomer() && $this->getCustomer()->getTaxExempt()) {
return $this->zeroTax();
}
$billingAddress = Factory::getInstance()->getEnvironment()->getBillingAddress();
$shippingAddress = Factory::getInstance()->getEnvironment()->getShippingAddress();
$billingTax = $billingAddress ? $this->taxRepository->getByAddress($billingAddress) : null;
$shippingTax = $shippingAddress ? $this->taxRepository->getByAddress($shippingAddress) : null;
$taxes = [];
if ($shippingTax && $shippingTax->applyToShipping()) {
$taxes[] = $shippingTax;
}
if ($billingTax && $billingTax->applyToBilling()) {
$taxes[] = $billingTax;
}
if (count($taxes) > 1) {
$taxes = [$billingTax];
}
return $taxes[0] ?? parent::getDefaultTaxClass();
}
protected function zeroTax()
{
$taxClass = new OnlineShopTaxClass();
$taxClass->setTaxEntryCombinationType(TaxEntry::CALCULATION_MODE_COMBINE);
return $taxClass;
}
public function getAttributeName()
{
return $this->attributeName;
}
public function setAttributeName($attributeName)
{
$this->attributeName = $attributeName;
}
}