Files
prep-step/CLAUDE.md
T
davideandClaude Sonnet 5 5c9661eb12 Fix euristica BOM, unifica script/GUI su un'unica fonte, aggiungi test integrazione/E2E
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>
2026-09-21 13:43:54 +02:00

9.3 KiB

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/.

dotnet build -c Release
dotnet run -c Release

Pubblicazione come eseguibile standalone (single-file, self-contained, Windows x64):

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.