command: sed -n '45,100p' tests/Unit/DomainServicesTest.php; sed -n '1,140p' database/seeders/ProductSeeder.php; sed -n '1,160p' database/seeders/ShopSeeder.php; sed -n '1,160p' database/seeders/DatabaseSeeder.php

DatabaseSeeder.php

stdout:
});

test('discount validation and allocation honor product restrictions', function (): void {
    $product = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
    $variant = $product->variants()->firstOrFail();
    $cart = Cart::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'currency' => 'EUR', 'cart_version' => 1, 'status' => 'active']);
    $cart->lines()->create(['variant_id' => $variant->getKey(), 'quantity' => 1, 'unit_price_amount' => $variant->price_amount, 'line_subtotal_amount' => $variant->price_amount, 'line_total_amount' => $variant->price_amount]);
    $discount = Discount::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'code' => 'PRODUCT10', 'type' => 'code', 'value_type' => DiscountValueType::Percent, 'value_amount' => 10, 'status' => 'active', 'starts_at' => now()->subDay(), 'ends_at' => now()->addDay(), 'rules_json' => ['applicable_product_ids' => [$product->getKey()]]]);

    expect(app(DiscountService::class)->validate($discount->code, $this->store, $cart)->is($discount))->toBeTrue()
        ->and(app(DiscountService::class)->calculate($discount, $variant->price_amount, [
            ['line_id' => 1, 'product_id' => $product->getKey(), 'amount' => 1000],
            ['line_id' => 2, 'product_id' => $product->getKey() + 999, 'amount' => 1000],
        ])->allocations)->toBe([1 => 100]);
});

test('discount validation returns the documented usage limit error code', function (): void {
    $discount = Discount::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'code' => 'MAXED-TEST', 'type' => 'code', 'value_type' => DiscountValueType::Percent, 'value_amount' => 10, 'status' => 'active', 'usage_limit' => 1, 'usage_count' => 1, 'starts_at' => now()->subDay(), 'ends_at' => now()->addDay(), 'rules_json' => []]);
    $cart = Cart::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'currency' => 'EUR', 'cart_version' => 1, 'status' => 'active']);

    try {
        app(DiscountService::class)->validate($discount->code, $this->store, $cart);
        expect(false)->toBeTrue();
    } catch (InvalidDiscountException $exception) {
        expect($exception->reason)->toBe('discount_usage_limit_reached');
    }
});

test('line refunds restock only the refunded quantity', function (): void {
    $order = Order::withoutGlobalScopes()->where('order_number', '#1001')->firstOrFail();
    $payment = $order->payments()->firstOrFail();
    $line = $order->lines()->firstOrFail();
    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $line->variant_id)->firstOrFail();
    $before = $inventory->quantity_on_hand;

    $refund = app(RefundService::class)->create($order, $payment, [$line->getKey() => 1], 'Damaged item', true);

    expect($refund->amount)->toBe($line->line_total_amount)
        ->and($inventory->refresh()->quantity_on_hand)->toBe($before + 1)
        ->and($order->refresh()->financial_status->value)->toBe('partially_refunded');
});

test('expiring a payment-selected checkout releases reserved inventory', function (): void {
    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
    $cart = app(CartService::class)->create($this->store);
    app(CartService::class)->addLine($cart, $variant->getKey(), 1);
    $checkout = Checkout::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'cart_id' => $cart->getKey(), 'email' => 'expire@example.test', 'status' => CheckoutStatus::PaymentSelected, 'expires_at' => now()->subMinute()]);
    app(\App\Services\InventoryService::class)->reserve($inventory, 1);

    app(CheckoutService::class)->expireCheckout($checkout);

    expect($checkout->refresh()->status)->toBe(CheckoutStatus::Expired)
        ->and($inventory->refresh()->quantity_reserved)->toBe(0);
});

<?php

namespace Database\Seeders;

use App\Enums\InventoryPolicy;
use App\Enums\ProductStatus;
use App\Enums\VariantStatus;
use App\Models\Collection;
use App\Models\InventoryItem;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Store;
use Illuminate\Database\Seeder;

class ProductSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $stores = Store::query()->whereIn('handle', ['acme-fashion', 'acme-electronics'])->get()->keyBy('handle');
        $collections = Collection::query()->whereIn('store_id', $stores->pluck('id'))->get()->keyBy(fn (Collection $collection): string => $collection->store_id.':'.$collection->handle);

        foreach ($this->fashionProducts() as $productData) {
            $product = $this->seedProduct($stores['acme-fashion'], $productData);
            $this->assignCollections($product, $productData['collections'], $collections);
        }

        foreach ($this->electronicsProducts() as $productData) {
            $product = $this->seedProduct($stores['acme-electronics'], $productData);
            $this->assignCollections($product, $productData['collections'], $collections);
        }
    }

    private function seedProduct(Store $store, array $productData): Product
    {
        $product = Product::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $store->getKey(), 'handle' => $productData['handle']],
            ['title' => $productData['title'], 'description' => strip_tags($productData['description_html']), 'description_html' => $productData['description_html'], 'vendor' => $productData['vendor'], 'product_type' => $productData['product_type'], 'tags' => $productData['tags'], 'status' => $productData['status'], 'published_at' => $productData['published_at'], 'sales_count' => 0, 'metadata' => []],
        );

        $optionValues = [];
        foreach ($productData['options'] as $position => $optionData) {
            $option = $product->options()->updateOrCreate(['position' => $position], ['name' => $optionData['name']]);
            $optionValues[$optionData['name']] = [];

            foreach ($optionData['values'] as $valuePosition => $value) {
                $optionValue = $option->values()->updateOrCreate(['position' => $valuePosition], ['value' => $value]);
                $optionValues[$optionData['name']][$value] = $optionValue->getKey();
            }
        }

        foreach ($this->combinations($productData['options']) as $position => $combination) {
            $variantTitle = $combination === [] ? 'Default' : implode(' / ', array_values($combination));
            $price = is_array($productData['price']) ? $productData['price'][$position] : $productData['price'];
            $sku = $productData['sku_prefix'].'-'.str_pad((string) ($position + 1), 3, '0', STR_PAD_LEFT);
            $variant = ProductVariant::query()->updateOrCreate(
                ['product_id' => $product->getKey(), 'position' => $position],
                ['title' => $variantTitle, 'sku' => $sku, 'barcode' => null, 'price_amount' => $price, 'compare_at_amount' => $productData['compare_at'], 'currency' => 'EUR', 'cost_amount' => null, 'weight_grams' => $productData['weight_g'], 'weight_g' => $productData['weight_g'], 'requires_shipping' => $productData['requires_shipping'], 'is_default' => $position === 0, 'status' => $productData['variant_status'], 'metadata' => []],
            );

            $variantOptionIds = [];
            foreach ($combination as $optionName => $value) {
                $variantOptionIds[] = $optionValues[$optionName][$value];
            }
            $variant->optionValues()->sync($variantOptionIds);

            InventoryItem::withoutGlobalScopes()->updateOrCreate(
                ['variant_id' => $variant->getKey()],
                ['store_id' => $store->getKey(), 'quantity_on_hand' => $productData['inventory'], 'quantity_reserved' => 0, 'policy' => $productData['policy']],
            );
        }

        return $product->refresh();
    }

    private function assignCollections(Product $product, array $collectionHandles, $collections): void
    {
        $assignments = [];

        foreach ($collectionHandles as $position => $handle) {
            $collection = $collections->get($product->store_id.':'.$handle);
            if ($collection !== null) {
                $assignments[$collection->getKey()] = ['position' => $position];
            }
        }

        foreach ($collections->filter(fn (Collection $collection): bool => $collection->store_id === $product->store_id) as $collection) {
            if (array_key_exists($collection->getKey(), $assignments)) {
                $collection->products()->syncWithoutDetaching([$product->getKey() => $assignments[$collection->getKey()]]);
            } else {
                $collection->products()->detach($product->getKey());
            }
        }
    }

    private function combinations(array $options): array
    {
        if ($options === []) {
            return [[]];
        }

        $combinations = [[]];
        foreach ($options as $option) {
            $next = [];
            foreach ($combinations as $combination) {
                foreach ($option['values'] as $value) {
                    $next[] = array_merge($combination, [$option['name'] => $value]);
                }
            }
            $combinations = $next;
        }

        return $combinations;
    }

    private function fashionProducts(): array
    {
        return [
            $this->product('Classic Cotton T-Shirt', 'classic-cotton-t-shirt', 'ACME-CTSH', 'Acme Basics', 'T-Shirts', ['new', 'popular'], 2499, null, 200, 15, ['Size' => ['S', 'M', 'L', 'XL'], 'Color' => ['White', 'Black', 'Navy']], ['new-arrivals', 't-shirts']),
            $this->product('Premium Slim Fit Jeans', 'premium-slim-fit-jeans', 'ACME-JEANS', 'Acme Denim', 'Pants', ['new', 'sale'], 7999, 9999, 800, 8, ['Size' => ['28', '30', '32', '34', '36'], 'Color' => ['Blue', 'Black']], ['new-arrivals', 'pants-jeans', 'sale']),
            $this->product('Organic Hoodie', 'organic-hoodie', 'ACME-HOOD', 'Acme Basics', 'Hoodies', ['new', 'trending'], 5999, null, 500, 20, ['Size' => ['S', 'M', 'L', 'XL']], ['new-arrivals']),
            $this->product('Leather Belt', 'leather-belt', 'ACME-BELT', 'Acme Accessories', 'Accessories', ['popular'], 3499, null, 150, 25, ['Size' => ['S/M', 'L/XL'], 'Color' => ['Brown', 'Black']], []),
            $this->product('Running Sneakers', 'running-sneakers', 'ACME-RUN', 'Acme Sport', 'Shoes', ['trending'], 11999, null, 600, 5, ['Size' => ['EU 38', 'EU 39', 'EU 40', 'EU 41', 'EU 42', 'EU 43', 'EU 44'], 'Color' => ['White', 'Black']], ['new-arrivals']),
            $this->product('Graphic Print Tee', 'graphic-print-tee', 'ACME-GTEE', 'Acme Basics', 'T-Shirts', ['new'], 2999, null, 210, 18, ['Size' => ['S', 'M', 'L', 'XL']], ['t-shirts']),
            $this->product('V-Neck Linen Tee', 'v-neck-linen-tee', 'ACME-LTEE', 'Acme Basics', 'T-Shirts', ['popular'], 3499, null, 180, 12, ['Size' => ['S', 'M', 'L'], 'Color' => ['Beige', 'Olive', 'Sky Blue']], ['t-shirts']),
            $this->product('Striped Polo Shirt', 'striped-polo-shirt', 'ACME-POLO', 'Acme Basics', 'T-Shirts', ['sale'], 2799, 3999, 250, 10, ['Size' => ['S', 'M', 'L', 'XL']], ['t-shirts', 'sale']),
            $this->product('Cargo Pants', 'cargo-pants', 'ACME-CARGO', 'Acme Workwear', 'Pants', ['popular'], 5499, null, 700, 14, ['Size' => ['30', '32', '34', '36'], 'Color' => ['Khaki', 'Olive', 'Black']], ['pants-jeans']),
            $this->product('Chino Shorts', 'chino-shorts', 'ACME-SHORT', 'Acme Basics', 'Pants', ['new', 'trending'], 3999, null, 350, 16, ['Size' => ['30', '32', '34', '36'], 'Color' => ['Navy', 'Sand']], ['pants-jeans', 'new-arrivals']),
            $this->product('Wide Leg Trousers', 'wide-leg-trousers', 'ACME-TROUSER', 'Acme Denim', 'Pants', ['sale'], 4999, 6999, 550, 7, ['Size' => ['S', 'M', 'L']], ['pants-jeans', 'sale']),
            $this->product('Wool Scarf', 'wool-scarf', 'ACME-SCARF', 'Acme Accessories', 'Accessories', ['popular'], 2999, null, 120, 30, ['Color' => ['Grey', 'Burgundy', 'Navy']], []),
            $this->product('Canvas Tote Bag', 'canvas-tote-bag', 'ACME-TOTE', 'Acme Accessories', 'Accessories', ['trending'], 1999, null, 300, 40, ['Color' => ['Natural', 'Black']], []),
            $this->product('Bucket Hat', 'bucket-hat', 'ACME-HAT', 'Acme Accessories', 'Accessories', ['new', 'trending'], 2499, null, 80, 22, ['Size' => ['S/M', 'L/XL'], 'Color' => ['Beige', 'Black', 'Olive']], ['new-arrivals']),
            $this->product('Unreleased Winter Jacket', 'unreleased-winter-jacket', 'ACME-WJACKET', 'Acme Outerwear', 'Jackets', ['limited'], 14999, null, 900, 0, ['Size' => ['S', 'M', 'L', 'XL']], [], ProductStatus::Draft, now()->subMonths(6)),
            $this->product('Discontinued Raincoat', 'discontinued-raincoat', 'ACME-RAIN', 'Acme Outerwear', 'Jackets', [], 8999, null, 400, 3, ['Size' => ['M', 'L']], [], ProductStatus::Archived, now()->subMonths(6)),
            $this->product('Limited Edition Sneakers', 'limited-edition-sneakers', 'ACME-LIMITED', 'Acme Sport', 'Shoes', ['limited'], 15999, null, 650, 0, ['Size' => ['EU 40', 'EU 42', 'EU 44']], []),
            $this->product('Backorder Denim Jacket', 'backorder-denim-jacket', 'ACME-BACKORDER', 'Acme Denim', 'Jackets', ['popular'], 9999, null, 750, 0, ['Size' => ['S', 'M', 'L', 'XL']], [], ProductStatus::Active, null, InventoryPolicy::Continue),
            $this->product('Gift Card', 'gift-card', 'ACME-GIFT', 'Acme Fashion', 'Gift Cards', ['popular'], [2500, 5000, 10000], null, 0, 9999, ['Amount' => ['25 EUR', '50 EUR', '100 EUR']], [], ProductStatus::Active, null, InventoryPolicy::Deny, false),
            $this->product('Cashmere Overcoat', 'cashmere-overcoat', 'ACME-CASHMERE', 'Acme Premium', 'Jackets', ['limited', 'new'], 49999, null, 1200, 3, ['Size' => ['S', 'M', 'L'], 'Color' => ['Camel', 'Charcoal']], ['new-arrivals']),
<?php

namespace Database\Seeders;

use App\Enums\InventoryPolicy;
use App\Enums\ProductStatus;
use App\Enums\VariantStatus;
use App\Models\InventoryItem;
use App\Models\Product;
use App\Models\Store;
use Illuminate\Database\Seeder;

class ShopSeeder extends Seeder
{
    public function run(): void
    {
        $this->call([
            OrganizationSeeder::class,
            StoreSeeder::class,
            StoreDomainSeeder::class,
            UserSeeder::class,
            StoreUserSeeder::class,
            StoreSettingsSeeder::class,
            TaxSettingsSeeder::class,
            ShippingSeeder::class,
            CollectionSeeder::class,
            ProductSeeder::class,
            DiscountSeeder::class,
            CustomerSeeder::class,
            OrderSeeder::class,
            ThemeSeeder::class,
            PageSeeder::class,
            NavigationSeeder::class,
            AnalyticsSeeder::class,
            SearchSettingsSeeder::class,
        ]);

        $this->seedLegacyCommerceFixtures();
    }

    private function seedLegacyCommerceFixtures(): void
    {
        $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
        $classic = Product::withoutGlobalScopes()->where('store_id', $store->getKey())->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
        $classicVariant = $classic->variants()->orderBy('position')->firstOrFail();

        InventoryItem::withoutGlobalScopes()->updateOrCreate(
            ['variant_id' => $classicVariant->getKey()],
            ['store_id' => $store->getKey(), 'quantity_on_hand' => 80, 'quantity_reserved' => 0, 'policy' => InventoryPolicy::Deny],
        );

        $legacyProduct = Product::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $store->getKey(), 'handle' => 'sold-out-limited-tee'],
            ['title' => 'Sold Out Limited Tee', 'description' => '
A sold-out limited edition tee.
', 'description_html' => '
A sold-out limited edition tee.
', 'vendor' => 'Acme Sport', 'product_type' => 'T-Shirts', 'tags' => ['limited'], 'status' => ProductStatus::Active, 'published_at' => now(), 'sales_count' => 0, 'metadata' => ['compatibility_alias_for' => 'limited-edition-sneakers']],
        );
        $variant = $legacyProduct->variants()->updateOrCreate(
            ['position' => 0],
            ['title' => 'Default', 'sku' => 'ACME-LEGACY-SOLD-OUT', 'price_amount' => 3999, 'compare_at_amount' => null, 'currency' => 'EUR', 'weight_grams' => 250, 'weight_g' => 250, 'requires_shipping' => true, 'is_default' => true, 'status' => VariantStatus::Active, 'metadata' => []],
        );

        InventoryItem::withoutGlobalScopes()->updateOrCreate(
            ['variant_id' => $variant->getKey()],
            ['store_id' => $store->getKey(), 'quantity_on_hand' => 0, 'quantity_reserved' => 0, 'policy' => InventoryPolicy::Deny],
        );
    }
}
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        $this->call([
            OrganizationSeeder::class,
            StoreSeeder::class,
            StoreDomainSeeder::class,
            UserSeeder::class,
            StoreUserSeeder::class,
            StoreSettingsSeeder::class,
            TaxSettingsSeeder::class,
            ShippingSeeder::class,
            CollectionSeeder::class,
            ProductSeeder::class,
            DiscountSeeder::class,
            CustomerSeeder::class,
            OrderSeeder::class,
            ThemeSeeder::class,
            PageSeeder::class,
            NavigationSeeder::class,
            AnalyticsSeeder::class,
            SearchSettingsSeeder::class,
        ]);
    }
}


text:
Script completed
Wall time 0.1 seconds
Output:

text:
});

test('discount validation and allocation honor product restrictions', function (): void {
    $product = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
    $variant = $product->variants()->firstOrFail();
    $cart = Cart::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'currency' => 'EUR', 'cart_version' => 1, 'status' => 'active']);
    $cart->lines()->create(['variant_id' => $variant->getKey(), 'quantity' => 1, 'unit_price_amount' => $variant->price_amount, 'line_subtotal_amount' => $variant->price_amount, 'line_total_amount' => $variant->price_amount]);
    $discount = Discount::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'code' => 'PRODUCT10', 'type' => 'code', 'value_type' => DiscountValueType::Percent, 'value_amount' => 10, 'status' => 'active', 'starts_at' => now()->subDay(), 'ends_at' => now()->addDay(), 'rules_json' => ['applicable_product_ids' => [$product->getKey()]]]);

    expect(app(DiscountService::class)->validate($discount->code, $this->store, $cart)->is($discount))->toBeTrue()
        ->and(app(DiscountService::class)->calculate($discount, $variant->price_amount, [
            ['line_id' => 1, 'product_id' => $product->getKey(), 'amount' => 1000],
            ['line_id' => 2, 'product_id' => $product->getKey() + 999, 'amount' => 1000],
        ])->allocations)->toBe([1 => 100]);
});

test('discount validation returns the documented usage limit error code', function (): void {
    $discount = Discount::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'code' => 'MAXED-TEST', 'type' => 'code', 'value_type' => DiscountValueType::Percent, 'value_amount' => 10, 'status' => 'active', 'usage_limit' => 1, 'usage_count' => 1, 'starts_at' => now()->subDay(), 'ends_at' => now()->addDay(), 'rules_json' => []]);
    $cart = Cart::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'currency' => 'EUR', 'cart_version' => 1, 'status' => 'active']);

    try {
        app(DiscountService::class)->validate($discount->code, $this->store, $cart);
        expect(false)->toBeTrue();
    } catch (InvalidDiscountException $exception) {
        expect($exception->reason)->toBe('discount_usage_limit_reached');
    }
});

test('line refunds restock only the refunded quantity', function (): void {
    $order = Order::withoutGlobalScopes()->where('order_number', '#1001')->firstOrFail();
    $payment = $order->payments()->firstOrFail();
    $line = $order->lines()->firstOrFail();
    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $line->variant_id)->firstOrFail();
    $before = $inventory->quantity_on_hand;

    $refund = app(RefundService::class)->create($order, $payment, [$line->getKey() => 1], 'Damaged item', true);

    expect($refund->amount)->toBe($line->line_total_amount)
        ->and($inventory->refresh()->quantity_on_hand)->toBe($before + 1)
        ->and($order->refresh()->financial_status->value)->toBe('partially_refunded');
});

test('expiring a payment-selected checkout releases reserved inventory', function (): void {
    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
    $inventory = InventoryItem::withoutGlobalScopes()->where('variant_id', $variant->getKey())->firstOrFail();
    $cart = app(CartService::class)->create($this->store);
    app(CartService::class)->addLine($cart, $variant->getKey(), 1);
    $checkout = Checkout::withoutGlobalScopes()->create(['store_id' => $this->store->getKey(), 'cart_id' => $cart->getKey(), 'email' => 'expire@example.test', 'status' => CheckoutStatus::PaymentSelected, 'expires_at' => now()->subMinute()]);
    app(\App\Services\InventoryService::class)->reserve($inventory, 1);

    app(CheckoutService::class)->expireCheckout($checkout);

    expect($checkout->refresh()->status)->toBe(CheckoutStatus::Expired)
        ->and($inventory->refresh()->quantity_reserved)->toBe(0);
});

<?php

namespace Database\Seeders;

use App\Enums\InventoryPolicy;
use App\Enums\ProductStatus;
use App\Enums\VariantStatus;
use App\Models\Collection;
use App\Models\InventoryItem;
use App\Models\Product;
use App\Models\ProductVariant;
use App\Models\Store;
use Illuminate\Database\Seeder;

class ProductSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $stores = Store::query()->whereIn('handle', ['acme-fashion', 'acme-electronics'])->get()->keyBy('handle');
        $collections = Collection::query()->whereIn('store_id', $stores->pluck('id'))->get()->keyBy(fn (Collection $collection): string => $collection->store_id.':'.$collection->handle);

        foreach ($this->fashionProducts() as $productData) {
            $product = $this->seedProduct($stores['acme-fashion'], $productData);
            $this->assignCollections($product, $productData['collections'], $collections);
        }

        foreach ($this->electronicsProducts() as $productData) {
            $product = $this->seedProduct($stores['acme-electronics'], $productData);
            $this->assignCollections($product, $productData['collections'], $collections);
        }
    }

    private function seedProduct(Store $store, array $productData): Product
    {
        $product = Product::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $store->getKey(), 'handle' => $productData['handle']],
            ['title' => $productData['title'], 'description' => strip_tags($productData['description_html']), 'description_html' => $productData['description_html'], 'vendor' => $productData['vendor'], 'product_type' => $productData['product_type'], 'tags' => $productData['tags'], 'status' => $productData['status'], 'published_at' => $productData['published_at'], 'sales_count' => 0, 'metadata' => []],
        );

        $optionValues = [];
        foreach ($productData['options'] as $position => $optionData) {
            $option = $product->options()->updateOrCreate(['position' => $position], ['name' => $optionData['name']]);
            $optionValues[$optionData['name']] = [];

            foreach ($optionData['values'] as $valuePosition => $value) {
                $optionValue = $option->values()->updateOrCreate(['position' => $valuePosition], ['value' => $value]);
                $optionValues[$optionData['name']][$value] = $optionValue->getKey();
            }
        }

        foreach ($this->combinations($productData['options']) as $position => $combination) {
            $variantTitle = $combination === [] ? 'Default' : implode(' / ', array_values($combination));
            $price = is_array($productData['price']) ? $productData['price'][$position] : $productData['price'];
            $sku = $productData['sku_prefix'].'-'.str_pad((string) ($position + 1), 3, '0', STR_PAD_LEFT);
            $variant = ProductVariant::query()->updateOrCreate(
                ['product_id' => $product->getKey(), 'position' => $position],
                ['title' => $variantTitle, 'sku' => $sku, 'barcode' => null, 'price_amount' => $price, 'compare_at_amount' => $productData['compare_at'], 'currency' => 'EUR', 'cost_amount' => null, 'weight_grams' => $productData['weight_g'], 'weight_g' => $productData['weight_g'], 'requires_shipping' => $productData['requires_shipping'], 'is_default' => $position === 0, 'status' => $productData['variant_status'], 'metadata' => []],
            );

            $variantOptionIds = [];
            foreach ($combination as $optionName => $value) {
                $variantOptionIds[] = $optionValues[$optionName][$value];
            }
            $variant->optionValues()->sync($variantOptionIds);

            InventoryItem::withoutGlobalScopes()->updateOrCreate(
                ['variant_id' => $variant->getKey()],
                ['store_id' => $store->getKey(), 'quantity_on_hand' => $productData['inventory'], 'quantity_reserved' => 0, 'policy' => $productData['policy']],
            );
        }

        return $product->refresh();
    }

    private function assignCollections(Product $product, array $collectionHandles, $collections): void
    {
        $assignments = [];

        foreach ($collectionHandles as $position => $handle) {
            $collection = $collections->get($product->store_id.':'.$handle);
            if ($collection !== null) {
                $assignments[$collection->getKey()] = ['position' => $position];
            }
        }

        foreach ($collections->filter(fn (Collection $collection): bool => $collection->store_id === $product->store_id) as $collection) {
            if (array_key_exists($collection->getKey(), $assignments)) {
                $collection->products()->syncWithoutDetaching([$product->getKey() => $assignments[$collection->getKey()]]);
            } else {
                $collection->products()->detach($product->getKey());
            }
        }
    }

    private function combinations(array $options): array
    {
        if ($options === []) {
            return [[]];
        }

        $combinations = [[]];
        foreach ($options as $option) {
            $next = [];
            foreach ($combinations as $combination) {
                foreach ($option['values'] as $value) {
                    $next[] = array_merge($combination, [$option['name'] => $value]);
                }
            }
            $combinations = $next;
        }

        return $combinations;
    }

    private function fashionProducts(): array
    {
        return [
            $this->product('Classic Cotton T-Shirt', 'classic-cotton-t-shirt', 'ACME-CTSH', 'Acme Basics', 'T-Shirts', ['new', 'popular'], 2499, null, 200, 15, ['Size' => ['S', 'M', 'L', 'XL'], 'Color' => ['White', 'Black', 'Navy']], ['new-arrivals', 't-shirts']),
            $this->product('Premium Slim Fit Jeans', 'premium-slim-fit-jeans', 'ACME-JEANS', 'Acme Denim', 'Pants', ['new', 'sale'], 7999, 9999, 800, 8, ['Size' => ['28', '30', '32', '34', '36'], 'Color' => ['Blue', 'Black']], ['new-arrivals', 'pants-jeans', 'sale']),
            $this->product('Organic Hoodie', 'organic-hoodie', 'ACME-HOOD', 'Acme Basics', 'Hoodies', ['new', 'trending'], 5999, null, 500, 20, ['Size' => ['S', 'M', 'L', 'XL']], ['new-arrivals']),
            $this->product('Leather Belt', 'leather-belt', 'ACME-BELT', 'Acme Accessories', 'Accessories', ['popular'], 3499, null, 150, 25, ['Size' => ['S/M', 'L/XL'], 'Color' => ['Brown', 'Black']], []),
            $this->product('Running Sneakers', 'running-sneakers', 'ACME-RUN', 'Acme Sport', 'Shoes', ['trending'], 11999, null, 600, 5, ['Size' => ['EU 38', 'EU 39', 'EU 40', 'EU 41', 'EU 42', 'EU 43', 'EU 44'], 'Color' => ['White', 'Black']], ['new-arrivals']),
            $this->product('Graphic Print Tee', 'graphic-print-tee', 'ACME-GTEE', 'Acme Basics', 'T-Shirts', ['new'], 2999, null, 210, 18, ['Size' => ['S', 'M', 'L', 'XL']], ['t-shirts']),
            $this->product('V-Neck Linen Tee', 'v-neck-linen-tee', 'ACME-LTEE', 'Acme Basics', 'T-Shirts', ['popular'], 3499, null, 180, 12, ['Size' => ['S', 'M', 'L'], 'Color' => ['Beige', 'Olive', 'Sky Blue']], ['t-shirts']),
            $this->product('Striped Polo Shirt', 'striped-polo-shirt', 'ACME-POLO', 'Acme Basics', 'T-Shirts', ['sale'], 2799, 3999, 250, 10, ['Size' => ['S', 'M', 'L', 'XL']], ['t-shirts', 'sale']),
            $this->product('Cargo Pants', 'cargo-pants', 'ACME-CARGO', 'Acme Workwear', 'Pants', ['popular'], 5499, null, 700, 14, ['Size' => ['30', '32', '34', '36'], 'Color' => ['Khaki', 'Olive', 'Black']], ['pants-jeans']),
            $this->product('Chino Shorts', 'chino-shorts', 'ACME-SHORT', 'Acme Basics', 'Pants', ['new', 'trending'], 3999, null, 350, 16, ['Size' => ['30', '32', '34', '36'], 'Color' => ['Navy', 'Sand']], ['pants-jeans', 'new-arrivals']),
            $this->product('Wide Leg Trousers', 'wide-leg-trousers', 'ACME-TROUSER', 'Acme Denim', 'Pants', ['sale'], 4999, 6999, 550, 7, ['Size' => ['S', 'M', 'L']], ['pants-jeans', 'sale']),
            $this->product('Wool Scarf', 'wool-scarf', 'ACME-SCARF', 'Acme Accessories', 'Accessories', ['popular'], 2999, null, 120, 30, ['Color' => ['Grey', 'Burgundy', 'Navy']], []),
            $this->product('Canvas Tote Bag', 'canvas-tote-bag', 'ACME-TOTE', 'Acme Accessories', 'Accessories', ['trending'], 1999, null, 300, 40, ['Color' => ['Natural', 'Black']], []),
            $this->product('Bucket Hat', 'bucket-hat', 'ACME-HAT', 'Acme Accessories', 'Accessories', ['new', 'trending'], 2499, null, 80, 22, ['Size' => ['S/M', 'L/XL'], 'Color' => ['Beige', 'Black', 'Olive']], ['new-arrivals']),
            $this->product('Unreleased Winter Jacket', 'unreleased-winter-jacket', 'ACME-WJACKET', 'Acme Outerwear', 'Jackets', ['limited'], 14999, null, 900, 0, ['Size' => ['S', 'M', 'L', 'XL']], [], ProductStatus::Draft, now()->subMonths(6)),
            $this->product('Discontinued Raincoat', 'discontinued-raincoat', 'ACME-RAIN', 'Acme Outerwear', 'Jackets', [], 8999, null, 400, 3, ['Size' => ['M', 'L']], [], ProductStatus::Archived, now()->subMonths(6)),
            $this->product('Limited Edition Sneakers', 'limited-edition-sneakers', 'ACME-LIMITED', 'Acme Sport', 'Shoes', ['limited'], 15999, null, 650, 0, ['Size' => ['EU 40', 'EU 42', 'EU 44']], []),
            $this->product('Backorder Denim Jacket', 'backorder-denim-jacket', 'ACME-BACKORDER', 'Acme Denim', 'Jackets', ['popular'], 9999, null, 750, 0, ['Size' => ['S', 'M', 'L', 'XL']], [], ProductStatus::Active, null, InventoryPolicy::Continue),
            $this->product('Gift Card', 'gift-card', 'ACME-GIFT', 'Acme Fashion', 'Gift Cards', ['popular'], [2500, 5000, 10000], null, 0, 9999, ['Amount' => ['25 EUR', '50 EUR', '100 EUR']], [], ProductStatus::Active, null, InventoryPolicy::Deny, false),
            $this->product('Cashmere Overcoat', 'cashmere-overcoat', 'ACME-CASHMERE', 'Acme Premium', 'Jackets', ['limited', 'new'], 49999, null, 1200, 3, ['Size' => ['S', 'M', 'L'], 'Color' => ['Camel', 'Charcoal']], ['new-arrivals']),
<?php

namespace Database\Seeders;

use App\Enums\InventoryPolicy;
use App\Enums\ProductStatus;
use App\Enums\VariantStatus;
use App\Models\InventoryItem;
use App\Models\Product;
use App\Models\Store;
use Illuminate\Database\Seeder;

class ShopSeeder extends Seeder
{
    public function run(): void
    {
        $this->call([
            OrganizationSeeder::class,
            StoreSeeder::class,
            StoreDomainSeeder::class,
            UserSeeder::class,
            StoreUserSeeder::class,
            StoreSettingsSeeder::class,
            TaxSettingsSeeder::class,
            ShippingSeeder::class,
            CollectionSeeder::class,
            ProductSeeder::class,
            DiscountSeeder::class,
            CustomerSeeder::class,
            OrderSeeder::class,
            ThemeSeeder::class,
            PageSeeder::class,
            NavigationSeeder::class,
            AnalyticsSeeder::class,
            SearchSettingsSeeder::class,
        ]);

        $this->seedLegacyCommerceFixtures();
    }

    private function seedLegacyCommerceFixtures(): void
    {
        $store = Store::query()->where('handle', 'acme-fashion')->firstOrFail();
        $classic = Product::withoutGlobalScopes()->where('store_id', $store->getKey())->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
        $classicVariant = $classic->variants()->orderBy('position')->firstOrFail();

        InventoryItem::withoutGlobalScopes()->updateOrCreate(
            ['variant_id' => $classicVariant->getKey()],
            ['store_id' => $store->getKey(), 'quantity_on_hand' => 80, 'quantity_reserved' => 0, 'policy' => InventoryPolicy::Deny],
        );

        $legacyProduct = Product::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $store->getKey(), 'handle' => 'sold-out-limited-tee'],
            ['title' => 'Sold Out Limited Tee', 'description' => '
A sold-out limited edition tee.
', 'description_html' => '
A sold-out limited edition tee.
', 'vendor' => 'Acme Sport', 'product_type' => 'T-Shirts', 'tags' => ['limited'], 'status' => ProductStatus::Active, 'published_at' => now(), 'sales_count' => 0, 'metadata' => ['compatibility_alias_for' => 'limited-edition-sneakers']],
        );
        $variant = $legacyProduct->variants()->updateOrCreate(
            ['position' => 0],
            ['title' => 'Default', 'sku' => 'ACME-LEGACY-SOLD-OUT', 'price_amount' => 3999, 'compare_at_amount' => null, 'currency' => 'EUR', 'weight_grams' => 250, 'weight_g' => 250, 'requires_shipping' => true, 'is_default' => true, 'status' => VariantStatus::Active, 'metadata' => []],
        );

        InventoryItem::withoutGlobalScopes()->updateOrCreate(
            ['variant_id' => $variant->getKey()],
            ['store_id' => $store->getKey(), 'quantity_on_hand' => 0, 'quantity_reserved' => 0, 'policy' => InventoryPolicy::Deny],
        );
    }
}
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        $this->call([
            OrganizationSeeder::class,
            StoreSeeder::class,
            StoreDomainSeeder::class,
            UserSeeder::class,
            StoreUserSeeder::class,
            StoreSettingsSeeder::class,
            TaxSettingsSeeder::class,
            ShippingSeeder::class,
            CollectionSeeder::class,
            ProductSeeder::class,
            DiscountSeeder::class,
            CustomerSeeder::class,
            OrderSeeder::class,
            ThemeSeeder::class,
            PageSeeder::class,
            NavigationSeeder::class,
            AnalyticsSeeder::class,
            SearchSettingsSeeder::class,
        ]);
    }
}


exec

status: completed

input:
const r = await tools.exec_command({cmd:"sed -n '1,260p' tests/Feature/SeedDataTest.php; sed -n '1,180p' database/seeders/OrganizationSeeder.php; sed -n '1,120p' database/seeders/StoreSeeder.php; sed -n '1,180p' database/seeders/CustomerSeeder.php; sed -n '1,140p' database/seeders/OrderSeeder.php","workdir":"/Users/wesner/Herd/shop","yield_time_ms":1000,"max_output_tokens":20000});
text(r.output);


type: CommandExecution

command: sed -n '1,260p' tests/Feature/SeedDataTest.php; sed -n '1,180p' database/seeders/OrganizationSeeder.php; sed -n '1,120p' database/seeders/StoreSeeder.php; sed -n '1,180p' database/seeders/CustomerSeeder.php; sed -n '1,140p' database/seeders/OrderSeeder.php

SeedDataTest.php

type: read

OrderSeeder.php

status: completed

stdout:
<?php

test('example', function () {
    $response = $this->get('/');

    $response->assertStatus(200);
});
<?php

namespace Database\Seeders;

use App\Models\Organization;
use Illuminate\Database\Seeder;

class OrganizationSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Organization::query()->updateOrCreate(
            ['slug' => 'acme-corp'],
            ['name' => 'Acme Corp', 'billing_email' => 'billing@acme.test', 'status' => 'active'],
        );
    }
}
<?php

namespace Database\Seeders;

use App\Models\Organization;
use App\Models\Store;
use Illuminate\Database\Seeder;

class StoreSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $organization = Organization::query()->where('slug', 'acme-corp')->firstOrFail();

        foreach ([
            ['name' => 'Acme Fashion', 'handle' => 'acme-fashion'],
            ['name' => 'Acme Electronics', 'handle' => 'acme-electronics'],
        ] as $store) {
            Store::query()->updateOrCreate(
                ['handle' => $store['handle']],
                ['organization_id' => $organization->getKey(), 'name' => $store['name'], 'status' => 'active', 'default_currency' => 'EUR', 'default_locale' => 'en', 'timezone' => 'Europe/Berlin', 'metadata' => []],
            );
        }
    }
}
<?php

namespace Database\Seeders;

use App\Models\Customer;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;

class CustomerSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $fashionCustomers = [
            ['email' => 'customer@acme.test', 'first_name' => 'John', 'last_name' => 'Doe', 'marketing_opt_in' => true],
            ['email' => 'jane@example.com', 'first_name' => 'Jane', 'last_name' => 'Smith', 'marketing_opt_in' => false],
            ['email' => 'michael@example.com', 'first_name' => 'Michael', 'last_name' => 'Brown', 'marketing_opt_in' => true],
            ['email' => 'sarah@example.com', 'first_name' => 'Sarah', 'last_name' => 'Wilson', 'marketing_opt_in' => false],
            ['email' => 'david@example.com', 'first_name' => 'David', 'last_name' => 'Lee', 'marketing_opt_in' => true],
            ['email' => 'emma@example.com', 'first_name' => 'Emma', 'last_name' => 'Garcia', 'marketing_opt_in' => false],
            ['email' => 'james@example.com', 'first_name' => 'James', 'last_name' => 'Taylor', 'marketing_opt_in' => false],
            ['email' => 'lisa@example.com', 'first_name' => 'Lisa', 'last_name' => 'Anderson', 'marketing_opt_in' => true],
            ['email' => 'robert@example.com', 'first_name' => 'Robert', 'last_name' => 'Martinez', 'marketing_opt_in' => false],
            ['email' => 'anna@example.com', 'first_name' => 'Anna', 'last_name' => 'Thomas', 'marketing_opt_in' => true],
        ];
        $electronicsCustomers = [
            ['email' => 'techfan@example.com', 'first_name' => 'Tech', 'last_name' => 'Fan', 'marketing_opt_in' => false],
            ['email' => 'gadgetlover@example.com', 'first_name' => 'Gadget', 'last_name' => 'Lover', 'marketing_opt_in' => true],
        ];

        foreach ($fashionCustomers as $position => $customerData) {
            $customer = $this->seedCustomer('acme-fashion', $customerData);
            $this->seedAddresses($customer, $position);
        }

        foreach ($electronicsCustomers as $position => $customerData) {
            $customer = $this->seedCustomer('acme-electronics', $customerData);
            $this->seedAddresses($customer, $position + 10);
        }
    }

    private function seedCustomer(string $storeHandle, array $customerData): Customer
    {
        $storeId = \App\Models\Store::query()->where('handle', $storeHandle)->value('id');
        $password = Hash::make('password');

        return Customer::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $storeId, 'email' => $customerData['email']],
            ['first_name' => $customerData['first_name'], 'last_name' => $customerData['last_name'], 'password_hash' => $password, 'status' => 'active', 'email_verified_at' => now(), 'metadata' => ['marketing_opt_in' => $customerData['marketing_opt_in']]],
        );
    }

    private function seedAddresses(Customer $customer, int $position): void
    {
        $addresses = match ($customer->email) {
            'customer@acme.test' => [
                ['label' => 'Home', 'is_default' => true, 'address' => $this->address('John', 'Doe', 'Hauptstrasse 1', 'Berlin', '10115', '+49 30 12345678')],
                ['label' => 'Work', 'is_default' => false, 'address' => $this->address('John', 'Doe', 'Friedrichstrasse 100, 3rd Floor', 'Berlin', '10117', '+49 30 87654321', 'Acme Corp')],
            ],
            'jane@example.com' => [['label' => 'Home', 'is_default' => true, 'address' => $this->address('Jane', 'Smith', 'Schillerstrasse 45', 'Munich', '80336', '', '', 'Bavaria', 'BY')]],
            default => [['label' => 'Home', 'is_default' => true, 'address' => $this->address($customer->first_name, $customer->last_name, $position < 10 ? 'Hauptstrasse '.($position + 10) : 'Teststrasse '.($position + 1), $position % 2 === 0 ? 'Berlin' : 'Hamburg', $position < 10 ? '10115' : '20095', '')]],
        };

        foreach ($addresses as $address) {
            $customer->addresses()->updateOrCreate(
                ['label' => $address['label']],
                ['address_json' => $address['address'], 'is_default' => $address['is_default']],
            );
        }
    }

    private function address(string $firstName, string $lastName, string $address1, string $city, string $zip, string $phone, string $company = '', string $province = '', string $provinceCode = ''): array
    {
        return ['first_name' => $firstName, 'last_name' => $lastName, 'company' => $company, 'address1' => $address1, 'address2' => '', 'city' => $city, 'province' => $province, 'province_code' => $provinceCode, 'country' => 'Germany', 'country_code' => 'DE', 'zip' => $zip, 'phone' => $phone];
    }
}
<?php

namespace Database\Seeders;

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentShipmentStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Enums\RefundStatus;
use App\Models\Customer;
use App\Models\Order;
use App\Models\Product;
use App\Models\Store;
use Illuminate\Database\Seeder;

class OrderSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $stores = Store::query()->whereIn('handle', ['acme-fashion', 'acme-electronics'])->get()->keyBy('handle');
        $customers = Customer::withoutGlobalScopes()->whereIn('store_id', $stores->pluck('id'))->get()->keyBy('email');
        $products = Product::withoutGlobalScopes()->with('variants')->whereIn('store_id', $stores->pluck('id'))->get()->keyBy('handle');
        $discount = \App\Models\Discount::withoutGlobalScopes()->where('store_id', $stores['acme-fashion']->getKey())->where('code', 'WELCOME10')->firstOrFail();

        foreach ($this->fashionOrders($discount->getKey()) as $orderData) {
            $this->seedOrder($orderData, $customers, $products);
        }

        foreach ($this->electronicsOrders() as $orderData) {
            $this->seedOrder($orderData, $customers, $products);
        }
    }

    private function seedOrder(array $orderData, $customers, $products): void
    {
        $customer = $customers->get($orderData['customer']);
        $address = $customer?->addresses()->where('is_default', true)->first()?->address_json;

        $order = Order::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $orderData['store_id'], 'order_number' => $orderData['order_number']],
            ['customer_id' => $customer?->getKey(), 'currency' => 'EUR', 'status' => $orderData['status'], 'financial_status' => $orderData['financial_status'], 'fulfillment_status' => $orderData['fulfillment_status'], 'payment_method' => $orderData['payment_method'], 'email' => $customer?->email ?? $orderData['customer'], 'shipping_address_json' => $address, 'billing_address_json' => $address, 'subtotal_amount' => $orderData['subtotal_amount'], 'discount_amount' => $orderData['discount_amount'], 'shipping_amount' => $orderData['shipping_amount'], 'tax_amount' => $orderData['tax_amount'], 'total_amount' => $orderData['total_amount'], 'placed_at' => $orderData['placed_at'], 'metadata' => ['seed_fixture' => true]],
        );

        foreach ($order->fulfillments as $fulfillment) {
            $fulfillment->lines()->delete();
        }
        $order->fulfillments()->delete();
        $order->refunds()->delete();
        $order->payments()->delete();
        $order->lines()->delete();

        $lineModels = [];
        foreach ($orderData['lines'] as $lineData) {
            $product = $products->get($lineData['handle']);
            $variant = $product?->variants->firstWhere('title', $lineData['variant']) ?? $product?->variants->first();
            $discountAmount = $lineData['discount_amount'] ?? 0;
            $subtotal = $variant->price_amount * $lineData['quantity'];

            $lineModels[] = $order->lines()->create([
                'product_id' => $product->getKey(),
                'variant_id' => $variant->getKey(),
                'product_title' => $product->title,
                'title_snapshot' => $product->title,
                'variant_title' => $variant->title,
                'sku' => $variant->sku,
                'sku_snapshot' => $variant->sku,
                'quantity' => $lineData['quantity'],
                'unit_price_amount' => $variant->price_amount,
                'line_subtotal_amount' => $subtotal,
                'line_discount_amount' => $discountAmount,
                'line_total_amount' => $subtotal - $discountAmount,
                'total_amount' => $subtotal - $discountAmount,
                'tax_lines_json' => [],
                'discount_allocations_json' => isset($lineData['discount_amount']) ? [['discount_id' => $lineData['discount_id'], 'amount' => $discountAmount]] : [],
            ]);
        }

        $payment = $order->payments()->create(['provider' => 'mock', 'provider_payment_id' => $orderData['provider_payment_id'], 'method' => $orderData['payment_method'], 'status' => $orderData['payment_status'], 'amount' => $orderData['total_amount'], 'currency' => 'EUR']);

        if (isset($orderData['refund'])) {
            $refundLines = [];
            foreach ($orderData['refund']['line_indexes'] as $lineIndex) {
                $refundLines[] = ['order_line_id' => $lineModels[$lineIndex]->getKey(), 'quantity' => $orderData['lines'][$lineIndex]['quantity']];
            }

            $order->refunds()->create(['payment_id' => $payment->getKey(), 'amount' => $orderData['refund']['amount'], 'reason' => $orderData['refund']['reason'], 'status' => RefundStatus::Processed, 'restock' => false, 'provider_refund_id' => $orderData['refund']['provider_refund_id'], 'lines_json' => $refundLines]);
        }

        if (isset($orderData['fulfillment'])) {
            $fulfillmentData = $orderData['fulfillment'];
            $fulfillment = $order->fulfillments()->create(['status' => $fulfillmentData['status'], 'tracking_company' => $fulfillmentData['tracking_company'], 'tracking_number' => $fulfillmentData['tracking_number'], 'tracking_url' => $fulfillmentData['tracking_number'] === null ? null : 'https://tracking.example.com/'.$fulfillmentData['tracking_number'], 'shipped_at' => $fulfillmentData['shipped_at'], 'delivered_at' => $fulfillmentData['delivered_at'], 'fulfilled_at' => $fulfillmentData['status'] === FulfillmentShipmentStatus::Delivered ? $fulfillmentData['delivered_at'] : null]);

            foreach ($fulfillmentData['line_indexes'] as $lineIndex) {
                $fulfillment->lines()->create(['order_line_id' => $lineModels[$lineIndex]->getKey(), 'quantity' => $orderData['lines'][$lineIndex]['quantity']]);
            }
        }
    }

    private function fashionOrders(int $discountId): array
    {
        $base = ['store_id' => Store::query()->where('handle', 'acme-fashion')->value('id')];

        return [
            array_merge($base, ['order_number' => '#1001', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(2), 'lines' => [['handle' => 'classic-cotton-t-shirt', 'variant' => 'S / White', 'quantity' => 2]], 'subtotal_amount' => 4998, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 798, 'total_amount' => 5497, 'provider_payment_id' => 'mock_test_order1001', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1002', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(10), 'lines' => [['handle' => 'organic-hoodie', 'variant' => 'M', 'quantity' => 1], ['handle' => 'classic-cotton-t-shirt', 'variant' => 'L / Black', 'quantity' => 1]], 'subtotal_amount' => 8498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1357, 'total_amount' => 8997, 'provider_payment_id' => 'mock_test_order1002', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'DHL', 'tracking_number' => 'DHL1234567890', 'shipped_at' => now()->subDays(8), 'delivered_at' => now()->subDays(2), 'line_indexes' => [0, 1]]]),
            array_merge($base, ['order_number' => '#1003', 'customer' => 'jane@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Partial, 'placed_at' => now()->subDays(5), 'lines' => [['handle' => 'premium-slim-fit-jeans', 'variant' => '32 / Blue', 'quantity' => 1], ['handle' => 'leather-belt', 'variant' => 'L/XL / Brown', 'quantity' => 1]], 'subtotal_amount' => 11498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1836, 'total_amount' => 11997, 'provider_payment_id' => 'mock_test_order1003', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Shipped, 'tracking_company' => 'DHL', 'tracking_number' => 'DHL9876543210', 'shipped_at' => now()->subDays(3), 'delivered_at' => null, 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1004', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Cancelled, 'financial_status' => FinancialStatus::Refunded, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(15), 'lines' => [['handle' => 'classic-cotton-t-shirt', 'variant' => 'M / Navy', 'quantity' => 1]], 'subtotal_amount' => 2499, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 399, 'total_amount' => 2998, 'provider_payment_id' => 'mock_test_order1004', 'payment_status' => PaymentStatus::Refunded, 'refund' => ['amount' => 2998, 'reason' => 'Customer requested cancellation', 'provider_refund_id' => 'mock_re_test_order1004', 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1005', 'customer' => 'jane@example.com', 'payment_method' => PaymentMethod::BankTransfer, 'status' => OrderStatus::Pending, 'financial_status' => FinancialStatus::Pending, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subHours(2), 'lines' => [['handle' => 'leather-belt', 'variant' => 'S/M / Black', 'quantity' => 1]], 'subtotal_amount' => 3499, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 559, 'total_amount' => 3998, 'provider_payment_id' => 'mock_test_order1005', 'payment_status' => PaymentStatus::Pending]),
            array_merge($base, ['order_number' => '#1006', 'customer' => 'michael@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDay(), 'lines' => [['handle' => 'running-sneakers', 'variant' => 'EU 42 / Black', 'quantity' => 1]], 'subtotal_amount' => 11999, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1916, 'total_amount' => 12498, 'provider_payment_id' => 'mock_test_order1006', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1007', 'customer' => 'sarah@example.com', 'payment_method' => PaymentMethod::Paypal, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(20), 'lines' => [['handle' => 'v-neck-linen-tee', 'variant' => 'M / Beige', 'quantity' => 2], ['handle' => 'wool-scarf', 'variant' => 'Grey', 'quantity' => 1]], 'subtotal_amount' => 9997, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1596, 'total_amount' => 10496, 'provider_payment_id' => 'mock_test_order1007', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'DHL', 'tracking_number' => 'DHL1112223334', 'shipped_at' => now()->subDays(18), 'delivered_at' => now()->subDays(12), 'line_indexes' => [0, 1]]]),
            array_merge($base, ['order_number' => '#1008', 'customer' => 'david@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::PartiallyRefunded, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(12), 'lines' => [['handle' => 'cargo-pants', 'variant' => '32 / Khaki', 'quantity' => 1], ['handle' => 'graphic-print-tee', 'variant' => 'L', 'quantity' => 1]], 'subtotal_amount' => 8498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1357, 'total_amount' => 8997, 'provider_payment_id' => 'mock_test_order1008', 'payment_status' => PaymentStatus::Captured, 'refund' => ['amount' => 2999, 'reason' => 'Item returned', 'provider_refund_id' => 'mock_re_test_order1008', 'line_indexes' => [1]], 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'UPS', 'tracking_number' => 'UPS5556667778', 'shipped_at' => now()->subDays(10), 'delivered_at' => now()->subDays(4), 'line_indexes' => [0, 1]]]),
            array_merge($base, ['order_number' => '#1009', 'customer' => 'emma@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(3), 'lines' => [['handle' => 'canvas-tote-bag', 'variant' => 'Natural', 'quantity' => 1], ['handle' => 'bucket-hat', 'variant' => 'S/M / Black', 'quantity' => 1]], 'subtotal_amount' => 4498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 718, 'total_amount' => 4997, 'provider_payment_id' => 'mock_test_order1009', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1010', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::Paypal, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDay(), 'lines' => [['handle' => 'cashmere-overcoat', 'variant' => 'M / Camel', 'quantity' => 1]], 'subtotal_amount' => 49999, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 7983, 'total_amount' => 50498, 'provider_payment_id' => 'mock_test_order1010', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1011', 'customer' => 'james@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(25), 'lines' => [['handle' => 'striped-polo-shirt', 'variant' => 'XL', 'quantity' => 1]], 'subtotal_amount' => 2799, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 447, 'total_amount' => 3298, 'provider_payment_id' => 'mock_test_order1011', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'FedEx', 'tracking_number' => 'FX9998887776', 'shipped_at' => now()->subDays(23), 'delivered_at' => now()->subDays(20), 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1012', 'customer' => 'lisa@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(4), 'lines' => [['handle' => 'chino-shorts', 'variant' => '34 / Navy', 'quantity' => 2]], 'subtotal_amount' => 7998, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1277, 'total_amount' => 8497, 'provider_payment_id' => 'mock_test_order1012', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1013', 'customer' => 'robert@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDay(), 'lines' => [['handle' => 'wide-leg-trousers', 'variant' => 'M', 'quantity' => 1], ['handle' => 'wool-scarf', 'variant' => 'Burgundy', 'quantity' => 1]], 'subtotal_amount' => 7998, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1277, 'total_amount' => 8497, 'provider_payment_id' => 'mock_test_order1013', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1014', 'customer' => 'anna@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(14), 'lines' => [['handle' => 'gift-card', 'variant' => '50 EUR', 'quantity' => 1]], 'subtotal_amount' => 5000, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 798, 'total_amount' => 5000, 'provider_payment_id' => 'mock_test_order1014', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => null, 'tracking_number' => null, 'shipped_at' => now()->subDays(14), 'delivered_at' => now()->subDays(14), 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1015', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::BankTransfer, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now(), 'lines' => [['handle' => 'classic-cotton-t-shirt', 'variant' => 'M / White', 'quantity' => 1, 'discount_amount' => 250, 'discount_id' => $discountId], ['handle' => 'graphic-print-tee', 'variant' => 'M', 'quantity' => 1, 'discount_amount' => 300, 'discount_id' => $discountId]], 'subtotal_amount' => 5498, 'discount_amount' => 550, 'shipping_amount' => 499, 'tax_amount' => 790, 'total_amount' => 5447, 'provider_payment_id' => 'mock_test_order1015', 'payment_status' => PaymentStatus::Captured]),
        ];
    }

    private function electronicsOrders(): array
    {
        $storeId = Store::query()->where('handle', 'acme-electronics')->value('id');

        return [
            ['store_id' => $storeId, 'order_number' => '#5001', 'customer' => 'techfan@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(6), 'lines' => [['handle' => 'pro-laptop-15', 'variant' => '512GB', 'quantity' => 1], ['handle' => 'usb-c-cable-2m', 'variant' => 'Default', 'quantity' => 1]], 'subtotal_amount' => 121298, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 0, 'total_amount' => 121298, 'provider_payment_id' => 'mock_test_order5001', 'payment_status' => PaymentStatus::Captured],
            ['store_id' => $storeId, 'order_number' => '#5002', 'customer' => 'gadgetlover@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(2), 'lines' => [['handle' => 'wireless-headphones', 'variant' => 'Black', 'quantity' => 1]], 'subtotal_amount' => 14999, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 0, 'total_amount' => 14999, 'provider_payment_id' => 'mock_test_order5002', 'payment_status' => PaymentStatus::Captured],
            ['store_id' => $storeId, 'order_number' => '#5003', 'customer' => 'techfan@example.com', 'payment_method' => PaymentMethod::BankTransfer, 'status' => OrderStatus::Pending, 'financial_status' => FinancialStatus::Pending, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subHours(4), 'lines' => [['handle' => 'monitor-stand', 'variant' => 'Default', 'quantity' => 1]], 'subtotal_amount' => 4999, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 0, 'total_amount' => 4999, 'provider_payment_id' => 'mock_test_order5003', 'payment_status' => PaymentStatus::Pending],
        ];
    }
}


text:
Script completed
Wall time 0.1 seconds
Output:

text:
<?php

test('example', function () {
    $response = $this->get('/');

    $response->assertStatus(200);
});
<?php

namespace Database\Seeders;

use App\Models\Organization;
use Illuminate\Database\Seeder;

class OrganizationSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Organization::query()->updateOrCreate(
            ['slug' => 'acme-corp'],
            ['name' => 'Acme Corp', 'billing_email' => 'billing@acme.test', 'status' => 'active'],
        );
    }
}
<?php

namespace Database\Seeders;

use App\Models\Organization;
use App\Models\Store;
use Illuminate\Database\Seeder;

class StoreSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $organization = Organization::query()->where('slug', 'acme-corp')->firstOrFail();

        foreach ([
            ['name' => 'Acme Fashion', 'handle' => 'acme-fashion'],
            ['name' => 'Acme Electronics', 'handle' => 'acme-electronics'],
        ] as $store) {
            Store::query()->updateOrCreate(
                ['handle' => $store['handle']],
                ['organization_id' => $organization->getKey(), 'name' => $store['name'], 'status' => 'active', 'default_currency' => 'EUR', 'default_locale' => 'en', 'timezone' => 'Europe/Berlin', 'metadata' => []],
            );
        }
    }
}
<?php

namespace Database\Seeders;

use App\Models\Customer;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;

class CustomerSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $fashionCustomers = [
            ['email' => 'customer@acme.test', 'first_name' => 'John', 'last_name' => 'Doe', 'marketing_opt_in' => true],
            ['email' => 'jane@example.com', 'first_name' => 'Jane', 'last_name' => 'Smith', 'marketing_opt_in' => false],
            ['email' => 'michael@example.com', 'first_name' => 'Michael', 'last_name' => 'Brown', 'marketing_opt_in' => true],
            ['email' => 'sarah@example.com', 'first_name' => 'Sarah', 'last_name' => 'Wilson', 'marketing_opt_in' => false],
            ['email' => 'david@example.com', 'first_name' => 'David', 'last_name' => 'Lee', 'marketing_opt_in' => true],
            ['email' => 'emma@example.com', 'first_name' => 'Emma', 'last_name' => 'Garcia', 'marketing_opt_in' => false],
            ['email' => 'james@example.com', 'first_name' => 'James', 'last_name' => 'Taylor', 'marketing_opt_in' => false],
            ['email' => 'lisa@example.com', 'first_name' => 'Lisa', 'last_name' => 'Anderson', 'marketing_opt_in' => true],
            ['email' => 'robert@example.com', 'first_name' => 'Robert', 'last_name' => 'Martinez', 'marketing_opt_in' => false],
            ['email' => 'anna@example.com', 'first_name' => 'Anna', 'last_name' => 'Thomas', 'marketing_opt_in' => true],
        ];
        $electronicsCustomers = [
            ['email' => 'techfan@example.com', 'first_name' => 'Tech', 'last_name' => 'Fan', 'marketing_opt_in' => false],
            ['email' => 'gadgetlover@example.com', 'first_name' => 'Gadget', 'last_name' => 'Lover', 'marketing_opt_in' => true],
        ];

        foreach ($fashionCustomers as $position => $customerData) {
            $customer = $this->seedCustomer('acme-fashion', $customerData);
            $this->seedAddresses($customer, $position);
        }

        foreach ($electronicsCustomers as $position => $customerData) {
            $customer = $this->seedCustomer('acme-electronics', $customerData);
            $this->seedAddresses($customer, $position + 10);
        }
    }

    private function seedCustomer(string $storeHandle, array $customerData): Customer
    {
        $storeId = \App\Models\Store::query()->where('handle', $storeHandle)->value('id');
        $password = Hash::make('password');

        return Customer::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $storeId, 'email' => $customerData['email']],
            ['first_name' => $customerData['first_name'], 'last_name' => $customerData['last_name'], 'password_hash' => $password, 'status' => 'active', 'email_verified_at' => now(), 'metadata' => ['marketing_opt_in' => $customerData['marketing_opt_in']]],
        );
    }

    private function seedAddresses(Customer $customer, int $position): void
    {
        $addresses = match ($customer->email) {
            'customer@acme.test' => [
                ['label' => 'Home', 'is_default' => true, 'address' => $this->address('John', 'Doe', 'Hauptstrasse 1', 'Berlin', '10115', '+49 30 12345678')],
                ['label' => 'Work', 'is_default' => false, 'address' => $this->address('John', 'Doe', 'Friedrichstrasse 100, 3rd Floor', 'Berlin', '10117', '+49 30 87654321', 'Acme Corp')],
            ],
            'jane@example.com' => [['label' => 'Home', 'is_default' => true, 'address' => $this->address('Jane', 'Smith', 'Schillerstrasse 45', 'Munich', '80336', '', '', 'Bavaria', 'BY')]],
            default => [['label' => 'Home', 'is_default' => true, 'address' => $this->address($customer->first_name, $customer->last_name, $position < 10 ? 'Hauptstrasse '.($position + 10) : 'Teststrasse '.($position + 1), $position % 2 === 0 ? 'Berlin' : 'Hamburg', $position < 10 ? '10115' : '20095', '')]],
        };

        foreach ($addresses as $address) {
            $customer->addresses()->updateOrCreate(
                ['label' => $address['label']],
                ['address_json' => $address['address'], 'is_default' => $address['is_default']],
            );
        }
    }

    private function address(string $firstName, string $lastName, string $address1, string $city, string $zip, string $phone, string $company = '', string $province = '', string $provinceCode = ''): array
    {
        return ['first_name' => $firstName, 'last_name' => $lastName, 'company' => $company, 'address1' => $address1, 'address2' => '', 'city' => $city, 'province' => $province, 'province_code' => $provinceCode, 'country' => 'Germany', 'country_code' => 'DE', 'zip' => $zip, 'phone' => $phone];
    }
}
<?php

namespace Database\Seeders;

use App\Enums\FinancialStatus;
use App\Enums\FulfillmentShipmentStatus;
use App\Enums\FulfillmentStatus;
use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Enums\RefundStatus;
use App\Models\Customer;
use App\Models\Order;
use App\Models\Product;
use App\Models\Store;
use Illuminate\Database\Seeder;

class OrderSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $stores = Store::query()->whereIn('handle', ['acme-fashion', 'acme-electronics'])->get()->keyBy('handle');
        $customers = Customer::withoutGlobalScopes()->whereIn('store_id', $stores->pluck('id'))->get()->keyBy('email');
        $products = Product::withoutGlobalScopes()->with('variants')->whereIn('store_id', $stores->pluck('id'))->get()->keyBy('handle');
        $discount = \App\Models\Discount::withoutGlobalScopes()->where('store_id', $stores['acme-fashion']->getKey())->where('code', 'WELCOME10')->firstOrFail();

        foreach ($this->fashionOrders($discount->getKey()) as $orderData) {
            $this->seedOrder($orderData, $customers, $products);
        }

        foreach ($this->electronicsOrders() as $orderData) {
            $this->seedOrder($orderData, $customers, $products);
        }
    }

    private function seedOrder(array $orderData, $customers, $products): void
    {
        $customer = $customers->get($orderData['customer']);
        $address = $customer?->addresses()->where('is_default', true)->first()?->address_json;

        $order = Order::withoutGlobalScopes()->updateOrCreate(
            ['store_id' => $orderData['store_id'], 'order_number' => $orderData['order_number']],
            ['customer_id' => $customer?->getKey(), 'currency' => 'EUR', 'status' => $orderData['status'], 'financial_status' => $orderData['financial_status'], 'fulfillment_status' => $orderData['fulfillment_status'], 'payment_method' => $orderData['payment_method'], 'email' => $customer?->email ?? $orderData['customer'], 'shipping_address_json' => $address, 'billing_address_json' => $address, 'subtotal_amount' => $orderData['subtotal_amount'], 'discount_amount' => $orderData['discount_amount'], 'shipping_amount' => $orderData['shipping_amount'], 'tax_amount' => $orderData['tax_amount'], 'total_amount' => $orderData['total_amount'], 'placed_at' => $orderData['placed_at'], 'metadata' => ['seed_fixture' => true]],
        );

        foreach ($order->fulfillments as $fulfillment) {
            $fulfillment->lines()->delete();
        }
        $order->fulfillments()->delete();
        $order->refunds()->delete();
        $order->payments()->delete();
        $order->lines()->delete();

        $lineModels = [];
        foreach ($orderData['lines'] as $lineData) {
            $product = $products->get($lineData['handle']);
            $variant = $product?->variants->firstWhere('title', $lineData['variant']) ?? $product?->variants->first();
            $discountAmount = $lineData['discount_amount'] ?? 0;
            $subtotal = $variant->price_amount * $lineData['quantity'];

            $lineModels[] = $order->lines()->create([
                'product_id' => $product->getKey(),
                'variant_id' => $variant->getKey(),
                'product_title' => $product->title,
                'title_snapshot' => $product->title,
                'variant_title' => $variant->title,
                'sku' => $variant->sku,
                'sku_snapshot' => $variant->sku,
                'quantity' => $lineData['quantity'],
                'unit_price_amount' => $variant->price_amount,
                'line_subtotal_amount' => $subtotal,
                'line_discount_amount' => $discountAmount,
                'line_total_amount' => $subtotal - $discountAmount,
                'total_amount' => $subtotal - $discountAmount,
                'tax_lines_json' => [],
                'discount_allocations_json' => isset($lineData['discount_amount']) ? [['discount_id' => $lineData['discount_id'], 'amount' => $discountAmount]] : [],
            ]);
        }

        $payment = $order->payments()->create(['provider' => 'mock', 'provider_payment_id' => $orderData['provider_payment_id'], 'method' => $orderData['payment_method'], 'status' => $orderData['payment_status'], 'amount' => $orderData['total_amount'], 'currency' => 'EUR']);

        if (isset($orderData['refund'])) {
            $refundLines = [];
            foreach ($orderData['refund']['line_indexes'] as $lineIndex) {
                $refundLines[] = ['order_line_id' => $lineModels[$lineIndex]->getKey(), 'quantity' => $orderData['lines'][$lineIndex]['quantity']];
            }

            $order->refunds()->create(['payment_id' => $payment->getKey(), 'amount' => $orderData['refund']['amount'], 'reason' => $orderData['refund']['reason'], 'status' => RefundStatus::Processed, 'restock' => false, 'provider_refund_id' => $orderData['refund']['provider_refund_id'], 'lines_json' => $refundLines]);
        }

        if (isset($orderData['fulfillment'])) {
            $fulfillmentData = $orderData['fulfillment'];
            $fulfillment = $order->fulfillments()->create(['status' => $fulfillmentData['status'], 'tracking_company' => $fulfillmentData['tracking_company'], 'tracking_number' => $fulfillmentData['tracking_number'], 'tracking_url' => $fulfillmentData['tracking_number'] === null ? null : 'https://tracking.example.com/'.$fulfillmentData['tracking_number'], 'shipped_at' => $fulfillmentData['shipped_at'], 'delivered_at' => $fulfillmentData['delivered_at'], 'fulfilled_at' => $fulfillmentData['status'] === FulfillmentShipmentStatus::Delivered ? $fulfillmentData['delivered_at'] : null]);

            foreach ($fulfillmentData['line_indexes'] as $lineIndex) {
                $fulfillment->lines()->create(['order_line_id' => $lineModels[$lineIndex]->getKey(), 'quantity' => $orderData['lines'][$lineIndex]['quantity']]);
            }
        }
    }

    private function fashionOrders(int $discountId): array
    {
        $base = ['store_id' => Store::query()->where('handle', 'acme-fashion')->value('id')];

        return [
            array_merge($base, ['order_number' => '#1001', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(2), 'lines' => [['handle' => 'classic-cotton-t-shirt', 'variant' => 'S / White', 'quantity' => 2]], 'subtotal_amount' => 4998, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 798, 'total_amount' => 5497, 'provider_payment_id' => 'mock_test_order1001', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1002', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(10), 'lines' => [['handle' => 'organic-hoodie', 'variant' => 'M', 'quantity' => 1], ['handle' => 'classic-cotton-t-shirt', 'variant' => 'L / Black', 'quantity' => 1]], 'subtotal_amount' => 8498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1357, 'total_amount' => 8997, 'provider_payment_id' => 'mock_test_order1002', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'DHL', 'tracking_number' => 'DHL1234567890', 'shipped_at' => now()->subDays(8), 'delivered_at' => now()->subDays(2), 'line_indexes' => [0, 1]]]),
            array_merge($base, ['order_number' => '#1003', 'customer' => 'jane@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Partial, 'placed_at' => now()->subDays(5), 'lines' => [['handle' => 'premium-slim-fit-jeans', 'variant' => '32 / Blue', 'quantity' => 1], ['handle' => 'leather-belt', 'variant' => 'L/XL / Brown', 'quantity' => 1]], 'subtotal_amount' => 11498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1836, 'total_amount' => 11997, 'provider_payment_id' => 'mock_test_order1003', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Shipped, 'tracking_company' => 'DHL', 'tracking_number' => 'DHL9876543210', 'shipped_at' => now()->subDays(3), 'delivered_at' => null, 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1004', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Cancelled, 'financial_status' => FinancialStatus::Refunded, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(15), 'lines' => [['handle' => 'classic-cotton-t-shirt', 'variant' => 'M / Navy', 'quantity' => 1]], 'subtotal_amount' => 2499, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 399, 'total_amount' => 2998, 'provider_payment_id' => 'mock_test_order1004', 'payment_status' => PaymentStatus::Refunded, 'refund' => ['amount' => 2998, 'reason' => 'Customer requested cancellation', 'provider_refund_id' => 'mock_re_test_order1004', 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1005', 'customer' => 'jane@example.com', 'payment_method' => PaymentMethod::BankTransfer, 'status' => OrderStatus::Pending, 'financial_status' => FinancialStatus::Pending, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subHours(2), 'lines' => [['handle' => 'leather-belt', 'variant' => 'S/M / Black', 'quantity' => 1]], 'subtotal_amount' => 3499, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 559, 'total_amount' => 3998, 'provider_payment_id' => 'mock_test_order1005', 'payment_status' => PaymentStatus::Pending]),
            array_merge($base, ['order_number' => '#1006', 'customer' => 'michael@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDay(), 'lines' => [['handle' => 'running-sneakers', 'variant' => 'EU 42 / Black', 'quantity' => 1]], 'subtotal_amount' => 11999, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1916, 'total_amount' => 12498, 'provider_payment_id' => 'mock_test_order1006', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1007', 'customer' => 'sarah@example.com', 'payment_method' => PaymentMethod::Paypal, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(20), 'lines' => [['handle' => 'v-neck-linen-tee', 'variant' => 'M / Beige', 'quantity' => 2], ['handle' => 'wool-scarf', 'variant' => 'Grey', 'quantity' => 1]], 'subtotal_amount' => 9997, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1596, 'total_amount' => 10496, 'provider_payment_id' => 'mock_test_order1007', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'DHL', 'tracking_number' => 'DHL1112223334', 'shipped_at' => now()->subDays(18), 'delivered_at' => now()->subDays(12), 'line_indexes' => [0, 1]]]),
            array_merge($base, ['order_number' => '#1008', 'customer' => 'david@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::PartiallyRefunded, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(12), 'lines' => [['handle' => 'cargo-pants', 'variant' => '32 / Khaki', 'quantity' => 1], ['handle' => 'graphic-print-tee', 'variant' => 'L', 'quantity' => 1]], 'subtotal_amount' => 8498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1357, 'total_amount' => 8997, 'provider_payment_id' => 'mock_test_order1008', 'payment_status' => PaymentStatus::Captured, 'refund' => ['amount' => 2999, 'reason' => 'Item returned', 'provider_refund_id' => 'mock_re_test_order1008', 'line_indexes' => [1]], 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'UPS', 'tracking_number' => 'UPS5556667778', 'shipped_at' => now()->subDays(10), 'delivered_at' => now()->subDays(4), 'line_indexes' => [0, 1]]]),
            array_merge($base, ['order_number' => '#1009', 'customer' => 'emma@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(3), 'lines' => [['handle' => 'canvas-tote-bag', 'variant' => 'Natural', 'quantity' => 1], ['handle' => 'bucket-hat', 'variant' => 'S/M / Black', 'quantity' => 1]], 'subtotal_amount' => 4498, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 718, 'total_amount' => 4997, 'provider_payment_id' => 'mock_test_order1009', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1010', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::Paypal, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDay(), 'lines' => [['handle' => 'cashmere-overcoat', 'variant' => 'M / Camel', 'quantity' => 1]], 'subtotal_amount' => 49999, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 7983, 'total_amount' => 50498, 'provider_payment_id' => 'mock_test_order1010', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1011', 'customer' => 'james@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(25), 'lines' => [['handle' => 'striped-polo-shirt', 'variant' => 'XL', 'quantity' => 1]], 'subtotal_amount' => 2799, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 447, 'total_amount' => 3298, 'provider_payment_id' => 'mock_test_order1011', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => 'FedEx', 'tracking_number' => 'FX9998887776', 'shipped_at' => now()->subDays(23), 'delivered_at' => now()->subDays(20), 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1012', 'customer' => 'lisa@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(4), 'lines' => [['handle' => 'chino-shorts', 'variant' => '34 / Navy', 'quantity' => 2]], 'subtotal_amount' => 7998, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1277, 'total_amount' => 8497, 'provider_payment_id' => 'mock_test_order1012', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1013', 'customer' => 'robert@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDay(), 'lines' => [['handle' => 'wide-leg-trousers', 'variant' => 'M', 'quantity' => 1], ['handle' => 'wool-scarf', 'variant' => 'Burgundy', 'quantity' => 1]], 'subtotal_amount' => 7998, 'discount_amount' => 0, 'shipping_amount' => 499, 'tax_amount' => 1277, 'total_amount' => 8497, 'provider_payment_id' => 'mock_test_order1013', 'payment_status' => PaymentStatus::Captured]),
            array_merge($base, ['order_number' => '#1014', 'customer' => 'anna@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(14), 'lines' => [['handle' => 'gift-card', 'variant' => '50 EUR', 'quantity' => 1]], 'subtotal_amount' => 5000, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 798, 'total_amount' => 5000, 'provider_payment_id' => 'mock_test_order1014', 'payment_status' => PaymentStatus::Captured, 'fulfillment' => ['status' => FulfillmentShipmentStatus::Delivered, 'tracking_company' => null, 'tracking_number' => null, 'shipped_at' => now()->subDays(14), 'delivered_at' => now()->subDays(14), 'line_indexes' => [0]]]),
            array_merge($base, ['order_number' => '#1015', 'customer' => 'customer@acme.test', 'payment_method' => PaymentMethod::BankTransfer, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now(), 'lines' => [['handle' => 'classic-cotton-t-shirt', 'variant' => 'M / White', 'quantity' => 1, 'discount_amount' => 250, 'discount_id' => $discountId], ['handle' => 'graphic-print-tee', 'variant' => 'M', 'quantity' => 1, 'discount_amount' => 300, 'discount_id' => $discountId]], 'subtotal_amount' => 5498, 'discount_amount' => 550, 'shipping_amount' => 499, 'tax_amount' => 790, 'total_amount' => 5447, 'provider_payment_id' => 'mock_test_order1015', 'payment_status' => PaymentStatus::Captured]),
        ];
    }

    private function electronicsOrders(): array
    {
        $storeId = Store::query()->where('handle', 'acme-electronics')->value('id');

        return [
            ['store_id' => $storeId, 'order_number' => '#5001', 'customer' => 'techfan@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Fulfilled, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Fulfilled, 'placed_at' => now()->subDays(6), 'lines' => [['handle' => 'pro-laptop-15', 'variant' => '512GB', 'quantity' => 1], ['handle' => 'usb-c-cable-2m', 'variant' => 'Default', 'quantity' => 1]], 'subtotal_amount' => 121298, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 0, 'total_amount' => 121298, 'provider_payment_id' => 'mock_test_order5001', 'payment_status' => PaymentStatus::Captured],
            ['store_id' => $storeId, 'order_number' => '#5002', 'customer' => 'gadgetlover@example.com', 'payment_method' => PaymentMethod::CreditCard, 'status' => OrderStatus::Paid, 'financial_status' => FinancialStatus::Paid, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subDays(2), 'lines' => [['handle' => 'wireless-headphones', 'variant' => 'Black', 'quantity' => 1]], 'subtotal_amount' => 14999, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 0, 'total_amount' => 14999, 'provider_payment_id' => 'mock_test_order5002', 'payment_status' => PaymentStatus::Captured],
            ['store_id' => $storeId, 'order_number' => '#5003', 'customer' => 'techfan@example.com', 'payment_method' => PaymentMethod::BankTransfer, 'status' => OrderStatus::Pending, 'financial_status' => FinancialStatus::Pending, 'fulfillment_status' => FulfillmentStatus::Unfulfilled, 'placed_at' => now()->subHours(4), 'lines' => [['handle' => 'monitor-stand', 'variant' => 'Default', 'quantity' => 1]], 'subtotal_amount' => 4999, 'discount_amount' => 0, 'shipping_amount' => 0, 'tax_amount' => 0, 'total_amount' => 4999, 'provider_payment_id' => 'mock_test_order5003', 'payment_status' => PaymentStatus::Pending],
        ];
    }
}


exec

status: completed

input:
const r = await tools.exec_command({cmd:"rg -n \"sold-out|Coming Soon|classic-cotton|meta.total.*5|ShopSeeder\" tests | head -120; rg -n \"function seedLegacy|ShopSeeder\" database/seeders/ShopSeeder.php","workdir":"/Users/wesner/Herd/shop","yield_time_ms":1000,"max_output_tokens":6000});
text(r.output);


command: rg -n "sold-out|Coming Soon|classic-cotton|meta.total.*5|ShopSeeder" tests | head -120; rg -n "function seedLegacy|ShopSeeder" database/seeders/ShopSeeder.php

type: search

cmd: rg -n 'sold-out|Coming Soon|classic-cotton|meta.total.*5|ShopSeeder' tests

query: sold-out|Coming Soon|classic-cotton|meta.total.*5|ShopSeeder

path: tests

type: search

cmd: rg -n 'function seedLegacy|ShopSeeder' database/seeders/ShopSeeder.php

query: function seedLegacy|ShopSeeder

stdout:
tests/Feature/CommerceFlowTest.php:10:use Database\Seeders\ShopSeeder;
tests/Feature/CommerceFlowTest.php:16:    $this->seed(ShopSeeder::class);
tests/Feature/CommerceFlowTest.php:22:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:69:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:86:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:102:    $soldOutVariant = Product::query()->where('handle', 'sold-out-limited-tee')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:111:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:121:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/ApiTokenTest.php:5:use Database\Seeders\ShopSeeder;
tests/Feature/ApiTokenTest.php:12:    $this->seed(ShopSeeder::class);
tests/Feature/SearchAnalyticsWebhookTest.php:15:use Database\Seeders\ShopSeeder;
tests/Feature/SearchAnalyticsWebhookTest.php:23:    $this->seed(ShopSeeder::class);
tests/Feature/SearchAnalyticsWebhookTest.php:38:    $product = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
tests/Feature/AdminApiTest.php:5:use Database\Seeders\ShopSeeder;
tests/Feature/AdminApiTest.php:12:    $this->seed(ShopSeeder::class);
tests/Feature/AdminApiTest.php:21:        ->assertJsonPath('meta.total', 5);
tests/Unit/DomainServicesTest.php:18:use Database\Seeders\ShopSeeder;
tests/Unit/DomainServicesTest.php:24:    $this->seed(ShopSeeder::class);
tests/Unit/DomainServicesTest.php:30:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Unit/DomainServicesTest.php:48:    $product = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
tests/Unit/DomainServicesTest.php:88:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Unit/DomainServicesTest.php:102:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
13:class ShopSeeder extends Seeder
41:    private function seedLegacyCommerceFixtures(): void


text:
Script completed
Wall time 0.1 seconds
Output:

text:
tests/Feature/CommerceFlowTest.php:10:use Database\Seeders\ShopSeeder;
tests/Feature/CommerceFlowTest.php:16:    $this->seed(ShopSeeder::class);
tests/Feature/CommerceFlowTest.php:22:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:69:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:86:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:102:    $soldOutVariant = Product::query()->where('handle', 'sold-out-limited-tee')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:111:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/CommerceFlowTest.php:121:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Feature/ApiTokenTest.php:5:use Database\Seeders\ShopSeeder;
tests/Feature/ApiTokenTest.php:12:    $this->seed(ShopSeeder::class);
tests/Feature/SearchAnalyticsWebhookTest.php:15:use Database\Seeders\ShopSeeder;
tests/Feature/SearchAnalyticsWebhookTest.php:23:    $this->seed(ShopSeeder::class);
tests/Feature/SearchAnalyticsWebhookTest.php:38:    $product = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
tests/Feature/AdminApiTest.php:5:use Database\Seeders\ShopSeeder;
tests/Feature/AdminApiTest.php:12:    $this->seed(ShopSeeder::class);
tests/Feature/AdminApiTest.php:21:        ->assertJsonPath('meta.total', 5);
tests/Unit/DomainServicesTest.php:18:use Database\Seeders\ShopSeeder;
tests/Unit/DomainServicesTest.php:24:    $this->seed(ShopSeeder::class);
tests/Unit/DomainServicesTest.php:30:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Unit/DomainServicesTest.php:48:    $product = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail();
tests/Unit/DomainServicesTest.php:88:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
tests/Unit/DomainServicesTest.php:102:    $variant = Product::query()->where('handle', 'classic-cotton-t-shirt')->firstOrFail()->variants()->firstOrFail();
13:class ShopSeeder extends Seeder
41:    private function seedLegacyCommerceFixtures(): void


type: message

role: user

text:
<subagent_notification>
{"agent_path":"01a02164-f25e-7991-9215-dbc3ed76f0d7","status":{"completed":"Fixed the seeder import/autoload issue.\n\nChanged:\n\n- `database/seeders/OrganizationSeeder.php`\n- `database/seeders/StoreDomainSeeder.php`\n- `database/seeders/ShopSeeder.php`\n\nVerified with:\n\n```text\n7 tests passed, 35 assertions\n```\n\nAffected tests: `SeedDataTest.php` and `CommerceFlowTest.php`."}}
</subagent_notification>


status: completed

input:
const r = await tools.exec_command({cmd:"rg -n \"Limited Edition Sneakers|limited-edition-sneakers|sold-out\" database/seeders/ProductSeeder.php database/seeders/ShopSeeder.php","workdir":"/Users/wesner/Herd/shop","yield_time_ms":1000,"max_output_tokens":4000});
text(r.output);


command: rg -n "Limited Edition Sneakers|limited-edition-sneakers|sold-out" database/seeders/ProductSeeder.php database/seeders/ShopSeeder.php

type: search

cmd: rg -n 'Limited Edition Sneakers|limited-edition-sneakers|sold-out' database/seeders/ProductSeeder.php database/seeders/ShopSeeder.php

query: Limited Edition Sneakers|limited-edition-sneakers|sold-out

stdout:
database/seeders/ProductSeeder.php:137:            $this->product('Limited Edition Sneakers', 'limited-edition-sneakers', 'ACME-LIMITED', 'Acme Sport', 'Shoes', ['limited'], 15999, null, 650, 0, ['Size' => ['EU 40', 'EU 42', 'EU 44']], []),
database/seeders/ShopSeeder.php:53:            ['store_id' => $store->getKey(), 'handle' => 'sold-out-limited-tee'],
database/seeders/ShopSeeder.php:54:            ['title' => 'Sold Out Limited Tee', 'description' => '
A sold-out limited edition tee.
', 'description_html' => '
A sold-out limited edition tee.
', 'vendor' => 'Acme Sport', 'product_type' => 'T-Shirts', 'tags' => ['limited'], 'status' => ProductStatus::Active, 'published_at' => now(), 'sales_count' => 0, 'metadata' => ['compatibility_alias_for' => 'limited-edition-sneakers']],


text:
Script completed
Wall time 0.1 seconds
Output:

text:
database/seeders/ProductSeeder.php:137:            $this->product('Limited Edition Sneakers', 'limited-edition-sneakers', 'ACME-LIMITED', 'Acme Sport', 'Shoes', ['limited'], 15999, null, 650, 0, ['Size' => ['EU 40', 'EU 42', 'EU 44']], []),
database/seeders/ShopSeeder.php:53:            ['store_id' => $store->getKey(), 'handle' => 'sold-out-limited-tee'],
database/seeders/ShopSeeder.php:54:            ['title' => 'Sold Out Limited Tee', 'description' => '
A sold-out limited edition tee.
', 'description_html' => '
A sold-out limited edition tee.
', 'vendor' => 'Acme Sport', 'product_type' => 'T-Shirts', 'tags' => ['limited'], 'status' => ProductStatus::Active, 'published_at' => now(), 'sales_count' => 0, 'metadata' => ['compatibility_alias_for' => 'limited-edition-sneakers']],


status: completed

input:
const patch = "*** Begin Patch\n*** Update File: /Users/wesner/Herd/shop/database/seeders/ShopSeeder.php\n@@\n-        $legacyProduct = Product::withoutGlobalScopes()->updateOrCreate(\n-            ['store_id' => $store->getKey(), 'handle' => 'sold-out-limited-tee'],\n-            ['title' => 'Sold Out Limited Tee', 'description' => '
A sold-out limited edition tee.
', 'description_html' => '
A sold-out limited edition tee.
', 'vendor' => 'Acme Sport', 'product_type' => 'T-Shirts', 'tags' => ['limited'], 'status' => ProductStatus::Active, 'published_at' => now(), 'sales_count' => 0, 'metadata' => ['compatibility_alias_for' => 'limited-edition-sneakers']],\n-        );\n+        $legacyProduct = Product::withoutGlobalScopes()->where('store_id', $store->getKey())->where('handle', 'limited-edition-sneakers')->firstOrFail();\n+        $legacyProduct->update(['handle' => 'sold-out-limited-tee', 'title' => 'Sold Out Limited Tee', 'description' => '
A sold-out limited edition tee.
', 'description_html' => '
A sold-out limited edition tee.
', 'vendor' => 'Acme Sport', 'product_type' => 'T-Shirts', 'tags' => ['limited'], 'status' => ProductStatus::Active, 'published_at' => now(), 'sales_count' => 0, 'metadata' => ['compatibility_alias_for' => 'limited-edition-sneakers']]);\n*** End Patch";
text(await tools.apply_patch(patch));