Due bug reali trovati confrontando l'estrazione BOM con la BOM ufficiale Creo: un componente scartato per placement fallito in un file veniva bloccato per sempre anche quando il file giusto aveva un vero placement (perdendo interi sotto-alberi come 9256510047), e i codici con suffisso (_C01 ecc.) richiedevano sempre placement esplicito invece dell'eccezione per occorrenze ripetute già presente nella GUI. Entrambi corretti. AssemblyComponentScanner reso pubblico e scripts/BomViaDb.cs, ExtractCreoStrings.cs riscritti per referenziarlo via "#:project" invece di duplicare l'euristica: un'unica fonte di verità condivisa da GUI e script standalone. Aggiunti test di integrazione per Indexer.ScanAsync (mai coperto oltre al parsing del nome file) e test end-to-end che ricostruiscono l'intera pipeline disco -> indice -> risoluzione albero componenti senza toccare la UI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
150 lines
9.3 KiB
Markdown
150 lines
9.3 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Cos'è questo progetto
|
|
|
|
`PrepStep` è il nome tecnico del progetto (cartella, namespace, csproj, eseguibile
|
|
`PrepStep.exe`); il nome mostrato all'utente finale è **Cevolani StepPrep** (`<Product>`/
|
|
`<AssemblyTitle>` in `PrepStep/PrepStep.csproj`, usato nel titolo della finestra insieme
|
|
alla versione, `<Version>`, attualmente `0.1.0`). È un'app Windows Forms (.NET 10, WinForms) che indicizza e permette di
|
|
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`). Il flusso a valle (fasi 2-5, vedi sotto) prepara i file
|
|
`raw/` da passare a Creo Distributed Batch per l'esportazione STEP: la app è quindi un
|
|
pre-processo per quel passaggio, non lo sostituisce.
|
|
|
|
## Comandi
|
|
|
|
Tutti da eseguire dentro `PrepStep/`.
|
|
|
|
```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
|
|
```
|
|
|
|
`PrepStep.Tests/` (xUnit) contiene unit e integration test — vedi
|
|
`dotnet test` da dentro quella cartella. Riferimento al progetto principale
|
|
via `ProjectReference` + `InternalsVisibleTo` (in `PrepStep.csproj`), così
|
|
i test possono chiamare direttamente `Indexer.ParseFilename` e
|
|
`AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli come API
|
|
pubblica.
|
|
|
|
## Architettura
|
|
|
|
Il programma è tutto in `PrepStep/` (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`.
|
|
- **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 la **cartella di lavoro** (`_cartellaLavoro`, mostrata in `_lblCartellaLavoro`,
|
|
cambiabile con "Cambia cartella..." → `ScegliCartellaLavoro`): destinazione di CSV,
|
|
`raw/` per tutte le fasi successive (gli STEP esportati a mano con Creo vanno in
|
|
`step/`, dentro la stessa cartella). All'avvio
|
|
`InizializzaCartellaLavoro` propone l'ultima usata (ricordata in
|
|
`%AppData%/PrepStep/ultima_cartella_lavoro.txt`, stesso pattern di
|
|
`ultimo_db.txt` per il DB) se esiste ancora, altrimenti `AppContext.BaseDirectory`
|
|
— non dipende da un marker di repo (niente più `CLAUDE.md`/`TrovaRadiceRepo`),
|
|
quindi funziona identica anche sull'exe pubblicato standalone (`PrepStep.exe`)
|
|
copiato su un'altra macchina. 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 nella cartella di lavoro; 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/` dentro la cartella di lavoro
|
|
(`CopiaFileTrovati`, parallela — vedi `docs/copia-raw-parallela.md`).
|
|
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** — appena si entra nella fase, `AggiornaAnteprimaAsm`
|
|
mostra in una `ListView` a icone i file `.asm` della distinta importata (esclusi i
|
|
sotto-assiemi di fase 4) già presenti in `raw/` — letti dal filesystem locale, non
|
|
dall'indice/share — trascinabili (drag&drop, `ItemDrag` → `DoDragDrop` con
|
|
`DataFormats.FileDrop`) direttamente su Creo o Esplora risorse, per l'esportazione
|
|
STEP con Creo Distributed Batch. "Verifica completezza assiemi" controlla
|
|
ricorsivamente (sui percorsi originali in indice, non su `raw/`) se tutti i
|
|
sotto-componenti di ogni assieme della distinta sono nell'indice.
|
|
- **Indexer.cs** — logica di scansione del disco e scrittura/aggiornamento del DB
|
|
SQLite (`Indexer.ScanAsync`). Cammina tutte le cartelle di primo livello trovate sotto
|
|
la radice (scoperte dinamicamente con `Directory.GetDirectories`, non un elenco fisso)
|
|
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).
|
|
- **UiStile.cs** — stile bottoni condiviso da `Form1` e dai dialog secondari
|
|
(`Primario`/`Secondario`, entrambi `AutoSize` col padding invece di una `Size` fissa
|
|
in pixel, per evitare che il testo vada a capo e si tagli quando non ci sta) e
|
|
`Arrotonda` per gli angoli dei bottoni "Avanti"/"Indietro" del wizard.
|
|
- **app.ico** — icona dell'app (logo Cevolani + pezzo + STEP, sfondo trasparente),
|
|
referenziata da `<ApplicationIcon>` in `PrepStep.csproj` e riletta a runtime in
|
|
`Form1.BuildUi()` via `Icon.ExtractAssociatedIcon(Application.ExecutablePath)` per
|
|
la titlebar (stessa icona dell'exe, nessun file duplicato nell'output).
|
|
|
|
### 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`).
|
|
|
|
## Script standalone (`scripts/`)
|
|
|
|
`scripts/` contiene C# file-based apps (.NET 10, `dotnet run scripts/Nome.cs -- arg1 arg2`),
|
|
senza csproj proprio — dipendenze NuGet extra si aggiungono con `#:package Nome@versione` in
|
|
cima al file. `ExtractCreoStrings.cs` e `BomViaDb.cs` risolvono ricorsivamente l'albero
|
|
componenti di un `.asm` contro `cad_index.db` da riga di comando (stessa logica di
|
|
`Form1.RisolviAlberoComponenti`/`AssiemeCompleto`): entrambi referenziano
|
|
`PrepStep/PrepStep.csproj` via `#:project` (più `#:property TargetFramework=net10.0-windows`,
|
|
richiesto perché il progetto principale è WinForms) invece di duplicare l'euristica di
|
|
estrazione/placement, che vive solo in `PrepStep/AssemblyComponentScanner.cs` — un'unica
|
|
fonte di verità condivisa da GUI e script, vedi `docs/formato-asm.md`. Le due varianti restano
|
|
distinte solo nel candidato passato a `EstraiCodiciReferenziati`: `ExtractCreoStrings.cs` non
|
|
passa `codiciNoti` (riconosce solo i codici numerici Pro-E, dalla forma, senza bisogno del
|
|
DB); `BomViaDb.cs` lo passa, per intercettare anche i nomi alfabetici delle parti commerciali
|
|
validati contro l'indice. `Analyze.cs` dumpa il contesto testo/hex attorno a un pattern in un
|
|
file binario, per investigare a mano nuovi falsi positivi prima di toccare la regex; `Query.cs`
|
|
esegue una query SQL ad-hoc contro `cad_index.db` da riga di comando.
|
|
|
|
Il formato binario `.asm`, l'euristica di estrazione codici e i falsi positivi noti (ID vista
|
|
`ModelView#`, self-reference, riferimenti fantasma a codici superati/rinominati — sintatticamente
|
|
identici a un componente vero, non filtrabili in modo affidabile) sono documentati in
|
|
`docs/formato-asm.md`.
|