147 lines
5 KiB
PHP
147 lines
5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Infrastructure\Adapters\Repositories;
|
|
|
|
use App\Models\Order;
|
|
use App\Models\OrderLine;
|
|
use Carbon\CarbonImmutable;
|
|
use Carbon\CarbonInterval;
|
|
use Domain\Models\Entities\Order as DomainOrder;
|
|
use Domain\Models\ValueObjects\Entities\OrderId;
|
|
use Domain\Models\ValueObjects\Entities\ShopId;
|
|
use Domain\Models\ValueObjects\OrderLine as DomainOrderLine;
|
|
use Domain\Models\ValueObjects\PickupTimeSlot;
|
|
use Domain\Ports\Repositories\OrderRepository;
|
|
use Illuminate\Support\Carbon;
|
|
use Ramsey\Uuid\Uuid;
|
|
|
|
class EloquentOrderRepository implements OrderRepository
|
|
{
|
|
#[\Override]
|
|
public function find(OrderId $id): ?DomainOrder
|
|
{
|
|
$eloquentOrder = Order::query()
|
|
->with('lines')
|
|
->where('id', $id->value)
|
|
->first();
|
|
|
|
if (! $eloquentOrder) {
|
|
return null;
|
|
}
|
|
|
|
return $this->toEntity($eloquentOrder);
|
|
}
|
|
|
|
#[\Override]
|
|
public function persist(DomainOrder $order): void
|
|
{
|
|
$eloquentOrder = Order::query()
|
|
->where('id', $order->id->value->toString())
|
|
->firstOrNew();
|
|
|
|
$eloquentOrder->id = $order->id->value->toString();
|
|
$eloquentOrder->shop_id = $order->shopId->value->toString();
|
|
$eloquentOrder->reference = $order->reference;
|
|
$eloquentOrder->employee = clone $order->employee;
|
|
$eloquentOrder->delivery_address = clone $order->deliveryAddress;
|
|
$eloquentOrder->pickup_day = Carbon::instance($order->pickupTimeSlot->getAt());
|
|
$eloquentOrder->status = $order->status;
|
|
$eloquentOrder->total = clone $order->getTotal();
|
|
|
|
$eloquentOrder->save();
|
|
|
|
OrderLine::query()
|
|
->where('order_id', $order->id->value->toString())
|
|
->delete();
|
|
|
|
$linesToInsert = [];
|
|
$now = now();
|
|
|
|
foreach ($order->getLines() as $line) {
|
|
$eloquentOrderLine = new OrderLine();
|
|
$eloquentOrderLine->order_id = $order->id->value->toString();
|
|
$eloquentOrderLine->product = clone $line->product;
|
|
$eloquentOrderLine->quantity = $line->quantity;
|
|
$eloquentOrderLine->total_ttc = clone $line->totalTtc;
|
|
|
|
// Use values directly from the domain OrderLine
|
|
$eloquentOrderLine->tax_rate = $line->product->taxRate;
|
|
$eloquentOrderLine->unit_price = clone $line->unitPriceHt;
|
|
$eloquentOrderLine->unit_tax = clone $line->unitTax;
|
|
$eloquentOrderLine->unit_discount = clone $line->unitDiscount;
|
|
$eloquentOrderLine->total_discount = clone $line->totalDiscount;
|
|
$eloquentOrderLine->total_ht = clone $line->totalHt;
|
|
$eloquentOrderLine->total_tax = clone $line->totalTax;
|
|
|
|
$attributes = $eloquentOrderLine->getAttributes();
|
|
$attributes['created_at'] = $now;
|
|
$attributes['updated_at'] = $now;
|
|
|
|
$linesToInsert[] = $attributes;
|
|
}
|
|
|
|
if (! empty($linesToInsert)) {
|
|
OrderLine::query()->insert($linesToInsert);
|
|
}
|
|
}
|
|
|
|
#[\Override]
|
|
public function delete(DomainOrder $order): void
|
|
{
|
|
Order::query()
|
|
->where('id', $order->id->value)
|
|
->delete();
|
|
}
|
|
|
|
/** @return array<int, DomainOrder> */
|
|
public function getAll(): array
|
|
{
|
|
return Order::query()
|
|
->with('lines')
|
|
->get()
|
|
->map(fn (Order $eloquentOrder) => $this->toEntity($eloquentOrder))
|
|
->all();
|
|
}
|
|
|
|
private function toEntity(Order $model): DomainOrder
|
|
{
|
|
$lines = $model->lines->map(function (OrderLine $line) {
|
|
return new DomainOrderLine(
|
|
product: $line->product,
|
|
quantity: $line->quantity,
|
|
unitPriceHt: $line->unit_price,
|
|
unitDiscount: $line->unit_discount,
|
|
unitTax: $line->unit_tax,
|
|
totalHt: $line->total_ht,
|
|
totalDiscount: $line->total_discount,
|
|
totalTax: $line->total_tax,
|
|
totalTtc: $line->total_ttc
|
|
);
|
|
})->all();
|
|
|
|
if ($model->shop === null) {
|
|
throw new \UnexpectedValueException('Order missing shop');
|
|
}
|
|
|
|
if ($model->employee === null) {
|
|
throw new \UnexpectedValueException('Order missing employee');
|
|
}
|
|
|
|
return new DomainOrder(
|
|
id: $model->getId(),
|
|
shopId: new ShopId(Uuid::fromString((string) $model->shop_id)),
|
|
reference: $model->reference,
|
|
employee: clone $model->employee,
|
|
deliveryAddress: clone $model->delivery_address,
|
|
pickupTimeSlot: new PickupTimeSlot(
|
|
$model->pickup_day ? CarbonImmutable::instance($model->pickup_day) : CarbonImmutable::now(),
|
|
CarbonInterval::minutes(PickupTimeSlot::LENGTH)
|
|
),
|
|
status: $model->status,
|
|
total: clone $model->total,
|
|
lines: $lines
|
|
);
|
|
}
|
|
}
|