Output:
Chunk ID: 029719
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 955
Output:
<?php

namespace App\Livewire\Admin\Orders;

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Models\Order;
use App\Models\Store;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Livewire\Attributes\Locked;
use Livewire\Component;
use Livewire\WithPagination;
use Throwable;

class Index extends Component
{
    use WithPagination;

    #[Locked]
    public int $storeId;

    public string $search = '';

    public string $statusFilter = 'all';

    public string $financialStatusFilter = 'all';

    public string $fulfillmentStatusFilter = 'all';

    public string $dateFrom = '';

    public string $dateTo = '';

    public function mount(): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $this->storeId = $store->getKey();
    }

    public function updatedSearch(): void
    {
        $this->resetPage();
    }

    public function updatedStatusFilter(): void
    {
        $this->resetPage();
    }

    public function updatedFinancialStatusFilter(): void
    {
        $this->resetPage();
    }

    public function updatedFulfillmentStatusFilter(): void
    {
        $this->resetPage();
    }

    public function updatedDateFrom(): void
    {
        $this->resetPage();
    }

    public function updatedDateTo(): void
    {
        $this->resetPage();
    }

    public function orders(): LengthAwarePaginator
    {
        $dateFrom = $this->parsedDate($this->dateFrom);
        $dateTo = $this->parsedDate($this->dateTo, endOfDay: true);

        return Order::withoutGlobalScopes()
            ->with('customer')
            ->withCount('lines')
            ->where('store_id', $this->storeId)
            ->when($this->search !== '', function (Builder $query): void {
                $search = '%'.$this->search.'%';

                $query->where(function (Builder $query) use ($search): void {
                    $query
                        ->where('order_number', 'like', $search)
                        ->orWhere('email', 'like', $search)
                        ->orWhereHas('customer', fn (Builder $query) => $query->where('name', 'like', $search));
                });
            })
            ->when($this->statusFilter !== 'all', fn (Builder $query) => $query->where('status', $this->statusFilter))
            ->when($this->financialStatusFilter !== 'all', fn (Builder $query) => $query->where('financial_status', $this->financialStatusFilter))
            ->when($this->fulfillmentStatusFilter !== 'all', fn (Builder $query) => $query->where('fulfillment_status', $this->fulfillmentStatusFilter))
            ->when($dateFrom instanceof Carbon, fn (Builder $query) => $query->where('placed_at', '>=', $dateFrom))
            ->when($dateTo instanceof Carbon, fn (Builder $query) => $query->where('placed_at', '<=', $dateTo))
            ->latest('placed_at')
            ->latest('id')
            ->paginate(20);
    }

    public function render(): mixed
    {
        return view('livewire.admin.orders.index', [
            'orders' => $this->orders(),
            'statuses' => OrderStatus::cases(),
            'financialStatuses' => FinancialStatus::cases(),
            'fulfillmentStatuses' => FulfillmentStatus::cases(),
        ])->layout('layouts.app', [
            'title' => __('Orders'),
        ]);
    }

    private function parsedDate(string $value, bool $endOfDay = false): ?Carbon
    {
        if ($value === '') {
            return null;
        }

        try {
            $date = Carbon::parse($value);

            return $endOfDay ? $date->endOfDay() : $date->startOfDay();
        } catch (Throwable) {
            return null;
        }
    }
}


Output:
Chunk ID: c3edb3
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1949
Output:
<?php

namespace App\Livewire\Admin\Orders;

use App\Enums\RefundStatus;
use App\Exceptions\InvalidFulfillmentOperationException;
use App\Exceptions\InvalidOrderOperationException;
use App\Exceptions\InvalidRefundOperationException;
use App\Models\Fulfillment;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Refund;
use App\Models\Store;
use App\Services\FulfillmentService;
use App\Services\OrderService;
use App\Services\RefundService;
use App\Support\Money;
use Illuminate\Validation\ValidationException;
use Livewire\Attributes\Locked;
use Livewire\Component;

class Show extends Component
{
    #[Locked]
    public int $storeId;

    #[Locked]
    public int $orderId;

    public string $refundAmount = '';

    public string $refundReason = '';

    /**
     * @var array<int, int>
     */
    public array $fulfillmentLineQuantities = [];

    public string $trackingCompany = '';

    public string $trackingNumber = '';

    public string $trackingUrl = '';

    public function mount(Order $order): void
    {
        $store = app('current_store');

        abort_unless($store instanceof Store, 404);

        $order = Order::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->whereKey($order->getKey())
            ->first();

        abort_unless($order instanceof Order, 404);

        $this->storeId = $store->getKey();
        $this->orderId = $order->getKey();
        $this->resetFulfillmentLineQuantities($this->order());
    }

    public function confirmBankTransferPayment(OrderService $orders): void
    {
        try {
            $orders->confirmBankTransferPayment($this->order());
            $this->resetFulfillmentLineQuantities($this->order());
            $this->dispatch('toast', type: 'success', message: __('Payment confirmed'));
        } catch (InvalidOrderOperationException $exception) {
            throw ValidationException::withMessages([
                'orderAction' => $exception->getMessage(),
            ]);
        }
    }

    public function processRefund(RefundService $refunds): void
    {
        $this->validate([
            'refundAmount' => ['nullable', 'numeric', 'min:0.01'],
            'refundReason' => ['nullable', 'string', 'max:500'],
        ]);

        $request = [
            'reason' => $this->refundReason !== '' ? $this->refundReason : null,
        ];

        if ($this->refundAmount !== '') {
            $request['amount'] = Money::fromDecimalString($this->refundAmount);
        }

        try {
            $refunds->process($this->order(), $request);
            $this->refundAmount = '';
            $this->refundReason = '';
            $this->modal('refund-order')->close();
            $this->dispatch('toast', type: 'success', message: __('Refund processed'));
        } catch (InvalidRefundOperationException $exception) {
            throw ValidationException::withMessages([
                'refundAmount' => $exception->getMessage(),
            ]);
        }
    }

    public function createFulfillment(FulfillmentService $fulfillments): void
    {
        $this->validate([
            'fulfillmentLineQuantities' => ['array'],
            'trackingCompany' => ['nullable', 'string', 'max:255'],
            'trackingNumber' => ['nullable', 'string', 'max:255'],
            'trackingUrl' => ['nullable', 'url', 'max:2048'],
        ]);

        $lines = collect($this->fulfillmentLineQuantities)
            ->mapWithKeys(fn (mixed $quantity, int|string $lineId): array => [(int) $lineId => (int) $quantity])
            ->filter(fn (int $quantity): bool => $quantity > 0)
            ->all();

        if ($lines === []) {
            throw ValidationException::withMessages([
                'fulfillment' => __('At least one fulfillment line is required.'),
            ]);
        }

        try {
            $fulfillments->create($this->order(), $lines, [
                'tracking_company' => $this->trackingCompany !== '' ? $this->trackingCompany : null,
                'tracking_number' => $this->trackingNumber !== '' ? $this->trackingNumber : null,
                'tracking_url' => $this->trackingUrl !== '' ? $this->trackingUrl : null,
            ]);

            $this->trackingCompany = '';
            $this->trackingNumber = '';
            $this->trackingUrl = '';
            $this->resetFulfillmentLineQuantities($this->order());
            $this->modal('fulfillment-order')->close();
            $this->dispatch('toast', type: 'success', message: __('Fulfillment created'));
        } catch (InvalidFulfillmentOperationException $exception) {
            throw ValidationException::withMessages([
                'fulfillment' => $exception->getMessage(),
            ]);
        }
    }

    public function markFulfillmentShipped(int $fulfillmentId, FulfillmentService $fulfillments): void
    {
        try {
            $fulfillments->markShipped($this->fulfillment($fulfillmentId));
            $this->dispatch('toast', type: 'success', message: __('Fulfillment marked as shipped'));
        } catch (InvalidFulfillmentOperationException $exception) {
            throw ValidationException::withMessages([
                'fulfillment' => $exception->getMessage(),
            ]);
        }
    }

    public function markFulfillmentDelivered(int $fulfillmentId, FulfillmentService $fulfillments): void
    {
        try {
            $fulfillments->markDelivered($this->fulfillment($fulfillmentId));
            $this->dispatch('toast', type: 'success', message: __('Fulfillment marked as delivered'));
        } catch (InvalidFulfillmentOperationException $exception) {
            throw ValidationException::withMessages([
                'fulfillment' => $exception->getMessage(),
            ]);
        }
    }

    public function render(): mixed
    {
        $order = $this->order();

        return view('livewire.admin.orders.show', [
            'order' => $order,
            'remainingFulfillmentQuantities' => $this->remainingFulfillmentQuantities($order),
            'refundableAmount' => $this->refundableAmount($order),
        ])->layout('layouts.app', [
            'title' => $order->order_number,
        ]);
    }

    private function order(): Order
    {
        return Order::withoutGlobalScopes()
            ->with([
                'customer',
                'lines.fulfillmentLines',
                'payments',
                'refunds',
                'fulfillments.lines.orderLine',
            ])
            ->where('store_id', $this->storeId)
            ->whereKey($this->orderId)
            ->firstOrFail();
    }

    private function fulfillment(int $fulfillmentId): Fulfillment
    {
        $fulfillment = $this->order()
            ->fulfillments
            ->firstWhere('id', $fulfillmentId);

        abort_unless($fulfillment instanceof Fulfillment, 404);

        return $fulfillment;
    }

    /**
     * @return array<int, int>
     */
    private function remainingFulfillmentQuantities(Order $order): array
    {
        return $order->lines
            ->mapWithKeys(function (OrderLine $line): array {
                $fulfilled = $line->fulfillmentLines->sum('quantity');

                return [$line->getKey() => max(0, $line->quantity - $fulfilled)];
            })
            ->all();
    }

    private function resetFulfillmentLineQuantities(Order $order): void
    {
        $this->fulfillmentLineQuantities = $this->remainingFulfillmentQuantities($order);
    }

    private function refundableAmount(Order $order): int
    {
        $refunded = $order->refunds
            ->reject(fn (Refund $refund): bool => $refund->status === RefundStatus::Failed)
            ->sum('amount');

        return max(0, $order->total_amount - $refunded);
    }
}


Output:
Chunk ID: 8cda50
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1557
Output:

        <flux:heading size="xl">Orders</flux:heading>
        <flux:text class="mt-1">Review orders, payment status, and fulfillment progress.</flux:text>

        <flux:input wire:model.live.debounce.300ms="search" icon="magnifying-glass" placeholder="Search orders or customers..." aria-label="Search orders" />

        <flux:select wire:model.live="statusFilter" aria-label="Order status filter">
            <flux:select.option value="all">All orders</flux:select.option>
            @foreach ($statuses as $status)
                <flux:select.option value="{{ $status->value }}">{{ Str::title($status->value) }}</flux:select.option>
            @endforeach
        </flux:select>

        <flux:select wire:model.live="financialStatusFilter" aria-label="Financial status filter">
            <flux:select.option value="all">All financial</flux:select.option>
            @foreach ($financialStatuses as $status)
                <flux:select.option value="{{ $status->value }}">{{ Str::headline($status->value) }}</flux:select.option>
            @endforeach
        </flux:select>

        <flux:select wire:model.live="fulfillmentStatusFilter" aria-label="Fulfillment status filter">
            <flux:select.option value="all">All fulfillment</flux:select.option>
            @foreach ($fulfillmentStatuses as $status)
                <flux:select.option value="{{ $status->value }}">{{ Str::headline($status->value) }}</flux:select.option>
            @endforeach
        </flux:select>

        <flux:input type="date" wire:model.live="dateFrom" aria-label="Placed from" />
        <flux:input type="date" wire:model.live="dateTo" aria-label="Placed to" />

                        Order
                        Customer
                        Status
                        Fulfillment
                        Items
                        Total
                        Placed

                    @forelse ($orders as $order)
                        @php
                            $financialColor = match ($order->financial_status->value) {
                                'paid' => 'green',
                                'partially_refunded' => 'amber',
                                'refunded', 'voided' => 'red',
                                default => 'zinc',
                            };
                            $fulfillmentColor = match ($order->fulfillment_status->value) {
                                'fulfilled' => 'green',
                                'partial' => 'amber',
                                default => 'zinc',
                            };
                        @endphp

getKey() }}">

                                    {{ $order->order_number }}

{{ Str::headline($order->status->value) }}

{{ $order->customer?->name ?: 'Guest' }}

{{ $order->email }}

                                <flux:badge :color="$financialColor">{{ Str::headline($order->financial_status->value) }}</flux:badge>

                                <flux:badge :color="$fulfillmentColor">{{ Str::headline($order->fulfillment_status->value) }}</flux:badge>

                            {{ $order->lines_count }}

                                <x-storefront.price :amount="$order->total_amount" :currency="$order->currency" class="justify-end" />

                            {{ $order->placed_at?->format('M j, Y H:i') }}

                    @empty

                                        <flux:icon name="shopping-bag" class="size-6" />

                                    <flux:heading size="lg">No orders found</flux:heading>
                                    <flux:text>Orders will appear here after checkout completion.</flux:text>

                    @endforelse

    {{ $orders->links() }}


Output:
Chunk ID: d33734
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 4003
Output:

            <flux:button :href="route('admin.orders.index')" wire:navigate variant="ghost" icon="arrow-left">
                Orders
            </flux:button>

                <flux:heading size="xl">{{ $order->order_number }}</flux:heading>
                <flux:text class="mt-1">{{ $order->email }} · {{ $order->placed_at?->format('M j, Y H:i') }}</flux:text>

            @if ($order->payment_method === \App\Enums\PaymentMethod::BankTransfer && $order->financial_status === \App\Enums\FinancialStatus::Pending)
                <flux:button wire:click="confirmBankTransferPayment" variant="primary" icon="banknotes">
                    Confirm payment
                </flux:button>
            @endif

            @if ($refundableAmount > 0)
                <flux:modal.trigger name="refund-order">
                    <flux:button variant="danger" icon="receipt-refund">
                        Refund
                    </flux:button>
                </flux:modal.trigger>
            @endif

            @if (in_array($order->financial_status, [\App\Enums\FinancialStatus::Paid, \App\Enums\FinancialStatus::PartiallyRefunded], true) && collect($remainingFulfillmentQuantities)->sum() > 0)
                <flux:modal.trigger name="fulfillment-order">
                    <flux:button variant="filled" icon="truck">
                        Create fulfillment
                    </flux:button>
                </flux:modal.trigger>
            @endif

    @error('orderAction')

            {{ $message }}

    @enderror

    @error('fulfillment')

            {{ $message }}

    @enderror

Order

                <flux:badge>{{ Str::headline($order->status->value) }}</flux:badge>

Payment

                <flux:badge :color="$order->financial_status->value === 'paid' ? 'green' : ($order->financial_status->value === 'pending' ? 'amber' : 'zinc')">
                    {{ Str::headline($order->financial_status->value) }}
                </flux:badge>

Fulfillment

                <flux:badge :color="$order->fulfillment_status->value === 'fulfilled' ? 'green' : ($order->fulfillment_status->value === 'partial' ? 'amber' : 'zinc')">
                    {{ Str::headline($order->fulfillment_status->value) }}
                </flux:badge>

Total

                {{ \App\Support\Money::format($order->total_amount, $order->currency) }}

                    <flux:heading size="lg">Line items</flux:heading>

                    @foreach ($order->lines as $line)

getKey() }}">

{{ $line->title_snapshot }}

{{ $line->sku_snapshot ?: 'No SKU' }}

Qty {{ $line->quantity }}

{{ \App\Support\Money::format($line->total_amount, $order->currency) }}

                    @endforeach

                    <flux:heading size="lg">Payments</flux:heading>

                    @foreach ($order->payments as $payment)

getKey() }}">

{{ Str::headline($payment->method->value) }}

{{ $payment->provider_payment_id }}

                                <flux:badge>{{ Str::headline($payment->status->value) }}</flux:badge>
                                {{ \App\Support\Money::format($payment->amount, $payment->currency) }}

                    @endforeach

                    <flux:heading size="lg">Fulfillments</flux:heading>

                    @forelse ($order->fulfillments as $fulfillment)

getKey() }}">

                                    <flux:badge>{{ Str::headline($fulfillment->status->value) }}</flux:badge>
                                    @if ($fulfillment->tracking_number)

{{ $fulfillment->tracking_company }} {{ $fulfillment->tracking_number }}

                                    @endif

                                    @if ($fulfillment->status === \App\Enums\FulfillmentShipmentStatus::Pending)
                                        <flux:button wire:click="markFulfillmentShipped({{ $fulfillment->getKey() }})" size="sm" variant="filled">Mark shipped</flux:button>
                                    @endif
                                    @if ($fulfillment->status === \App\Enums\FulfillmentShipmentStatus::Shipped)
                                        <flux:button wire:click="markFulfillmentDelivered({{ $fulfillment->getKey() }})" size="sm" variant="filled">Mark delivered</flux:button>
                                    @endif

                                @foreach ($fulfillment->lines as $line)

getKey() }}">
                                        {{ $line->orderLine?->title_snapshot }} · Qty {{ $line->quantity }}

                                @endforeach

                    @empty

No fulfillments yet.

                    @endforelse

                <flux:heading size="lg">Customer</flux:heading>

{{ $order->customer?->name ?: 'Guest checkout' }}

{{ $order->email }}

                @if ($order->customer)
                    <flux:button :href="route('admin.customers.show', $order->customer)" wire:navigate variant="filled" size="sm" class="mt-4">
                        View customer
                    </flux:button>
                @endif

                <flux:heading size="lg">Summary</flux:heading>

                        Subtotal
                        {{ \App\Support\Money::format($order->subtotal_amount, $order->currency) }}

                        Discount
                        -{{ \App\Support\Money::format($order->discount_amount, $order->currency) }}

                        Shipping
                        {{ \App\Support\Money::format($order->shipping_amount, $order->currency) }}

                        Tax
                        {{ \App\Support\Money::format($order->tax_amount, $order->currency) }}

                        Total
                        {{ \App\Support\Money::format($order->total_amount, $order->currency) }}

                <flux:heading size="lg">Refunds</flux:heading>

                    @forelse ($order->refunds as $refund)

getKey() }}">

{{ \App\Support\Money::format($refund->amount, $order->currency) }}

{{ $refund->reason ?: 'No reason' }}

                            <flux:badge>{{ Str::headline($refund->status->value) }}</flux:badge>

                    @empty

No refunds processed.

                    @endforelse

    <flux:modal name="refund-order" class="md:w-[32rem]">
        <form wire:submit="processRefund" class="space-y-6">

                <flux:heading size="lg">Process refund</flux:heading>
                <flux:text class="mt-2">Refundable amount: {{ \App\Support\Money::format($refundableAmount, $order->currency) }}</flux:text>

            <flux:input wire:model="refundAmount" label="Amount" placeholder="{{ number_format($refundableAmount / 100, 2, '.', '') }}" />
            <flux:error name="refundAmount" />
            <flux:textarea wire:model="refundReason" label="Reason" rows="3" />

                <flux:modal.close>
                    <flux:button variant="filled">Cancel</flux:button>
                </flux:modal.close>
                <flux:button type="submit" variant="danger">Process refund</flux:button>

        </form>
    </flux:modal>

    <flux:modal name="fulfillment-order" class="md:w-[38rem]">
        <form wire:submit="createFulfillment" class="space-y-6">

                <flux:heading size="lg">Create fulfillment</flux:heading>
                <flux:text class="mt-2">Select the remaining quantities included in this shipment.</flux:text>

                @foreach ($order->lines as $line)
                    @php($remaining = $remainingFulfillmentQuantities[$line->getKey()] ?? 0)
                    <flux:input
                        type="number"
                        min="0"
                        max="{{ $remaining }}"
                        wire:model="fulfillmentLineQuantities.{{ $line->getKey() }}"
                        label="{{ $line->title_snapshot }} ({{ $remaining }} remaining)"
                        wire:key="fulfillment-input-{{ $line->getKey() }}"
                    />
                @endforeach

            <flux:error name="fulfillment" />

                <flux:input wire:model="trackingCompany" label="Carrier" placeholder="DHL" />
                <flux:input wire:model="trackingNumber" label="Tracking number" />

                    <flux:input wire:model="trackingUrl" label="Tracking URL" />

            <flux:error name="trackingUrl" />

                <flux:modal.close>
                    <flux:button variant="filled">Cancel</flux:button>
                </flux:modal.close>
                <flux:button type="submit" variant="primary">Create fulfillment</flux:button>

        </form>
    </flux:modal>


sed -n '1,180p' database/factories/OrderFactory.php


sed -n '1,160p' database/factories/OrderLineFactory.php


sed -n '1,150p' database/factories/PaymentFactory.php


sed -n '1,140p' database/factories/CustomerFactory.php


sed -n '1,180p' database/factories/OrderFactory.php

<?php

namespace Database\Factories;

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Models\Checkout;
use App\Models\Customer;
use App\Models\Store;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Order>
 */
class OrderFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        $subtotal = fake()->numberBetween(2500, 25000);
        $shipping = fake()->randomElement([0, 499, 799]);
        $tax = 0;

        return [
            'store_id' => Store::factory(),
            'checkout_id' => null,
            'customer_id' => null,
            'order_number' => '#'.fake()->unique()->numberBetween(1001, 9999),
            'payment_method' => PaymentMethod::CreditCard,
            'status' => OrderStatus::Paid,
            'financial_status' => FinancialStatus::Paid,
            'fulfillment_status' => FulfillmentStatus::Unfulfilled,
            'currency' => 'EUR',
            'subtotal_amount' => $subtotal,
            'discount_amount' => 0,
            'shipping_amount' => $shipping,
            'tax_amount' => $tax,
            'total_amount' => $subtotal + $shipping + $tax,
            'email' => fake()->safeEmail(),
            'billing_address_json' => $this->address(),
            'shipping_address_json' => $this->address(),
            'placed_at' => now(),
        ];
    }

    public function forCheckout(?Checkout $checkout = null): static
    {
        return $this->state(fn (array $attributes): array => [
            'checkout_id' => $checkout?->getKey() ?? Checkout::factory(),
        ]);
    }

    public function forCustomer(?Customer $customer = null): static
    {
        return $this->state(fn (array $attributes): array => [
            'customer_id' => $customer?->getKey() ?? Customer::factory(),
        ]);
    }

    public function paid(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Paid,
            'financial_status' => FinancialStatus::Paid,
        ]);
    }

    public function pending(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Pending,
            'financial_status' => FinancialStatus::Pending,
        ]);
    }

    public function creditCard(): static
    {
        return $this->state(fn (array $attributes): array => [
            'payment_method' => PaymentMethod::CreditCard,
        ]);
    }

    public function paypal(): static
    {
        return $this->state(fn (array $attributes): array => [
            'payment_method' => PaymentMethod::Paypal,
        ]);
    }

    public function bankTransfer(): static
    {
        return $this->state(fn (array $attributes): array => [
            'payment_method' => PaymentMethod::BankTransfer,
            'status' => OrderStatus::Pending,
            'financial_status' => FinancialStatus::Pending,
        ]);
    }

    public function cancelled(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Cancelled,
            'financial_status' => FinancialStatus::Voided,
        ]);
    }

    public function partiallyFulfilled(): static
    {
        return $this->state(fn (array $attributes): array => [
            'fulfillment_status' => FulfillmentStatus::Partial,
        ]);
    }

    public function fulfilled(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Fulfilled,
            'financial_status' => FinancialStatus::Paid,
            'fulfillment_status' => FulfillmentStatus::Fulfilled,
        ]);
    }

    public function refunded(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Refunded,
            'financial_status' => FinancialStatus::Refunded,
        ]);
    }

    /**
     * @return array<string, string|null>
     */
    private function address(): array
    {
        return [
            'first_name' => fake()->firstName(),
            'last_name' => fake()->lastName(),
            'address1' => fake()->streetAddress(),
            'address2' => null,
            'city' => fake()->city(),
            'province_code' => null,
            'country' => 'DE',
            'postal_code' => fake()->postcode(),
        ];
    }
}


sed -n '1,160p' database/factories/OrderLineFactory.php

<?php

namespace Database\Factories;

use App\Models\Order;
use App\Models\ProductVariant;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\OrderLine>
 */
class OrderLineFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        $quantity = fake()->numberBetween(1, 3);
        $unitPrice = fake()->numberBetween(1000, 10000);

        return [
            'order_id' => Order::factory(),
            'product_id' => null,
            'variant_id' => ProductVariant::factory(),
            'title_snapshot' => fake()->words(3, true),
            'sku_snapshot' => 'SKU-'.fake()->unique()->numerify('####'),
            'quantity' => $quantity,
            'unit_price_amount' => $unitPrice,
            'total_amount' => $unitPrice * $quantity,
            'tax_lines_json' => [],
            'discount_allocations_json' => [],
        ];
    }
}


sed -n '1,150p' database/factories/PaymentFactory.php

<?php

namespace Database\Factories;

use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Models\Order;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Payment>
 */
class PaymentFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'order_id' => Order::factory(),
            'provider' => 'mock',
            'method' => PaymentMethod::CreditCard,
            'provider_payment_id' => 'mock_payment_'.fake()->unique()->lexify('????????????????'),
            'status' => PaymentStatus::Captured,
            'amount' => fake()->numberBetween(2500, 25000),
            'currency' => 'EUR',
            'raw_json_encrypted' => [
                'success' => true,
                'status' => PaymentStatus::Captured->value,
            ],
        ];
    }

    public function pending(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => PaymentStatus::Pending,
        ]);
    }

    public function failed(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => PaymentStatus::Failed,
            'raw_json_encrypted' => [
                'success' => false,
                'status' => PaymentStatus::Failed->value,
                'error_code' => 'card_declined',
            ],
        ]);
    }

    public function refunded(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => PaymentStatus::Refunded,
        ]);
    }

    public function paypal(): static
    {
        return $this->state(fn (array $attributes): array => [
            'method' => PaymentMethod::Paypal,
        ]);
    }

    public function bankTransfer(): static
    {
        return $this->state(fn (array $attributes): array => [
            'method' => PaymentMethod::BankTransfer,
            'status' => PaymentStatus::Pending,
            'provider_payment_id' => 'mock_bank_'.fake()->unique()->lexify('????????????????'),
        ]);
    }
}


sed -n '1,140p' database/factories/CustomerFactory.php

<?php

namespace Database\Factories;

use App\Models\Store;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Customer>
 */
class CustomerFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'store_id' => Store::factory(),
            'email' => fake()->unique()->safeEmail(),
            'password' => 'password',
            'name' => fake()->name(),
            'marketing_opt_in' => false,
        ];
    }

    public function guest(): static
    {
        return $this->state(fn (array $attributes): array => [
            'password' => null,
        ]);
    }
}


Output:
Chunk ID: d07926
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1152
Output:
<?php

namespace Database\Factories;

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Models\Checkout;
use App\Models\Customer;
use App\Models\Store;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Order>
 */
class OrderFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        $subtotal = fake()->numberBetween(2500, 25000);
        $shipping = fake()->randomElement([0, 499, 799]);
        $tax = 0;

        return [
            'store_id' => Store::factory(),
            'checkout_id' => null,
            'customer_id' => null,
            'order_number' => '#'.fake()->unique()->numberBetween(1001, 9999),
            'payment_method' => PaymentMethod::CreditCard,
            'status' => OrderStatus::Paid,
            'financial_status' => FinancialStatus::Paid,
            'fulfillment_status' => FulfillmentStatus::Unfulfilled,
            'currency' => 'EUR',
            'subtotal_amount' => $subtotal,
            'discount_amount' => 0,
            'shipping_amount' => $shipping,
            'tax_amount' => $tax,
            'total_amount' => $subtotal + $shipping + $tax,
            'email' => fake()->safeEmail(),
            'billing_address_json' => $this->address(),
            'shipping_address_json' => $this->address(),
            'placed_at' => now(),
        ];
    }

    public function forCheckout(?Checkout $checkout = null): static
    {
        return $this->state(fn (array $attributes): array => [
            'checkout_id' => $checkout?->getKey() ?? Checkout::factory(),
        ]);
    }

    public function forCustomer(?Customer $customer = null): static
    {
        return $this->state(fn (array $attributes): array => [
            'customer_id' => $customer?->getKey() ?? Customer::factory(),
        ]);
    }

    public function paid(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Paid,
            'financial_status' => FinancialStatus::Paid,
        ]);
    }

    public function pending(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Pending,
            'financial_status' => FinancialStatus::Pending,
        ]);
    }

    public function creditCard(): static
    {
        return $this->state(fn (array $attributes): array => [
            'payment_method' => PaymentMethod::CreditCard,
        ]);
    }

    public function paypal(): static
    {
        return $this->state(fn (array $attributes): array => [
            'payment_method' => PaymentMethod::Paypal,
        ]);
    }

    public function bankTransfer(): static
    {
        return $this->state(fn (array $attributes): array => [
            'payment_method' => PaymentMethod::BankTransfer,
            'status' => OrderStatus::Pending,
            'financial_status' => FinancialStatus::Pending,
        ]);
    }

    public function cancelled(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Cancelled,
            'financial_status' => FinancialStatus::Voided,
        ]);
    }

    public function partiallyFulfilled(): static
    {
        return $this->state(fn (array $attributes): array => [
            'fulfillment_status' => FulfillmentStatus::Partial,
        ]);
    }

    public function fulfilled(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Fulfilled,
            'financial_status' => FinancialStatus::Paid,
            'fulfillment_status' => FulfillmentStatus::Fulfilled,
        ]);
    }

    public function refunded(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => OrderStatus::Refunded,
            'financial_status' => FinancialStatus::Refunded,
        ]);
    }

    /**
     * @return array<string, string|null>
     */
    private function address(): array
    {
        return [
            'first_name' => fake()->firstName(),
            'last_name' => fake()->lastName(),
            'address1' => fake()->streetAddress(),
            'address2' => null,
            'city' => fake()->city(),
            'province_code' => null,
            'country' => 'DE',
            'postal_code' => fake()->postcode(),
        ];
    }
}


Output:
Chunk ID: b7a8c1
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 262
Output:
<?php

namespace Database\Factories;

use App\Models\Order;
use App\Models\ProductVariant;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\OrderLine>
 */
class OrderLineFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        $quantity = fake()->numberBetween(1, 3);
        $unitPrice = fake()->numberBetween(1000, 10000);

        return [
            'order_id' => Order::factory(),
            'product_id' => null,
            'variant_id' => ProductVariant::factory(),
            'title_snapshot' => fake()->words(3, true),
            'sku_snapshot' => 'SKU-'.fake()->unique()->numerify('####'),
            'quantity' => $quantity,
            'unit_price_amount' => $unitPrice,
            'total_amount' => $unitPrice * $quantity,
            'tax_lines_json' => [],
            'discount_allocations_json' => [],
        ];
    }
}


Output:
Chunk ID: 9d3cb1
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 555
Output:
<?php

namespace Database\Factories;

use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Models\Order;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Payment>
 */
class PaymentFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'order_id' => Order::factory(),
            'provider' => 'mock',
            'method' => PaymentMethod::CreditCard,
            'provider_payment_id' => 'mock_payment_'.fake()->unique()->lexify('????????????????'),
            'status' => PaymentStatus::Captured,
            'amount' => fake()->numberBetween(2500, 25000),
            'currency' => 'EUR',
            'raw_json_encrypted' => [
                'success' => true,
                'status' => PaymentStatus::Captured->value,
            ],
        ];
    }

    public function pending(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => PaymentStatus::Pending,
        ]);
    }

    public function failed(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => PaymentStatus::Failed,
            'raw_json_encrypted' => [
                'success' => false,
                'status' => PaymentStatus::Failed->value,
                'error_code' => 'card_declined',
            ],
        ]);
    }

    public function refunded(): static
    {
        return $this->state(fn (array $attributes): array => [
            'status' => PaymentStatus::Refunded,
        ]);
    }

    public function paypal(): static
    {
        return $this->state(fn (array $attributes): array => [
            'method' => PaymentMethod::Paypal,
        ]);
    }

    public function bankTransfer(): static
    {
        return $this->state(fn (array $attributes): array => [
            'method' => PaymentMethod::BankTransfer,
            'status' => PaymentStatus::Pending,
            'provider_payment_id' => 'mock_bank_'.fake()->unique()->lexify('????????????????'),
        ]);
    }
}


Output:
Chunk ID: cd26e3
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 199
Output:
<?php

namespace Database\Factories;

use App\Models\Store;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Customer>
 */
class CustomerFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'store_id' => Store::factory(),
            'email' => fake()->unique()->safeEmail(),
            'password' => 'password',
            'name' => fake()->name(),
            'marketing_opt_in' => false,
        ];
    }

    public function guest(): static
    {
        return $this->state(fn (array $attributes): array => [
            'password' => null,
        ]);
    }
}


sed -n '1,260p' app/Services/FulfillmentService.php


sed -n '1,240p' app/Services/OrderService.php


sed -n '1,220p' app/Services/RefundService.php


sed -n '1,260p' app/Services/FulfillmentService.php

<?php

namespace App\Services;

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentShipmentStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Events\FulfillmentCreated;
use App\Events\FulfillmentDelivered;
use App\Events\FulfillmentShipped;
use App\Exceptions\InvalidFulfillmentOperationException;
use App\Models\Fulfillment;
use App\Models\FulfillmentLine;
use App\Models\Order;
use App\Models\OrderLine;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class FulfillmentService
{
    /**
     * @param  array<int|string, int>  $lines
     * @param  array<string, mixed>  $trackingData
     */
    public function create(Order $order, array $lines, array $trackingData = []): Fulfillment
    {
        return DB::transaction(function () use ($order, $lines, $trackingData): Fulfillment {
            $order = $this->freshOrder($order);
            $this->assertCanFulfill($order);

            $requestedLines = $this->normalizeLines($lines);

            if ($requestedLines->isEmpty()) {
                throw InvalidFulfillmentOperationException::because('At least one fulfillment line is required.');
            }

            $requestedLines->each(function (int $quantity, int $lineId) use ($order): void {
                $line = $order->lines->firstWhere('id', $lineId);

                if (! $line instanceof OrderLine) {
                    throw InvalidFulfillmentOperationException::because('Fulfillment line does not belong to this order.');
                }

                $remaining = $line->quantity - $this->fulfilledQuantity($line);

                if ($quantity > $remaining) {
                    throw InvalidFulfillmentOperationException::because('Fulfillment quantity exceeds the unfulfilled quantity.');
                }
            });

            $fulfillment = Fulfillment::query()->create([
                'order_id' => $order->getKey(),
                'status' => FulfillmentShipmentStatus::Pending,
                'tracking_company' => data_get($trackingData, 'tracking_company'),
                'tracking_number' => data_get($trackingData, 'tracking_number'),
                'tracking_url' => data_get($trackingData, 'tracking_url'),
            ]);

            $requestedLines->each(function (int $quantity, int $lineId) use ($fulfillment): void {
                $fulfillment->lines()->create([
                    'order_line_id' => $lineId,
                    'quantity' => $quantity,
                ]);
            });

            $this->updateOrderFulfillmentStatus($order);

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentCreated($fulfillment));

            return $fulfillment;
        });
    }

    public function markShipped(Fulfillment $fulfillment): Fulfillment
    {
        return DB::transaction(function () use ($fulfillment): Fulfillment {
            $fulfillment = $this->freshFulfillment($fulfillment);

            if ($fulfillment->status !== FulfillmentShipmentStatus::Pending) {
                throw InvalidFulfillmentOperationException::because('Only pending fulfillments can be marked as shipped.');
            }

            $fulfillment->forceFill([
                'status' => FulfillmentShipmentStatus::Shipped,
                'shipped_at' => now(),
            ])->save();

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentShipped($fulfillment));

            return $fulfillment;
        });
    }

    public function markDelivered(Fulfillment $fulfillment): Fulfillment
    {
        return DB::transaction(function () use ($fulfillment): Fulfillment {
            $fulfillment = $this->freshFulfillment($fulfillment);

            if ($fulfillment->status !== FulfillmentShipmentStatus::Shipped) {
                throw InvalidFulfillmentOperationException::because('Only shipped fulfillments can be marked as delivered.');
            }

            $fulfillment->forceFill([
                'status' => FulfillmentShipmentStatus::Delivered,
                'delivered_at' => now(),
            ])->save();

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentDelivered($fulfillment));

            return $fulfillment;
        });
    }

    public function autoFulfillDigital(Order $order): ?Fulfillment
    {
        return DB::transaction(function () use ($order): ?Fulfillment {
            $order = $this->freshOrder($order);

            if ($order->fulfillments()->exists() || $order->lines->isEmpty()) {
                return null;
            }

            $allDigital = $order->lines->every(fn (OrderLine $line): bool => $line->variant?->requires_shipping === false);

            if (! $allDigital) {
                return null;
            }

            $fulfillment = Fulfillment::query()->create([
                'order_id' => $order->getKey(),
                'status' => FulfillmentShipmentStatus::Delivered,
                'shipped_at' => now(),
                'delivered_at' => now(),
            ]);

            $order->lines->each(function (OrderLine $line) use ($fulfillment): void {
                $fulfillment->lines()->create([
                    'order_line_id' => $line->getKey(),
                    'quantity' => $line->quantity,
                ]);
            });

            $order->forceFill([
                'status' => OrderStatus::Fulfilled,
                'fulfillment_status' => FulfillmentStatus::Fulfilled,
            ])->save();

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentCreated($fulfillment));
            event(new FulfillmentDelivered($fulfillment));

            return $fulfillment;
        });
    }

    private function freshOrder(Order $order): Order
    {
        return Order::withoutGlobalScopes()
            ->with([
                'lines.variant' => fn ($query) => $query->withoutGlobalScopes(),
                'fulfillments.lines',
            ])
            ->whereKey($order->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function freshFulfillment(Fulfillment $fulfillment): Fulfillment
    {
        return Fulfillment::query()
            ->with('lines.orderLine')
            ->whereKey($fulfillment->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function assertCanFulfill(Order $order): void
    {
        if (! in_array($order->financial_status, [FinancialStatus::Paid, FinancialStatus::PartiallyRefunded], true)) {
            throw InvalidFulfillmentOperationException::because('Fulfillment cannot be created until payment is confirmed.');
        }
    }

    /**
     * @param  array<int|string, int>  $lines
     * @return Collection<int, int>
     */
    private function normalizeLines(array $lines): Collection
    {
        return collect($lines)
            ->mapWithKeys(fn (mixed $quantity, int|string $lineId): array => [(int) $lineId => (int) $quantity])
            ->filter(fn (int $quantity): bool => $quantity > 0);
    }

    private function fulfilledQuantity(OrderLine $line): int
    {
        return (int) FulfillmentLine::query()
            ->where('order_line_id', $line->getKey())
            ->sum('quantity');
    }

    private function updateOrderFulfillmentStatus(Order $order): void
    {
        $allFulfilled = $order->lines->every(function (OrderLine $line): bool {
            return $this->fulfilledQuantity($line) >= $line->quantity;
        });

        $order->forceFill([
            'status' => $allFulfilled ? OrderStatus::Fulfilled : $order->status,
            'fulfillment_status' => $allFulfilled ? FulfillmentStatus::Fulfilled : FulfillmentStatus::Partial,
        ])->save();
    }
}


sed -n '1,240p' app/Services/OrderService.php

<?php

namespace App\Services;

use App\Enums\CartStatus;
use App\Enums\CheckoutStatus;
use App\Enums\FinancialStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Events\OrderCancelled;
use App\Events\OrderCreated;
use App\Events\OrderPaid;
use App\Exceptions\InvalidCheckoutTransitionException;
use App\Exceptions\InvalidOrderOperationException;
use App\Exceptions\PaymentFailedException;
use App\Models\CartLine;
use App\Models\Checkout;
use App\Models\Discount;
use App\Models\InventoryItem;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\ProductOptionValue;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Models\StoreSettings;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use ValueError;

class OrderService
{
    public function __construct(
        private readonly PaymentService $payments,
        private readonly InventoryService $inventory,
        private readonly PricingEngine $pricing,
        private readonly FulfillmentService $fulfillments,
        private readonly DiscountService $discounts,
    ) {}

    /**
     * Create an order from a checkout after payment has been selected.
     *
     * @param  array<string, mixed>  $paymentMethodData
     */
    public function createFromCheckout(Checkout $checkout, array $paymentMethodData = []): Order
    {
        try {
            return DB::transaction(function () use ($checkout, $paymentMethodData): Order {
                $checkout = $this->freshCheckout($checkout);
                $existingOrder = Order::withoutGlobalScopes()
                    ->where('checkout_id', $checkout->getKey())
                    ->first();

                if ($existingOrder instanceof Order) {
                    return $existingOrder->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);
                }

                if ($checkout->status !== CheckoutStatus::PaymentSelected) {
                    throw InvalidCheckoutTransitionException::because("Checkout cannot transition from {$checkout->status->value}.");
                }

                if ($checkout->totals_json === null) {
                    $this->pricing->calculate($checkout);
                    $checkout = $this->freshCheckout($checkout);
                }

                $method = $this->paymentMethod($checkout);
                $paymentResult = $this->payments->charge($checkout, $method, $paymentMethodData);

                if (! $paymentResult->success) {
                    throw PaymentFailedException::fromResult($paymentResult);
                }

                $paidImmediately = $paymentResult->status === PaymentStatus::Captured;
                $totals = $checkout->totals_json ?? [];

                $order = Order::withoutGlobalScopes()->create([
                    'store_id' => $checkout->store_id,
                    'checkout_id' => $checkout->getKey(),
                    'customer_id' => $checkout->customer_id,
                    'order_number' => $this->nextOrderNumber($checkout->store),
                    'payment_method' => $method,
                    'status' => $paidImmediately ? OrderStatus::Paid : OrderStatus::Pending,
                    'financial_status' => $paidImmediately ? FinancialStatus::Paid : FinancialStatus::Pending,
                    'fulfillment_status' => FulfillmentStatus::Unfulfilled,
                    'currency' => (string) data_get($totals, 'currency', $checkout->cart->currency),
                    'subtotal_amount' => (int) data_get($totals, 'subtotal', 0),
                    'discount_amount' => (int) data_get($totals, 'discount', 0),
                    'shipping_amount' => (int) data_get($totals, 'shipping', 0),
                    'tax_amount' => (int) data_get($totals, 'tax', 0),
                    'total_amount' => (int) data_get($totals, 'total', 0),
                    'email' => $checkout->email,
                    'billing_address_json' => $checkout->billing_address_json,
                    'shipping_address_json' => $checkout->shipping_address_json,
                    'placed_at' => now(),
                ]);

                $this->createOrderLines($checkout, $order, $this->discountAllocationsByCartLine($checkout));

                $order->payments()->create([
                    'provider' => 'mock',
                    'method' => $method,
                    'provider_payment_id' => $paymentResult->referenceId,
                    'status' => $paymentResult->status,
                    'amount' => $order->total_amount,
                    'currency' => $order->currency,
                    'raw_json_encrypted' => $paymentResult->toArray(),
                ]);

                if ($paidImmediately) {
                    $this->commitReservedInventory($checkout);
                }

                $checkout->cart->forceFill([
                    'status' => CartStatus::Converted,
                ])->save();

                $checkout->forceFill([
                    'status' => CheckoutStatus::Completed,
                    'expires_at' => null,
                ])->save();

                $this->incrementDiscountUsage($checkout);

                if ($paidImmediately) {
                    $this->fulfillments->autoFulfillDigital($order);
                }

                $order = $order->refresh()->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);

                event(new OrderCreated($order));

                if ($paidImmediately) {
                    event(new OrderPaid($order));
                }

                return $order;
            });
        } catch (PaymentFailedException $exception) {
            $this->releaseFailedPaymentReservation($checkout);

            throw $exception;
        }
    }

    public function confirmBankTransferPayment(Order $order): Order
    {
        return DB::transaction(function () use ($order): Order {
            $order = $this->freshOrder($order);
            $this->assertPendingBankTransfer($order);

            $order->payments()
                ->where('status', PaymentStatus::Pending->value)
                ->update(['status' => PaymentStatus::Captured->value]);

            $this->commitReservedOrderInventory($order);

            $order->forceFill([
                'status' => OrderStatus::Paid,
                'financial_status' => FinancialStatus::Paid,
            ])->save();

            $this->fulfillments->autoFulfillDigital($order);

            $order = $order->refresh()->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);

            event(new OrderPaid($order));

            return $order;
        });
    }

    public function cancelUnpaidBankTransferOrder(Order $order): Order
    {
        return DB::transaction(function () use ($order): Order {
            $order = $this->freshOrder($order);
            $this->assertPendingBankTransfer($order);

            $this->releaseReservedOrderInventory($order);

            $order->payments()
                ->where('status', PaymentStatus::Pending->value)
                ->update(['status' => PaymentStatus::Failed->value]);

            $order->forceFill([
                'status' => OrderStatus::Cancelled,
                'financial_status' => FinancialStatus::Voided,
            ])->save();

            $order = $order->refresh()->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);

            event(new OrderCancelled($order));

            return $order;
        });
    }

    private function freshCheckout(Checkout $checkout): Checkout
    {
        return Checkout::withoutGlobalScopes()
            ->with(['cart', 'store'])
            ->whereKey($checkout->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function freshOrder(Order $order): Order
    {
        return Order::withoutGlobalScopes()
            ->with(['lines', 'payments', 'store.settings'])
            ->whereKey($order->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function paymentMethod(Checkout $checkout): PaymentMethod
    {
        try {
            return PaymentMethod::from((string) $checkout->payment_method);
        } catch (ValueError) {
            throw InvalidCheckoutTransitionException::because('Payment method is invalid.');
        }
    }

    private function nextOrderNumber(Store $store): string
    {
        $settings = StoreSettings::query()
            ->where('store_id', $store->getKey())
            ->first()
            ?->settings_json ?? [];
        $prefix = (string) data_get($settings, 'order_number_prefix', '#');
        $start = max(1, (int) data_get($settings, 'order_number_start', 1001));
        $maxExisting = Order::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->pluck('order_number')
            ->map(fn (string $orderNumber): ?int => $this->sequenceFromOrderNumber($orderNumber))
            ->filter()
            ->max();


Output:
Chunk ID: cb2ee6
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1974
Output:
<?php

namespace App\Services;

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentShipmentStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Events\FulfillmentCreated;
use App\Events\FulfillmentDelivered;
use App\Events\FulfillmentShipped;
use App\Exceptions\InvalidFulfillmentOperationException;
use App\Models\Fulfillment;
use App\Models\FulfillmentLine;
use App\Models\Order;
use App\Models\OrderLine;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class FulfillmentService
{
    /**
     * @param  array<int|string, int>  $lines
     * @param  array<string, mixed>  $trackingData
     */
    public function create(Order $order, array $lines, array $trackingData = []): Fulfillment
    {
        return DB::transaction(function () use ($order, $lines, $trackingData): Fulfillment {
            $order = $this->freshOrder($order);
            $this->assertCanFulfill($order);

            $requestedLines = $this->normalizeLines($lines);

            if ($requestedLines->isEmpty()) {
                throw InvalidFulfillmentOperationException::because('At least one fulfillment line is required.');
            }

            $requestedLines->each(function (int $quantity, int $lineId) use ($order): void {
                $line = $order->lines->firstWhere('id', $lineId);

                if (! $line instanceof OrderLine) {
                    throw InvalidFulfillmentOperationException::because('Fulfillment line does not belong to this order.');
                }

                $remaining = $line->quantity - $this->fulfilledQuantity($line);

                if ($quantity > $remaining) {
                    throw InvalidFulfillmentOperationException::because('Fulfillment quantity exceeds the unfulfilled quantity.');
                }
            });

            $fulfillment = Fulfillment::query()->create([
                'order_id' => $order->getKey(),
                'status' => FulfillmentShipmentStatus::Pending,
                'tracking_company' => data_get($trackingData, 'tracking_company'),
                'tracking_number' => data_get($trackingData, 'tracking_number'),
                'tracking_url' => data_get($trackingData, 'tracking_url'),
            ]);

            $requestedLines->each(function (int $quantity, int $lineId) use ($fulfillment): void {
                $fulfillment->lines()->create([
                    'order_line_id' => $lineId,
                    'quantity' => $quantity,
                ]);
            });

            $this->updateOrderFulfillmentStatus($order);

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentCreated($fulfillment));

            return $fulfillment;
        });
    }

    public function markShipped(Fulfillment $fulfillment): Fulfillment
    {
        return DB::transaction(function () use ($fulfillment): Fulfillment {
            $fulfillment = $this->freshFulfillment($fulfillment);

            if ($fulfillment->status !== FulfillmentShipmentStatus::Pending) {
                throw InvalidFulfillmentOperationException::because('Only pending fulfillments can be marked as shipped.');
            }

            $fulfillment->forceFill([
                'status' => FulfillmentShipmentStatus::Shipped,
                'shipped_at' => now(),
            ])->save();

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentShipped($fulfillment));

            return $fulfillment;
        });
    }

    public function markDelivered(Fulfillment $fulfillment): Fulfillment
    {
        return DB::transaction(function () use ($fulfillment): Fulfillment {
            $fulfillment = $this->freshFulfillment($fulfillment);

            if ($fulfillment->status !== FulfillmentShipmentStatus::Shipped) {
                throw InvalidFulfillmentOperationException::because('Only shipped fulfillments can be marked as delivered.');
            }

            $fulfillment->forceFill([
                'status' => FulfillmentShipmentStatus::Delivered,
                'delivered_at' => now(),
            ])->save();

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentDelivered($fulfillment));

            return $fulfillment;
        });
    }

    public function autoFulfillDigital(Order $order): ?Fulfillment
    {
        return DB::transaction(function () use ($order): ?Fulfillment {
            $order = $this->freshOrder($order);

            if ($order->fulfillments()->exists() || $order->lines->isEmpty()) {
                return null;
            }

            $allDigital = $order->lines->every(fn (OrderLine $line): bool => $line->variant?->requires_shipping === false);

            if (! $allDigital) {
                return null;
            }

            $fulfillment = Fulfillment::query()->create([
                'order_id' => $order->getKey(),
                'status' => FulfillmentShipmentStatus::Delivered,
                'shipped_at' => now(),
                'delivered_at' => now(),
            ]);

            $order->lines->each(function (OrderLine $line) use ($fulfillment): void {
                $fulfillment->lines()->create([
                    'order_line_id' => $line->getKey(),
                    'quantity' => $line->quantity,
                ]);
            });

            $order->forceFill([
                'status' => OrderStatus::Fulfilled,
                'fulfillment_status' => FulfillmentStatus::Fulfilled,
            ])->save();

            $fulfillment = $fulfillment->refresh()->load('lines.orderLine');

            event(new FulfillmentCreated($fulfillment));
            event(new FulfillmentDelivered($fulfillment));

            return $fulfillment;
        });
    }

    private function freshOrder(Order $order): Order
    {
        return Order::withoutGlobalScopes()
            ->with([
                'lines.variant' => fn ($query) => $query->withoutGlobalScopes(),
                'fulfillments.lines',
            ])
            ->whereKey($order->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function freshFulfillment(Fulfillment $fulfillment): Fulfillment
    {
        return Fulfillment::query()
            ->with('lines.orderLine')
            ->whereKey($fulfillment->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function assertCanFulfill(Order $order): void
    {
        if (! in_array($order->financial_status, [FinancialStatus::Paid, FinancialStatus::PartiallyRefunded], true)) {
            throw InvalidFulfillmentOperationException::because('Fulfillment cannot be created until payment is confirmed.');
        }
    }

    /**
     * @param  array<int|string, int>  $lines
     * @return Collection<int, int>
     */
    private function normalizeLines(array $lines): Collection
    {
        return collect($lines)
            ->mapWithKeys(fn (mixed $quantity, int|string $lineId): array => [(int) $lineId => (int) $quantity])
            ->filter(fn (int $quantity): bool => $quantity > 0);
    }

    private function fulfilledQuantity(OrderLine $line): int
    {
        return (int) FulfillmentLine::query()
            ->where('order_line_id', $line->getKey())
            ->sum('quantity');
    }

    private function updateOrderFulfillmentStatus(Order $order): void
    {
        $allFulfilled = $order->lines->every(function (OrderLine $line): bool {
            return $this->fulfilledQuantity($line) >= $line->quantity;
        });

        $order->forceFill([
            'status' => $allFulfilled ? OrderStatus::Fulfilled : $order->status,
            'fulfillment_status' => $allFulfilled ? FulfillmentStatus::Fulfilled : FulfillmentStatus::Partial,
        ])->save();
    }
}


Output:
Chunk ID: 1da52c
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2269
Output:
<?php

namespace App\Services;

use App\Enums\CartStatus;
use App\Enums\CheckoutStatus;
use App\Enums\FinancialStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Events\OrderCancelled;
use App\Events\OrderCreated;
use App\Events\OrderPaid;
use App\Exceptions\InvalidCheckoutTransitionException;
use App\Exceptions\InvalidOrderOperationException;
use App\Exceptions\PaymentFailedException;
use App\Models\CartLine;
use App\Models\Checkout;
use App\Models\Discount;
use App\Models\InventoryItem;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\ProductOptionValue;
use App\Models\ProductVariant;
use App\Models\Store;
use App\Models\StoreSettings;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use ValueError;

class OrderService
{
    public function __construct(
        private readonly PaymentService $payments,
        private readonly InventoryService $inventory,
        private readonly PricingEngine $pricing,
        private readonly FulfillmentService $fulfillments,
        private readonly DiscountService $discounts,
    ) {}

    /**
     * Create an order from a checkout after payment has been selected.
     *
     * @param  array<string, mixed>  $paymentMethodData
     */
    public function createFromCheckout(Checkout $checkout, array $paymentMethodData = []): Order
    {
        try {
            return DB::transaction(function () use ($checkout, $paymentMethodData): Order {
                $checkout = $this->freshCheckout($checkout);
                $existingOrder = Order::withoutGlobalScopes()
                    ->where('checkout_id', $checkout->getKey())
                    ->first();

                if ($existingOrder instanceof Order) {
                    return $existingOrder->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);
                }

                if ($checkout->status !== CheckoutStatus::PaymentSelected) {
                    throw InvalidCheckoutTransitionException::because("Checkout cannot transition from {$checkout->status->value}.");
                }

                if ($checkout->totals_json === null) {
                    $this->pricing->calculate($checkout);
                    $checkout = $this->freshCheckout($checkout);
                }

                $method = $this->paymentMethod($checkout);
                $paymentResult = $this->payments->charge($checkout, $method, $paymentMethodData);

                if (! $paymentResult->success) {
                    throw PaymentFailedException::fromResult($paymentResult);
                }

                $paidImmediately = $paymentResult->status === PaymentStatus::Captured;
                $totals = $checkout->totals_json ?? [];

                $order = Order::withoutGlobalScopes()->create([
                    'store_id' => $checkout->store_id,
                    'checkout_id' => $checkout->getKey(),
                    'customer_id' => $checkout->customer_id,
                    'order_number' => $this->nextOrderNumber($checkout->store),
                    'payment_method' => $method,
                    'status' => $paidImmediately ? OrderStatus::Paid : OrderStatus::Pending,
                    'financial_status' => $paidImmediately ? FinancialStatus::Paid : FinancialStatus::Pending,
                    'fulfillment_status' => FulfillmentStatus::Unfulfilled,
                    'currency' => (string) data_get($totals, 'currency', $checkout->cart->currency),
                    'subtotal_amount' => (int) data_get($totals, 'subtotal', 0),
                    'discount_amount' => (int) data_get($totals, 'discount', 0),
                    'shipping_amount' => (int) data_get($totals, 'shipping', 0),
                    'tax_amount' => (int) data_get($totals, 'tax', 0),
                    'total_amount' => (int) data_get($totals, 'total', 0),
                    'email' => $checkout->email,
                    'billing_address_json' => $checkout->billing_address_json,
                    'shipping_address_json' => $checkout->shipping_address_json,
                    'placed_at' => now(),
                ]);

                $this->createOrderLines($checkout, $order, $this->discountAllocationsByCartLine($checkout));

                $order->payments()->create([
                    'provider' => 'mock',
                    'method' => $method,
                    'provider_payment_id' => $paymentResult->referenceId,
                    'status' => $paymentResult->status,
                    'amount' => $order->total_amount,
                    'currency' => $order->currency,
                    'raw_json_encrypted' => $paymentResult->toArray(),
                ]);

                if ($paidImmediately) {
                    $this->commitReservedInventory($checkout);
                }

                $checkout->cart->forceFill([
                    'status' => CartStatus::Converted,
                ])->save();

                $checkout->forceFill([
                    'status' => CheckoutStatus::Completed,
                    'expires_at' => null,
                ])->save();

                $this->incrementDiscountUsage($checkout);

                if ($paidImmediately) {
                    $this->fulfillments->autoFulfillDigital($order);
                }

                $order = $order->refresh()->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);

                event(new OrderCreated($order));

                if ($paidImmediately) {
                    event(new OrderPaid($order));
                }

                return $order;
            });
        } catch (PaymentFailedException $exception) {
            $this->releaseFailedPaymentReservation($checkout);

            throw $exception;
        }
    }

    public function confirmBankTransferPayment(Order $order): Order
    {
        return DB::transaction(function () use ($order): Order {
            $order = $this->freshOrder($order);
            $this->assertPendingBankTransfer($order);

            $order->payments()
                ->where('status', PaymentStatus::Pending->value)
                ->update(['status' => PaymentStatus::Captured->value]);

            $this->commitReservedOrderInventory($order);

            $order->forceFill([
                'status' => OrderStatus::Paid,
                'financial_status' => FinancialStatus::Paid,
            ])->save();

            $this->fulfillments->autoFulfillDigital($order);

            $order = $order->refresh()->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);

            event(new OrderPaid($order));

            return $order;
        });
    }

    public function cancelUnpaidBankTransferOrder(Order $order): Order
    {
        return DB::transaction(function () use ($order): Order {
            $order = $this->freshOrder($order);
            $this->assertPendingBankTransfer($order);

            $this->releaseReservedOrderInventory($order);

            $order->payments()
                ->where('status', PaymentStatus::Pending->value)
                ->update(['status' => PaymentStatus::Failed->value]);

            $order->forceFill([
                'status' => OrderStatus::Cancelled,
                'financial_status' => FinancialStatus::Voided,
            ])->save();

            $order = $order->refresh()->load(['lines', 'payments', 'refunds', 'fulfillments.lines']);

            event(new OrderCancelled($order));

            return $order;
        });
    }

    private function freshCheckout(Checkout $checkout): Checkout
    {
        return Checkout::withoutGlobalScopes()
            ->with(['cart', 'store'])
            ->whereKey($checkout->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function freshOrder(Order $order): Order
    {
        return Order::withoutGlobalScopes()
            ->with(['lines', 'payments', 'store.settings'])
            ->whereKey($order->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function paymentMethod(Checkout $checkout): PaymentMethod
    {
        try {
            return PaymentMethod::from((string) $checkout->payment_method);
        } catch (ValueError) {
            throw InvalidCheckoutTransitionException::because('Payment method is invalid.');
        }
    }

    private function nextOrderNumber(Store $store): string
    {
        $settings = StoreSettings::query()
            ->where('store_id', $store->getKey())
            ->first()
            ?->settings_json ?? [];
        $prefix = (string) data_get($settings, 'order_number_prefix', '#');
        $start = max(1, (int) data_get($settings, 'order_number_start', 1001));
        $maxExisting = Order::withoutGlobalScopes()
            ->where('store_id', $store->getKey())
            ->pluck('order_number')
            ->map(fn (string $orderNumber): ?int => $this->sequenceFromOrderNumber($orderNumber))
            ->filter()
            ->max();


sed -n '1,220p' app/Services/RefundService.php

<?php

namespace App\Services;

use App\Enums\FinancialStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentStatus;
use App\Enums\RefundStatus;
use App\Events\OrderRefunded;
use App\Exceptions\InvalidRefundOperationException;
use App\Models\InventoryItem;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Payment;
use App\Models\Refund;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class RefundService
{
    public function __construct(
        private readonly PaymentService $payments,
        private readonly InventoryService $inventory,
    ) {}

    /**
     * @param  array{amount?: int, lines?: array<int|string, int>, reason?: string|null, restock?: bool}  $request
     */
    public function process(Order $order, array $request = []): Refund
    {
        return DB::transaction(function () use ($order, $request): Refund {
            $order = $this->freshOrder($order);
            $payment = $this->refundablePayment($order);
            $refundable = $this->refundableAmount($order);
            $lineQuantities = $this->lineQuantities($order, $request['lines'] ?? []);
            $amount = $this->refundAmount($order, $request, $lineQuantities, $refundable);

            $result = $this->payments->refund($payment, $amount);

            if (! $result->success) {
                throw InvalidRefundOperationException::because($result->errorMessage ?? 'Refund could not be processed.');
            }

            $refund = $order->refunds()->create([
                'payment_id' => $payment->getKey(),
                'amount' => $amount,
                'reason' => data_get($request, 'reason'),
                'status' => $result->status,
                'provider_refund_id' => $result->referenceId,
            ]);

            if ((bool) data_get($request, 'restock', false)) {
                $this->restock($order, $lineQuantities);
            }

            $this->updateOrderFinancialStatus($order, $payment);

            $order = $order->refresh();
            $refund = $refund->refresh();

            event(new OrderRefunded($order, $refund));

            return $refund;
        });
    }

    private function freshOrder(Order $order): Order
    {
        return Order::withoutGlobalScopes()
            ->with(['lines', 'payments', 'refunds'])
            ->whereKey($order->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function refundablePayment(Order $order): Payment
    {
        $payment = $order->payments
            ->where('status', PaymentStatus::Captured)
            ->sortByDesc('id')
            ->first();

        if (! $payment instanceof Payment) {
            throw InvalidRefundOperationException::because('Order does not have a captured payment to refund.');
        }

        return $payment;
    }

    private function refundableAmount(Order $order): int
    {
        $refunded = $order->refunds
            ->reject(fn (Refund $refund): bool => $refund->status === RefundStatus::Failed)
            ->sum('amount');

        return $order->total_amount - $refunded;
    }

    /**
     * @param  array<string, mixed>  $request
     * @param  Collection<int, int>  $lineQuantities
     */
    private function refundAmount(Order $order, array $request, Collection $lineQuantities, int $refundable): int
    {
        $amount = array_key_exists('amount', $request)
            ? (int) $request['amount']
            : ($lineQuantities->isNotEmpty() ? $this->lineRefundAmount($order, $lineQuantities) : $refundable);

        if ($amount <= 0) {
            throw InvalidRefundOperationException::because('Refund amount must be greater than zero.');
        }

        if ($amount > $refundable) {
            throw InvalidRefundOperationException::because('Refund amount exceeds the remaining refundable amount.');
        }

        return $amount;
    }

    /**
     * @param  array<int|string, int>  $lines
     * @return Collection<int, int>
     */
    private function lineQuantities(Order $order, array $lines): Collection
    {
        return collect($lines)
            ->mapWithKeys(fn (mixed $quantity, int|string $lineId): array => [(int) $lineId => (int) $quantity])
            ->filter(fn (int $quantity): bool => $quantity > 0)
            ->each(function (int $quantity, int $lineId) use ($order): void {
                $line = $order->lines->firstWhere('id', $lineId);

                if (! $line instanceof OrderLine) {
                    throw InvalidRefundOperationException::because('Refund line does not belong to this order.');
                }

                if ($quantity > $line->quantity) {
                    throw InvalidRefundOperationException::because('Refund quantity exceeds the ordered quantity.');
                }
            });
    }

    /**
     * @param  Collection<int, int>  $lineQuantities
     */
    private function lineRefundAmount(Order $order, Collection $lineQuantities): int
    {
        return $lineQuantities->reduce(function (int $total, int $quantity, int $lineId) use ($order): int {
            $line = $order->lines->firstWhere('id', $lineId);

            if (! $line instanceof OrderLine) {
                return $total;
            }

            return $total + (int) round($line->total_amount / $line->quantity * $quantity);
        }, 0);
    }

    /**
     * @param  Collection<int, int>  $lineQuantities
     */
    private function restock(Order $order, Collection $lineQuantities): void
    {
        $linesToRestock = $lineQuantities->isNotEmpty()
            ? $lineQuantities
            : $order->lines->mapWithKeys(fn (OrderLine $line): array => [$line->getKey() => $line->quantity]);

        $linesToRestock->each(function (int $quantity, int $lineId) use ($order): void {
            $line = $order->lines->firstWhere('id', $lineId);

            if (! $line instanceof OrderLine || $line->variant_id === null) {
                return;
            }

            $item = InventoryItem::withoutGlobalScopes()
                ->where('variant_id', $line->variant_id)
                ->first();

            if ($item instanceof InventoryItem) {
                $this->inventory->restock($item, $quantity);
            }
        });
    }

    private function updateOrderFinancialStatus(Order $order, Payment $payment): void
    {
        $totalRefunded = $order->refunds()
            ->where('status', '!=', RefundStatus::Failed->value)
            ->sum('amount');

        if ($totalRefunded >= $order->total_amount) {
            $order->forceFill([
                'status' => OrderStatus::Refunded,
                'financial_status' => FinancialStatus::Refunded,
            ])->save();

            $payment->forceFill([
                'status' => PaymentStatus::Refunded,
            ])->save();

            return;
        }

        $order->forceFill([
            'financial_status' => FinancialStatus::PartiallyRefunded,
        ])->save();
    }
}


Output:
Chunk ID: a9615a
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1752
Output:
<?php

namespace App\Services;

use App\Enums\FinancialStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentStatus;
use App\Enums\RefundStatus;
use App\Events\OrderRefunded;
use App\Exceptions\InvalidRefundOperationException;
use App\Models\InventoryItem;
use App\Models\Order;
use App\Models\OrderLine;
use App\Models\Payment;
use App\Models\Refund;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class RefundService
{
    public function __construct(
        private readonly PaymentService $payments,
        private readonly InventoryService $inventory,
    ) {}

    /**
     * @param  array{amount?: int, lines?: array<int|string, int>, reason?: string|null, restock?: bool}  $request
     */
    public function process(Order $order, array $request = []): Refund
    {
        return DB::transaction(function () use ($order, $request): Refund {
            $order = $this->freshOrder($order);
            $payment = $this->refundablePayment($order);
            $refundable = $this->refundableAmount($order);
            $lineQuantities = $this->lineQuantities($order, $request['lines'] ?? []);
            $amount = $this->refundAmount($order, $request, $lineQuantities, $refundable);

            $result = $this->payments->refund($payment, $amount);

            if (! $result->success) {
                throw InvalidRefundOperationException::because($result->errorMessage ?? 'Refund could not be processed.');
            }

            $refund = $order->refunds()->create([
                'payment_id' => $payment->getKey(),
                'amount' => $amount,
                'reason' => data_get($request, 'reason'),
                'status' => $result->status,
                'provider_refund_id' => $result->referenceId,
            ]);

            if ((bool) data_get($request, 'restock', false)) {
                $this->restock($order, $lineQuantities);
            }

            $this->updateOrderFinancialStatus($order, $payment);

            $order = $order->refresh();
            $refund = $refund->refresh();

            event(new OrderRefunded($order, $refund));

            return $refund;
        });
    }

    private function freshOrder(Order $order): Order
    {
        return Order::withoutGlobalScopes()
            ->with(['lines', 'payments', 'refunds'])
            ->whereKey($order->getKey())
            ->lockForUpdate()
            ->firstOrFail();
    }

    private function refundablePayment(Order $order): Payment
    {
        $payment = $order->payments
            ->where('status', PaymentStatus::Captured)
            ->sortByDesc('id')
            ->first();

        if (! $payment instanceof Payment) {
            throw InvalidRefundOperationException::because('Order does not have a captured payment to refund.');
        }

        return $payment;
    }

    private function refundableAmount(Order $order): int
    {
        $refunded = $order->refunds
            ->reject(fn (Refund $refund): bool => $refund->status === RefundStatus::Failed)
            ->sum('amount');

        return $order->total_amount - $refunded;
    }

    /**
     * @param  array<string, mixed>  $request
     * @param  Collection<int, int>  $lineQuantities
     */
    private function refundAmount(Order $order, array $request, Collection $lineQuantities, int $refundable): int
    {
        $amount = array_key_exists('amount', $request)
            ? (int) $request['amount']
            : ($lineQuantities->isNotEmpty() ? $this->lineRefundAmount($order, $lineQuantities) : $refundable);

        if ($amount <= 0) {
            throw InvalidRefundOperationException::because('Refund amount must be greater than zero.');
        }

        if ($amount > $refundable) {
            throw InvalidRefundOperationException::because('Refund amount exceeds the remaining refundable amount.');
        }

        return $amount;
    }

    /**
     * @param  array<int|string, int>  $lines
     * @return Collection<int, int>
     */
    private function lineQuantities(Order $order, array $lines): Collection
    {
        return collect($lines)
            ->mapWithKeys(fn (mixed $quantity, int|string $lineId): array => [(int) $lineId => (int) $quantity])
            ->filter(fn (int $quantity): bool => $quantity > 0)
            ->each(function (int $quantity, int $lineId) use ($order): void {
                $line = $order->lines->firstWhere('id', $lineId);

                if (! $line instanceof OrderLine) {
                    throw InvalidRefundOperationException::because('Refund line does not belong to this order.');
                }

                if ($quantity > $line->quantity) {
                    throw InvalidRefundOperationException::because('Refund quantity exceeds the ordered quantity.');
                }
            });
    }

    /**
     * @param  Collection<int, int>  $lineQuantities
     */
    private function lineRefundAmount(Order $order, Collection $lineQuantities): int
    {
        return $lineQuantities->reduce(function (int $total, int $quantity, int $lineId) use ($order): int {
            $line = $order->lines->firstWhere('id', $lineId);

            if (! $line instanceof OrderLine) {
                return $total;
            }

            return $total + (int) round($line->total_amount / $line->quantity * $quantity);
        }, 0);
    }

    /**
     * @param  Collection<int, int>  $lineQuantities
     */
    private function restock(Order $order, Collection $lineQuantities): void
    {
        $linesToRestock = $lineQuantities->isNotEmpty()
            ? $lineQuantities
            : $order->lines->mapWithKeys(fn (OrderLine $line): array => [$line->getKey() => $line->quantity]);

        $linesToRestock->each(function (int $quantity, int $lineId) use ($order): void {
            $line = $order->lines->firstWhere('id', $lineId);

            if (! $line instanceof OrderLine || $line->variant_id === null) {
                return;
            }

            $item = InventoryItem::withoutGlobalScopes()
                ->where('variant_id', $line->variant_id)
                ->first();

            if ($item instanceof InventoryItem) {
                $this->inventory->restock($item, $quantity);
            }
        });
    }

    private function updateOrderFinancialStatus(Order $order, Payment $payment): void
    {
        $totalRefunded = $order->refunds()
            ->where('status', '!=', RefundStatus::Failed->value)
            ->sum('amount');

        if ($totalRefunded >= $order->total_amount) {
            $order->forceFill([
                'status' => OrderStatus::Refunded,
                'financial_status' => FinancialStatus::Refunded,
            ])->save();

            $payment->forceFill([
                'status' => PaymentStatus::Refunded,
            ])->save();

            return;
        }

        $order->forceFill([
            'financial_status' => FinancialStatus::PartiallyRefunded,
        ])->save();
    }
}


Suite 4 needs more than a test file: the current order detail page has the core actions, but it does not yet expose the spec’s timeline or unpaid-fulfillment guard message. I’m activating the Laravel/Livewire/Flux/Pest skills for this slice and will use Boost docs before making those UI/test changes.


sed -n '1,180p' /Users/fabianwesner/Herd/shop/.agents/skills/laravel-best-practices/SKILL.md


sed -n '1,180p' /Users/fabianwesner/Herd/shop/.agents/skills/livewire-development/SKILL.md


pestphp/pest livewire/livewire livewire/flux laravel/framework

browser testing authenticated session form modal select click

Livewire modal form submit action validation testing

Flux modal form button callout badge testing

Laravel factories relationships browser tests actingAs session