modules/CDev/VolumeDiscounts/src/Model/VolumeDiscount.php line 62

Open in your IDE?
  1. <?php
  2. /**
  3.  * Copyright (c) 2011-present Qualiteam software Ltd. All rights reserved.
  4.  * See https://www.x-cart.com/license-agreement.html for license details.
  5.  */
  6. namespace CDev\VolumeDiscounts\Model;
  7. use ApiPlatform\Core\Annotation as ApiPlatform;
  8. use CDev\VolumeDiscounts\API\Endpoint\VolumeDiscount\DTO\VolumeDiscountInput;
  9. use CDev\VolumeDiscounts\API\Endpoint\VolumeDiscount\DTO\VolumeDiscountOutput;
  10. use CDev\VolumeDiscounts\Logic\Order\Modifier\Discount;
  11. use Doctrine\ORM\Mapping as ORM;
  12. use XLite\Core\Database;
  13. use XLite\Model\Membership;
  14. use XLite\Model\Zone;
  15. use XLite\View\FormField\Input\PriceOrPercent;
  16. use XLite\View\FormField\Select\AbsoluteOrPercent;
  17. /**
  18.  * Volume discount model
  19.  *
  20.  * @ORM\Entity
  21.  * @ORM\Table  (name="volume_discounts",
  22.  *      indexes={
  23.  *          @ORM\Index (name="date_range", columns={"dateRangeBegin","dateRangeEnd"}),
  24.  *          @ORM\Index (name="subtotal", columns={"subtotalRangeBegin"}),
  25.  *      }
  26.  * )
  27.  * @ApiPlatform\ApiResource(
  28.  *     shortName="Volume Discount",
  29.  *     input=VolumeDiscountInput::class,
  30.  *     output=VolumeDiscountOutput::class,
  31.  *     itemOperations={
  32.  *          "get"={
  33.  *              "method"="GET",
  34.  *              "path"="/volume_discounts/{id}.{_format}",
  35.  *              "identifiers"={"id"},
  36.  *              "requirements"={"id"="\d+"}
  37.  *          },
  38.  *          "put"={
  39.  *              "method"="PUT",
  40.  *              "path"="/volume_discounts/{id}.{_format}",
  41.  *              "identifiers"={"id"},
  42.  *              "requirements"={"id"="\d+"}
  43.  *          },
  44.  *          "delete"={
  45.  *              "method"="DELETE",
  46.  *              "path"="/volume_discounts/{id}.{_format}",
  47.  *              "identifiers"={"id"},
  48.  *              "requirements"={"id"="\d+"}
  49.  *          }
  50.  *     },
  51.  *     collectionOperations={
  52.  *          "get"={
  53.  *              "method"="GET",
  54.  *              "identifiers"={},
  55.  *              "path"="/volume_discounts.{_format}"
  56.  *          },
  57.  *          "post"={
  58.  *              "method"="POST",
  59.  *              "identifiers"={},
  60.  *              "path"="/volume_discounts.{_format}"
  61.  *          }
  62.  *     }
  63.  * )
  64.  */
  65. class VolumeDiscount extends \XLite\Model\AEntity
  66. {
  67.     public const TYPE_PERCENT  '%';
  68.     public const TYPE_ABSOLUTE '$';
  69.     /**
  70.      * Discount unique ID
  71.      *
  72.      * @var   integer
  73.      *
  74.      * @ORM\Id
  75.      * @ORM\GeneratedValue (strategy="AUTO")
  76.      * @ORM\Column         (type="integer", options={ "unsigned": true })
  77.      */
  78.     protected $id;
  79.     /**
  80.      * Value
  81.      *
  82.      * @var   float
  83.      *
  84.      * @ORM\Column (type="decimal", precision=14, scale=4)
  85.      */
  86.     protected $value 0.0000;
  87.     /**
  88.      * Type
  89.      *
  90.      * @var   string
  91.      *
  92.      * @ORM\Column (type="string", options={ "fixed": true }, length=1)
  93.      */
  94.     protected $type self::TYPE_PERCENT;
  95.     /**
  96.      * Subtotal range (begin)
  97.      *
  98.      * @var   float
  99.      *
  100.      * @ORM\Column (type="decimal", precision=14, scale=4)
  101.      */
  102.     protected $subtotalRangeBegin 0;
  103.     /**
  104.      * Membership
  105.      *
  106.      * @var   \XLite\Model\Membership
  107.      *
  108.      * @ORM\ManyToOne (targetEntity="XLite\Model\Membership")
  109.      * @ORM\JoinColumn (name="membership_id", referencedColumnName="membership_id", onDelete="CASCADE")
  110.      */
  111.     protected $membership;
  112.     /**
  113.      * Zones
  114.      *
  115.      * @var   \Doctrine\Common\Collections\ArrayCollection
  116.      *
  117.      * @ORM\ManyToMany (targetEntity="XLite\Model\Zone", inversedBy="volumeDiscounts")
  118.      * @ORM\JoinTable (name="zones_volume_discounts",
  119.      *      joinColumns={@ORM\JoinColumn (name="volume_discount_id", referencedColumnName="id", onDelete="CASCADE")},
  120.      *      inverseJoinColumns={@ORM\JoinColumn (name="zone_id", referencedColumnName="zone_id", onDelete="CASCADE")}
  121.      * )
  122.      */
  123.     protected $zones;
  124.     /**
  125.      * Date range (begin)
  126.      *
  127.      * @var   integer
  128.      *
  129.      * @ORM\Column (type="integer", options={ "unsigned": true })
  130.      */
  131.     protected $dateRangeBegin 0;
  132.     /**
  133.      * Date range (end)
  134.      *
  135.      * @var   integer
  136.      *
  137.      * @ORM\Column (type="integer", options={ "unsigned": true })
  138.      */
  139.     protected $dateRangeEnd 0;
  140.     /**
  141.      * Constructor
  142.      *
  143.      * @param array $data Entity properties OPTIONAL
  144.      */
  145.     public function __construct(array $data = [])
  146.     {
  147.         $this->zones = new \Doctrine\Common\Collections\ArrayCollection();
  148.         parent::__construct($data);
  149.     }
  150.     /**
  151.      * Returns handling fee
  152.      *
  153.      * @return array
  154.      */
  155.     public function getDiscount()
  156.     {
  157.         return [
  158.             PriceOrPercent::PRICE_VALUE => $this->getValue(),
  159.             PriceOrPercent::TYPE_VALUE  => $this->getType() === static::TYPE_PERCENT
  160.                 AbsoluteOrPercent::TYPE_PERCENT
  161.                 AbsoluteOrPercent::TYPE_ABSOLUTE
  162.         ];
  163.     }
  164.     /**
  165.      * Set Discount
  166.      *
  167.      * @param array $Discount
  168.      * @return VolumeDiscount
  169.      */
  170.     public function setDiscount($Discount): VolumeDiscount
  171.     {
  172.         $this->setValue(
  173.             $Discount[PriceOrPercent::PRICE_VALUE] ?? 0
  174.         );
  175.         $this->setType(
  176.             isset($Discount[PriceOrPercent::TYPE_VALUE])
  177.             && $Discount[PriceOrPercent::TYPE_VALUE] === AbsoluteOrPercent::TYPE_PERCENT
  178.                 ? static::TYPE_PERCENT
  179.                 : static::TYPE_ABSOLUTE
  180.         );
  181.         return $this;
  182.     }
  183.     /**
  184.      * Check - discount is absolute or not
  185.      *
  186.      * @return boolean
  187.      */
  188.     public function isAbsolute()
  189.     {
  190.         return $this->getType() === static::TYPE_ABSOLUTE;
  191.     }
  192.     /**
  193.      * Get discount amount
  194.      *
  195.      * @param \XLite\Model\Order $order Order
  196.      *
  197.      * @return float
  198.      */
  199.     public function getAmount(\XLite\Model\Order $order)
  200.     {
  201.         $subTotal $order->getSubtotal();
  202.         /** @var \XLite\Model\Order\Surcharge $surcharge */
  203.         foreach ($order->getSurchargesByType(\XLite\Model\Base\Surcharge::TYPE_DISCOUNT) as $surcharge) {
  204.             if (
  205.                 $surcharge->getAvailable()
  206.                 && !$surcharge->getInclude()
  207.                 && $surcharge->getCode() !== Discount::MODIFIER_CODE
  208.             ) {
  209.                 $subTotal += $order->getCurrency()->roundValue($surcharge->getValue());
  210.             }
  211.         }
  212.         $discount $this->isAbsolute()
  213.             ? $this->getValue()
  214.             : ($subTotal $this->getValue() / 100);
  215.         return min($discount$subTotal);
  216.     }
  217.     /**
  218.      * Get id
  219.      *
  220.      * @return integer
  221.      */
  222.     public function getId()
  223.     {
  224.         return $this->id;
  225.     }
  226.     /**
  227.      * Set value
  228.      *
  229.      * @param float $value
  230.      * @return VolumeDiscount
  231.      */
  232.     public function setValue($value)
  233.     {
  234.         $this->value $value;
  235.         return $this;
  236.     }
  237.     /**
  238.      * Get value
  239.      *
  240.      * @return float
  241.      */
  242.     public function getValue()
  243.     {
  244.         return $this->value;
  245.     }
  246.     /**
  247.      * Set type
  248.      *
  249.      * @param string $type
  250.      * @return VolumeDiscount
  251.      */
  252.     public function setType($type)
  253.     {
  254.         $this->type $type;
  255.         return $this;
  256.     }
  257.     /**
  258.      * Get type
  259.      *
  260.      * @return string
  261.      */
  262.     public function getType()
  263.     {
  264.         return $this->type;
  265.     }
  266.     /**
  267.      * Set subtotalRangeBegin
  268.      *
  269.      * @param float $subtotalRangeBegin
  270.      * @return VolumeDiscount
  271.      */
  272.     public function setSubtotalRangeBegin($subtotalRangeBegin)
  273.     {
  274.         $this->subtotalRangeBegin $subtotalRangeBegin;
  275.         return $this;
  276.     }
  277.     /**
  278.      * Get subtotalRangeBegin
  279.      *
  280.      * @return float
  281.      */
  282.     public function getSubtotalRangeBegin()
  283.     {
  284.         return $this->subtotalRangeBegin;
  285.     }
  286.     /**
  287.      * Set dateRangeBegin
  288.      *
  289.      * @param integer $dateRangeBegin
  290.      * @return VolumeDiscount
  291.      */
  292.     public function setDateRangeBegin($dateRangeBegin)
  293.     {
  294.         $this->dateRangeBegin $dateRangeBegin;
  295.         return $this;
  296.     }
  297.     /**
  298.      * Get dateRangeBegin
  299.      *
  300.      * @return integer
  301.      */
  302.     public function getDateRangeBegin()
  303.     {
  304.         return $this->dateRangeBegin;
  305.     }
  306.     /**
  307.      * Set dateRangeEnd
  308.      *
  309.      * @param integer $dateRangeEnd
  310.      * @return VolumeDiscount
  311.      */
  312.     public function setDateRangeEnd($dateRangeEnd)
  313.     {
  314.         $this->dateRangeEnd $dateRangeEnd;
  315.         return $this;
  316.     }
  317.     /**
  318.      * Get dateRangeEnd
  319.      *
  320.      * @return integer
  321.      */
  322.     public function getDateRangeEnd()
  323.     {
  324.         return $this->dateRangeEnd;
  325.     }
  326.     /**
  327.      * Get real dateRangeEnd ()
  328.      *
  329.      * @return integer
  330.      */
  331.     public function getRealDateRangeEnd()
  332.     {
  333.         return $this->dateRangeEnd == 0
  334.             PHP_INT_MAX
  335.             $this->dateRangeEnd;
  336.     }
  337.     /**
  338.      * Add zone
  339.      *
  340.      * @param Zone $zone
  341.      *
  342.      * @return VolumeDiscount
  343.      */
  344.     public function addZone(Zone $zone)
  345.     {
  346.         $this->zones[] = $zone;
  347.         return $this;
  348.     }
  349.     /**
  350.      * Get zones
  351.      *
  352.      * @return \Doctrine\Common\Collections\Collection
  353.      */
  354.     public function getZones()
  355.     {
  356.         return $this->zones;
  357.     }
  358.     /**
  359.      * Clear zones
  360.      */
  361.     public function clearZones(): void
  362.     {
  363.         if ($this->getZones()) {
  364.             $this->getZones()->clear();
  365.         }
  366.     }
  367.     /**
  368.      * Set membership
  369.      *
  370.      * @param string|null|Membership $membership
  371.      * @return VolumeDiscount
  372.      */
  373.     public function setMembership($membership)
  374.     {
  375.         if (is_string($membership)) {
  376.             $this->membership Database::getRepo(Membership::class)->find($membership);
  377.             return $this;
  378.         }
  379.         $this->membership $membership;
  380.         return $this;
  381.     }
  382.     /**
  383.      * Get membership
  384.      *
  385.      * @return Membership|null
  386.      */
  387.     public function getMembership(): ?Membership
  388.     {
  389.         return $this->membership;
  390.     }
  391.     /**
  392.      * Check - volume discount is expired or not
  393.      *
  394.      * @return boolean
  395.      */
  396.     public function isExpired(): bool
  397.     {
  398.         return $this->getDateRangeEnd() && $this->getDateRangeEnd() < \XLite\Core\Converter::time();
  399.     }
  400. }