feat(portal): lead module, WHMCS sync report/contacts/mapping, service lifecycle email templates

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
baodev0
2026-10-21 16:55:19 +07:00
co-authored by Claude Sonnet 5.5
parent 3c7710f1de
commit a443ec3bf6
66 changed files with 2032 additions and 124 deletions
@@ -4,24 +4,25 @@ namespace App\Console\Commands\Whmcs;
use App\Integrations\Whmcs\Extractors\InvoiceExtractor;
use App\Jobs\Whmcs\SyncInvoiceJob;
use App\Integrations\Whmcs\Support\SyncReport;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class SyncInvoicesCommand extends Command
{
protected $signature = 'whmcs:sync-invoices {--sync : Run each record inline instead of queueing it}';
protected $signature = 'whmcs:sync-invoices {--sync : Run each record inline instead of queueing it} {--missing-only : Only records not yet synced (new, or order without customer)}';
protected $description = 'Extract invoices (with their line items) from WHMCS and upsert them into invoices/invoice_items';
public function handle(InvoiceExtractor $extractor): int
{
$sync = (bool) $this->option('sync');
$total = DB::connection('whmcs')->table('tblinvoices')->count();
$missingOnly = (bool) $this->option('missing-only');
$total = $extractor->extract($missingOnly)->count();
$bar = $this->output->createProgressBar($total);
$bar->start();
foreach ($extractor->extract() as $row) {
foreach ($extractor->extract($missingOnly) as $row) {
$job = new SyncInvoiceJob((array) $row);
$sync ? dispatch_sync($job) : dispatch($job);
$bar->advance();
@@ -31,6 +32,8 @@ class SyncInvoicesCommand extends Command
$this->newLine();
$this->info("Dispatched {$total} invoice(s) for sync.");
app(SyncReport::class)->finish($this);
return Command::SUCCESS;
}
}