netgescon-day0/app/Filament/Pages/Fornitore/ImpostazioniArchivio.php

264 lines
9.8 KiB
PHP

<?php
namespace App\Filament\Pages\Fornitore;
use App\Filament\Pages\Fornitore\Concerns\ResolvesOperatoreContext;
use App\Filament\Pages\Gescon\FornitoreScheda;
use App\Models\Fornitore;
use App\Models\User;
use App\Support\ArchivioPaths;
use BackedEnum;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Storage;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Livewire\WithFileUploads;
use UnitEnum;
class ImpostazioniArchivio extends Page
{
use ResolvesOperatoreContext;
use WithFileUploads;
protected static ?string $navigationLabel = 'Impostazioni';
protected static ?string $title = 'Impostazioni fornitore';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-cog-6-tooth';
protected static UnitEnum|string|null $navigationGroup = 'Fornitore';
protected static ?int $navigationSort = 5;
protected static ?string $slug = 'fornitore/impostazioni';
protected string $view = 'filament.pages.fornitore.impostazioni-archivio';
public ?Fornitore $fornitore = null;
public bool $missingAdminContext = false;
public string $tecnorepairMdbPath = '';
public string $lastImportOutput = '';
public $tecnorepairMdbUpload;
/** @var array<int, array<string, string>> */
public array $archiveFolders = [];
/** @var array<int, array<string, string>> */
public array $moduleRows = [];
/** @var array<string, mixed>|null */
public ?array $googleWorkspaceStatus = null;
public static function canAccess(): bool
{
$user = auth()->user();
return $user instanceof User
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'fornitore']);
}
public function mount(): void
{
[$fornitore] = $this->resolveOperatoreContext(allowAdminWithoutSupplier: true);
if (! $fornitore instanceof Fornitore) {
$this->missingAdminContext = true;
return;
}
$this->fornitore = $fornitore;
$this->refreshArchiveSummary();
}
public function saveUploadedTecnoRepairMdb(): void
{
if (! $this->fornitore instanceof Fornitore) {
return;
}
$upload = $this->tecnorepairMdbUpload;
if (! $upload instanceof TemporaryUploadedFile) {
Notification::make()->title('Seleziona prima un file MDB')->warning()->send();
return;
}
$extension = strtolower((string) $upload->getClientOriginalExtension());
if ($extension !== 'mdb') {
Notification::make()->title('Carica un file .mdb')->warning()->send();
return;
}
$relativeBase = $this->getArchiveRelativeBase();
if ($relativeBase === null) {
Notification::make()->title('Archivio fornitore non disponibile')->danger()->send();
return;
}
$filename = 'TecnoRepairDB-' . now()->format('Ymd-His') . '.mdb';
$stored = $upload->storeAs($relativeBase . '/tecnorepair/imports', $filename, 'local');
$this->tecnorepairMdbPath = storage_path('app/' . $stored);
$this->tecnorepairMdbUpload = null;
$this->refreshArchiveSummary();
Notification::make()->title('Archivio TecnoRepair caricato')->body($filename)->success()->send();
}
public function importTecnoRepairFromArchive(bool $dryRun = false): void
{
if (! $this->fornitore instanceof Fornitore) {
return;
}
$mdbPath = trim($this->tecnorepairMdbPath);
if ($mdbPath === '' || ! is_file($mdbPath)) {
Notification::make()->title('Percorso MDB non valido')->warning()->send();
return;
}
$adminId = (int) ($this->fornitore->amministratore_id ?? 0);
if ($adminId <= 0) {
Notification::make()->title('Amministratore del fornitore non trovato')->danger()->send();
return;
}
try {
Artisan::call('tecnorepair:import-legacy', [
'amministratore' => $adminId,
'--mdb' => $mdbPath,
'--fornitore-id' => (int) $this->fornitore->id,
'--force-primary' => true,
'--dry-run' => $dryRun,
]);
} catch (\Throwable $e) {
Notification::make()->title('Import TecnoRepair fallito')->body($e->getMessage())->danger()->send();
return;
}
$this->lastImportOutput = trim(Artisan::output());
$this->refreshArchiveSummary();
Notification::make()
->title($dryRun ? 'Simulazione TecnoRepair completata' : 'Import TecnoRepair completato')
->body($this->lastImportOutput !== '' ? $this->lastImportOutput : 'Operazione completata.')
->success()
->send();
}
public function getSchedaFornitoreUrl(): string
{
return FornitoreScheda::getUrl(['record' => (int) ($this->fornitore?->id ?? 0)], panel: 'admin-filament');
}
public function getTicketsUrl(): string
{
return TicketOperativi::getUrl(['fornitore' => (int) ($this->fornitore?->id ?? 0)], panel: 'admin-filament');
}
public function getProdottiUrl(): string
{
return ProdottiCatalogo::getUrl(['fornitore' => (int) ($this->fornitore?->id ?? 0)], panel: 'admin-filament');
}
public function getGoogleConnectUrl(): string
{
return route('oauth.google.redirect', [
'return_to' => request()->getRequestUri(),
]);
}
public function getGoogleDisconnectUrl(): string
{
return route('oauth.google.disconnect', [
'return_to' => request()->getRequestUri(),
]);
}
private function refreshArchiveSummary(): void
{
$relativeBase = $this->getArchiveRelativeBase();
$absoluteBase = $relativeBase ? storage_path('app/' . $relativeBase) : null;
if ($relativeBase !== null) {
foreach ([
'documenti',
'rubrica',
'fe',
'prodotti',
'comunicazioni',
'tecnorepair/imports',
'tecnorepair/allegati',
'temp/upload',
'temp/processing',
'logs',
] as $folder) {
Storage::disk('local')->makeDirectory($relativeBase . '/' . $folder);
}
}
$this->archiveFolders = $relativeBase === null ? [] : [
['label' => 'Base archivio', 'path' => (string) $absoluteBase],
['label' => 'Rubrica fornitore', 'path' => storage_path('app/' . $relativeBase . '/rubrica')],
['label' => 'FE fornitore', 'path' => storage_path('app/' . $relativeBase . '/fe')],
['label' => 'Prodotti e catalogo', 'path' => storage_path('app/' . $relativeBase . '/prodotti')],
['label' => 'Comunicazioni / Post-it', 'path' => storage_path('app/' . $relativeBase . '/comunicazioni')],
['label' => 'TecnoRepair import', 'path' => storage_path('app/' . $relativeBase . '/tecnorepair/imports')],
];
if ($relativeBase !== null && $this->tecnorepairMdbPath === '') {
$latest = collect(Storage::disk('local')->files($relativeBase . '/tecnorepair/imports'))
->filter(fn(string $path): bool => str_ends_with(strtolower($path), '.mdb'))
->sortDesc()
->first();
if (is_string($latest) && $latest !== '') {
$this->tecnorepairMdbPath = storage_path('app/' . $latest);
}
}
$stats = $this->fornitore?->tecnorepair_stats ?? ['total' => 0, 'open' => 0, 'closed' => 0, 'serials' => 0];
$this->googleWorkspaceStatus = $this->resolveGoogleWorkspaceStatus();
$this->moduleRows = [
['module' => 'Rubrica fornitore', 'status' => 'pronto', 'note' => 'Vista fornitore filtrata ma agganciata all\'anagrafica unica.'],
['module' => 'Google Workspace', 'status' => data_get($this->googleWorkspaceStatus, 'connected', false) ? 'collegato' : 'da collegare', 'note' => 'Rubrica e sincronizzazioni smartphone riusano l\'account Google del contesto amministratore.'],
['module' => 'TecnoRepair MDB', 'status' => ((int) ($stats['total'] ?? 0) > 0) ? 'importato' : 'da importare', 'note' => 'Schede: ' . (int) ($stats['total'] ?? 0) . ' · aperte: ' . (int) ($stats['open'] ?? 0) . ' · chiuse: ' . (int) ($stats['closed'] ?? 0)],
['module' => 'Catalogo fornitore', 'status' => 'attivo', 'note' => 'Il catalogo vero resta nella pagina Prodotti.'],
['module' => 'Comunicazioni / Post-it', 'status' => 'predisposto', 'note' => 'Cartelle e contesto archivio pronti per agganciare chiamate, post-it ed email.'],
['module' => 'FE e documenti', 'status' => 'predisposto', 'note' => 'Archivio separato per FE, documenti e flussi contabili del fornitore.'],
];
}
/**
* @return array<string, mixed>|null
*/
private function resolveGoogleWorkspaceStatus(): ?array
{
$amministratore = $this->fornitore?->amministratore;
if (! $amministratore) {
return null;
}
$oauth = (array) (($amministratore->impostazioni['google']['oauth'] ?? null) ?: []);
return [
'connected' => (bool) ($oauth['connected'] ?? false),
'email' => (string) ($oauth['email'] ?? ''),
'name' => (string) ($oauth['name'] ?? ''),
'connected_at' => (string) ($oauth['connected_at'] ?? ''),
];
}
private function getArchiveRelativeBase(): ?string
{
if (! $this->fornitore instanceof Fornitore) {
return null;
}
return ArchivioPaths::fornitoreBase($this->fornitore, $this->fornitore->amministratore);
}
}