Launcher status and import operativa polish

This commit is contained in:
michele 2026-04-08 20:22:28 +00:00
parent c079737b5b
commit 772a077e01
5 changed files with 155 additions and 31 deletions

View File

@ -5,6 +5,8 @@ # Changelog
## [Unreleased]
- Initial open-source release prep.
- Reworked Supporto > Aggiornamento Nodo to show local/remote commit dates, explicit pending commit counts, and a clear note that Git updates do not move storage archives or private uploaded data.
- Reorganized the Importazione Archivi operational tab so the action buttons come first, followed by the explanatory blocks and command fields.
- Removed active-stabile filtering from topbar avvisi/urgenze counters and from the Google ticket-operativi box so cross-stabile operational tickets stay visible.
- Removed the Google Workspace widget from the main/support dashboard, leaving the full panel only under Impostazioni > Google.
- Tightened Filament sidebar navigation spacing between main menu groups for denser top-level navigation.

View File

@ -85,12 +85,20 @@ class Modifiche extends Page
public ?string $gitCurrentCommit = null;
public ?string $gitCurrentCommitDate = null;
public ?string $gitRemoteCommit = null;
public ?string $gitRemoteCommitDate = null;
public bool $gitWorkingTreeDirty = false;
public string $gitAheadBehind = '-';
public int $gitAheadCount = 0;
public int $gitBehindCount = 0;
public bool $gitSyncInProgress = false;
public ?string $gitSyncJobId = null;
@ -1051,12 +1059,18 @@ private function loadGitWorkspaceStatus(): void
{
$this->gitCurrentBranch = $this->runGitProcess(['rev-parse', '--abbrev-ref', 'HEAD']);
$this->gitCurrentCommit = $this->runGitProcess(['rev-parse', '--short', 'HEAD']);
$this->gitCurrentCommitDate = $this->runGitProcess(['show', '-s', '--date=format:%d/%m/%Y %H:%M', '--format=%cd', 'HEAD']);
$this->gitRemoteCommit = $this->runGitProcess(['rev-parse', '--short', 'refs/remotes/' . $this->gitRemote . '/' . $this->gitBranch]);
$this->gitRemoteCommitDate = $this->runGitProcess(['show', '-s', '--date=format:%d/%m/%Y %H:%M', '--format=%cd', 'refs/remotes/' . $this->gitRemote . '/' . $this->gitBranch]);
$this->gitWorkingTreeDirty = trim((string) ($this->runGitProcess(['status', '--porcelain']) ?? '')) !== '';
$this->gitAheadCount = 0;
$this->gitBehindCount = 0;
$aheadBehind = $this->runGitProcess(['rev-list', '--left-right', '--count', 'HEAD...refs/remotes/' . $this->gitRemote . '/' . $this->gitBranch]);
if (is_string($aheadBehind) && preg_match('/^(\d+)\s+(\d+)$/', trim($aheadBehind), $matches) === 1) {
$this->gitAheadBehind = 'ahead ' . $matches[1] . ' / behind ' . $matches[2];
$this->gitAheadCount = (int) $matches[1];
$this->gitBehindCount = (int) $matches[2];
$this->gitAheadBehind = 'ahead ' . $this->gitAheadCount . ' / behind ' . $this->gitBehindCount;
} else {
$this->gitAheadBehind = '-';
}

View File

@ -1,3 +1,62 @@
# SESSION HANDOFF - 2026-04-08
## Contesto operativo attuale
- Stabile pilota: `0021`
- Obiettivo reale: import sicuro solo per stabili gia presenti, senza fallback vuoti o inventati su unita, nominativi, millesimi e voci di spesa.
- Regola utente vincolante:
- l'ultimo anno disponibile e la base autorevole dello stato corrente
- la chiave certa dell'unita e `condomin.cod_cond`
- il codice mnemonico operatore resta `Palazzina/Scala/Interno`, ma non deve diventare la chiave interna in fallback
- gli anni precedenti servono per costruire cronologia e variazioni, non per sovrascrivere il nominativo corrente
- niente righe vuote, `interno` inventati, o completamenti artificiali che rompano telefono, nominativi o allineamento unita
## Fix gia applicate e verificate
- `app/Console/Commands/ImportGesconFullPipeline.php`
- i placeholder `dettaglio_millesimi` a zero vengono creati solo con opzione esplicita `--fill-missing-millesimi`
- migliorato il fallback di aggancio `voci_spesa -> tabelle_millesimali` quando manca il match per anno gestione
- preflight staging reso sensibile a `cod_stabile + legacy_year`, non solo a `cod_stabile`
- `app/Console/Commands/NetgesconQaMillesimiSpeseCommand.php`
- nuovo comando QA per verificare allineamento unita, nominativi, millesimi, voci e archivi legacy
- `app/Filament/Pages/Strumenti/PostItGestione.php`
- raggruppamento post-it ora phone-first
- chiamate ai gruppi `601` e `603` non risposte da un interno reale trattate come missed in UI
- `app/Console/Commands/SmdrListenCommand.php`
- nuove chiamate SMDR su `601`/`603` marcate missed se non emerge un vero interno finale
## Evidenze gia verificate
- Per `0021`, il preflight prima caricava solo `legacy_year=0003`; dopo il fix ha caricato correttamente anche `0004`.
- Dry-run verificato:
- `condomin 0021/0004 = 214`
- `comproprietari 0021/0004 = 11`
- `voc_spe 0021/0004 = 73`
- Dopo il fix sulle voci, per `0021/0003` i codici legacy voce trovano tutti la corrispondente voce di dominio e non restano piu voci agganciate senza tabella default per i casi verificati.
- Sul call board, il numero `3388155553` collassa in un solo gruppo; esiste almeno un caso reale `601 -> 206` che resta correttamente answered.
## Punto aperto principale
La prossima modifica strutturale da fare e in `ImportGesconFullPipeline.php`, nella parte che ricostruisce unita/nominativi da staging:
1. partire dall'ultimo anno disponibile come snapshot corrente autorevole
2. identificare l'unita da `cod_cond` e usare `scala`, `interno`, `sub` solo come supporto di riconciliazione
3. evitare la creazione di unita artificiali o fallback tipo `A/0` se non esiste una base certa in archivio
4. aggiungere gli anni precedenti come variazioni storiche in `unita_immobiliare_nominativi`, senza riscrivere il corrente con dati piu vecchi
5. mantenere continuita contabile con collegamento a unita e ruolo storico `C`/`I` per rate emesse e incassi
## Anomalie note da non coprire con fallback
- In dominio esistono ancora 5 unita attive di `0021` senza nominativo corrente: `A/0`, `A/42`, `A/43`, `A/215`, `A/216`.
- Verifica fatta: queste unita non risultano in `gescon_import.condomin` per `0021/0003` nei dati controllati; non vanno auto-riempite con nominativi fittizi.
- Decisione da prendere nella prossima sessione: review/archiviazione/disattivazione guidata, non compensazione automatica.
## Prompt di ripartenza consigliato
"Riparti da docs/ai/SESSION_HANDOFF.md, docs/ai/TOPICS_INDEX.md, docs/ai/LATEST_2_CHATS_RECOVERY.md e dal topic docs/ai/topics/import-unita-cod-cond.md. Prima allinea la logica di import unita/nominativi all'ultimo anno autorevole basato su cod_cond, senza fallback inventati. Poi valida l'impatto contabile su rate e incassi."
---
# SESSION HANDOFF 2026-02-27
## Contesto operativo
@ -50,10 +109,12 @@ ## Prompt di ripartenza consigliato
## CHECKPOINT 2026-03-02 17:45:02
### Stato rapido
- Branch: main
- Ultimo commit: 49002765 2025-11-10 Auto-sync commit: 2025-11-10 12:40:03
### File modificati (git status --short)
```
M .gitignore
M .vscode/tasks.json
@ -10568,6 +10629,7 @@ ### File modificati (git status --short)
```
### Ultimi file toccati (max 20)
```
.gitignore
.vscode/tasks.json
@ -10592,15 +10654,19 @@ ### Ultimi file toccati (max 20)
```
### Bug trovati / verificati in questa sessione
-
### Decisioni prese
-
### Prossimo step operativo
-
### Prompt di ripartenza
Riparti da docs/ai/SESSION_HANDOFF.md, usa l'ultimo CHECKPOINT, continua dal "Prossimo step operativo" senza rifare analisi generale.
---
@ -10608,10 +10674,12 @@ ### Prompt di ripartenza
## CHECKPOINT 2026-03-02 18:33:07
### Stato rapido
- Branch: main
- Ultimo commit: 49002765 2025-11-10 Auto-sync commit: 2025-11-10 12:40:03
### File modificati (git status --short)
```
M .gitignore
M .vscode/tasks.json
@ -21126,6 +21194,7 @@ ### File modificati (git status --short)
```
### Ultimi file toccati (max 20)
```
.gitignore
.vscode/tasks.json
@ -21150,15 +21219,19 @@ ### Ultimi file toccati (max 20)
```
### Bug trovati / verificati in questa sessione
-
### Decisioni prese
-
### Prossimo step operativo
-
### Prompt di ripartenza
Riparti da docs/ai/SESSION_HANDOFF.md, usa l'ultimo CHECKPOINT, continua dal "Prossimo step operativo" senza rifare analisi generale.
---
@ -21166,10 +21239,12 @@ ### Prompt di ripartenza
## CHECKPOINT 2026-03-03 09:35:25
### Stato rapido
- Branch: main
- Ultimo commit: 49002765 2025-11-10 Auto-sync commit: 2025-11-10 12:40:03
### File modificati (git status --short)
```
M .gitignore
M .vscode/tasks.json
@ -31684,6 +31759,7 @@ ### File modificati (git status --short)
```
### Ultimi file toccati (max 20)
```
.gitignore
.vscode/tasks.json
@ -31708,15 +31784,19 @@ ### Ultimi file toccati (max 20)
```
### Bug trovati / verificati in questa sessione
-
### Decisioni prese
-
### Prossimo step operativo
-
### Prompt di ripartenza
Riparti da docs/ai/SESSION_HANDOFF.md, usa l'ultimo CHECKPOINT, continua dal "Prossimo step operativo" senza rifare analisi generale.
---
@ -31724,10 +31804,12 @@ ### Prompt di ripartenza
## CHECKPOINT 2026-03-03 10:26:27
### Stato rapido
- Branch: main
- Ultimo commit: 49002765 2025-11-10 Auto-sync commit: 2025-11-10 12:40:03
### File modificati (git status --short)
```
M .gitignore
M .vscode/tasks.json
@ -42242,6 +42324,7 @@ ### File modificati (git status --short)
```
### Ultimi file toccati (max 20)
```
.gitignore
.vscode/tasks.json
@ -42266,13 +42349,17 @@ ### Ultimi file toccati (max 20)
```
### Bug trovati / verificati in questa sessione
-
### Decisioni prese
-
### Prossimo step operativo
-
### Prompt di ripartenza
Riparti da docs/ai/SESSION_HANDOFF.md, usa l'ultimo CHECKPOINT, continua dal "Prossimo step operativo" senza rifare analisi generale.

View File

@ -7,35 +7,42 @@
Se importi `unità`, `soggetti` o `diritti`, la pagina ora lancia anche il re-sync di anagrafiche, ruoli rubrica e bonifica recapiti/contatti collegati allo stabile selezionato.
</div>
<div class="rounded-xl border border-slate-200 bg-white p-4">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="text-sm font-semibold text-slate-900">Azioni operative</div>
<div class="mt-1 text-xs text-slate-600">Prima esegui i pulsanti di preparazione, poi il flusso di import, infine gli eventuali riallineamenti.</div>
</div>
<div class="text-xs text-slate-600">Stabile attuale: <span class="font-semibold text-slate-900">{{ $selectedLabel !== '' ? $selectedLabel : 'nessuno' }}</span></div>
</div>
<div class="mt-4 flex flex-wrap gap-2">
<x-filament::button type="button" size="sm" wire:click="loadStabili">Carica elenco stabili</x-filament::button>
<x-filament::button type="button" size="sm" color="gray" wire:click="caricaAnniDaGenerale" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Carica anni</x-filament::button>
<x-filament::button type="button" size="sm" color="success" wire:click="creaStabileDaMdb" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Crea / apri stabile</x-filament::button>
<x-filament::button type="button" size="sm" color="gray" wire:click="eseguiImportSelezionato" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Importa dati selezionati</x-filament::button>
<x-filament::button type="button" size="sm" color="primary" wire:click="eseguiImportAllineamentoCompleto" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Import + allineamento</x-filament::button>
<x-filament::button type="button" size="sm" color="info" wire:click="aggiornaFornitoriGescon" :disabled="blank(data_get($data ?? [], 'path_root'))">Aggiorna fornitori</x-filament::button>
<x-filament::button type="button" size="sm" color="warning" wire:click="risincronizzaRelazioniImportate" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Risincronizza relazioni</x-filament::button>
<x-filament::button type="button" size="sm" color="info" wire:click="aggiornaAnagraficheDaCondomin" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Sync anagrafiche</x-filament::button>
<x-filament::button type="button" size="sm" color="warning" wire:click="refreshImportTagLegacyFornitoriGlobale" :disabled="blank(data_get($data ?? [], 'path_root'))">Refresh TAG fornitori</x-filament::button>
</div>
</div>
<div class="grid gap-4 xl:grid-cols-3">
<div class="rounded-xl border border-slate-200 bg-white p-4">
<div class="text-sm font-semibold text-slate-900">1. Setup archivio</div>
<div class="mt-3 flex flex-wrap gap-2">
<x-filament::button type="button" size="sm" wire:click="loadStabili">Carica elenco stabili</x-filament::button>
<x-filament::button type="button" size="sm" color="gray" wire:click="caricaAnniDaGenerale" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Carica anni</x-filament::button>
<x-filament::button type="button" size="sm" color="success" wire:click="creaStabileDaMdb" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Crea / apri stabile</x-filament::button>
</div>
<div class="mt-3 text-xs text-slate-600">Stabile attuale: {{ $selectedLabel !== '' ? $selectedLabel : 'nessuno' }}</div>
<div class="mt-2 text-xs text-slate-600">Carica elenco stabili, recupera gli anni dalla base generale e crea o riapri lo stabile locale prima dell'import vero e proprio.</div>
</div>
<div class="rounded-xl border border-slate-200 bg-white p-4">
<div class="text-sm font-semibold text-slate-900">2. Import / aggiornamento</div>
<div class="mt-3 flex flex-wrap gap-2">
<x-filament::button type="button" size="sm" color="gray" wire:click="eseguiImportSelezionato" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Importa dati selezionati</x-filament::button>
<x-filament::button type="button" size="sm" color="primary" wire:click="eseguiImportAllineamentoCompleto" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Import + allineamento</x-filament::button>
<x-filament::button type="button" size="sm" color="info" wire:click="aggiornaFornitoriGescon" :disabled="blank(data_get($data ?? [], 'path_root'))">Aggiorna fornitori</x-filament::button>
</div>
<div class="mt-3 text-xs text-slate-600">Usa `Import + allineamento` come flusso principale; `Importa dati selezionati` serve per slice mirate.</div>
<div class="mt-2 text-xs text-slate-600">Usa Import + allineamento come flusso principale. Importa dati selezionati resta utile solo per slice mirate o recuperi puntuali.</div>
</div>
<div class="rounded-xl border border-slate-200 bg-white p-4">
<div class="text-sm font-semibold text-slate-900">3. Re-sync relazioni</div>
<div class="mt-3 flex flex-wrap gap-2">
<x-filament::button type="button" size="sm" color="warning" wire:click="risincronizzaRelazioniImportate" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Risincronizza relazioni</x-filament::button>
<x-filament::button type="button" size="sm" color="info" wire:click="aggiornaAnagraficheDaCondomin" :disabled="empty($stabiliOptions) || blank(data_get($data ?? [], 'stabile_code'))">Sync anagrafiche</x-filament::button>
<x-filament::button type="button" size="sm" color="warning" wire:click="refreshImportTagLegacyFornitoriGlobale" :disabled="blank(data_get($data ?? [], 'path_root'))">Refresh TAG fornitori</x-filament::button>
</div>
<div class="mt-3 text-xs text-slate-600">Serve quando i dati locali esistono già e vuoi riallineare rubrica, ruoli e recapiti senza reimportare tutto.</div>
<div class="mt-2 text-xs text-slate-600">Serve quando i dati locali esistono già e vuoi riallineare rubrica, ruoli, recapiti e tag fornitori senza rilanciare l'intero import.</div>
</div>
</div>

View File

@ -82,12 +82,26 @@
<div class="mt-3 space-y-1 text-[11px] text-slate-600">
<div>Branch locale: <span class="font-mono font-medium">{{ $this->gitCurrentBranch ?? '-' }}</span></div>
<div>Commit locale: <span class="font-mono font-medium">{{ $this->gitCurrentCommit ?? '-' }}</span></div>
<div>Data commit locale: <span class="font-medium">{{ $this->gitCurrentCommitDate ?? '-' }}</span></div>
<div>Commit remoto: <span class="font-mono font-medium">{{ $this->gitRemoteCommit ?? '-' }}</span></div>
<div>Data commit remoto: <span class="font-medium">{{ $this->gitRemoteCommitDate ?? '-' }}</span></div>
<div>Tracking: <span class="font-medium">{{ $this->gitAheadBehind }}</span></div>
<div>Aggiornamenti da caricare sul nodo: <span class="font-semibold {{ (int) $this->pendingGitCommitCount > 0 ? 'text-amber-700' : 'text-emerald-700' }}">{{ (int) $this->pendingGitCommitCount }}</span></div>
<div>Commit locali da inviare: <span class="font-semibold {{ (int) $this->gitAheadCount > 0 ? 'text-sky-700' : 'text-slate-700' }}">{{ (int) $this->gitAheadCount }}</span></div>
<div>Working tree: <span class="font-medium {{ $this->gitWorkingTreeDirty ? 'text-rose-700' : 'text-emerald-700' }}">{{ $this->gitWorkingTreeDirty ? 'sporco' : 'pulito' }}</span></div>
<div>Ultima sync Git: <span class="font-medium">{{ $this->lastGitSyncAt ?? '-' }}</span></div>
<div>Ultimo update: <span class="font-medium">{{ $this->lastUpdateAt ?? '-' }}</span></div>
</div>
<div class="mt-3 rounded-lg border border-slate-200 bg-slate-50 p-3 text-[11px] text-slate-600">
Git sync e update codice aggiornano i file versionati nel repository. Gli archivi caricati manualmente dentro storage o cartelle private non vengono trasferiti da Git, salvo procedure dedicate di backup/sync dati.
</div>
@if(filled($this->pendingGitPreviewIssue))
<div class="mt-3 rounded-lg border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900">
{{ $this->pendingGitPreviewIssue }}
</div>
@endif
</div>
</div>