<?php
namespace Roothirsch\Tuer24Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Roothirsch\Tuer24Bundle\Repository\Tuer24StockRepository;
#[ORM\Entity(repositoryClass: "Roothirsch\Tuer24Bundle\Repository\Tuer24StockRepository")]
#[ORM\Table(name: 'roothirsch_tuer24_stock')]
#[ORM\HasLifecycleCallbacks]
class Tuer24Stock
{
use TimestampableEntity;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\OneToOne(targetEntity: Tuer24Product::class, inversedBy: 'stock')]
#[ORM\JoinColumn(name: "product_id", referencedColumnName: "id", nullable: false, onDelete: "CASCADE")]
private $product;
#[ORM\Column(type: 'integer')]
#[Assert\NotBlank]
#[Assert\PositiveOrZero]
private $quantity = 0;
#[ORM\Column(type: 'integer')]
#[Assert\PositiveOrZero]
private $reservedQuantity = 0;
#[ORM\Column(type: 'integer', nullable: true)]
#[Assert\PositiveOrZero]
private $lowStockThreshold;
#[ORM\Column(type: 'boolean')]
private $trackInventory = true;
#[ORM\Column(type: 'string', length: 255, nullable: true)]
private $stockStatus;
#[ORM\Column(type: 'text', nullable: true)]
private $stockNotes;
#[ORM\Column(type: 'boolean')]
private $allowBackorders = false;
/**
* Get id
*
* @return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* Get product
*
* @return Tuer24Product|null
*/
public function getProduct(): ?Tuer24Product
{
return $this->product;
}
/**
* Set product
*
* @param Tuer24Product|null $product
* @return $this
*/
public function setProduct(?Tuer24Product $product): self
{
$this->product = $product;
return $this;
}
/**
* Get quantity
*
* @return int|null
*/
public function getQuantity(): ?int
{
return $this->quantity;
}
/**
* Set quantity
*
* @param int $quantity
* @return $this
*/
public function setQuantity(int $quantity): self
{
$this->quantity = $quantity;
return $this;
}
/**
* Get reserved quantity
*
* @return int|null
*/
public function getReservedQuantity(): ?int
{
return $this->reservedQuantity;
}
/**
* Set reserved quantity
*
* @param int $reservedQuantity
* @return $this
*/
public function setReservedQuantity(int $reservedQuantity): self
{
$this->reservedQuantity = $reservedQuantity;
return $this;
}
/**
* Get available quantity (total minus reserved)
*
* @return int
*/
public function getAvailableQuantity(): int
{
return max(0, $this->quantity - $this->reservedQuantity);
}
/**
* Get low stock threshold
*
* @return int|null
*/
public function getLowStockThreshold(): ?int
{
return $this->lowStockThreshold;
}
/**
* Set low stock threshold
*
* @param int|null $lowStockThreshold
* @return $this
*/
public function setLowStockThreshold(?int $lowStockThreshold): self
{
$this->lowStockThreshold = $lowStockThreshold;
return $this;
}
/**
* Check if stock is low
*
* @return bool
*/
public function isLowStock(): bool
{
if ($this->lowStockThreshold === null) {
return false;
}
return $this->getAvailableQuantity() <= $this->lowStockThreshold;
}
/**
* Get track inventory
*
* @return bool|null
*/
public function getTrackInventory(): ?bool
{
return $this->trackInventory;
}
/**
* Set track inventory
*
* @param bool $trackInventory
* @return $this
*/
public function setTrackInventory(bool $trackInventory): self
{
$this->trackInventory = $trackInventory;
return $this;
}
/**
* Get stock status
*
* @return string|null
*/
public function getStockStatus(): ?string
{
return $this->stockStatus;
}
/**
* Set stock status
*
* @param string|null $stockStatus
* @return $this
*/
public function setStockStatus(?string $stockStatus): self
{
$this->stockStatus = $stockStatus;
return $this;
}
/**
* Get stock notes
*
* @return string|null
*/
public function getStockNotes(): ?string
{
return $this->stockNotes;
}
/**
* Set stock notes
*
* @param string|null $stockNotes
* @return $this
*/
public function setStockNotes(?string $stockNotes): self
{
$this->stockNotes = $stockNotes;
return $this;
}
/**
* Get allow backorders
*
* @return bool|null
*/
public function getAllowBackorders(): ?bool
{
return $this->allowBackorders;
}
/**
* Set allow backorders
*
* @param bool $allowBackorders
* @return $this
*/
public function setAllowBackorders(bool $allowBackorders): self
{
$this->allowBackorders = $allowBackorders;
return $this;
}
/**
* Check if product is in stock
*
* @return bool
*/
public function isInStock(): bool
{
// If not tracking inventory, always return true
if (!$this->trackInventory) {
return true;
}
// If allowing backorders, always return true
if ($this->allowBackorders) {
return true;
}
// Otherwise, check if available quantity is greater than 0
return $this->getAvailableQuantity() > 0;
}
/**
* Reserve quantity for an order
*
* @param int $quantity
* @return bool
*/
public function reserveQuantity(int $quantity): bool
{
// If not tracking inventory, always allow
if (!$this->trackInventory) {
return true;
}
// If quantity is available, reserve it
if ($this->getAvailableQuantity() >= $quantity || $this->allowBackorders) {
$this->reservedQuantity += $quantity;
return true;
}
// Not enough stock
return false;
}
/**
* Release reserved quantity
*
* @param int $quantity
* @return $this
*/
public function releaseReservedQuantity(int $quantity): self
{
$this->reservedQuantity = max(0, $this->reservedQuantity - $quantity);
return $this;
}
/**
* Adjust stock (increase or decrease)
*
* @param int $adjustment
* @return $this
*/
public function adjustStock(int $adjustment): self
{
$newQuantity = $this->quantity + $adjustment;
$this->quantity = max(0, $newQuantity);
return $this;
}
/**
* String representation of stock
*
* @return string
*/
public function __toString(): string
{
return (string)$this->getQuantity();
}
}