Table of Contents

FLOW-ENE-001 — Inserimento di una lettura contatore (Energy Center)

Flusso end-to-end di scrittura di una lettura energetica (letturaa manuale di un contatore) del modulo Energy / Energia. Path pilota: ReadingDetail.ascx (creazione interattiva di una lettura da parte di un operatore Energy Center). Backend Oracle INFOCAD_TEST38 (connessione MainConnection), accesso via stored procedure ODP.NET (Oracle.DataAccess, wrapper DataLayer.ExecuteNonQueryStoredProcedure, nessun ORM). La Business Logic è ospitata in un Windows Service raggiunto dai Controller via .NET Remoting (Activator.GetObject).

  • Flow ID: FLOW-ENE-001
  • Repository: InfocadWeb (ASP.NET Web Forms, C# — EnergyCenterWeb) + InfocadServer (Energy Controllers/BL/DAL)
  • Confidence complessiva: VERIFIED (catena UI → codebehind → Controller → BL → DAL → nome stored procedure) · VERIFIED (mappa stored procedure → tabelle, letta dal sorgente USER_SOURCE e da USER_DEPENDENCIES)

Obiettivo di business

Consentire a un operatore Energy Center (o a un lettore mobile via WCF) di registrare la lettura di un contatore (NRG_METERS) a una certa data, con eventuale immagine di prova della lettura. Al termine la lettura è persistita in NRG_DATACOLLECTOR con il consumo (MEASUREAMOUNT) calcolato rispetto all'ultima lettura precedente; se la lettura è manuale (COLLECTSOURCE = 'M') viene salvata anche l'immagine in NRG_READINGS_IMG. La procedura gestisce inoltre la ripartizione (spalmatura) del consumo sui giorni intercorsi dall'ultima lettura.

Attori

  • Operatore Energy Center (utente autenticato, grant 15020 per l'inserimento / 15010 per la modifica, oppure SuperAdmin) — path interattivo ReadingDetail.ascx.
  • Lettore mobile / integrazione — WCF EnergyReaderWCF.svc operazione SetMeterMonoRead / SetMeterMultiRead (stesso entry point BL DataCollectorController.InsertDataCollect).
  • Windows Service Energy BL (server-side) — host remoto della Business Logic EnergyDataCollector_BL, raggiunto via .NET Remoting.
  • Oracle INFOCAD_TEST38 (hub del modulo Energy: tabelle NRG_*, anagrafiche EDIFICI/COMPRENSORI_).

Trigger

Click sul pulsante di salvataggio del dettaglio lettura: evento btnSave_Click in ReadingDetail.ascx.cs:319 (postback ASP.NET Web Forms), quando la finestra DetailPage.aspx è aperta in modalità Crea (op=1).

Frontend entry point

  • Shell modulo: EnergyCenterWeb/Default.aspx (modello shell-page + UserControl caricati dinamicamente); il menu di sinistra (LeftContentMenu.ascx) attiva Readings.ascx.
  • Lista letture: Readings.ascx → griglia Grids/ReadingsGrid.ascx (usa DataCollectorController readingCTRL); il toolbar espone InsertMeterRead / InsertAccountRead (ReadingsGrid.ascx.cs:273-274).
  • Finestra di dettaglio: la griglia apre WindowPages/DetailPage.aspx (JS OpenItemDetail(...), ReadingsGrid.ascx.cs:237-239) con detail=readings e op=1.
  • Control di dettaglio: DetailPage.aspx.cs:184-192 carica UserControls/Details/ReadingDetail.ascx (Descor.EnergyCenterWeb.UserControls.Details.ReadingDetail), impostando OperationType = Crea.
  • Gate di accesso: DetailPage : Cassandra.InfocadSecurity.CassandraPage (autenticazione shell Cassandra); visibilità pulsante Salva vincolata a HasUserGrant("15020") / SuperAdmin (ReadingDetail.ascx.cs:121-124).

Sequenza principale (main sequence)

  1. L'operatore apre la lista letture (Readings.ascx) filtrata per edificio/contatore e sceglie "Aggiungi lettura contatore" → apertura DetailPage.aspx?detail=readings&op=1.
  2. DetailPage.Page_Load (:130) legge i query-string, imposta OperationType=Crea e carica ReadingDetail.ascx (:186-191).
  3. ReadingDetail prepara la UI (selettore contatore, data, valore, immagine); mostra il pulsante Salva solo con grant 15020/SuperAdmin (:121-124).
  4. L'operatore compila data (rdpCollectDate), valore (txtMeasureRead), eventuale immagine e conferma → btnSave_Click (:319) → Salva() (:297).
  5. In modalità Crea, Salva() chiama InsertDataCollector() (:310).
  6. InsertDataCollector (:250): customerDataCollectorValueChanged() (:282) travasa i valori del form su CurrentReading e forza CollectSourceString = "M" (lettura manuale, :293); checkCollectDate() (:255) e la guardia su data/valore (:256) impediscono letture antecedenti o inferiori all'ultima.
  7. Se le validazioni passano → int insOK = m_datacollectorCtrl.InsertDataCollect(CurrentReading) (:263).
  8. Controller DataCollectorController.InsertDataCollect (DataCollectorController.cs:68) inoltra alla BL remota ((IEnergyDataCollector_BL)this.DAO).InsertDataCollect(data); il DAO è un proxy Remoting creato in DaoActivate(Ctrl_DataCollector) (:15) → DAOFactory.CreateDAOActivator.GetObject(typeof(IEnergyDataCollector_BL), ... Service_EnergyDataCollector) (DAOFactory.cs:25-26).
  9. BL EnergyDataCollector_BL.InsertDataCollect (EnergyDataCollector_BL.cs:68) → EnergyDAL.EnergyDALFactory.GetEnergyDataCollectorDAL().InsertDataCollect(data) (:72); la factory istanzia via reflection il DAL Energy.EnergyDAL.<DALNamespace>.EnergyDataCollector_DAL (OracleODP) (EnergyDALFactory.cs:45-47).
  10. DAL EnergyDataCollector_DAL.InsertDataCollect (EnergyDataCollector_DAL.cs:385) apre un DataLayer(ConnectionName="MainConnection"), popola ~24 OracleParameter (incl. BLOB immagini e PIDENTITY OUT), quindi dl.ExecuteNonQueryStoredProcedure("NRG_INSERTDATACOLLECTOR") (:455) e legge l'id generato da PIDENTITY (:459).
  11. Oracle NRG_INSERTDATACOLLECTOR calcola il consumo dall'ultima lettura, decide se spalmare il valore sui giorni intercorsi e delega gli INSERT a NRG_ADDDATACOLLECTOR.
  12. NRG_ADDDATACOLLECTOR esegue INSERT INTO NRG_DATACOLLECTOR (... ) VALUES (...) RETURNING ID_DATACOLLECTOR INTO PIDENTITY; il trigger BEFORE INSERT valorizza la PK da SEQ_NRG_DATACOLLECTOR.
  13. Se PCOLLECTSOURCE = 'M' (caso della UI manuale) e id > 0 → NRG_ADDREADINGIMAGES scrive l'immagine in NRG_READINGS_IMG.
  14. Ritorno dell'id fino alla UI; ReadingDetail mostra insOKLabel/insUpdKOLabel (:266-269) e chiude la finestra (CloseWindow(), :324) con refresh della griglia chiamante.

API / service

  • Path interattivo: nessun servizio SOAP/WCF — postback ASP.NET Web Forms diretto; il ponte Web→Server è .NET Remoting (Controller EnergyControllers → BL EnergyBL ospitata nel Windows Service).
  • Path programmatico equivalente (stesso BL): WCF EnergyCenterWeb/WebService/EnergyReaderWCF.svc, operazioni SetMeterMonoRead (IEnergyReaderWCF.cs:26) e SetMeterMultiRead (:29), che costruiscono un DataCollector con CollectSourceEnum.Manuale e chiamano DataCollectorController.InsertDataCollect (EnergyReaderWCF.svc.cs:156,164).

Backend

  • Web codebehind: Descor.EnergyCenterWeb.UserControls.Details.ReadingDetail (InfocadWeb/WebMachine/CASSANDRA/EnergyCenterWeb/UserControls/Details/ReadingDetail.ascx.cs).
  • Controller: Descor.Energy.EnergyControllers.DataCollectorController (InfocadServer/EnergyControllers/DataCollectorController.cs) — proxy verso la BL remota.
  • BL: Descor.Energy.EnergyBL.EnergyDataCollector_BL (InfocadServer/EnergyBL/EnergyDataCollector_BL.cs), ospitata nel Windows Service Energy.
  • DAL: Descor.Energy.EnergyDAL.OracleODP.EnergyDataCollector_DAL (InfocadServer/EnergyDAL/OracleODP/EnergyDataCollector_DAL.cs, Oracle.DataAccess).
  • Pattern DAL: new DataLayer(Properties.Settings.Default.ConnectionName) (default MainConnectionINFOCAD_TEST38) → dl.Parameters.Add(OracleParameter...)dl.ExecuteNonQueryStoredProcedure("PROC"); identity via parametro OUT PIDENTITY letto con ((OracleDecimal)p.Value).ToInt32().

Query / stored procedure

Passo Stored procedure / oggetto (Oracle, INFOCAD_TEST38) Chiamata da
Insert lettura (entry point) NRG_INSERTDATACOLLECTOR (OUT PIDENTITY) EnergyDataCollector_DAL.cs:455
Insert riga effettiva NRG_ADDDATACOLLECTOR (INSERT NRG_DATACOLLECTOR ... RETURNING ID_DATACOLLECTOR) chiamata interna da NRG_INSERTDATACOLLECTOR (sorgente USER_SOURCE)
Salvataggio immagine lettura (se COLLECTSOURCE='M') NRG_ADDREADINGIMAGES (INSERT NRG_READINGS_IMG) chiamata interna da NRG_ADDDATACOLLECTOR (sorgente USER_SOURCE)
Assegnazione PK trigger NRG_DATACOLLECTOR (BEFORE INSERT) → SEQ_NRG_DATACOLLECTOR.NEXTVAL trigger DB
Variante import massivo (non questo path) NRG_ADDMEASUREMENTDATA (OUT PIDENTITY) EnergyDataCollector_DAL.cs:370
Variante update lettura NRG_UPDATEDATACOLLECTOR EnergyDataCollector_DAL.cs:309

Tabelle lette (read)

  • INFOCAD_TEST38.NRG_DATACOLLECTOR — MAX(MEASUREREAD)/MAX(COLLECTDATE)/COUNT delle letture precedenti per calcolo consumo e spalmatura (in NRG_INSERTDATACOLLECTOR).
  • INFOCAD_TEST38.NRG_METERS — join per stato contatore (ISACTIVE=1, ISCANCELLED=0) e BUILDINGCODE.
  • INFOCAD_TEST38.NRG_DICTIONARY — nomi dei campi Mq/Mc/Persone (ID_KEY='FIELDUNIT') in NRG_ADDDATACOLLECTOR.
  • INFOCAD_TEST38.EDIFICI / INFOCAD_TEST38.COMPRENSORI_ — valori area/cubatura/persone associati all'edificio del contatore (SELECT + EXECUTE IMMEDIATE dinamico in NRG_ADDDATACOLLECTOR).

(fonte: sorgente USER_SOURCE delle procedure + USER_DEPENDENCIES. Nota: NRG_ADDMEASUREMENTDATA dipende anche da EDIFICI_, GLOBAL_COSTCENTRE, GLOBAL_COSTCENTRE_ENTITIES, NRG_IMPORTSOURCE, funzioni NRG_GETIDMETER/NRG_GETIMPORTSOURCE — path di import, non quello interattivo qui documentato.)

Tabelle modificate (write)

  • INFOCAD_TEST38.NRG_DATACOLLECTOR (INSERT — tabella-radice della lettura; PK ID_DATACOLLECTOR da SEQ_NRG_DATACOLLECTOR via trigger). VERIFIED (statement INSERT ... RETURNING nel sorgente di NRG_ADDDATACOLLECTOR).
  • INFOCAD_TEST38.NRG_READINGS_IMG (INSERT — immagine/i della lettura, solo se COLLECTSOURCE='M'). VERIFIED (dep. INSERT di NRG_ADDREADINGIMAGES).
  • INFOCAD_TEST38.SEQ_NRG_DATACOLLECTOR (consumo sequence via trigger BEFORE INSERT). VERIFIED (sorgente trigger).

Validazione

  • Lato UI/codebehind (ReadingDetail.ascx.cs):
    • checkCollectDate() (:255) e guardia hdnMaxDate / hdnMeasureRead (:256): blocca inserimenti con data ≤ ultima lettura o valore < ultima lettura → messaggio invalidDateOrMeasureMsg, nessuna scrittura.
    • CollectSourceString forzato a "M" (:293).
    • Visibilità pulsante Salva: grant 15020 (insert) / 15010 (update) o SuperAdmin (:115,124).
  • Lato DB (NRG_INSERTDATACOLLECTOR): calcolo PAMOUNT (consumo) come PMEASUREREAD - PLASTMEASUREREAD; se esistono letture precedenti (PEXIST>0) e più giorni intercorsi (PNUMGIORNI≥1) → spalmatura in più INSERT giornalieri; NVL/ROUND sui valori; PK garantita dal trigger.

Side effects

  • Creazione di una o più righe NRG_DATACOLLECTOR: una sola se non c'è lettura precedente o i giorni intercorsi < 1; altrimenti una riga per giorno intercorso (FOR I IN 1..PNUMGIORNI+1) con consumo ripartito, più la riga finale con la lettura reale.
  • Salvataggio immagine lettura in NRG_READINGS_IMG (path manuale 'M').
  • Consumo di SEQ_NRG_DATACOLLECTOR.
  • Aggiornamento UI: messaggio esito e chiusura finestra con refresh della griglia letture chiamante.

Percorsi alternativi / di errore

  • Errori di validazione UIresultMessage(...) con invalidDateOrMeasureMsg / invalidDateMsg, nessuna chiamata al Controller.
  • Modifica lettura (OperationType=Modifica) → UpdateDataCollector() (:217) → DataCollectorController.UpdateDataCollectNRG_UPDATEDATACOLLECTOR.
  • Eccezione nel DAL/DBcatch con Descor.Infrastructure.LogManager.ExceptionLogger.LogException(ex) a ogni livello (DAL :380, BL :74) e throw risalente; la UI rilancia (throw ex, :275).
  • Path lettura da contatore / immagini multiple → varianti ReadingCounterDetail.ascx (:313) e ReadingCounterImgsDetail.ascx (:543) che chiamano lo stesso InsertDataCollect.
  • Path mobile/WCFEnergyReaderWCF.SetMeterMonoRead: se la data coincide con l'ultima lettura chiama UpdateDataCollect, altrimenti InsertDataCollect (EnergyReaderWCF.svc.cs:154-164).
  • Path import massivo (diverso) → NRG_ADDMEASUREMENTDATA / NRG_INSERTDATACOLLECTOR da flussi di import file (non oggetto di questo flow).

Diagramma di sequenza

sequenceDiagram
    actor Op as Operatore Energy
    participant UI as Readings/DetailPage (EnergyCenterWeb)
    participant CB as ReadingDetail.ascx.cs (btnSave_Click)
    participant CTRL as DataCollectorController
    participant BL as EnergyDataCollector_BL (Windows Service, Remoting)
    participant DAL as EnergyDataCollector_DAL (OracleODP)
    participant DB as Oracle INFOCAD_TEST38

    Op->>UI: Aggiungi lettura (DetailPage op=Crea)
    UI->>CB: btnSave_Click -> Salva() -> InsertDataCollector()
    CB->>CB: customerDataCollectorValueChanged (CollectSource='M') + checkCollectDate
    CB->>CTRL: InsertDataCollect(CurrentReading)
    CTRL->>BL: (IEnergyDataCollector_BL) DAO.InsertDataCollect  [.NET Remoting]
    BL->>DAL: EnergyDALFactory...InsertDataCollect(data)
    DAL->>DB: ExecuteNonQueryStoredProcedure("NRG_INSERTDATACOLLECTOR") (OUT PIDENTITY)
    DB->>DB: NRG_INSERTDATACOLLECTOR: calcola consumo / spalmatura
    DB->>DB: NRG_ADDDATACOLLECTOR: INSERT NRG_DATACOLLECTOR RETURNING ID (trigger -> SEQ)
    DB->>DB: se 'M' -> NRG_ADDREADINGIMAGES: INSERT NRG_READINGS_IMG
    DB-->>DAL: PIDENTITY (id lettura)
    DAL-->>CB: id
    CB-->>Op: messaggio esito + CloseWindow + refresh griglia

Matrice di tracciabilità

Layer Artefatto Evidenza (file:riga)
UI (lista) Readings.ascx / ReadingsGrid.ascx (DataCollectorController readingCTRL) UserControls/Grids/ReadingsGrid.ascx.cs:17,273-274
UI (apertura dettaglio) DetailPage.aspx carica ReadingDetail.ascx (op=Crea) WindowPages/DetailPage.aspx.cs:159,184-192
Code-behind (trigger) btnSave_ClickSalvaInsertDataCollector ReadingDetail.ascx.cs:319,297,310,250
Code-behind (validazione+source) customerDataCollectorValueChanged (CollectSource='M') / checkCollectDate ReadingDetail.ascx.cs:282,293,255-256
Code-behind (chiamata BL) m_datacollectorCtrl.InsertDataCollect(CurrentReading) ReadingDetail.ascx.cs:263
Controller DataCollectorController.InsertDataCollect (proxy Remoting) EnergyControllers/DataCollectorController.cs:68
Controller (attivazione DAO) DaoActivate(Ctrl_DataCollector)Activator.GetObject(..Service_EnergyDataCollector) Ctrl_Base.cs:24, DAOFactory.cs:25-26
BL EnergyDataCollector_BL.InsertDataCollectEnergyDALFactory EnergyBL/EnergyDataCollector_BL.cs:68,72
DAL factory GetEnergyDataCollectorDAL (reflection su EnergyDAL.<ns>.EnergyDataCollector_DAL) EnergyDAL/EnergyDALFactory.cs:45-47
DAL InsertDataCollectExecuteNonQueryStoredProcedure("NRG_INSERTDATACOLLECTOR") EnergyDAL/OracleODP/EnergyDataCollector_DAL.cs:385,455
DAL (connessione) ConnectionName default MainConnection EnergyDAL/Properties/Settings.Designer.cs:28
DB (proc) NRG_INSERTDATACOLLECTOR (consumo/spalmatura) USER_SOURCE INFOCAD_TEST38
DB (proc) NRG_ADDDATACOLLECTORINSERT NRG_DATACOLLECTOR RETURNING ID_DATACOLLECTOR USER_SOURCE INFOCAD_TEST38
DB (proc) NRG_ADDREADINGIMAGESINSERT NRG_READINGS_IMG USER_SOURCE + USER_DEPENDENCIES
DB (trigger) NRG_DATACOLLECTOR BEFORE INSERT → SEQ_NRG_DATACOLLECTOR USER_TRIGGERS / USER_SOURCE
Reverse (WCF) EnergyReaderWCF.SetMeterMonoReadInsertDataCollect WebService/EnergyReaderWCF.svc.cs:156,164, IEnergyReaderWCF.cs:26

Reverse trace (dallo stored procedure / metodo BL ai chiamanti)

grep "InsertDataCollect" conferma che lo stesso entry point (DataCollectorController.InsertDataCollectEnergyDataCollector_BL.InsertDataCollectEnergyDataCollector_DAL.InsertDataCollectNRG_INSERTDATACOLLECTOR) è condiviso da:

  • UI interattiva lettura: ReadingDetail.ascx.cs:263 (questo flow);
  • UI lettura da contatore/immagini: ReadingCounterDetail.ascx.cs:313, ReadingCounterImgsDetail.ascx.cs:543;
  • WCF mobile: EnergyReaderWCF.svc.cs:156,164 (SetMeterMonoRead) e altri overload multi-lettura.

La procedura NRG_INSERTDATACOLLECTOR è l'unico wrapper che orchestra NRG_ADDDATACOLLECTOR (INSERT effettivo); NRG_ADDDATACOLLECTOR (da USER_DEPENDENCIES) referenzia NRG_DATACOLLECTOR, NRG_METERS, NRG_DICTIONARY, EDIFICI/COMPRENSORI_ e NRG_ADDREADINGIMAGES. Forward e reverse concordano → NO CONFLICTING.

  • Calcolo consumo: MEASUREAMOUNT = lettura corrente − ultima lettura precedente attiva; se assente/0 → 0.
  • Spalmatura: se tra ultima lettura e data corrente intercorrono più giorni, il consumo viene ripartito con INSERT giornalieri (source 'm') più la riga finale con la lettura reale (source 'M').
  • Origine lettura: COLLECTSOURCE='M' (manuale) attiva il salvataggio immagine (NRG_ADDREADINGIMAGES); import automatici usano altri codici.
  • Grant: 15020 inserimento lettura, 15010 modifica (o SuperAdmin).
  • Anagrafica edificio: i campi area/cubatura/persone denormalizzati sulla lettura sono presi da EDIFICI/COMPRENSORI_ in base ai campi mappati in NRG_DICTIONARY (ID_KEY='FIELDUNIT').

Evidenza (file:line)

Catena codice (VERIFIED)

  • ReadingsGrid.ascx.cs:17 (DataCollectorController), :237-239 (apre DetailPage.aspx), :273-274 (toolbar InsertMeterRead/InsertAccountRead)
  • DetailPage.aspx.cs:130,159,184-192 (op=Crea → carica ReadingDetail.ascx)
  • ReadingDetail.ascx.cs:121-124 (grant), :250 (InsertDataCollector), :255-256 (validazione), :263 (InsertDataCollect), :282-293 (CollectSource='M'), :297,310 (Salva), :319 (btnSave_Click)
  • DataCollectorController.cs:15 (DaoActivate(Ctrl_DataCollector)), :68 (InsertDataCollect)
  • Ctrl_Base.cs:24 (DAOFactory.CreateDAO), DAOFactory.cs:25-26 (Remoting Service_EnergyDataCollector)
  • EnergyDataCollector_BL.cs:68,72 (BL → EnergyDALFactory)
  • EnergyDALFactory.cs:45-47 (reflection DAL OracleODP)
  • EnergyDataCollector_DAL.cs:385 (InsertDataCollect), :401-453 (parametri, PIDENTITY OUT :428), :455 (ExecuteNonQueryStoredProcedure("NRG_INSERTDATACOLLECTOR")), :459 (lettura id)
  • EnergyDAL/Properties/Settings.Designer.cs:28 (ConnectionName=MainConnection)
  • Reverse: ReadingCounterDetail.ascx.cs:313, ReadingCounterImgsDetail.ascx.cs:543, EnergyReaderWCF.svc.cs:156,164, IEnergyReaderWCF.cs:26

Database (VERIFIED — INFOCAD_TEST38, lookup read-only bounded)

  • USER_OBJECTS: NRG_INSERTDATACOLLECTOR (PROCEDURE, VALID), NRG_ADDMEASUREMENTDATA (PROCEDURE, VALID), NRG_DATACOLLECTOR (TABLE + TRIGGER), SEQ_NRG_DATACOLLECTOR (SEQUENCE)
  • USER_SOURCE NRG_INSERTDATACOLLECTOR: calcolo PAMOUNT, PEXIST, PNUMGIORNI, loop di spalmatura, chiamate a NRG_ADDDATACOLLECTOR
  • USER_SOURCE NRG_ADDDATACOLLECTOR: INSERT INTO NRG_DATACOLLECTOR (...) VALUES (...) RETURNING ID_DATACOLLECTOR INTO PIDENTITY; SELECT su NRG_DICTIONARY, EDIFICI/COMPRENSORI_, NRG_METERS; IF PCOLLECTSOURCE='M' → NRG_ADDREADINGIMAGES
  • USER_SOURCE trigger NRG_DATACOLLECTOR BEFORE INSERT: SEQ_NRG_DATACOLLECTOR.NEXTVAL
  • USER_DEPENDENCIES NRG_INSERTDATACOLLECTORNRG_ADDDATACOLLECTOR, NRG_DATACOLLECTOR, NRG_METERS
  • USER_DEPENDENCIES NRG_ADDREADINGIMAGESNRG_READINGS_IMG (TABLE)

Confidence

  • VERIFIED: catena UI → code-behind → Controller → BL → DAL → nome stored procedure (letta sul sorgente C#).
  • VERIFIED: mappa stored procedure → tabelle scritte/lette (sorgente PL/SQL da USER_SOURCE + USER_DEPENDENCIES su INFOCAD_TEST38).
  • INFERRED: mapping IIS/virtual directory di EnergyCenterWeb sotto la shell Cassandra (runtime, non ispezionato).

Open questions

  • Valore effettivo di DALNamespace in configurazione (atteso OracleODP) e assembly BL registrato per il canale Remoting Service_EnergyDataCollector.
  • Struttura di NRG_READINGS_IMG e numero di righe scritte per lettura multi-immagine (A1/A2/A3).
  • Comportamento della spalmatura per contatori con ISACTIVE=0/ISCANCELLED=1 (esclusi dal calcolo di PLASTMEASUREREAD).
  • NRG_ADDMEASUREMENTDATA (path import) tocca anche GLOBAL_COSTCENTRE* — mapping del flusso di import massivo non documentato qui.
  • Comportamento in configurazioni PROD (visto solo TEST38).