Files
dewemoji/app/routes/console.php

122 lines
4.2 KiB
PHP

<?php
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schedule;
use App\Services\LiveSqlImportService;
use App\Services\Billing\PaypalWebhookProcessor;
use App\Services\Billing\PayPalPlanSyncService;
use App\Models\Order;
use App\Models\Payment;
use App\Models\Subscription;
use App\Models\WebhookEvent;
use Illuminate\Support\Facades\Mail;
use App\Mail\TestMailketing;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
Artisan::command('dewemoji:import-live-sql {path : Absolute path to dewemojiAPI_DB.sql} {--truncate : Truncate target tables first} {--batch=500 : Insert batch size}', function () {
$path = (string) $this->argument('path');
$truncate = (bool) $this->option('truncate');
$batch = (int) $this->option('batch');
$importer = app(LiveSqlImportService::class);
$importer->import($path, $truncate, $batch, $this->output);
})->purpose('Import live SQL dump into the current database');
Artisan::command('dewemoji:webhooks:process {--limit=100 : Max events to process} {--status=pending,received : Comma-separated statuses}', function () {
$limit = (int) $this->option('limit');
$statuses = array_filter(array_map('trim', explode(',', (string) $this->option('status'))));
if (empty($statuses)) {
$this->error('No statuses provided.');
return 1;
}
$processor = app(PaypalWebhookProcessor::class);
$events = WebhookEvent::query()
->whereIn('status', $statuses)
->orderBy('id')
->limit($limit)
->get();
$processed = 0;
$failed = 0;
foreach ($events as $event) {
try {
if ($event->provider === 'paypal') {
$processor->process((string) ($event->event_type ?? ''), $event->payload ?? []);
}
$event->update([
'status' => 'processed',
'processed_at' => now(),
'error' => null,
]);
$processed++;
} catch (\Throwable $e) {
$event->update([
'status' => 'error',
'processed_at' => now(),
'error' => $e->getMessage(),
]);
$failed++;
}
}
$this->info("Processed {$processed} events, failed {$failed}.");
return 0;
})->purpose('Process pending webhook events');
Schedule::command('dewemoji:webhooks:process --limit=200')->everyMinute()->withoutOverlapping();
Artisan::command('paypal:sync-plans {--mode=both : sandbox|live|both}', function () {
$mode = (string) $this->option('mode');
$service = app(PayPalPlanSyncService::class);
$runMode = match ($mode) {
'sandbox' => ['sandbox'],
'live' => ['live'],
default => ['sandbox', 'live'],
};
foreach ($runMode as $env) {
$this->info("Syncing PayPal plans: {$env}");
$result = $service->sync($env);
$this->line("Created: {$result['created']} · Updated: {$result['updated']} · Deactivated: {$result['deactivated']} · Skipped: {$result['skipped']}");
}
})->purpose('Create/rotate PayPal plans based on pricing plans');
Artisan::command('mailketing:test {email : Recipient email address}', function () {
$email = (string) $this->argument('email');
try {
Mail::to($email)->send(new TestMailketing());
$this->info("Mailketing test email sent to {$email}.");
return 0;
} catch (\Throwable $e) {
$this->error('Mailketing test failed: '.$e->getMessage());
return 1;
}
})->purpose('Send a Mailketing API test email');
Artisan::command('dewemoji:normalize-statuses', function () {
$subs = Subscription::query()
->where('status', 'cancelled')
->update(['status' => 'canceled']);
$orders = Order::query()
->where('status', 'cancelled')
->update(['status' => 'canceled']);
$payments = Payment::query()
->where('status', 'cancelled')
->update(['status' => 'canceled']);
$this->info("Normalized statuses: subscriptions={$subs}, orders={$orders}, payments={$payments}");
return 0;
})->purpose('Normalize legacy cancelled status spelling to canceled');