src/Ecommerce/PriceSystem/Event/PriceSystem.php line 38

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by Elements.at New Media Solutions GmbH
  4.  *
  5.  */
  6. namespace App\Ecommerce\PriceSystem\Event;
  7. use App\Ecommerce\PricingManager\Environment;
  8. use App\Model\Shop\Event\EventProduct;
  9. use App\Model\Shop\Event\ShopDynamicPrice;
  10. use Carbon\Carbon;
  11. use Elements\Bundle\TicketShopFrameworkBundle\Service\CartService;
  12. use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
  13. use Pimcore\Bundle\EcommerceFrameworkBundle\Model\CheckoutableInterface;
  14. use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\CachingPriceSystem;
  15. use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\Price;
  16. use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\PriceSystemInterface;
  17. use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\TaxManagement\TaxCalculationService;
  18. use Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\TaxManagement\TaxEntry;
  19. use Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\PriceInfoInterface;
  20. use Pimcore\Bundle\EcommerceFrameworkBundle\PricingManager\PricingManagerLocatorInterface;
  21. use Pimcore\Bundle\EcommerceFrameworkBundle\Type\Decimal;
  22. use Pimcore\Model\DataObject\AbstractObject;
  23. use Pimcore\Model\DataObject\OnlineShopTaxClass;
  24. use Pimcore\Model\Exception\UnsupportedException;
  25. class PriceSystem extends CachingPriceSystem implements PriceSystemInterface
  26. {
  27.     public function __construct(
  28.         PricingManagerLocatorInterface $pricingManagers,
  29.         private CartService $cartService
  30.     ) {
  31.         parent::__construct($pricingManagers);
  32.     }
  33.     protected function initPriceInfoInstance(mixed $quantityScaleCheckoutableInterface $product$products nullCarbon $date null): \Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\PriceInfoInterface
  34.     {
  35.         $priceInfo $this->createPriceInfoInstance($quantityScale$product$products$date);
  36.         if ($quantityScale !== \Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\PriceInfoInterface::MIN_PRICE) {
  37.             $priceInfo->setQuantity($quantityScale);
  38.         }
  39.         $priceInfo->setProduct($product);
  40.         $priceInfo->setProducts($products);
  41.         $priceInfo->setPriceSystem($this);
  42.         $priceInfo->setBaseAmount($priceInfo->getPrice()->getAmount()->asNumeric());
  43.         // apply pricing rules
  44.         /** @var \Elements\Bundle\TicketShopFrameworkBundle\Ecommerce\PricingManager\PriceInfo $priceInfoWithRules */
  45.         $priceInfoWithRules $this->getPricingManager()->applyProductRules($priceInfo);
  46.         $priceInfoWithRules->setBaseAmount($priceInfo->getPrice()->getAmount());
  47.         /** @var Environment $env */
  48.         $env $priceInfoWithRules->getEnvironment();
  49.         $env->setCartForProduct($this->cartService->getCart());
  50.         if ($product instanceof EventProduct) {
  51.             $orderDate $product->getProductStartDate();
  52.             if ($orderDate) {
  53.                 $env->setStartDate($orderDate);
  54.             }
  55.         }
  56.         return $priceInfoWithRules;
  57.     }
  58.     /**
  59.      * @param mixed $quantityScale
  60.      * @param CheckoutableInterface $product
  61.      * @param CheckoutableInterface[] $products
  62.      * @param Carbon|null $date
  63.      *
  64.      * @return PriceInfo
  65.      */
  66.     public function createPriceInfoInstance(
  67.         mixed $quantityScale,
  68.         CheckoutableInterface $product,
  69.         mixed $products,
  70.         ?Carbon $date null
  71.     ): PriceInfo {
  72.         if (!$product instanceof EventProduct) {
  73.             throw new UnsupportedException('Object must be of type EventProduct');
  74.         }
  75.         $priceInfo = new PriceInfo($product);
  76.         $priceInfo->setQuantity($quantityScale);
  77.         $priceInfo->setPrices($this->getPrices($product$date));
  78.         $priceInfo->setPrice($this->calculatePrice($product$date));
  79.         $priceInfo->setDate($date);
  80.         $this->applyTaxes($product$priceInfo);
  81.         return $priceInfo;
  82.     }
  83.     /**
  84.      * @param EventProduct $product
  85.      * @param null|int $quantityScale
  86.      * @param array<mixed>|null $products
  87.      * @param Carbon|null $date
  88.      *
  89.      * @return PriceInfoInterface
  90.      */
  91.     public function getPriceInfo(CheckoutableInterface $product$quantityScale null$products nullCarbon $date null): PriceInfoInterface
  92.     {
  93.         $pId $product->getId();
  94.         if (empty($date)) {
  95.             $date $product->getEventStartDate();
  96.         }
  97.         if ($date) {
  98.             $pId .= $date->getTimestamp();
  99.         }
  100.         if (!array_key_exists($pId$this->priceInfos)) {
  101.             $this->priceInfos[$pId] = [];
  102.         }
  103.         $quantityScaleKey = (string)$quantityScale;
  104.         if (empty($this->priceInfos[$pId][$quantityScaleKey])) {
  105.             $priceInfo $this->initPriceInfoInstance($quantityScale$product$products$date);
  106.             $this->priceInfos[$pId][$quantityScaleKey] = $priceInfo;
  107.         }
  108.         /** @phpstan-ignore-next-line  */
  109.         return $this->priceInfos[$pId][$quantityScaleKey];
  110.     }
  111.     /**
  112.      * Calculate price for order item configuration
  113.      *
  114.      * @param EventProduct $product
  115.      * @param Carbon|null $date
  116.      *
  117.      * @return Price
  118.      */
  119.     protected function calculatePrice(EventProduct $productCarbon $date null): Price
  120.     {
  121.         $price 0;
  122.         if ($product->getType() == AbstractObject::OBJECT_TYPE_VARIANT) {
  123.             /** @var ShopDynamicPrice $priceObj */
  124.             $priceObj $product->getOrderedPriceItem();
  125.             $price $priceObj->getPrice($date);
  126.         } else {
  127.             if ($priceObjects $product->getPriceObjects()) {
  128.                 $price $priceObjects[0]->getPrice($date);
  129.             }
  130.         }
  131.         return new Price(Decimal::fromNumeric($price), Factory::getInstance()->getEnvironment()->getDefaultCurrency(), true);
  132.     }
  133.     /**
  134.      * Get prices from shopPrice descriptions
  135.      *
  136.      * @param EventProduct $product
  137.      * @param ?Carbon $date
  138.      *
  139.      * @return Price[]
  140.      */
  141.     public function getPrices(EventProduct $productCarbon $date null): array
  142.     {
  143.         $prices = [];
  144.         foreach ($product->getPrices() as $priceRelation) {
  145.             /** @var ShopDynamicPrice $dynamicPriceObject */
  146.             $dynamicPriceObject $priceRelation->getObject();
  147.             $prices[$dynamicPriceObject->getId()] = new Price(
  148.                 Decimal::fromNumeric($dynamicPriceObject->getPrice($product->getProductStartDate() ?: $date) ?: 0),
  149.                 Factory::getInstance()->getEnvironment()->getDefaultCurrency(), true
  150.             );
  151.         }
  152.         return $prices;
  153.     }
  154.     /**
  155.      * @param EventProduct $product
  156.      *
  157.      * @return OnlineShopTaxClass
  158.      */
  159.     public function getTaxClassForProduct(CheckoutableInterface $product): OnlineShopTaxClass
  160.     {
  161.         $taxRate $this->getDefaultTaxClass();
  162.         $startDate $product->getEventStartDate() ?? Carbon::today();
  163.         if ($startDate->year == 2024 && $taxRate->getNewTaxRate()) {
  164.             $taxRate $taxRate->getNewTaxRate();
  165.         }
  166.         return $taxRate;
  167.     }
  168.     /**
  169.      * @param EventProduct $product
  170.      * @param \Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\PriceInfoInterface $priceInfo
  171.      *
  172.      * @return void
  173.      *
  174.      * @throws \Pimcore\Bundle\EcommerceFrameworkBundle\Exception\UnsupportedException
  175.      */
  176.     protected function applyTaxes(CheckoutableInterface $product\Pimcore\Bundle\EcommerceFrameworkBundle\PriceSystem\PriceInfoInterface $priceInfo): void
  177.     {
  178.         $price $priceInfo->getPrice();
  179.         $taxClass $this->getTaxClassForProduct($product);
  180.         $totalPrice $priceInfo->getTotalPrice();
  181.         if ($taxClass->getTaxEntryCombinationType()) {
  182.             $price->setTaxEntryCombinationMode($taxClass->getTaxEntryCombinationType());
  183.             $price->setTaxEntries(TaxEntry::convertTaxEntries($taxClass));
  184.             $totalPrice->setTaxEntryCombinationMode($taxClass->getTaxEntryCombinationType());
  185.             $totalPrice->setTaxEntries(TaxEntry::convertTaxEntries($taxClass));
  186.         }
  187.         $taxCalculationService $this->getTaxCalculationService();
  188.         $taxCalculationService->updateTaxes($priceTaxCalculationService::CALCULATION_FROM_GROSS);
  189.         $taxCalculationService->updateTaxes($totalPriceTaxCalculationService::CALCULATION_FROM_GROSS);
  190.     }
  191. }