src/Bidcoz/Bundle/CoreBundle/Entity/Auction/Item.php line 38

Open in your IDE?
  1. <?php
  2. namespace Bidcoz\Bundle\CoreBundle\Entity\Auction;
  3. use Bidcoz\Bundle\CoreBundle\Entity\Contact\Company;
  4. use Bidcoz\Bundle\CoreBundle\Entity\Email\Email;
  5. use Bidcoz\Bundle\CoreBundle\Entity\Email\ItemTemplate;
  6. use Bidcoz\Bundle\CoreBundle\Entity\Purchase\BuyItNowItemPurchase;
  7. use Bidcoz\Bundle\CoreBundle\Entity\Purchase\ItemPurchase;
  8. use Bidcoz\Bundle\CoreBundle\Entity\Purchase\Purchase;
  9. use Bidcoz\Bundle\CoreBundle\Entity\User;
  10. use Bidcoz\Bundle\CoreBundle\ObjectChange\ObjectChangeTrackable;
  11. use Doctrine\Common\Collections\ArrayCollection;
  12. use Doctrine\Common\Collections\Collection;
  13. use Doctrine\ORM\Mapping as ORM;
  14. use JMS\Serializer\Annotation as Serialize;
  15. use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
  16. use Symfony\Component\Validator\Constraints as Assert;
  17. use Symfony\Component\Validator\Context\ExecutionContextInterface;
  18. /**
  19.  * @ORM\Entity(repositoryClass="ItemRepository")
  20.  * @ORM\Table(
  21.  *      name="auction_items",
  22.  *      uniqueConstraints={
  23.  *          @ORM\UniqueConstraint(name="number_uniq", columns={"auction_id", "item_number"})
  24.  *      }
  25.  * )
  26.  * @Serialize\ExclusionPolicy("all")
  27.  * @ORM\EntityListeners({"\Bidcoz\Bundle\CoreBundle\EntityListener\AuctionItemListener"})
  28.  *
  29.  * @UniqueEntity(
  30.  *     fields={"auction", "number"},
  31.  *     errorPath="number",
  32.  *     message="Item number must be unique", groups={"edit"}
  33.  * )
  34.  */
  35. class Item implements ObjectChangeTrackable
  36. {
  37.     /**
  38.      * @ORM\Id
  39.      * @ORM\Column(name="id", type="integer")
  40.      * @ORM\GeneratedValue(strategy="AUTO")
  41.      * @Serialize\Expose
  42.      */
  43.     protected $id;
  44.     /**
  45.      * @ORM\Column(name="item_number", type="string")
  46.      * @Serialize\Expose
  47.      */
  48.     protected $number;
  49.     /**
  50.      * @ORM\ManyToOne(targetEntity="Auction", inversedBy="items")
  51.      * @ORM\JoinColumn(name="auction_id", referencedColumnName="id", onDelete="CASCADE")
  52.      */
  53.     protected ?Auction $auction null;
  54.     /**
  55.      * @ORM\Column(name="name", type="text")
  56.      * @Assert\NotBlank(message="Name is required", groups={"Default", "donation"})
  57.      * @Serialize\Expose
  58.      */
  59.     protected $name;
  60.     /**
  61.      * @ORM\Column(name="description", type="text")
  62.      * @Assert\NotBlank(message="Description is required", groups={"Default", "donation"})
  63.      */
  64.     protected $description;
  65.     /**
  66.      * @ORM\Column(name="short_description", type="string", length=50, nullable=true)
  67.      * @Assert\Length(max=50, maxMessage="Short Description limited to 50 chars.")
  68.      */
  69.     protected $shortDescription;
  70.     /**
  71.      * @ORM\ManyToOne(targetEntity="ItemCategory", inversedBy="items", cascade={"persist"})
  72.      * @Serialize\Expose
  73.      */
  74.     protected ?ItemCategory $category null;
  75.     /**
  76.      * @ORM\ManyToOne(targetEntity="ItemType", inversedBy="items")
  77.      * @Serialize\Expose
  78.      */
  79.     protected ?ItemType $type null;
  80.     /**
  81.      * @ORM\ManyToOne(targetEntity="ItemSaleType", inversedBy="items")
  82.      * @ORM\JoinColumn(name="sale_type_id", referencedColumnName="id")
  83.      * @Serialize\Expose
  84.      */
  85.     protected ?ItemSaleType $saleType null;
  86.     /**
  87.      * @ORM\ManyToOne(targetEntity="ItemCondition", inversedBy="items")
  88.      * @Serialize\Expose
  89.      */
  90.     protected ?ItemCondition $condition null;
  91.     /**
  92.      * @ORM\ManyToOne(targetEntity="AuctionVenue")
  93.      * @Assert\NotBlank(message="Venue is required")
  94.      * @Serialize\Expose
  95.      */
  96.     protected ?AuctionVenue $venue null;
  97.     /**
  98.      * @ORM\Column(name="min_bid", type="decimal", scale=2, precision=10, nullable=true)
  99.      * @Assert\Range(min=0)
  100.      * @Serialize\Expose
  101.      */
  102.     protected $minBid;
  103.     /**
  104.      * @ORM\Column(name="reserve_price", type="decimal", scale=2, precision=10, nullable=true)
  105.      * @Assert\Range(min=0)
  106.      * @Serialize\Expose
  107.      */
  108.     protected $reservePrice;
  109.     /**
  110.      * @ORM\Column(name="buy_it_now_price", type="decimal", scale=2, precision=10, nullable=true)
  111.      * @Assert\Range(min=0)
  112.      * @Serialize\Expose
  113.      */
  114.     protected $buyItNowPrice;
  115.     /**
  116.      * @ORM\Column(name="bid_increment", type="decimal", scale=2, precision=10, nullable=true)
  117.      * @Assert\Range(min=0)
  118.      * @Serialize\Expose
  119.      */
  120.     protected $bidIncrement;
  121.     /**
  122.      * @ORM\Column(name="tax_deduct_amount", type="decimal", scale=2, precision=10, nullable=false)
  123.      * @Assert\Range(min=0)
  124.      * @Serialize\Expose
  125.      */
  126.     protected $taxDeductibleAmount 0;
  127.     /**
  128.      * @ORM\Column(name="est_value", type="decimal", scale=2, precision=10, nullable=true)
  129.      * @Assert\Range(min=0, groups={"Default", "donation"})
  130.      * @Serialize\Expose
  131.      */
  132.     protected $estimatedValue;
  133.     /**
  134.      * @ORM\Column(name="est_value_display", type="boolean")
  135.      */
  136.     protected $estimatedValueDisplay false;
  137.     /**
  138.      * @ORM\Column(name="begin_quantity", type="integer", nullable=true)
  139.      * @Assert\Range(min=0)
  140.      */
  141.     protected $beginQuantity 1;
  142.     /**
  143.      * @ORM\Column(name="current_quantity", type="integer", nullable=true)
  144.      * @Assert\Range(min=0)
  145.      * @Serialize\Expose
  146.      */
  147.     protected $currentQuantity 1;
  148.     /**
  149.      * @ORM\Column(name="overtime_bidding_extended", type="boolean");
  150.      */
  151.     protected $overtimeBiddingExtended false;
  152.     /**
  153.      * @ORM\Column(name="featured", type="boolean")
  154.      */
  155.     protected $featured false;
  156.     /**
  157.      * @ORM\ManyToOne(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\User")
  158.      * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
  159.      * @Serialize\Expose
  160.      */
  161.     protected ?User $donor null;
  162.     /**
  163.      * @ORM\ManyToOne(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\Contact\Company")
  164.      * @ORM\JoinColumn(name="company_id", referencedColumnName="id", onDelete="SET NULL")
  165.      * @Serialize\Expose
  166.      */
  167.     protected ?Company $company null;
  168.     /**
  169.      * @ORM\Column(name="donor_anonymous", type="boolean")
  170.      */
  171.     protected $donorAnonymous false;
  172.     /**
  173.      * @ORM\Column(name="pickup_instructions", type="text", nullable=true)
  174.      * @Serialize\Expose
  175.      * @Serialize\Accessor(getter="getPickupInstructions")
  176.      */
  177.     protected $pickupInstructions;
  178.     /**
  179.      * @var ItemImage[]|Collection|null
  180.      * @ORM\OneToMany(targetEntity="ItemImage", mappedBy="item", orphanRemoval=true, cascade={"persist"})
  181.      * @Serialize\Expose
  182.      */
  183.     protected ?Collection $images null;
  184.     /**
  185.      * @ORM\Column(name="bid_begin", type="datetime", nullable=true)
  186.      * @Serialize\Expose
  187.      */
  188.     protected $itemBidBegin;
  189.     /**
  190.      * @ORM\Column(name="bid_end", type="datetime", nullable=true)
  191.      * @Serialize\Expose
  192.      */
  193.     protected $itemBidEnd;
  194.     /**
  195.      * @var Bid[]|Collection|null
  196.      * @ORM\OneToMany(targetEntity="Bid", mappedBy="item", cascade={"persist"})
  197.      */
  198.     protected ?Collection $bids null;
  199.     /**
  200.      * @var WatchListItem[]|Collection|null
  201.      * @ORM\OneToMany(targetEntity="WatchListItem", mappedBy="item", cascade={"persist"})
  202.      */
  203.     protected ?Collection $watchList null;
  204.     /**
  205.      * @ORM\OneToOne(targetEntity="Bid", cascade={"persist"})
  206.      * @ORM\JoinColumn(name="winning_bid_id", referencedColumnName="id", onDelete="SET NULL")
  207.      * @Serialize\Expose
  208.      */
  209.     protected ?Bid $winningBid null;
  210.     /**
  211.      * @ORM\OneToOne(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\Purchase\ItemPurchase", mappedBy="item", cascade={"persist", "remove"})
  212.      */
  213.     protected ?ItemPurchase $purchase null;
  214.     /**
  215.      * @var ItemPurchase[]|Collection|null
  216.      * @ORM\OneToMany(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\Purchase\ItemPurchase", mappedBy="item", cascade={"persist", "remove"})
  217.      */
  218.     protected ?Collection $purchases null;
  219.     /**
  220.      * @ORM\Column(name="active", type="boolean")
  221.      */
  222.     protected $active true;
  223.     /**
  224.      * @ORM\OneToOne(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\Email\Email", cascade={"persist"})
  225.      * @ORM\JoinColumn(name="donor_receipt_email_id", referencedColumnName="id")
  226.      */
  227.     protected ?Email $donorReceiptEmail null;
  228.     /**
  229.      * @var Item[]|Collection|null
  230.      * @ORM\OneToMany(targetEntity="Item", mappedBy="parentItem", cascade={"persist"})
  231.      * @Serialize\Expose
  232.      */
  233.     protected ?Collection $packagedItems null;
  234.     /**
  235.      * @ORM\ManyToOne(targetEntity="Item", inversedBy="packagedItems")
  236.      * @ORM\JoinColumn(name="item_package_id", referencedColumnName="id")
  237.      * @Serialize\Expose
  238.      */
  239.     protected ?Item $parentItem null;
  240.     /**
  241.      * @ORM\OneToMany(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\Ticket\TicketType", mappedBy="includeItem")
  242.      */
  243.     protected $includedWithTicketTypes;
  244.     /**
  245.      * @ORM\OneToMany(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\Registration\RegistrationType", mappedBy="includeItem")
  246.      */
  247.     protected $includedWithRegistrationTypes;
  248.     /**
  249.      * @ORM\Column(name="question_text", type="string", length=255, nullable=true)
  250.      * @Assert\Length(max=255, maxMessage="Question Text limited to 255 chars.")
  251.      */
  252.     protected $questionText;
  253.     /**
  254.      * @ORM\Column(name="question_required", type="boolean")
  255.      */
  256.     protected $questionRequired false;
  257.     /**
  258.      * @ORM\Column(name="collect_email", type="boolean")
  259.      */
  260.     protected $collectEmail false;
  261.     /**
  262.      * @ORM\ManyToOne(targetEntity="Bidcoz\Bundle\CoreBundle\Entity\Email\ItemTemplate", inversedBy="items")
  263.      * @ORM\JoinColumn(name="template_id", referencedColumnName="id")
  264.      */
  265.     protected ?ItemTemplate $template null;
  266.     /**
  267.      * @ORM\Column(name="sort_order", type="integer")
  268.      * @Assert\NotNull
  269.      */
  270.     protected $sortOrder 0;
  271.     /**
  272.      * @ORM\Column(name="created_at", type="datetime")
  273.      * @Serialize\Expose
  274.      */
  275.     protected $createdAt;
  276.     /**
  277.      * @ORM\Column(name="show_purchasers", type="boolean")
  278.      */
  279.     protected $showPurchasers false;
  280.     public function __construct(Auction $auction null)
  281.     {
  282.         $this->auction       $auction;
  283.         $this->images        = new ArrayCollection();
  284.         $this->bids          = new ArrayCollection();
  285.         $this->watchList     = new ArrayCollection();
  286.         $this->packagedItems = new ArrayCollection();
  287.         $this->purchases     = new ArrayCollection();
  288.         $this->createdAt     = new \DateTime();
  289.     }
  290.     public function cloneItem()
  291.     {
  292.         $newItem                     = clone $this;
  293.         $newItem->id                 null;
  294.         $newItem->number             null;
  295.         $newItem->auction            null;
  296.         $newItem->winningBid         null;
  297.         $newItem->purchase           null;
  298.         $newItem->images             = new ArrayCollection();
  299.         $newItem->bids               = new ArrayCollection();
  300.         $newItem->watchList          = new ArrayCollection();
  301.         $newItem->purchases          = new ArrayCollection();
  302.         $newItem->createdAt          = new \DateTime();
  303.         $newItem->itemBidBegin       null;
  304.         $newItem->itemBidEnd         null;
  305.         $newItem->pickupInstructions null;
  306.         $newItem->donorReceiptEmail  null;
  307.         $newItem->packagedItems      = new ArrayCollection();
  308.         return $newItem;
  309.     }
  310.     public function setId($id)
  311.     {
  312.         $this->id $id;
  313.     }
  314.     public function getId()
  315.     {
  316.         return $this->id;
  317.     }
  318.     public function setNumber($number)
  319.     {
  320.         $this->number $number;
  321.     }
  322.     public function getNumber()
  323.     {
  324.         return $this->number ?: '';
  325.     }
  326.     public function resetNumber()
  327.     {
  328.         $this->number null;
  329.     }
  330.     public function setName($name)
  331.     {
  332.         $this->name $name;
  333.     }
  334.     public function getName()
  335.     {
  336.         return $this->name;
  337.     }
  338.     public function setDescription($description)
  339.     {
  340.         $this->description $description;
  341.     }
  342.     public function getDescription()
  343.     {
  344.         return $this->description;
  345.     }
  346.     public function setShortDescription(string $shortDescription null)
  347.     {
  348.         $this->shortDescription $shortDescription;
  349.     }
  350.     /**
  351.      * @Serialize\VirtualProperty
  352.      * @Serialize\SerializedName("description")
  353.      */
  354.     public function getShortDescription()
  355.     {
  356.         return $this->shortDescription;
  357.     }
  358.     public function setMinBid($minBid)
  359.     {
  360.         $this->minBid $minBid;
  361.     }
  362.     public function getMinBid()
  363.     {
  364.         return $this->minBid;
  365.     }
  366.     public function setReservePrice($reservePrice)
  367.     {
  368.         $this->reservePrice $reservePrice;
  369.     }
  370.     public function getReservePrice()
  371.     {
  372.         return $this->reservePrice;
  373.     }
  374.     public function setType(?ItemType $type): void
  375.     {
  376.         $this->type $type;
  377.     }
  378.     public function getType(): ?ItemType
  379.     {
  380.         return $this->type;
  381.     }
  382.     public function setVenue(?AuctionVenue $venue): void
  383.     {
  384.         $this->venue $venue;
  385.     }
  386.     public function getVenue(): ?AuctionVenue
  387.     {
  388.         return $this->venue;
  389.     }
  390.     public function isOnline()
  391.     {
  392.         return $this->venue && AuctionVenue::ONLINE === $this->venue->getId();
  393.     }
  394.     public function isOnsite()
  395.     {
  396.         return $this->venue && AuctionVenue::ONSITE === $this->venue->getId();
  397.     }
  398.     public function isOnlineAndOnsite()
  399.     {
  400.         return null == $this->venue;
  401.     }
  402.     public function setSaleType(?ItemSaleType $saleType): void
  403.     {
  404.         $this->saleType $saleType;
  405.     }
  406.     public function getSaleType(): ?ItemSaleType
  407.     {
  408.         return $this->saleType;
  409.     }
  410.     public function isDonation()
  411.     {
  412.         return $this->saleType && ItemSaleType::DONATION == $this->saleType->getId();
  413.     }
  414.     public function isAuctionType()
  415.     {
  416.         return $this->saleType && ItemSaleType::AUCTION == $this->saleType->getId();
  417.     }
  418.     public function isFixedPrice()
  419.     {
  420.         return $this->saleType && ItemSaleType::FIXED_PRICE == $this->saleType->getId();
  421.     }
  422.     public function isManualType()
  423.     {
  424.         return $this->saleType && ItemSaleType::MANUAL == $this->saleType->getId();
  425.     }
  426.     public function isConsignmentType()
  427.     {
  428.         return $this->type && ItemType::CONSIGNMENT == $this->type->getId();
  429.     }
  430.     public function isPackagedItem()
  431.     {
  432.         return (bool) $this->parentItem;
  433.     }
  434.     public function setParentItem(Item $parentItem null)
  435.     {
  436.         $this->parentItem $parentItem;
  437.     }
  438.     public function getParentItem()
  439.     {
  440.         return $this->parentItem;
  441.     }
  442.     public function setTaxDeductibleAmount($taxDeductibleAmount)
  443.     {
  444.         $this->taxDeductibleAmount $taxDeductibleAmount;
  445.     }
  446.     public function getTaxDeductibleAmount()
  447.     {
  448.         return $this->taxDeductibleAmount;
  449.     }
  450.     public function setEstimatedValue($estimatedValue)
  451.     {
  452.         $this->estimatedValue $estimatedValue;
  453.     }
  454.     public function getEstimatedValue($calculate false)
  455.     {
  456.         if ($calculate) {
  457.             $qty $this->isFixedPrice()
  458.                 ? $this->beginQuantity
  459.                 1;
  460.             return round($this->estimatedValue $qty2);
  461.         } else {
  462.             return $this->estimatedValue;
  463.         }
  464.     }
  465.     public function setEstimatedValueDisplay($estimatedValueDisplay)
  466.     {
  467.         $this->estimatedValueDisplay $estimatedValueDisplay;
  468.     }
  469.     public function getEstimatedValueDisplay()
  470.     {
  471.         return $this->estimatedValueDisplay;
  472.     }
  473.     public function showEstimatedDisplay()
  474.     {
  475.         return $this->estimatedValueDisplay && $this->estimatedValue;
  476.     }
  477.     /**
  478.      * @Serialize\VirtualProperty
  479.      * @Serialize\SerializedName("estValue")
  480.      */
  481.     public function getEstimatedValueString(): string
  482.     {
  483.         if (!$this->getEstimatedValue()) {
  484.             return '';
  485.         }
  486.         return $this->showEstimatedDisplay()
  487.             ? 'Priceless'
  488.             '$'.money_format('%i'$this->getEstimatedValue());
  489.     }
  490.     public function setBeginQuantity($beginQuantity)
  491.     {
  492.         $this->beginQuantity $beginQuantity;
  493.     }
  494.     public function getBeginQuantity()
  495.     {
  496.         return $this->beginQuantity;
  497.     }
  498.     public function setAuction(?Auction $auction): void
  499.     {
  500.         $this->auction $auction;
  501.     }
  502.     public function getAuction(): ?Auction
  503.     {
  504.         return $this->auction;
  505.     }
  506.     public function setCategory(?ItemCategory $category null): void
  507.     {
  508.         $this->category $category;
  509.     }
  510.     public function getCategory(): ?ItemCategory
  511.     {
  512.         return $this->category;
  513.     }
  514.     /**
  515.      * @return Collection|ItemImage[]|null
  516.      */
  517.     public function getImages(): ?Collection
  518.     {
  519.         return $this->images;
  520.     }
  521.     public function addImage(?ItemImage $image): void
  522.     {
  523.         if (!$this->images->contains($image)) {
  524.             $this->images->add($image);
  525.         }
  526.     }
  527.     public function removeImage(?ItemImage $image): void
  528.     {
  529.         if ($this->images->contains($image)) {
  530.             $this->images->removeElement($image);
  531.         }
  532.     }
  533.     public function setPrimaryImage(ItemImage $image): void
  534.     {
  535.         foreach ($this->images as $i) {
  536.             $i->setPrimary(false);
  537.         }
  538.         $image->setPrimary(true);
  539.     }
  540.     public function getPrimaryImage()
  541.     {
  542.         $filtered $this->getImages()->filter(function ($image) {
  543.             return $image->isPrimary();
  544.         });
  545.         return $filtered->first();
  546.     }
  547.     public function hasCustomBidDates()
  548.     {
  549.         return $this->itemBidBegin || $this->itemBidEnd;
  550.     }
  551.     public function getBidBegin()
  552.     {
  553.         if ($this->itemBidBegin) {
  554.             return $this->itemBidBegin;
  555.         }
  556.         return $this->isOnsite()
  557.             ? $this->getAuction()->getOnsiteBegin()
  558.             : $this->getAuction()->getOnlineBegin();
  559.     }
  560.     public function getBidEnd()
  561.     {
  562.         if ($this->itemBidEnd) {
  563.             return $this->itemBidEnd;
  564.         }
  565.         return $this->isOnsite()
  566.             ? $this->getAuction()->getOnsiteEnd()
  567.             : $this->getAuction()->getOnlineEnd();
  568.     }
  569.     public function isItemWithinBidTimeframe()
  570.     {
  571.         $now = new \DateTime();
  572.         return $now >= $this->getBidBegin() && $now <= $this->getBidEnd();
  573.     }
  574.     public function isItemUpcoming()
  575.     {
  576.         $now = new \DateTime();
  577.         return $now <= $this->getBidBegin();
  578.     }
  579.     public function isItemOver()
  580.     {
  581.         $now = new \DateTime();
  582.         return $now >= $this->getBidEnd();
  583.     }
  584.     public function setItemBidBegin(\DateTime $date null)
  585.     {
  586.         $this->itemBidBegin $date;
  587.     }
  588.     public function getItemBidBegin()
  589.     {
  590.         return $this->itemBidBegin;
  591.     }
  592.     public function setItemBidEnd(\DateTime $date null)
  593.     {
  594.         $this->itemBidEnd $date;
  595.     }
  596.     public function getItemBidEnd()
  597.     {
  598.         return $this->itemBidEnd;
  599.     }
  600.     public function isWithinOvertimeBiddingWindow()
  601.     {
  602.         $windowBegin = new \DateTime('+5 minutes');
  603.         return $this->getBidEnd() < $windowBegin;
  604.     }
  605.     /**
  606.      * @return Collection|Bid[]|null
  607.      */
  608.     public function getBids(): ?Collection
  609.     {
  610.         return $this->bids;
  611.     }
  612.     public function setBids(?Collection $bids): void
  613.     {
  614.         $this->bids $bids;
  615.     }
  616.     public function addBid(?Bid $bid): void
  617.     {
  618.         if (!$this->bids->contains($bid)) {
  619.             $this->bids->add($bid);
  620.             $bid->setItem($this);
  621.         }
  622.     }
  623.     public function removeBid(?Bid $bid): void
  624.     {
  625.         if ($this->bids->contains($bid)) {
  626.             $this->bids->removeElement($bid);
  627.         }
  628.     }
  629.     public function getActiveBids(): Collection
  630.     {
  631.         return $this->bids->filter(function (Bid $bid) {
  632.             return $bid->isActive();
  633.         });
  634.     }
  635.     public function hasUserBid(User $user)
  636.     {
  637.         return $this->bids->exists(function ($index$bid) use ($user) {
  638.             return $bid->getUser() == $user && $bid->isActive();
  639.         });
  640.     }
  641.     public function setCurrentQuantity($currentQuantity)
  642.     {
  643.         $this->currentQuantity $currentQuantity;
  644.     }
  645.     public function getCurrentQuantity()
  646.     {
  647.         return $this->currentQuantity;
  648.     }
  649.     public function decrementCurrentQuantity()
  650.     {
  651.         --$this->currentQuantity;
  652.         foreach ($this->packagedItems as $item) {
  653.             $item->decrementCurrentQuantity();
  654.         }
  655.     }
  656.     public function incrementCurrentQuantity()
  657.     {
  658.         ++$this->currentQuantity;
  659.         foreach ($this->packagedItems as $item) {
  660.             $item->incrementCurrentQuantity();
  661.         }
  662.     }
  663.     public function setOvertimeBiddingExtended($overtimeBiddingExtended)
  664.     {
  665.         $this->overtimeBiddingExtended $overtimeBiddingExtended;
  666.     }
  667.     public function getOvertimeBiddingExtended()
  668.     {
  669.         return $this->overtimeBiddingExtended;
  670.     }
  671.     public function setFeatured($featured)
  672.     {
  673.         $this->featured $featured;
  674.     }
  675.     public function getFeatured()
  676.     {
  677.         return $this->featured;
  678.     }
  679.     public function setDonor(?User $donor null): void
  680.     {
  681.         $this->donor $donor;
  682.     }
  683.     public function getDonor(): ?User
  684.     {
  685.         return $this->donor;
  686.     }
  687.     public function setCompany(?Company $company null): void
  688.     {
  689.         $this->company $company;
  690.     }
  691.     public function getCompany(): ?Company
  692.     {
  693.         return $this->company;
  694.     }
  695.     public function setDonorAnonymous($donorAnonymous)
  696.     {
  697.         $this->donorAnonymous $donorAnonymous;
  698.     }
  699.     public function isDonorAnonymous()
  700.     {
  701.         return $this->donorAnonymous;
  702.     }
  703.     public function hasCustomPickupInstructions()
  704.     {
  705.         return $this->pickupInstructions && strlen($this->pickupInstructions);
  706.     }
  707.     public function setCustomPickupInstructions($pickupInstructions)
  708.     {
  709.         $this->pickupInstructions $pickupInstructions;
  710.     }
  711.     public function getCustomPickupInstructions()
  712.     {
  713.         return $this->pickupInstructions;
  714.     }
  715.     public function getPickupInstructions()
  716.     {
  717.         return $this->pickupInstructions ?: $this->auction->getPickupInstructions();
  718.     }
  719.     public function setCondition(?ItemCondition $condition): void
  720.     {
  721.         $this->condition $condition;
  722.     }
  723.     public function getCondition(): ?ItemCondition
  724.     {
  725.         return $this->condition;
  726.     }
  727.     public function setBuyItNowPrice($buyItNowPrice)
  728.     {
  729.         $this->buyItNowPrice $buyItNowPrice;
  730.     }
  731.     public function getBuyItNowPrice()
  732.     {
  733.         return $this->buyItNowPrice;
  734.     }
  735.     public function setFixedPrice($buyItNowPrice)
  736.     {
  737.         $this->buyItNowPrice $buyItNowPrice;
  738.     }
  739.     public function getFixedPrice()
  740.     {
  741.         return $this->saleType && ItemSaleType::FIXED_PRICE === $this->saleType->getId() ? $this->buyItNowPrice null;
  742.     }
  743.     public function setBuyItNowOnlyPrice($buyItNowPrice)
  744.     {
  745.         $this->buyItNowPrice $buyItNowPrice;
  746.     }
  747.     public function getBuyItNowOnlyPrice()
  748.     {
  749.         return $this->saleType && ItemSaleType::FIXED_PRICE !== $this->saleType->getId() ? $this->buyItNowPrice null;
  750.     }
  751.     public function setBidIncrement($bidIncrement)
  752.     {
  753.         $this->bidIncrement $bidIncrement;
  754.     }
  755.     public function getBidIncrement()
  756.     {
  757.         return $this->bidIncrement;
  758.     }
  759.     /**
  760.      * @return Collection|WatchListItem[]|null
  761.      */
  762.     public function getWatchList(): ?Collection
  763.     {
  764.         return $this->watchList;
  765.     }
  766.     public function setWatchList(?Collection $watchList): void
  767.     {
  768.         $this->watchList $watchList;
  769.     }
  770.     public function addWatchListItem(WatchListItem $watchListItem): void
  771.     {
  772.         if (!$this->watchList->contains($watchListItem)) {
  773.             $this->watchList->add($watchListItem);
  774.         }
  775.     }
  776.     public function removeWatchListItem(WatchListItem $watchListItem): void
  777.     {
  778.         if ($this->watchList->contains($watchListItem)) {
  779.             $this->watchList->removeElement($watchListItem);
  780.         }
  781.     }
  782.     public function setWinningBid(?Bid $bid null): void
  783.     {
  784.         $this->winningBid $bid;
  785.     }
  786.     public function getWinningBid(): ?Bid
  787.     {
  788.         return $this->winningBid;
  789.     }
  790.     public function isWinningBid(?Bid $bid): bool
  791.     {
  792.         return $bid == $this->winningBid;
  793.     }
  794.     public function getCurrentBidAmount()
  795.     {
  796.         if ($winningBid $this->getWinningBid()) {
  797.             return $winningBid->getAmount();
  798.         }
  799.         return $this->minBid;
  800.     }
  801.     public function setPurchase(?ItemPurchase $purchase): void
  802.     {
  803.         $this->purchase $purchase;
  804.     }
  805.     public function getPurchase(): ?ItemPurchase
  806.     {
  807.         return $this->purchase;
  808.     }
  809.     public function unsetPurchase()
  810.     {
  811.         $this->purchase null;
  812.     }
  813.     public function isPaidFor(): bool
  814.     {
  815.         if (!$this->purchase) {
  816.             return false;
  817.         }
  818.         // there is a purchase, if hold in cart return true, else check that there is a transaction
  819.         if ($this->getCampaign()->getHoldItemsInCart()) {
  820.             return true;
  821.         }
  822.         return (bool) $this->purchase->getTransaction();
  823.     }
  824.     public function isBuyItNowPurchase(): bool
  825.     {
  826.         return (bool) $this->purchase && $this->purchase instanceof BuyItNowItemPurchase;
  827.     }
  828.     public function setActive($active)
  829.     {
  830.         $this->active $active;
  831.     }
  832.     public function isActive()
  833.     {
  834.         return $this->active;
  835.     }
  836.     public function setDonorReceiptEmail(?Email $email): void
  837.     {
  838.         $this->donorReceiptEmail $email;
  839.     }
  840.     public function getDonorReceiptEmail(): ?Email
  841.     {
  842.         return $this->donorReceiptEmail;
  843.     }
  844.     public function getPackagedItems(): ?Collection
  845.     {
  846.         return $this->packagedItems;
  847.     }
  848.     public function addPackagedItem(Item $item): void
  849.     {
  850.         if (!$this->packagedItems->contains($item)) {
  851.             $this->packagedItems->add($item);
  852.             $item->setParentItem($this);
  853.         }
  854.     }
  855.     public function removePackagedItem(Item $item): void
  856.     {
  857.         if ($this->packagedItems->contains($item)) {
  858.             $this->packagedItems->removeElement($item);
  859.             $item->setParentItem(null);
  860.         }
  861.     }
  862.     public function getPackagedItemIds(): array
  863.     {
  864.         return array_map(static fn (Item $item) => $item->getId(), $this->packagedItems->toArray());
  865.     }
  866.     public function setPackagedItems($items = []): void
  867.     {
  868.         foreach ($this->packagedItems as $before) {
  869.             $before->setParentItem(null);
  870.         }
  871.         $this->packagedItems = new ArrayCollection();
  872.         foreach ($items as $after) {
  873.             $after->setParentItem($this);
  874.             $this->packagedItems->add($after);
  875.         }
  876.     }
  877.     public function hasPackagedItems(): bool
  878.     {
  879.         return (bool) count($this->packagedItems);
  880.     }
  881.     public function getCreatedAt()
  882.     {
  883.         return $this->createdAt;
  884.     }
  885.     public function setShowPurchasers($showPurchasers)
  886.     {
  887.         $this->showPurchasers $showPurchasers;
  888.     }
  889.     public function getShowPurchasers()
  890.     {
  891.         return $this->showPurchasers;
  892.     }
  893.     /**
  894.      * @Assert\Callback
  895.      */
  896.     public function ensurePricingValid(ExecutionContextInterface $context)
  897.     {
  898.         if ($this->isFixedPrice() && (!$this->buyItNowPrice || $this->buyItNowPrice <= 0)) {
  899.             $context->buildViolation('Fixed Purchase Price must be > $0')
  900.                 ->atPath('buyItNowPrice')
  901.                 ->addViolation();
  902.         } elseif ($this->isAuctionType() && (!$this->minBid || $this->minBid <= 0)) {
  903.             $context->buildViolation('Minimum Bid required for auction items')
  904.                 ->atPath('minBid')
  905.                 ->addViolation();
  906.         }
  907.     }
  908.     /**
  909.      * @Assert\Callback
  910.      */
  911.     public function ensureValidType(ExecutionContextInterface $context)
  912.     {
  913.         if ($this->isManualType() && !$this->isOnsite()) {
  914.             $context->buildViolation('Manual Bid only available for Event Venue venue')
  915.                 ->atPath('saleType')
  916.                 ->addViolation();
  917.         }
  918.     }
  919.     /**
  920.      * @Assert\Callback
  921.      */
  922.     public function ensureValidDates(ExecutionContextInterface $context)
  923.     {
  924.         return;
  925.         $campaign $this->getCampaign();
  926.         if (!$campaign) {
  927.             return;
  928.         }
  929.         $format 'M. jS g:i a T';
  930.         if ($this->getBidBegin() < $campaign->getCampaignBegin()) {
  931.             $context->buildViolation(sprintf('Cannot start before Campaign begins: %s'$campaign->getCampaignBegin()->format($format)))
  932.                 ->atPath('itemBidBegin')
  933.                 ->addViolation();
  934.         }
  935.         if ($this->getBidEnd() > $campaign->getCampaignEnd()) {
  936.             $context->buildViolation(sprintf('Cannot end after Campaign ends: %s'$campaign->getCampaignEnd()->format($format)))
  937.                 ->atPath('itemBidEnd')
  938.                 ->addViolation();
  939.         }
  940.     }
  941.     /**
  942.      * @Assert\Callback
  943.      */
  944.     public function ensureBidIncrement(ExecutionContextInterface $context)
  945.     {
  946.         if ($this->isFixedPrice() || $this->isDonation()) {
  947.             return;
  948.         }
  949.         if (!$this->bidIncrement) {
  950.             $context->buildViolation('Bid Increment is required')
  951.                 ->atPath('bidIncrement')
  952.                 ->addViolation();
  953.         }
  954.     }
  955.     public function getCampaign()
  956.     {
  957.         return $this->auction->getCampaign();
  958.     }
  959.     public function getObjectName()
  960.     {
  961.         return sprintf('Item %d'$this->id);
  962.     }
  963.     public function getIncludedWithTicketTypes()
  964.     {
  965.         return $this->includedWithTicketTypes;
  966.     }
  967.     public function getIncludedWithRegistrationTypes()
  968.     {
  969.         return $this->includedWithRegistrationTypes;
  970.     }
  971.     public function setQuestionText(?string $questionText)
  972.     {
  973.         $this->questionText $questionText;
  974.     }
  975.     public function getQuestionText()
  976.     {
  977.         return $this->questionText;
  978.     }
  979.     public function setQuestionRequired(bool $questionRequired)
  980.     {
  981.         $this->questionRequired $questionRequired;
  982.     }
  983.     public function isQuestionRequired(): bool
  984.     {
  985.         return $this->questionRequired;
  986.     }
  987.     public function setCollectEmail(bool $collectEmail)
  988.     {
  989.         $this->collectEmail $collectEmail;
  990.     }
  991.     public function getCollectEmail(): bool
  992.     {
  993.         return $this->collectEmail;
  994.     }
  995.     public function setTemplate(ItemTemplate $template)
  996.     {
  997.         $this->template $template;
  998.     }
  999.     public function getTemplate()
  1000.     {
  1001.         return $this->template;
  1002.     }
  1003.     public function setSortOrder($sortOrder)
  1004.     {
  1005.         $this->sortOrder $sortOrder;
  1006.     }
  1007.     public function getSortOrder()
  1008.     {
  1009.         return $this->sortOrder;
  1010.     }
  1011.     public function isSoldOut(): bool
  1012.     {
  1013.         if ($this->isFixedPrice() || $this->isDonation()) {
  1014.             return $this->getCurrentQuantity() <= 0;
  1015.         } elseif ($this->isAuctionType()) {
  1016.             $campaign $this->getCampaign();
  1017.             if ($campaign->getHoldItemsInCart()) {
  1018.                 return $this->isBuyItNowPurchase();
  1019.             } else {
  1020.                 return $this->isPaidFor();
  1021.             }
  1022.         }
  1023.         return false;
  1024.     }
  1025.     public function getTrackedParams()
  1026.     {
  1027.         return [
  1028.             'itemBidBegin'    => 'Bid Begin',
  1029.             'itemBidEnd'      => 'Bid End',
  1030.             'currentQuantity' => 'Current Quantity',
  1031.             'saleType'        => 'Sale Type',
  1032.             'venue'           => 'Venue',
  1033.             'minBid'          => 'Min Bid',
  1034.             'reservePrice'    => 'Reserve Price',
  1035.             'buyItNowPrice'   => 'Buy It Now Price',
  1036.             'estimatedValue'  => 'Estimated Value',
  1037.         ];
  1038.     }
  1039.     public function __toString()
  1040.     {
  1041.         return sprintf('%d (%d) - %s'$this->id$this->number$this->name);
  1042.     }
  1043.     public function getPurchases(): ?Collection
  1044.     {
  1045.         return $this->purchases;
  1046.     }
  1047.     public function setPurchases(?Collection $purchases): void
  1048.     {
  1049.         $this->purchases $purchases;
  1050.     }
  1051.     public function addPurchase(Purchase $purchase): void
  1052.     {
  1053.         if (!$this->purchases->contains($purchase)) {
  1054.             $this->purchases->add($purchase);
  1055.             if ($purchase instanceof ItemPurchase) {
  1056.                 $purchase->setItem($this);
  1057.             }
  1058.         }
  1059.     }
  1060.     public function removePurchase(Purchase $purchase): void
  1061.     {
  1062.         if ($this->purchases->contains($purchase)) {
  1063.             $this->purchases->removeElement($purchase);
  1064.             if ($purchase instanceof ItemPurchase) {
  1065.                 $purchase->setItem(null);
  1066.             }
  1067.         }
  1068.     }
  1069. }