diff --git a/src/Command/WipeCatalogCommand.php b/src/Command/WipeCatalogCommand.php index 22f237f..bd5dc5b 100644 --- a/src/Command/WipeCatalogCommand.php +++ b/src/Command/WipeCatalogCommand.php @@ -3,6 +3,7 @@ namespace Modules\Core\Command; use Illuminate\Console\Command; +use Lunar\Models\CartLine; use Lunar\Models\Product; use Modules\Core\Auth\Models\Staff; use Modules\Core\Auth\Services\OtpService; @@ -15,9 +16,10 @@ use function Laravel\Prompts\text; * Irreversibly deletes every Product and everything that only exists * because of a product — variants, variant prices, product-option value * assignments, product images/media, product associations, the - * ImportMapping rows tying them back to an external source, and the - * Meilisearch product index. Deliberately does NOT touch catalog - * STRUCTURE other products could still reference: ProductOption/ + * ImportMapping rows tying them back to an external source, product- + * variant CartLine rows (line items only — Cart records themselves are + * left alone), and the Meilisearch product index. Deliberately does NOT + * touch catalog STRUCTURE other products could still reference: ProductOption/ * ProductOptionValue definitions ("Size", "Color" as reusable option * types), Brands, Collections, Tags, Customer Groups — none of those are * products, they're config a merchant would otherwise have to rebuild @@ -150,6 +152,18 @@ class WipeCatalogCommand extends Command { ImportMapping::whereIn('source_type', ['product', 'variant', 'image'])->delete(); + // Only the line items — not the parent Cart rows. This command is + // meant for early-stage/setup use where no real customer carts + // matter yet, but a customer's Cart record also anchors their + // session/coupon/address state; deleting it outright is more than + // "the catalog is gone" calls for. Leaving every variant a cart + // line could reference about to be force-deleted below would + // otherwise reproduce the exact storefront crash this step exists + // to prevent: CartLine::purchasable() resolves to null, + // PricingManager::for() throws a TypeError on every page load that + // renders the cart drawer. + CartLine::where('purchasable_type', 'product_variant')->delete(); + while (true) { // withTrashed(): Product/ProductVariant both use SoftDeletes // — a plain query would stop seeing a product the moment