feat(Reminder process): add 4 reminder phases for membership (Retzien)
All checks were successful
Deploy Roxane to Preprod / deploy (push) Successful in 1m21s
All checks were successful
Deploy Roxane to Preprod / deploy (push) Successful in 1m21s
This commit is contained in:
150
app/Console/Commands/MemberRenewalProcessCommand.php
Normal file
150
app/Console/Commands/MemberRenewalProcessCommand.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Member;
|
||||
use App\Services\MemberRenewalService;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\Console\Command\Command as CommandAlias;
|
||||
|
||||
class MemberRenewalProcessCommand extends Command
|
||||
{
|
||||
protected $signature = 'members:renewal-process
|
||||
{--phase=auto : Phase à exécuter (auto|reminder_1|reminder_2|reminder_3|deactivate)}
|
||||
{--year= : Année de renouvellement (par défaut : année suivante)}
|
||||
{--dry-run : Mode simulation}
|
||||
{email? : Email d\'un adhérent spécifique}';
|
||||
|
||||
protected $description = 'Processus de relances pour renouvellement adhésion';
|
||||
|
||||
public function __construct(
|
||||
protected MemberRenewalService $renewalService
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$dryRun = $this->option('dry-run');
|
||||
$emailFilter = $this->argument('email');
|
||||
$phaseOption = $this->option('phase');
|
||||
$year = $this->option('year') ?? now()->addYear()->year;
|
||||
|
||||
$this->info(
|
||||
$dryRun
|
||||
? 'DRY-RUN activé – aucune modification ne sera effectuée'
|
||||
: 'Mode réel activé'
|
||||
);
|
||||
|
||||
$phase = $phaseOption === 'auto' ? $this->determinePhase() : $phaseOption;
|
||||
|
||||
if ($phase === null) {
|
||||
$this->warn('Mode auto : aucune phase détectée pour la date actuelle');
|
||||
|
||||
return CommandAlias::SUCCESS;
|
||||
}
|
||||
|
||||
$this->info("Phase détectée : {$phase}");
|
||||
$this->info("Année de renouvellement : {$year}");
|
||||
|
||||
if ($emailFilter) {
|
||||
$this->warn("Mode utilisateur unique : {$emailFilter}");
|
||||
}
|
||||
|
||||
$members = $this->getEligibleMembers($emailFilter);
|
||||
|
||||
if ($members->isEmpty()) {
|
||||
$this->info('Aucun adhérent éligible');
|
||||
|
||||
return CommandAlias::SUCCESS;
|
||||
}
|
||||
|
||||
$this->info("{$members->count()} adhérent(s) à traiter");
|
||||
|
||||
foreach ($members as $member) {
|
||||
try {
|
||||
$this->processMember($member, $phase, $year, $dryRun);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Erreur traitement adhérent relance', [
|
||||
'member_id' => $member->id,
|
||||
'phase' => $phase,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
$this->error("Erreur pour {$member->email} : {$e->getMessage()}");
|
||||
}
|
||||
}
|
||||
|
||||
$this->info(
|
||||
$dryRun
|
||||
? 'DRY-RUN terminé – aucune action effectuée'
|
||||
: 'Traitement terminé'
|
||||
);
|
||||
|
||||
return CommandAlias::SUCCESS;
|
||||
}
|
||||
|
||||
protected function determinePhase(): ?string
|
||||
{
|
||||
$today = now();
|
||||
|
||||
if ($today->month === 12 && $today->day >= 1 && $today->day <= 10) {
|
||||
return 'reminder_1';
|
||||
}
|
||||
|
||||
if ($today->month === 12 && $today->day >= 15 && $today->day <= 20) {
|
||||
return 'reminder_2';
|
||||
}
|
||||
|
||||
if ($today->month === 1 && $today->day >= 4 && $today->day <= 6) {
|
||||
return 'reminder_3';
|
||||
}
|
||||
|
||||
if ($today->month === 1 && $today->day >= 25 && $today->day <= 31) {
|
||||
return 'deactivate';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getEligibleMembers(?string $emailFilter): \Illuminate\Support\Collection
|
||||
{
|
||||
$query = Member::query()
|
||||
->where('status', 'valid')
|
||||
->whereHas('memberships', function ($q) {
|
||||
$q->where('status', 'active');
|
||||
});
|
||||
|
||||
if ($emailFilter) {
|
||||
$query->where('email', $emailFilter)
|
||||
->orWhere('retzien_email', $emailFilter);
|
||||
}
|
||||
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
protected function processMember(Member $member, string $phase, int $year, bool $dryRun): void
|
||||
{
|
||||
$this->line("• {$member->id} - {$member->email}");
|
||||
|
||||
if ($dryRun) {
|
||||
$this->info("[DRY-RUN] Phase {$phase}");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$sent = match ($phase) {
|
||||
'reminder_1' => $this->renewalService->sendReminder1($member, $year),
|
||||
'reminder_2' => $this->renewalService->sendReminder2($member, $year),
|
||||
'reminder_3' => $this->renewalService->sendReminder3($member, $year),
|
||||
'deactivate' => $this->renewalService->deactivateMember($member, $year),
|
||||
default => false,
|
||||
};
|
||||
|
||||
if ($sent) {
|
||||
$this->info(" ✓ Relance envoyée");
|
||||
} else {
|
||||
$this->warn(" → Aucune relance envoyée (Membre non concerné / mail de relance déjà envoyé / adhésion active pour {$year})");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace App\Console\Commands;
|
||||
use App\Models\Member;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use function Laravel\Prompts\progress;
|
||||
|
||||
class SyncServicesMembers extends Command
|
||||
@@ -31,7 +32,7 @@ class SyncServicesMembers extends Command
|
||||
// Tous les membres ayant une adhésion en court ont les services activés
|
||||
$this->info('Syncing services members...');
|
||||
|
||||
$members = Member::whereIn('status', ['valid', 'pending'] )->get();
|
||||
$members = Member::whereIn('status', ['valid', 'pending'])->get();
|
||||
|
||||
$progressBar = progress(label: 'Syncing services members', steps: $members->count());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user