From db4c4444733aaf8fdfd54eb878bef425bc4bb945 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Tue, 22 Sep 2026 14:12:27 +0200 Subject: [PATCH] Documenta il processo delle 5 fasi in architettura.md Il doc elencava i file sorgente e una tabella delle fasi, ma non il processo: cosa entra e cosa esce da ogni fase, e perche' la 4 e' piu' complicata di "leggi i componenti e copiali". Aggiunta una sezione che lo descrive come pipeline, con in chiaro le tre liste che la fase 4 raccoglie da ogni .asm - distinta, soppressi, riferimenti esterni - e per ognuna se si ricorre dentro e se un codice mancante va segnalato. Allineati alla stessa modifica i punti rimasti indietro: la riga della fase 4 nella tabella, la sezione sulla lettura dei .asm (che citava solo i soppressi), e l'elenco dei file di test, fermo a quattro su sette. --- docs/architettura.md | 93 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/docs/architettura.md b/docs/architettura.md index fb63bed..4e04b41 100644 --- a/docs/architettura.md +++ b/docs/architettura.md @@ -4,7 +4,8 @@ Panoramica di tutti i file sorgente e di come collaborano. `PrepStep` è il nome tecnico del progetto (cartella, namespace, csproj, eseguibile `PrepStep.exe`); **Cevolani StepPrep** è il nome mostrato all'utente finale (titolo finestra, icona, versione — vedi ``/`` in `PrepStep.csproj`). Per il "come si usa" vedi il `README.md` in root; per il -formato binario `.asm` vedi `docs/formato-asm.md`; per la parallelizzazione della +formato binario `.asm` vedi `docs/formato-asm.md` (euristica testuale) e +`docs/formato-asm-record.md` (parser esatto dei record); per la parallelizzazione della copia in `raw/` vedi `docs/copia-raw-parallela.md`. ## Vista d'insieme @@ -24,6 +25,58 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati drag&drop .asm su Creo → Distributed Batch → step/ (esportazione manuale) ``` +## Il processo, dall'inizio alla fine + +Le 5 fasi sono una pipeline: ognuna consuma quello che ha prodotto la precedente, e il +bottone "Avanti" si sblocca solo quando il risultato c'è (`AvantiConsentito`). Sotto, cosa +entra e cosa esce da ciascuna — il dettaglio dei metodi è nella tabella della sezione +successiva. + +**1. Indice della share → `cad_index.db`.** `Indexer.ScanAsync` cammina tutte le cartelle di +primo livello sotto `X:\`, riconosce i nomi Pro-E `..` e fa un upsert +incrementale (confronto su percorso+dimensione+data), così i giri successivi costano solo il +delta. Qui si sceglie anche la **cartella di lavoro**, che da qui in poi ospita tutto il resto. + +**2. Distinta del gestionale → CSV.** `DistintaBaseImporter.ConvertiInCsv` riduce l'export a +due colonne `componente;descrizione`. Se il nome del file segue la convenzione +`DBP__` aggiunge l'assieme generale come riga in più: da quel momento è un +componente come tutti gli altri, nessun caso speciale a valle. + +**3. Componenti del CSV → `raw/`.** Per ogni codice del CSV `TrovaPercorsiCad` cerca +nell'indice l'ultima versione (vista `files_ultima_versione`) e `CopiaFileTrovati` la copia in +`raw/` in parallelo. Finisce qui il livello "distinta": in `raw/` ci sono i componenti +elencati dal gestionale, non ancora quello che serve ad aprirli. + +**4. Chiusura ricorsiva dell'albero → `raw/` completa.** È il cuore del programma, ed è +l'unica fase che deve ragionare come Creo invece che come il gestionale. +`RisolviAlberoComponenti` tiene una coda di `.asm` da leggere, partendo da quelli già in +`raw/`, e per ognuno raccoglie **tre liste diverse**, che non vanno confuse (vedi +`docs/formato-asm-record.md` §7.3 e §7.5): + +| Lista | Da dove | Ricorsione | Se non è nell'indice | +|---|---|---|---| +| Componenti della distinta | sezione `members` (`EstraiCodiciReferenziati`) | sì | va nei "non trovati" | +| Componenti **soppressi** | stringhe di piazzamento (`EstraiCodiciSoppressi`) | no — Creo non carica i figli di un soppresso | ignorato: non è un componente, segnalarlo sarebbe un falso allarme | +| **Riferimenti esterni** | tabella dei modelli citati (`EstraiCodiciRiferimentiEsterni`) | sì — Creo carica il modello citato con tutto il suo albero | ignorato, stesso motivo | + +Ogni codice trovato viene copiato in `raw/` scegliendo **quale** copia con `ScegliPerCartella` +(§7.4: lo stesso codice esiste in più cartelle della share nel 13% dei casi, e vince quella +nella stessa cartella dell'assieme che lo referenzia); se è un `.asm` torna in coda e il giro +ricomincia, finché restano solo foglie. I rami raggiunti per riferimento esterno viaggiano con +un flag `Esterno` che li tiene fuori dall'elenco dei "non trovati": quell'elenco continua a +parlare solo della distinta, che è quello che l'utente si aspetta di leggerci. + +Il motivo per cui questa fase è più complicata di come sembra: **la lista dei componenti e la +lista dei file necessari al caricamento non coincidono**, e la seconda è più lunga. Quando si +sbaglia, Creo Distributed Batch non dice quale file manca — dice solo `[-4] Dati di input non +completi`. + +**5. Verifica e consegna a Creo.** `AggiornaAnteprimaAsm` mostra i `.asm` della distinta già +in `raw/` come icone trascinabili; "Verifica completezza assiemi" ricontrolla ricorsivamente +**sull'indice** (non su `raw/`) che ogni sotto-componente esista. L'esportazione STEP vera è +manuale e fuori dall'app: si trascinano i `.asm` su Creo Distributed Batch, che scrive in +`step/`. + ## Entry point - **Program.cs** — `Main()` standard WinForms: `Application.Run(new Form1())`. Nessuna logica. @@ -44,7 +97,7 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati | 1 | Database | "Aggiorna indice" → `Indexer.ScanAsync`; "Cambia cartella..." → `ScegliCartellaLavoro` | Crea/aggiorna `cad_index.db` scansionando la share; sceglie/mostra la cartella di lavoro | | 2 | Importa Distinta Base | selezione file → `ImportaDistinta` → `DistintaBaseImporter.ConvertiInCsv` | Xls/Xml gestionale → CSV componente;descrizione, scritto nella cartella di lavoro | | 3 | Crea cartella raw | "Crea cartella raw" → `CreaCartellaRaw` | `TrovaPercorsiCad` + `CopiaFileTrovati` (parallela) → `raw/` dentro la cartella di lavoro | - | 4 | Trova componenti referenziati | "Trova componenti referenziati" → `TrovaPrtReferenziati` → `RisolviAlberoComponenti` | Legge i `.asm` in `raw/`, risolve ricorsivamente sotto-assiemi/parti nell'indice e li copia anch'essi in `raw/`, insieme ai componenti soppressi che servono a Creo per aprire l'assieme | + | 4 | Trova componenti referenziati | "Trova componenti referenziati" → `TrovaPrtReferenziati` → `RisolviAlberoComponenti` | Legge i `.asm` in `raw/`, risolve ricorsivamente sotto-assiemi/parti nell'indice e li copia anch'essi in `raw/`, insieme ai componenti soppressi e ai modelli citati per riferimento esterno che servono a Creo per aprire l'assieme | | 5 | Verifica completezza | "Verifica completezza assiemi" → `VerificaCompletezzaAssiemi` | Completezza ricorsiva sui percorsi in indice. All'ingresso nella fase, `AggiornaAnteprimaAsm` mostra le icone trascinabili dei `.asm` della distinta già in `raw/`, da trascinare su Creo per l'esportazione STEP (Distributed Batch) | Stato condiviso tra le fasi (campi privati di `Form1`): `_dbPath`, `_cartellaLavoro`, @@ -90,8 +143,12 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati - **AsmRecordReader.cs** — legge esattamente la sezione `members` del binario `.asm` (id/tipo/ nome dei componenti diretti, con risoluzione del nome istanza di family table dal parametro `ConfigName`): nessuna euristica, struttura a record. Lancia `InvalidDataException` se il - file non ha una sezione `members` o se il conteggio dichiarato non torna. Dettagli in - `docs/formato-asm-record.md`. Condivisa con `scripts/CreoBom.cs` via `#:project`. + file non ha una sezione `members` o se il conteggio dichiarato non torna. Espone anche le + due liste "non di distinta": `EstraiCodiciSoppressi` (che passa da `members` per sapere + quali codici sono già noti, quindi può lanciare la stessa eccezione — `Form1.CodiciSoppressi` + la intercetta e restituisce vuoto) e `EstraiCodiciRiferimentiEsterni` (scansione a sé, non + lancia). Dettagli in `docs/formato-asm-record.md`. Condivisa con `scripts/CreoBom.cs` via + `#:project`. - **AssemblyComponentScanner.cs** — estrae euristicamente i codici componente referenziati contando le occorrenze di stringhe candidate nel testo binario. Due strategie: codici numerici Pro-E riconosciuti da soli via regex (come nei nomi file), e nomi alfabetici di @@ -101,10 +158,19 @@ Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati non copre, e la fonte di verità per `ExtractCreoStrings.cs`/`BomViaDb.cs`. Quella lista è **la distinta**, e non coincide con i file che servono a Creo per aprire -l'assieme: i componenti **soppressi** ne restano fuori (non sono nella BOM) ma il loro file -serve lo stesso, altrimenti il caricamento fallisce. `AsmRecordReader.EstraiCodiciSoppressi` -li restituisce a parte, e la fase 4 li copia in `raw/` senza contarli fra i "non trovati" — -vedi `docs/formato-asm-record.md` §7.3. +l'assieme: ne restano fuori due categorie, che il loro file serve comunque, altrimenti il +caricamento fallisce (`docs/formato-asm-record.md` §7.3). `AsmRecordReader` le restituisce a +parte, e la fase 4 le copia in `raw/` senza contarle fra i "non trovati": + +- `EstraiCodiciSoppressi` — i componenti **soppressi**: spariti da `members`, ancora citati + dalla feature che li posiziona. Non si ricorre dentro (Creo non carica i figli di un + componente soppresso). +- `EstraiCodiciRiferimentiEsterni` — i modelli legati da **riferimento esterno** (assembly + feature, datum copiati), elencati in una tabella a parte del binario (§7.5). Qui si ricorre + dentro, perché Creo carica il modello citato con tutto il suo albero. + +La fase 5 (`VerificaCompletezzaAssiemi`) usa invece **solo** i membri: è una domanda sulla +distinta, e contare le altre due liste produrrebbe falsi "componenti mancanti". ## Quale copia di un componente si copia in `raw/` @@ -198,6 +264,11 @@ dipendenze extra con `#:package Nome@versione` in testa al file): - **PrepStep.Tests/** (xUnit) — riferimento al progetto principale via `ProjectReference` + `InternalsVisibleTo` (in `PrepStep.csproj`), così i test chiamano direttamente `Indexer.ParseFilename` e `AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli - come API pubblica. File: `IndexerParseFilenameTests.cs`, - `AssemblyComponentScannerTests.cs`, `DistintaBaseImporterTests.cs`, - `CaseInsensitiveLookupIntegrationTests.cs`. + come API pubblica. File: `IndexerParseFilenameTests.cs`, `IndexerScanTests.cs`, + `AssemblyComponentScannerTests.cs`, `AsmRecordReaderTests.cs`, + `DistintaBaseImporterTests.cs`, `CaseInsensitiveLookupIntegrationTests.cs`, + `PipelineEndToEndTests.cs`. + + `AsmRecordReaderTests.cs` costruisce i `.asm` byte per byte con dei piccoli helper + (`Membro`, `ConfigName`, `ObjName`, `Riferimenti`): ogni caso strano trovato sulla share + diventa un test minimale invece di un file binario da versionare.