<?php
namespace App\Console\Commands;
use App\Modules\User\Models\User;
use App\Modules\Promotions\Jobs\AbandonedCartRecoveryJob;
use Illuminate\Console\Command;
/**
* Scheduled: every 30 minutes (see Console/Kernel.php)
*
* Looks for users who:
* 1. Have items in their cart
* 2. Last active more than 3h / 24h / 48h ago
* 3. Haven't already been emailed for the current sequence
*/
class RecoverAbandonedCartsCommand extends Command
{
protected $signature = 'carts:recover';
protected $description = 'Send abandoned cart recovery emails at 3h / 24h / 48h intervals';
public function handle(): int
{
$windows = [
['hours_min' => 3, 'hours_max' => 4, 'sequence' => 1],
['hours_min' => 24, 'hours_max' => 25, 'sequence' => 2],
['hours_min' => 48, 'hours_max' => 49, 'sequence' => 3],
];
foreach ($windows as $window) {
$users = User::whereHas('cart', fn ($q) => $q->whereHas('items'))
->whereBetween('cart_abandoned_at', [
now()->subHours($window['hours_max']),
now()->subHours($window['hours_min']),
])
->where('cart_recovery_sent', false)
->get();
foreach ($users as $user) {
AbandonedCartRecoveryJob::dispatch($user->id, $window['sequence']);
}
$this->info("Seq {$window['sequence']}: queued {$users->count()} recovery emails.");
}
return Command::SUCCESS;
}
}