<?php
namespace App\Entity;
use App\Repository\ProductRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ProductRepository::class)]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $slug = null;
#[ORM\Column(length: 255)]
private ?string $sku = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $barcode = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $description = null;
#[ORM\Column]
private array $images = [];
#[ORM\Column(nullable: true)]
private ?array $videos = null;
#[ORM\Column(nullable: true)]
private ?array $documents = null;
#[ORM\Column]
private ?float $price = null;
#[ORM\Column(nullable: true)]
private ?float $compareAtPrice = null;
#[ORM\Column]
private ?int $stock = null;
#[ORM\Column]
private ?int $minStockAlert = null;
#[ORM\Column]
private ?bool $manageStock = null;
#[ORM\Column]
private ?bool $allowBackorders = null;
#[ORM\Column(length: 20)]
private ?string $stockStatus = null;
#[ORM\Column(nullable: true)]
private ?float $weight = null;
#[ORM\Column(nullable: true)]
private ?float $length = null;
#[ORM\Column(nullable: true)]
private ?float $width = null;
#[ORM\Column(nullable: true)]
private ?float $height = null;
#[ORM\Column]
private ?bool $isDigital = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $digitalFile = null;
#[ORM\Column(nullable: true)]
private ?array $attributes = null;
#[ORM\Column(nullable: true)]
private ?array $variations = null;
#[ORM\Column]
private ?bool $isActive = null;
#[ORM\Column]
private ?bool $isFeatured = null;
#[ORM\Column]
private ?\DateTimeImmutable $publishedAt = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $availableFrom = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $availableTo = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $metaTitle = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $metaDescription = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $metaKeywords = null;
#[ORM\Column]
private ?int $viewCount = null;
#[ORM\Column]
private ?int $salesCount = null;
#[ORM\Column]
private ?float $averageRating = null;
#[ORM\Column]
private ?int $reviewCount = null;
#[ORM\Column(nullable: true)]
private ?array $tierPrices = null; // [{min:int, price:float}, ...]
#[ORM\Column(options: ["default" => false])]
private ?bool $hasTierPricing = false;
#[ORM\ManyToOne(inversedBy: 'products')]
#[ORM\JoinColumn(nullable: false)]
private ?Shop $shop = null;
#[ORM\ManyToOne(inversedBy: 'products')]
#[ORM\JoinColumn(nullable: false)]
private ?Category $category = null;
#[ORM\ManyToOne(inversedBy: 'products')]
#[ORM\JoinColumn(nullable: true)]
private ?Brand $brand = null;
#[ORM\ManyToOne(inversedBy: 'products')]
#[ORM\JoinColumn(nullable: true)]
private ?ProductCondition $condition = null;
#[ORM\OneToMany(targetEntity: ProductRanking::class, mappedBy: 'product')]
private Collection $rankings;
#[ORM\OneToMany(targetEntity: ProductVariant::class, mappedBy: 'product', cascade: ['persist', 'remove'])]
private Collection $variants;
#[ORM\OneToMany(targetEntity: ProductDetail::class, mappedBy: 'product', cascade: ['persist', 'remove'])]
private Collection $details;
#[ORM\Column(length: 255)]
private ?string $name = null;
public function __construct()
{
$this->variants = new ArrayCollection();
$this->details = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): static
{
$this->slug = $slug;
return $this;
}
public function getSku(): ?string
{
return $this->sku;
}
public function setSku(string $sku): static
{
$this->sku = $sku;
return $this;
}
public function getBarcode(): ?string
{
return $this->barcode;
}
public function setBarcode(?string $barcode): static
{
$this->barcode = $barcode;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): static
{
$this->description = $description;
return $this;
}
public function getImages(): array
{
return $this->images;
}
public function setImages(array $images): static
{
$this->images = $images;
return $this;
}
public function getVideos(): ?array
{
return $this->videos;
}
public function setVideos(?array $videos): static
{
$this->videos = $videos;
return $this;
}
public function getDocuments(): ?array
{
return $this->documents;
}
public function setDocuments(?array $documents): static
{
$this->documents = $documents;
return $this;
}
public function getPrice(): ?float
{
return $this->price;
}
public function setPrice(float $price): static
{
$this->price = $price;
return $this;
}
public function getCompareAtPrice(): ?float
{
return $this->compareAtPrice;
}
public function setCompareAtPrice(?float $compareAtPrice): static
{
$this->compareAtPrice = $compareAtPrice;
return $this;
}
public function getStock(): ?int
{
return $this->stock;
}
public function setStock(int $stock): static
{
$this->stock = $stock;
return $this;
}
public function getMinStockAlert(): ?int
{
return $this->minStockAlert;
}
public function setMinStockAlert(int $minStockAlert): static
{
$this->minStockAlert = $minStockAlert;
return $this;
}
public function isManageStock(): ?bool
{
return $this->manageStock;
}
public function setManageStock(bool $manageStock): static
{
$this->manageStock = $manageStock;
return $this;
}
public function isAllowBackorders(): ?bool
{
return $this->allowBackorders;
}
public function setAllowBackorders(bool $allowBackorders): static
{
$this->allowBackorders = $allowBackorders;
return $this;
}
public function getStockStatus(): ?string
{
return $this->stockStatus;
}
public function setStockStatus(string $stockStatus): static
{
$this->stockStatus = $stockStatus;
return $this;
}
public function getWeight(): ?float
{
return $this->weight;
}
public function setWeight(?float $weight): static
{
$this->weight = $weight;
return $this;
}
public function getLength(): ?float
{
return $this->length;
}
public function setLength(?float $length): static
{
$this->length = $length;
return $this;
}
public function getWidth(): ?float
{
return $this->width;
}
public function setWidth(?float $width): static
{
$this->width = $width;
return $this;
}
public function getHeight(): ?float
{
return $this->height;
}
public function setHeight(?float $height): static
{
$this->height = $height;
return $this;
}
public function isIsDigital(): ?bool
{
return $this->isDigital;
}
public function setIsDigital(bool $isDigital): static
{
$this->isDigital = $isDigital;
return $this;
}
public function getDigitalFile(): ?string
{
return $this->digitalFile;
}
public function setDigitalFile(?string $digitalFile): static
{
$this->digitalFile = $digitalFile;
return $this;
}
public function getAttributes(): ?array
{
return $this->attributes;
}
public function setAttributes(?array $attributes): static
{
$this->attributes = $attributes;
return $this;
}
public function getVariations(): ?array
{
return $this->variations;
}
public function setVariations(?array $variations): static
{
$this->variations = $variations;
return $this;
}
public function isIsActive(): ?bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): static
{
$this->isActive = $isActive;
return $this;
}
public function isIsFeatured(): ?bool
{
return $this->isFeatured;
}
public function setIsFeatured(bool $isFeatured): static
{
$this->isFeatured = $isFeatured;
return $this;
}
public function getPublishedAt(): ?\DateTimeImmutable
{
return $this->publishedAt;
}
public function setPublishedAt(\DateTimeImmutable $publishedAt): static
{
$this->publishedAt = $publishedAt;
return $this;
}
public function getAvailableFrom(): ?\DateTimeImmutable
{
return $this->availableFrom;
}
public function setAvailableFrom(?\DateTimeImmutable $availableFrom): static
{
$this->availableFrom = $availableFrom;
return $this;
}
public function getAvailableTo(): ?\DateTimeImmutable
{
return $this->availableTo;
}
public function setAvailableTo(?\DateTimeImmutable $availableTo): static
{
$this->availableTo = $availableTo;
return $this;
}
public function getMetaTitle(): ?string
{
return $this->metaTitle;
}
public function setMetaTitle(?string $metaTitle): static
{
$this->metaTitle = $metaTitle;
return $this;
}
public function getMetaDescription(): ?string
{
return $this->metaDescription;
}
public function setMetaDescription(?string $metaDescription): static
{
$this->metaDescription = $metaDescription;
return $this;
}
public function getMetaKeywords(): ?string
{
return $this->metaKeywords;
}
public function setMetaKeywords(?string $metaKeywords): static
{
$this->metaKeywords = $metaKeywords;
return $this;
}
public function getViewCount(): ?int
{
return $this->viewCount;
}
public function setViewCount(int $viewCount): static
{
$this->viewCount = $viewCount;
return $this;
}
public function getSalesCount(): ?int
{
return $this->salesCount;
}
public function setSalesCount(int $salesCount): static
{
$this->salesCount = $salesCount;
return $this;
}
public function getAverageRating(): ?float
{
return $this->averageRating;
}
public function setAverageRating(float $averageRating): static
{
$this->averageRating = $averageRating;
return $this;
}
public function getReviewCount(): ?int
{
return $this->reviewCount;
}
public function setReviewCount(int $reviewCount): static
{
$this->reviewCount = $reviewCount;
return $this;
}
public function getTierPrices(): ?array
{
return $this->tierPrices;
}
public function setTierPrices(?array $tierPrices): static
{
$this->tierPrices = $tierPrices;
return $this;
}
public function hasTierPricing(): ?bool
{
return $this->hasTierPricing;
}
public function setHasTierPricing(bool $hasTierPricing): static
{
$this->hasTierPricing = $hasTierPricing;
return $this;
}
public function getShop(): ?Shop
{
return $this->shop;
}
public function setShop(?Shop $shop): static
{
$this->shop = $shop;
return $this;
}
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): static
{
$this->category = $category;
return $this;
}
public function getBrand(): ?Brand
{
return $this->brand;
}
public function setBrand(?Brand $brand): static
{
$this->brand = $brand;
return $this;
}
public function getCondition(): ?ProductCondition
{
return $this->condition;
}
public function setCondition(?ProductCondition $condition): static
{
$this->condition = $condition;
return $this;
}
/**
* @return Collection<int, ProductRanking>
*/
public function getRankings(): Collection
{
return $this->rankings;
}
public function addRanking(ProductRanking $ranking): static
{
if (!$this->rankings->contains($ranking)) {
$this->rankings->add($ranking);
$ranking->setProduct($this);
}
return $this;
}
public function removeRanking(ProductRanking $ranking): static
{
if ($this->rankings->removeElement($ranking)) {
if ($ranking->getProduct() === $this) {
$ranking->setProduct(null);
}
}
return $this;
}
/**
* Obtenir le rang dans une catégorie spécifique
*/
public function getRankInCategory(Category $category): ?int
{
foreach ($this->rankings as $ranking) {
if ($ranking->getCategory() === $category) {
return $ranking->getRank();
}
}
return null;
}
/**
* Obtenir le meilleur rang du produit
*/
public function getBestRank(): ?int
{
$bestRank = null;
foreach ($this->rankings as $ranking) {
if ($bestRank === null || $ranking->getRank() < $bestRank) {
$bestRank = $ranking->getRank();
}
}
return $bestRank;
}
/**
* @return Collection<int, ProductVariant>
*/
public function getVariants(): Collection
{
return $this->variants;
}
public function addVariant(ProductVariant $variant): static
{
if (!$this->variants->contains($variant)) {
$this->variants->add($variant);
$variant->setProduct($this);
}
return $this;
}
public function removeVariant(ProductVariant $variant): static
{
if ($this->variants->removeElement($variant)) {
if ($variant->getProduct() === $this) {
$variant->setProduct(null);
}
}
return $this;
}
/**
* Obtenir la variante par défaut
*/
public function getDefaultVariant(): ?ProductVariant
{
foreach ($this->variants as $variant) {
if ($variant->isIsDefault() && $variant->isIsActive()) {
return $variant;
}
}
return $this->variants->first() ?: null;
}
/**
* Vérifier si le produit a des variantes
*/
public function hasVariants(): bool
{
return $this->variants->count() > 0;
}
/**
* @return Collection<int, ProductDetail>
*/
public function getDetails(): Collection
{
return $this->details;
}
public function addDetail(ProductDetail $detail): static
{
if (!$this->details->contains($detail)) {
$this->details->add($detail);
$detail->setProduct($this);
}
return $this;
}
public function removeDetail(ProductDetail $detail): static
{
if ($this->details->removeElement($detail)) {
if ($detail->getProduct() === $this) {
$detail->setProduct(null);
}
}
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
}