2026-09-16 09:58:55 +02:00
|
|
|
# CLAUDE.md
|
|
|
|
|
|
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
|
|
|
|
|
|
## Cos'è questo progetto
|
|
|
|
|
|
|
|
|
|
`CadSearchGui` è un'app Windows Forms (.NET 10, WinForms) che indicizza e permette di
|
2026-09-16 16:25:52 +02:00
|
|
|
cercare i file CAD Pro-ENGINEER/Creo contenuti in tutte le cartelle di primo livello
|
|
|
|
|
di un disco/share di rete (radice di default `X:\`), salvando i metadati in un DB
|
|
|
|
|
SQLite locale (`cad_index.db`).
|
2026-09-16 09:58:55 +02:00
|
|
|
|
|
|
|
|
## Comandi
|
|
|
|
|
|
|
|
|
|
Tutti da eseguire dentro `CadSearchGui/`.
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
dotnet build -c Release
|
|
|
|
|
dotnet run -c Release
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Pubblicazione come eseguibile standalone (single-file, self-contained, Windows x64):
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o publish
|
|
|
|
|
```
|
|
|
|
|
|
2026-09-16 16:25:52 +02:00
|
|
|
`CadSearchGui.Tests/` (xUnit) contiene unit e integration test — vedi
|
|
|
|
|
`dotnet test` da dentro quella cartella. Riferimento al progetto principale
|
|
|
|
|
via `ProjectReference` + `InternalsVisibleTo` (in `CadSearchGui.csproj`), così
|
|
|
|
|
i test possono chiamare direttamente `Indexer.ParseFilename` e
|
|
|
|
|
`AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli come API
|
|
|
|
|
pubblica.
|
2026-09-16 09:58:55 +02:00
|
|
|
|
|
|
|
|
## Architettura
|
|
|
|
|
|
|
|
|
|
Il programma è tutto in `CadSearchGui/` (nessun altro progetto nella solution — in
|
|
|
|
|
passato esisteva anche una CLI separata e uno script Python di indicizzazione,
|
|
|
|
|
entrambi rimossi: ora l'unico programma è questo, con GUI e indicizzazione integrate).
|
|
|
|
|
|
|
|
|
|
- **Program.cs** — entry point WinForms standard, avvia `Form1`.
|
2026-09-16 16:25:52 +02:00
|
|
|
- **Form1.cs** / **Form1.Designer.cs** — finestra principale, costruita come wizard: una
|
|
|
|
|
sola fase alla volta occupa tutta la finestra (`_panelFasi[]`/`NomiFasi`), si avanza
|
|
|
|
|
con "Avanti" solo quando la fase corrente è pronta (`AvantiConsentito`). La UI è
|
|
|
|
|
costruita interamente in codice in `Form1.BuildUi()` (nessun designer visuale usato).
|
|
|
|
|
`Form1.Designer.cs` contiene solo lo scheletro minimo (`InitializeComponent`/`Dispose`)
|
|
|
|
|
generato dal template. Le fasi, in ordine:
|
|
|
|
|
1. **Database** — carica/aggiorna l'indice, mostra data ultimo aggiornamento; qui vive
|
|
|
|
|
anche "Pulisci raw e step" (manutenzione, non fa parte del flusso a valle).
|
|
|
|
|
2. **Importa Distinta Base** — `DistintaBaseImporter.ConvertiInCsv` genera il CSV dei
|
|
|
|
|
componenti; se il nome del file segue la convenzione del gestionale
|
|
|
|
|
(`DBP_<codice>_<timestamp>`), l'assieme generale viene aggiunto come riga in più nel
|
|
|
|
|
CSV stesso (il foglio elenca solo i componenti sotto l'assieme, non l'assieme in sé).
|
|
|
|
|
Da qui in avanti l'assieme generale è un componente come tutti gli altri, nessun
|
|
|
|
|
caso speciale nel resto del codice.
|
|
|
|
|
3. **Crea cartella raw** — cerca nell'indice il percorso CAD di ogni componente del CSV
|
|
|
|
|
(`TrovaPercorsiCad`) e lo copia in `raw/` (`CopiaFileTrovati`).
|
|
|
|
|
4. **Trova componenti referenziati** — legge euristicamente i metadati binari dei `.asm`
|
|
|
|
|
già in `raw/` (`AssemblyComponentScanner`) per risolvere ricorsivamente i
|
|
|
|
|
sotto-assiemi/parti che contengono (`RisolviAlberoComponenti`), copiandoli anch'essi
|
|
|
|
|
in `raw/`.
|
|
|
|
|
5. **Verifica completezza e STEP** — "Verifica completezza assiemi" (ricorsivo sui
|
|
|
|
|
percorsi originali in indice, non su `raw/`) e "Report STEP realizzati" (confronto
|
|
|
|
|
con `step/`).
|
2026-09-16 09:58:55 +02:00
|
|
|
- **Indexer.cs** — logica di scansione del disco e scrittura/aggiornamento del DB
|
2026-09-16 16:25:52 +02:00
|
|
|
SQLite (`Indexer.ScanAsync`). Cammina tutte le cartelle di primo livello trovate sotto
|
|
|
|
|
la radice (scoperte dinamicamente con `Directory.GetDirectories`, non un elenco fisso)
|
2026-09-16 09:58:55 +02:00
|
|
|
con un walk manuale a stack (`Walk`, più veloce di `EnumerateFiles(..., AllDirectories)`
|
|
|
|
|
su share di rete con centinaia di migliaia di file), estrae da ogni nome file il
|
|
|
|
|
pattern Pro-E `<codice>.<tipo>.<versione>` via regex, e fa un upsert incrementale
|
|
|
|
|
riga per riga (confronto per `percorso_completo` + dimensione + data modifica).
|
|
|
|
|
Riporta il progresso tramite `IProgress<ScanProgress>`, marshalato automaticamente
|
|
|
|
|
sul thread UI. Contiene anche lo schema SQL del DB (tabella `files` + vista
|
|
|
|
|
`files_ultima_versione`, che seleziona solo l'ultima versione per
|
|
|
|
|
`(cartella_radice, codice, tipo_file)` usando `ROW_NUMBER() OVER (...)` — non un
|
|
|
|
|
self-join con `GROUP BY`, che su ~200k righe degenera in tempi quasi quadratici).
|
|
|
|
|
- **ProgressForm.cs** — dialog modale mostrato durante l'aggiornamento indice: barra
|
|
|
|
|
di progresso, conteggi nuovi/aggiornati/invariati/rimossi, tempo trascorso e stima
|
|
|
|
|
del tempo rimanente (calcolata dal ritmo file/secondo rispetto al totale atteso,
|
|
|
|
|
preso dal conteggio della scansione precedente salvato nel DB).
|
|
|
|
|
|
|
|
|
|
### Schema del DB (`cad_index.db`)
|
|
|
|
|
|
|
|
|
|
Tabella `files`: un record per ogni file trovato, con `percorso_completo` (chiave
|
|
|
|
|
univoca), `cartella_radice`, `famiglia` (primo livello di sottocartella),
|
|
|
|
|
`codice`/`tipo_file`/`versione` estratti dal nome file, dimensione, data modifica e
|
|
|
|
|
timestamp dell'ultima scansione (`scansionato_il`, usato per rilevare ed eliminare i
|
|
|
|
|
file non più presenti su disco a fine scansione).
|
|
|
|
|
|
|
|
|
|
Vista `files_ultima_versione`: stessa struttura, filtrata alla sola versione più
|
|
|
|
|
recente per codice+tipo.
|
|
|
|
|
|
|
|
|
|
### Percorso del DB
|
|
|
|
|
|
|
|
|
|
All'avvio la app cerca `cad_index.db` accanto all'eseguibile o nella working
|
|
|
|
|
directory corrente; se non lo trova, l'utente può selezionarlo con "Apri DB...".
|
|
|
|
|
Il bottone "Aggiorna indice" rilancia `Indexer.ScanAsync` sullo stesso path (radice
|
|
|
|
|
disco di default `X:\`, hardcoded in `Form1.RadiceDiscoDefault`).
|