Skip to content

Commit 576fa05

Browse files
simonhampclaude
andauthored
Add artisan command to resend lead notifications from a given date (#295)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7290646 commit 576fa05

2 files changed

Lines changed: 103 additions & 0 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace App\Console\Commands;
4+
5+
use App\Models\Lead;
6+
use App\Notifications\NewLeadSubmitted;
7+
use Illuminate\Console\Command;
8+
use Illuminate\Support\Carbon;
9+
use Illuminate\Support\Facades\Notification;
10+
11+
class ResendLeadNotifications extends Command
12+
{
13+
protected $signature = 'app:resend-lead-notifications {date : The date to resend leads from (Y-m-d)}';
14+
15+
protected $description = 'Re-send lead notifications to the sales email for leads submitted on or after a given date.';
16+
17+
public function handle(): void
18+
{
19+
$date = Carbon::createFromFormat('Y-m-d', $this->argument('date'))->startOfDay();
20+
21+
$leads = Lead::query()
22+
->where('created_at', '>=', $date)
23+
->orderBy('created_at')
24+
->get();
25+
26+
if ($leads->isEmpty()) {
27+
$this->info('No leads found from '.$date->toDateString().' onwards.');
28+
29+
return;
30+
}
31+
32+
$this->info("Found {$leads->count()} lead(s) from {$date->toDateString()} onwards.");
33+
34+
foreach ($leads as $lead) {
35+
Notification::route('mail', 'sales@nativephp.com')
36+
->notify(new NewLeadSubmitted($lead));
37+
38+
$this->line("Sent notification for lead: {$lead->company} ({$lead->email})");
39+
}
40+
41+
$this->info('Done.');
42+
}
43+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Tests\Feature;
4+
5+
use App\Models\Lead;
6+
use App\Notifications\NewLeadSubmitted;
7+
use Illuminate\Foundation\Testing\RefreshDatabase;
8+
use Illuminate\Support\Facades\Notification;
9+
use PHPUnit\Framework\Attributes\Test;
10+
use Tests\TestCase;
11+
12+
class ResendLeadNotificationsTest extends TestCase
13+
{
14+
use RefreshDatabase;
15+
16+
#[Test]
17+
public function it_resends_notifications_for_leads_from_the_given_date(): void
18+
{
19+
Notification::fake();
20+
21+
$oldLead = Lead::factory()->create(['created_at' => '2025-01-01 12:00:00']);
22+
$matchingLead = Lead::factory()->create(['created_at' => '2025-03-15 09:00:00']);
23+
$newerLead = Lead::factory()->create(['created_at' => '2025-03-16 14:00:00']);
24+
25+
$this->artisan('app:resend-lead-notifications', ['date' => '2025-03-15'])
26+
->expectsOutputToContain('Found 2 lead(s)')
27+
->expectsOutputToContain('Done.')
28+
->assertExitCode(0);
29+
30+
Notification::assertSentOnDemand(
31+
NewLeadSubmitted::class,
32+
function ($notification, $channels, $notifiable) use ($matchingLead) {
33+
return $notifiable->routes['mail'] === 'sales@nativephp.com'
34+
&& $notification->lead->is($matchingLead);
35+
}
36+
);
37+
38+
Notification::assertSentOnDemand(
39+
NewLeadSubmitted::class,
40+
function ($notification, $channels, $notifiable) use ($newerLead) {
41+
return $notifiable->routes['mail'] === 'sales@nativephp.com'
42+
&& $notification->lead->is($newerLead);
43+
}
44+
);
45+
46+
Notification::assertNotSentTo($oldLead, NewLeadSubmitted::class);
47+
}
48+
49+
#[Test]
50+
public function it_shows_message_when_no_leads_are_found(): void
51+
{
52+
Notification::fake();
53+
54+
$this->artisan('app:resend-lead-notifications', ['date' => '2099-01-01'])
55+
->expectsOutputToContain('No leads found')
56+
->assertExitCode(0);
57+
58+
Notification::assertNothingSent();
59+
}
60+
}

0 commit comments

Comments
 (0)