Certified/app/Console/Commands/MoneybirdSetup.php
2026-08-09 16:33:53 +02:00

124 lines
4.2 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Services\Moneybird\MoneybirdClient;
use App\Services\Moneybird\MoneybirdException;
use Illuminate\Console\Command;
/**
* One-time interactive helper for wiring up the Moneybird integration.
* Never writes .env itself — it only prints the values so you can decide
* what to do with them.
*/
class MoneybirdSetup extends Command
{
protected $signature = 'moneybird:setup';
protected $description = 'Discover your Moneybird administration/tax rate/ledger account IDs and (optionally) register the webhook';
public function handle(MoneybirdClient $client): int
{
if (blank(config('services.moneybird.api_token'))) {
$this->error('Set MONEYBIRD_API_TOKEN in .env first.');
return self::FAILURE;
}
$administrationId = config('services.moneybird.administration_id') ?: $this->discoverAdministration($client);
if ($administrationId === null) {
return self::FAILURE;
}
$this->line("Using administration_id: <info>{$administrationId}</info>");
// Every subsequent call reads administration_id straight from
// config, so make sure it's set for the rest of this run even if
// it was only just discovered above.
config(['services.moneybird.administration_id' => $administrationId]);
$this->newLine();
$this->listTaxRatesAndLedgerAccounts($client);
$this->newLine();
if ($this->confirm('Register a webhook now, pointing at '.config('app.url').'/webhooks/moneybird ?', false)) {
$this->registerWebhook($client);
}
return self::SUCCESS;
}
private function discoverAdministration(MoneybirdClient $client): ?string
{
try {
$administrations = $client->listAdministrations();
} catch (MoneybirdException $e) {
$this->error($e->getMessage());
return null;
}
if ($administrations === []) {
$this->error('No Moneybird administrations found for this token.');
return null;
}
if (count($administrations) === 1) {
return (string) $administrations[0]['id'];
}
$choices = collect($administrations)->mapWithKeys(fn ($admin) => [$admin['id'] => "{$admin['name']} ({$admin['id']})"]);
$selected = $this->choice('Multiple administrations found — pick one', $choices->values()->all());
return (string) $choices->search($selected);
}
private function listTaxRatesAndLedgerAccounts(MoneybirdClient $client): void
{
try {
$taxRates = $client->listTaxRates();
$ledgerAccounts = $client->listLedgerAccounts();
} catch (MoneybirdException $e) {
$this->error($e->getMessage());
return;
}
$this->info('Tax rates — pick one for MONEYBIRD_TAX_RATE_ID (optional, invoices work without it):');
$this->table(['id', 'name', 'percentage'], collect($taxRates)->map(fn ($rate) => [
$rate['id'], $rate['name'] ?? '', $rate['percentage'] ?? '',
]));
$this->info('Ledger accounts — pick one for MONEYBIRD_LEDGER_ACCOUNT_ID (optional):');
$this->table(['id', 'name'], collect($ledgerAccounts)->map(fn ($account) => [
$account['id'], $account['name'] ?? '',
]));
}
private function registerWebhook(MoneybirdClient $client): void
{
try {
$webhook = $client->createWebhook([
'url' => config('app.url').'/webhooks/moneybird',
'enabled_events' => [
'sales_invoice_created',
'sales_invoice_created_based_on_recurring',
'sales_invoice_state_changed_to_paid',
'sales_invoice_state_changed_to_late',
'sales_invoice_marked_as_uncollectible',
'recurring_sales_invoice_invoice_created',
],
]);
} catch (MoneybirdException $e) {
$this->error($e->getMessage());
return;
}
$this->info('Webhook registered. Add this to .env:');
$this->line('MONEYBIRD_WEBHOOK_TOKEN="'.$webhook['token'].'"');
}
}