12-05-2026 Frontend dev
This commit is contained in:
parent
405df0a122
commit
5b8bdf4182
779 changed files with 480564 additions and 6241 deletions
143
app/Services/Api/LegacyApiCustomerReporter.php
Normal file
143
app/Services/Api/LegacyApiCustomerReporter.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Api;
|
||||
|
||||
use App\Enums\RegistrationType;
|
||||
use App\Models\LegacyInvoice;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class LegacyApiCustomerReporter
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function report(string $portal = 'all'): array
|
||||
{
|
||||
$users = $this->candidateUsers($portal);
|
||||
$rows = $users
|
||||
->map(fn (User $user): array => $this->mapUser($user))
|
||||
->values();
|
||||
|
||||
return [
|
||||
'generated_at' => now()->toIso8601String(),
|
||||
'portal' => $portal,
|
||||
'source' => [
|
||||
'candidate_rule' => 'users.registration_type = apiuser OR Spatie role api-only',
|
||||
'eligibility_rule' => 'user is active AND latest legacy invoice status is paid',
|
||||
'missing_data' => [
|
||||
'Legacy api_key values are intentionally not imported.',
|
||||
'Legacy apiReadAccess/apiWriteAccess assignments are not preserved per-user beyond mapped roles.',
|
||||
'Users without archived legacy invoices require manual review.',
|
||||
],
|
||||
],
|
||||
'summary' => [
|
||||
'total_candidates' => $rows->count(),
|
||||
'eligible' => $rows->where('classification', 'eligible')->count(),
|
||||
'needs_review' => $rows->where('classification', 'needs_review')->count(),
|
||||
'blocked' => $rows->where('classification', 'blocked')->count(),
|
||||
],
|
||||
'customers' => $rows->all(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, User>
|
||||
*/
|
||||
private function candidateUsers(string $portal): Collection
|
||||
{
|
||||
return User::query()
|
||||
->select([
|
||||
'id',
|
||||
'name',
|
||||
'email',
|
||||
'portal',
|
||||
'registration_type',
|
||||
'is_active',
|
||||
'is_super_admin',
|
||||
'legacy_portal',
|
||||
'legacy_id',
|
||||
'last_login_at',
|
||||
])
|
||||
->with([
|
||||
'roles:id,name',
|
||||
'legacyInvoices' => fn ($query) => $query
|
||||
->select([
|
||||
'id',
|
||||
'user_id',
|
||||
'legacy_portal',
|
||||
'legacy_id',
|
||||
'number',
|
||||
'status',
|
||||
'invoice_date',
|
||||
'paid_at',
|
||||
'total_cents',
|
||||
])
|
||||
->latest('invoice_date')
|
||||
->latest('id'),
|
||||
])
|
||||
->where(function ($query): void {
|
||||
$query->where('registration_type', RegistrationType::ApiUser->value)
|
||||
->orWhereHas('roles', fn ($roles) => $roles->where('name', 'api-only'));
|
||||
})
|
||||
->when($portal !== 'all', fn ($query) => $query->where('portal', $portal))
|
||||
->orderBy('email')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function mapUser(User $user): array
|
||||
{
|
||||
$latestInvoice = $user->legacyInvoices->first();
|
||||
$classification = $this->classification($user, $latestInvoice);
|
||||
|
||||
return [
|
||||
'user_id' => $user->id,
|
||||
'email' => $user->email,
|
||||
'name' => $user->name,
|
||||
'portal' => $user->portal?->value,
|
||||
'legacy' => [
|
||||
'portal' => $user->legacy_portal,
|
||||
'id' => $user->legacy_id,
|
||||
],
|
||||
'registration_type' => $user->registration_type?->value,
|
||||
'roles' => $user->roles->pluck('name')->values()->all(),
|
||||
'is_active' => $user->is_active,
|
||||
'is_super_admin' => $user->is_super_admin,
|
||||
'last_login_at' => $user->last_login_at?->toDateTimeString(),
|
||||
'latest_legacy_invoice' => $latestInvoice ? [
|
||||
'id' => $latestInvoice->id,
|
||||
'legacy' => [
|
||||
'portal' => $latestInvoice->legacy_portal?->value,
|
||||
'id' => $latestInvoice->legacy_id,
|
||||
],
|
||||
'number' => $latestInvoice->number,
|
||||
'status' => $latestInvoice->status,
|
||||
'invoice_date' => $latestInvoice->invoice_date?->toDateString(),
|
||||
'paid_at' => $latestInvoice->paid_at?->toDateTimeString(),
|
||||
'total_cents' => $latestInvoice->total_cents,
|
||||
] : null,
|
||||
'classification' => $classification,
|
||||
'recommended_action' => match ($classification) {
|
||||
'eligible' => 'invite_to_generate_sanctum_token',
|
||||
'needs_review' => 'manual_billing_review_required',
|
||||
default => 'do_not_grant_api_access',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
private function classification(User $user, ?LegacyInvoice $latestInvoice): string
|
||||
{
|
||||
if (! $user->is_active) {
|
||||
return 'blocked';
|
||||
}
|
||||
|
||||
if ($latestInvoice === null) {
|
||||
return 'needs_review';
|
||||
}
|
||||
|
||||
return $latestInvoice->status === 'paid' ? 'eligible' : 'blocked';
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue