35 lines
2.8 KiB
PHP
35 lines
2.8 KiB
PHP
@extends('licensing::admin.layout')
|
|
@section('title', 'SonarDesk Billing Audit')
|
|
@section('content')
|
|
<h1>Billing Audit</h1>
|
|
<p class="muted">Local database checks only. No Paddle API requests, billing changes, webhook replays or licence mutations are performed.</p>
|
|
<div class="cards">
|
|
<div class="card"><div class="muted">Subscription-linked licences</div><div class="metric">{{ number_format($linkedCount) }}</div></div>
|
|
<div class="card"><div class="muted">Missing payment provider</div><div class="metric">{{ number_format($missingProvider) }}</div></div>
|
|
<div class="card"><div class="muted">Missing customer ID</div><div class="metric">{{ number_format($missingCustomer) }}</div></div>
|
|
<div class="card"><div class="muted">Missing subscription status</div><div class="metric">{{ number_format($missingStatus) }}</div></div>
|
|
<div class="card"><div class="muted">Webhook events stored</div><div class="metric">{{ number_format($eventCount) }}</div></div>
|
|
<div class="card"><div class="muted">Unprocessed events</div><div class="metric">{{ number_format($unprocessedEvents) }}</div></div>
|
|
<div class="card"><div class="muted">Events with errors</div><div class="metric">{{ number_format($failedEvents) }}</div></div>
|
|
</div>
|
|
<h2>Duplicate subscription identifiers (first 25)</h2>
|
|
<p class="muted">Multiple licences can legitimately share a subscription. Review these before deciding whether a record is incorrect.</p>
|
|
<div class="table-wrap"><table><thead><tr><th>Provider</th><th>Subscription ID</th><th>Licences</th></tr></thead><tbody>
|
|
@forelse ($duplicateSubscriptions as $row)
|
|
<tr><td>{{ $row->payment_provider ?? '—' }}</td><td>{{ $row->external_subscription_id }}</td><td>{{ $row->license_count }}</td></tr>
|
|
@empty<tr><td colspan="3">No repeated subscription identifiers.</td></tr>@endforelse
|
|
</tbody></table></div>
|
|
<h2>Duplicate webhook event identifiers (first 25)</h2>
|
|
<div class="table-wrap"><table><thead><tr><th>Provider</th><th>Event ID</th><th>Rows</th></tr></thead><tbody>
|
|
@forelse ($duplicateEvents as $row)
|
|
<tr><td>{{ $row->provider }}</td><td>{{ $row->external_event_id }}</td><td>{{ $row->event_count }}</td></tr>
|
|
@empty<tr><td colspan="3">No duplicate event identifiers.</td></tr>@endforelse
|
|
</tbody></table></div>
|
|
<h2>Recent processing errors</h2>
|
|
<div class="table-wrap"><table><thead><tr><th>When</th><th>Provider</th><th>Event type</th><th>Event ID</th><th>Error</th></tr></thead><tbody>
|
|
@forelse ($recentFailures as $event)
|
|
<tr><td>{{ $event->created_at?->format('d M Y H:i') ?? '—' }}</td><td>{{ $event->provider }}</td><td>{{ $event->event_type }}</td><td>{{ $event->external_event_id }}</td><td>{{ \Illuminate\Support\Str::limit($event->processing_error, 240) }}</td></tr>
|
|
@empty<tr><td colspan="5">No stored processing errors.</td></tr>@endforelse
|
|
</tbody></table></div>
|
|
@endsection
|