<?php
namespace App\Entity;
use App\Billing\Model\BillableItemInterface;
use App\Repository\ServiceUsageRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ServiceUsageRepository::class)]
class ServiceUsage implements BillableItemInterface
{
const STATUS_UNBILLED = 'UNBILLED';
const STATUS_BILLED = 'BILLED';
const STATUS_CANCELLED = 'CANCELLED';
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private ?Service $service = null;
#[ORM\Column(type: Types::FLOAT)]
private ?float $quantity = 1.0;
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $date = null;
#[ORM\Column(length: 50)]
private ?string $status = self::STATUS_UNBILLED;
#[ORM\ManyToOne(inversedBy: 'serviceUsages')]
private ?User $user = null;
#[ORM\ManyToOne(inversedBy: 'serviceUsages')]
private ?Organization $organization = null;
#[ORM\Column(type: Types::FLOAT, nullable: true)]
private ?float $unitPrice = null;
#[ORM\Column(type: Types::FLOAT, nullable: true)]
private ?float $exchangeRate = null;
#[ORM\Column(type: Types::FLOAT, nullable: true)]
private ?float $vatRate = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $description = null;
public function __construct()
{
$this->date = new \DateTime();
}
public function getId(): ?int
{
return $this->id;
}
public function getService(): ?Service
{
return $this->service;
}
public function setService(?Service $service): static
{
$this->service = $service;
return $this;
}
public function getQuantity(): ?float
{
return $this->quantity;
}
public function setQuantity(float $quantity): static
{
$this->quantity = $quantity;
return $this;
}
public function getDate(): ?\DateTimeInterface
{
return $this->date;
}
public function setDate(\DateTimeInterface $date): static
{
$this->date = $date;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): static
{
$this->status = $status;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): static
{
$this->user = $user;
return $this;
}
public function getOrganization(): ?Organization
{
return $this->organization;
}
public function setOrganization(?Organization $organization): static
{
$this->organization = $organization;
return $this;
}
public function getUnitPrice(): ?float
{
return $this->unitPrice;
}
public function setUnitPrice(?float $unitPrice): static
{
$this->unitPrice = $unitPrice;
return $this;
}
public function getExchangeRate(): ?float
{
return $this->exchangeRate;
}
public function setExchangeRate(?float $exchangeRate): static
{
$this->exchangeRate = $exchangeRate;
return $this;
}
public function getVatRate(): ?float
{
return $this->vatRate;
}
public function setVatRate(?float $vatRate): static
{
$this->vatRate = $vatRate;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): static
{
$this->description = $description;
return $this;
}
// BillableItemInterface
public function getBillableDescription(): string
{
$desc = $this->description;
if (!$desc) {
$desc = $this->service->getNom() . ' (x' . $this->quantity . ')';
}
if ($this->user) {
$nomComplet = $this->user->getPrenom() . ' ' . $this->user->getNom();
// Append only if not already in description (case insensitive check to be safe)
if (stripos($desc, $nomComplet) === false) {
$desc .= ' - ' . $nomComplet;
}
}
return $desc;
}
public function getBillablePrice(): float
{
// Base price calculation (from fixed unitPrice or service default)
$price = $this->unitPrice !== null ? $this->unitPrice : $this->service->getPrixUnitaire();
// Apply exchange rate if present (assuming unitPrice is in foreign currency)
if ($this->exchangeRate !== null) {
$price = $price * $this->exchangeRate;
}
return $price * $this->quantity;
}
public function getBillableVatRate(): float
{
// Use frozen VAT rate if available, otherwise Service default
return $this->vatRate !== null ? $this->vatRate : $this->service->getTva();
}
}