@extends('layouts.app') @section('title', __('Accounting')) @section('page-title', __('Accounting')) @section('page-subtitle', __('Connect your accounting software once — we pull the numbers and analyse them for you.')) @section('content') @php $providerMeta = [ 'exact_online' => [ 'name' => 'Exact Online', 'tagline' => __('One-click sign-in. Works for any Exact division.'), 'badge' => __('Recommended'), 'tone' => 'emerald', 'flow' => 'oauth', 'logo' => '#dc1e35', 'mark' => 'EO', 'highlights' => [__('Trial balance'), __('P&L'), __('Balance sheet')], ], 'odoo' => [ 'name' => 'Odoo', 'tagline' => __('JSON-RPC with an API key from your user profile.'), 'badge' => __('Self-hosted OK'), 'tone' => 'violet', 'flow' => 'manual', 'logo' => '#714b67', 'mark' => 'Od', 'highlights' => [__('Trial balance'), __('Journals'), __('P&L / BS')], ], 'billit' => [ 'name' => 'Billit', 'tagline' => __('Peppol-native invoicing — cash-basis P&L from sales & purchase orders.'), 'badge' => __('E-invoicing'), 'tone' => 'amber', 'flow' => 'manual', 'logo' => '#ff8a3c', 'mark' => 'Bi', 'highlights' => [__('Sales'), __('Purchases'), __('Cash P&L')], ], ]; $statusColors = [ 'connected' => 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300', 'error' => 'bg-rose-100 text-rose-700 dark:bg-rose-900/40 dark:text-rose-300', 'expired' => 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300', 'revoked' => 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300', 'running' => 'bg-sky-100 text-sky-700 dark:bg-sky-900/40 dark:text-sky-300', 'ready' => 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300', 'succeeded' => 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300', 'failed' => 'bg-rose-100 text-rose-700 dark:bg-rose-900/40 dark:text-rose-300', 'pending' => 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300', ]; $existingProviders = $integrations->pluck('provider')->all(); $connectedCount = $integrations->where('status', 'connected')->count(); $importsTotal = $imports->count(); $lastImport = $imports->where('status', 'succeeded')->first(); @endphp
{{-- ─── Hero ─────────────────────────────────────────────── --}}
{{ __('Read-only · zero file upload') }}

{{ __('Skip the file uploads — pull straight from your books.') }}

{{ __('We only read the numbers we need to analyse: trial balance, P&L, balance sheet. Nothing is written back to your accounting system.') }}

{{ $connectedCount }}
{{ __('Connected') }}
{{ $importsTotal }}
{{ __('Imports') }}
{{ $lastImport ? $lastImport->created_at->diffForHumans(short: true) : '—' }}
{{ __('Last sync') }}
{{-- ─── Connected accounts ─────────────────────────────────── --}}

{{ __('My accounts') }}

{{ __('Pick a period and import — it becomes a submission your firm can analyse.') }}

@if($integrations->isEmpty())
{{ __('No accounting connected yet') }}

{{ __('Pick a provider below — your firm will receive ready-to-analyse data without you having to upload anything.') }}

@else
@foreach($integrations as $i) @php $meta = $providerMeta[$i->provider] ?? ['name' => $i->providerLabel(), 'logo' => '#64748b', 'mark' => strtoupper(substr($i->providerLabel(), 0, 2))]; @endphp
{{ $meta['mark'] }}
{{ $i->label ?: $meta['name'] }}
{{ $meta['name'] }} @if($i->getConfig('company_name')) · {{ $i->getConfig('company_name') }} @endif @if($i->getConfig('division')) · {{ __('Div.') }} {{ $i->getConfig('division') }} @endif
{{ __($i->status) }}
{{ __('Connected') }}
{{ $i->connected_at?->diffForHumans() ?? '—' }}
{{ __('Last used') }}
{{ $i->last_used_at?->diffForHumans() ?? __('never') }}
@if($i->last_error && $i->status !== 'connected')
{{ $i->last_error }}
@endif {{-- Import form --}}
@csrf
{{ __('Pull data for period') }}
@foreach([ ['label' => __('YTD'), 'from' => now()->startOfYear()->toDateString(), 'to' => now()->toDateString()], ['label' => __('Last yr'), 'from' => now()->subYear()->startOfYear()->toDateString(), 'to' => now()->subYear()->endOfYear()->toDateString()], ['label' => __('Q1'), 'from' => now()->startOfYear()->toDateString(), 'to' => now()->startOfYear()->addMonths(3)->subDay()->toDateString()], ['label' => __('Last 12m'), 'from' => now()->subMonths(12)->toDateString(), 'to' => now()->toDateString()], ] as $p) @endforeach
@endforeach
@endif
{{-- ─── Add a connection ─────────────────────────────────────── --}}

{{ __('Connect another account') }}

{{ __('Read-only access — we never write to your accounting software.') }}

@foreach($available as $p) @php $meta = $providerMeta[$p['key']] ?? ['name' => $p['name'], 'tagline' => '', 'badge' => '', 'tone' => 'slate', 'flow' => 'manual', 'logo' => '#64748b', 'mark' => strtoupper(substr($p['name'], 0, 2)), 'highlights' => []]; $alreadyConnected = in_array($p['key'], $existingProviders, true); @endphp
{{ $meta['mark'] }}
{{ $meta['name'] }} @if(!empty($meta['badge'])) {{ $meta['badge'] }} @endif @if($alreadyConnected) {{ __('Linked') }} @endif

{{ $meta['tagline'] }}

@if(!empty($meta['highlights']))
@foreach($meta['highlights'] as $h) {{ $h }} @endforeach
@endif
@if($meta['flow'] === 'oauth') {{ __('OAuth sign-in') }} @else {{ __('API key') }} @endif {{ $alreadyConnected ? __('Add another') : __('Connect') }}
@endforeach
@if(!empty($locked))

{{ __('Not available to you') }}

@foreach($locked as $p) @php $meta = $providerMeta[$p['key']] ?? ['name' => $p['name'], 'tagline' => '', 'logo' => '#64748b', 'mark' => strtoupper(substr($p['name'], 0, 2)), 'highlights' => []]; $reason = $p['reason'] ?? null; $reasonCopy = match ($reason) { 'platform' => ['title' => __('Unavailable on this platform'), 'body' => __('This integration has been turned off platform-wide.'), 'tone' => 'slate', 'cta' => null], 'plan' => ['title' => __('Not in your current plan'), 'body' => __('Upgrade your subscription to unlock this integration.'), 'tone' => 'amber', 'cta' => __('Upgrade plan')], 'tenant' => ['title' => __('Disabled by your firm'), 'body' => __('Your workspace admin has hidden this integration. Contact them to enable it.'), 'tone' => 'rose', 'cta' => null], default => ['title' => __('Unavailable'), 'body' => '', 'tone' => 'slate', 'cta' => null], }; @endphp
{{ $meta['mark'] }}
{{ $meta['name'] }}

{{ $meta['tagline'] ?? '' }}

{{ $reasonCopy['title'] }}
@if($reasonCopy['body'])
{{ $reasonCopy['body'] }}
@endif
@if($reason === 'plan' && Route::has('billing.index')) {{ $reasonCopy['cta'] }} @endif
@endforeach
@endif
{{-- ─── Recent imports timeline ─────────────────────────────── --}} @if($imports->isNotEmpty())

{{ __('Recent imports') }}

@foreach($imports as $im) @endforeach
{{ __('Provider') }} {{ __('Period') }} {{ __('Status') }} {{ __('Records') }} {{ __('Action') }}
{{ $im->integration?->providerLabel() ?? '—' }} {{ $im->period_from?->toDateString() }} → {{ $im->period_to?->toDateString() }} @php $st = $statusColors[$im->status] ?? 'bg-slate-100 text-slate-700'; @endphp {{ __($im->status) }}
{{ $im->created_at->diffForHumans() }}
@if($im->counts) {{ array_sum($im->counts) }} {{ __('total') }} @elseif($im->error_message) {{ Str::limit($im->error_message, 60) }} @else — @endif
@if($im->status === 'ready')
@csrf
@csrf @method('DELETE')
@elseif($im->submission) {{ __('Open') }} @else @endif
@endif
@endsection