ldc-boutique-cnc-sable/domain/Models/Entities/Order.php
Jérémy Munsch c8f895c759
refactor: simplify use statements and type hints
- Removed fully qualified names for better readability.
- Streamlined code by using direct class references.
2026-10-29 20:35:35 +01:00

116 lines
3.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Domain\Models\Entities;
use Carbon\CarbonImmutable;
use Domain\Enums\OrderStatus;
use Domain\Events\AnOrderHasBeenPlaced;
use Domain\Events\Dto\OrderPlacedLine;
use Domain\Events\Dto\OrderPlacedShop;
use Domain\Models\ValueObjects\BasketProduct;
use Domain\Models\ValueObjects\DeliveryAddress;
use Domain\Models\ValueObjects\Entities\OrderId;
use Domain\Models\ValueObjects\Entities\ShopId;
use Domain\Models\ValueObjects\OrderEmployee;
use Domain\Models\ValueObjects\OrderLine;
use Domain\Models\ValueObjects\OrderReference;
use Domain\Models\ValueObjects\PickupTimeSlot;
use Money\Money;
use Shared\DDD\Entity;
/** @implements \Shared\DDD\Entity<\Domain\Models\ValueObjects\Entities\OrderId> */
final class Order implements Entity
{
public function __construct(
public readonly OrderId $id,
public readonly ShopId $shopId,
public readonly OrderReference $reference,
public readonly OrderEmployee $employee,
public readonly DeliveryAddress $deliveryAddress,
public readonly PickupTimeSlot $pickupTimeSlot,
public OrderStatus $status,
private readonly Money $total,
/** @var OrderLine[] */
private array $lines,
) {
if ($total->getAmount() <= 0) {
throw new \DomainException('Total amount must be greater than zero');
}
foreach ($lines as $line) {
if (! ($line instanceof OrderLine)) {
throw new \DomainException('All lines must be instances of OrderLine');
}
}
}
#[\Override]
public function id(): OrderId
{
return $this->id;
}
public function getTotal(): Money
{
return $this->total;
}
/** @return OrderLine[] */
public function getLines(): array
{
return $this->lines;
}
public function cancel(): void
{
if ($this->status === OrderStatus::CANCELED) {
return;
}
$this->status = OrderStatus::CANCELED;
}
public static function fromBasket(
OrderId $id,
OrderReference $reference,
Basket $basket,
PickupTimeSlot $pickupTimeSlot,
Shopper $shopper,
Shop $shop
): self {
$lines = array_map(
fn (BasketProduct $item) => OrderLine::fromBasketProduct($item),
array_values($basket->items())
);
return new self(
id: $id,
shopId: clone $shop->id(),
reference: $reference,
employee: OrderEmployee::fromShopper($shopper),
deliveryAddress: DeliveryAddress::fromShop($shop),
pickupTimeSlot: clone $pickupTimeSlot,
status: OrderStatus::VALIDATED,
total: clone $basket->totalTaxIncluded(),
lines: $lines
);
}
public function toPlacedEvent(): AnOrderHasBeenPlaced
{
return new AnOrderHasBeenPlaced(
orderId: $this->id(),
reference: $this->reference,
totalTtc: $this->getTotal(),
byMatricule: $this->employee->matricule,
employee: clone $this->employee,
shop: OrderPlacedShop::fromDeliveryAddress($this->deliveryAddress),
pickupDay: CarbonImmutable::instance($this->pickupTimeSlot->getAt()),
lines: array_map(
fn (OrderLine $line) => OrderPlacedLine::fromOrderLine($line),
$this->lines
)
);
}
}