FLOW-CEN-001 — Salvataggio di una compilazione (rilevazione/scheda di censimento) — Census
Flusso end-to-end di creazione di una nuova compilazione di censimento (rilevazione compilata a partire da una scheda di valutazione/
Evalsheet) del modulo Census / CensusCenter. Path pilota: click su Salva nel controlloCompilationView.ascx(compilazione interattiva da parte di un operatore). Le risposte compilate vengono serializzate in un documento XML e persistite nella tabellaCENSUS_XMLdi OracleINFOCAD_TEST38tramite la stored procedureCNS_NEWCOMPILATION_XML(nessun ORM). Il layer BL è raggiunto via .NET Remoting, non in-process.
- Flow ID: FLOW-CEN-001
- Repository: InfocadWeb (ASP.NET Web Forms, C#, CensusCenterWeb) + InfocadServer (CensusControllers/CensusBL/CensusDAL, C#)
- Confidence complessiva: VERIFIED (catena UI → controller → BL → DAL → stored procedure → tabella, confermata su codice E su sorgente DB Oracle)
Obiettivo di business
Consentire a un operatore di censimento di compilare e salvare una rilevazione (scheda/Evalsheet)
associata a un'entità di patrimonio (Edificio, Piano, UI). L'operatore seleziona l'entità e la scheda
tramite il wizard CompilationCreate, risponde alle domande (CensusRadCheckAnswer/CensusRadOpenAnswer)
e al salvataggio le risposte vengono serializzate in XML e archiviate come nuova riga in CENSUS_XML,
con id utente, entità, data di compilazione ed eventuale nota. Al termine esiste una nuova compilazione
identificata dal proprio ID.
Attori
- Operatore Census (utente autenticato con grant
20200sul modulo compilazioni, oppure SuperAdmin) — path interattivoCompilationView.ascx. Il permesso di editing/salvataggio è dato daCanEdit = WS.SessionProfile.SuperAdmin || HasUserGrant(20200)(CompilationView.ascx.cs:132-138). - Layer BL remoto
Descor.Census.CensusBL.CompilationBL— ospitato come servizio .NET Remoting (Windows service), raggiunto dai controller lato web. - Oracle
INFOCAD_TEST38(hub anagrafico; proceduraCNS_NEWCOMPILATION_XML, tabellaCENSUS_XML).
Trigger
Click sul pulsante Salva (CommandName = "SAVE") della toolbar RadToolBar della scheda di
compilazione: evento RadTB_ButtonClick in CompilationView.ascx.cs:640, ramo if (cmdName.Equals("SAVE"))
(:643). Il pulsante è visibile solo se CanEdit è vero (CompilationView.ascx.cs:351).
Frontend entry point
- Shell / creazione: wizard
CensusCenterWeb/UserControls/Compilation/CompilationCreate.aspx(CompilationCreate.aspx.cs) — selezione a cascata Distretto → Edificio → Piano/UI + sceltaEvalsheet, poi caricamento dei controlli dinamici della scheda (CVUserControl.LoadDynamicControls(),:414). - Control scheda / salvataggio:
CensusCenterWeb/UserControls/Compilation/CompilationView.ascx(CompilationView.ascx.cs) — rendering domande/risposte e pulsante Salva. - Pagina host per visualizzazione/riapertura:
CompilationViewPage.aspx(CompilationViewPage.aspx.cs:21-24). - Gate di accesso:
CanEdit(grant20200o SuperAdmin) lato UI (CompilationView.ascx.cs:132-138).
Sequenza principale (main sequence)
- L'operatore compila la scheda (risposte check/aperte) e preme Salva.
CompilationView.ascx.cs→RadTB_ButtonClick(:640) intercetta il comandoSAVE(:643) e costruisce l'XML della compilazione conCreateCensusXML(pnlContentCenter)(:645, corpo:572-633): elemento radice<compilation>con<entity>,<user>e<answers>(una<answer>per ogniCensusRadCheckAnswer:600-614eCensusRadOpenAnswer:616-630, conlinkedToField/linkedToTable).- Istanzia il controller
CompilationController(:646) e discrimina nuovo vs esistente:isNew = IdCompilation < 1(:648). SeIdCompilation > 0→Update_XML(...)(:651); altrimenti →Save_XML((Guid)WS.SessionLogin.ProviderUserKey, IdEntity, Entity, xml, Description)(:653). CompilationController.Save_XML(CompilationController.vb/.cs:19) inoltra alla BL castandobase.DAOaICompilationBL:((ICompilationBL)base.DAO).Save_XML(...)(:21).base.DAOè ottenuto in costruttore viaDaoActivate(enControllers.Ctrl_Compilation)(CompilationController.cs:17→Ctrl_Base.DaoActivateCtrl_Base.cs:20-23), che chiamaDAOFactory.CreateDAO(DAOFactory.cs:26-27):Activator.GetObject(typeof(ICompilationBL), CHANNEL://SERVERADDRESS/Service_Compilation)— proxy .NET Remoting verso il servizio BL.
CompilationBL.Save_XML(CompilationBL.cs:13-16) delega al DAL:CensusDALFactory.GetCompilationDAL().Save_XML(provUserKey, idEntity, entity, xml, note).CompilationDAL.Save_XML(CompilationDAL.cs:22-53) prepara i parametri Oracle (PIDUSERRaw,PIDENTITYInt32,PENTITYVarchar2,PXMLXmlType,PNOTEVarchar2,PIDCOMPILATIONOUT Int32) e invocadl.ExecuteNonQueryStoredProcedure("CNS_NEWCOMPILATION_XML")(:42); ritornaPIDCOMPILATION(nuovo id) viaOracleDecimal.ToInt32()(:43), oppure-1in caso di esito falso.- Oracle
CNS_NEWCOMPILATION_XML(INFOCAD_TEST38): esegueINSERT INTO CENSUS_XML (IDENTITY, ENTITY, IDUSER, COMPILATION_DATE, XML, DESCRIPTION) VALUES (PIDENTITY, PENTITY, PIDUSER, SYSDATE, PXML, PNOTE) RETURNING ID INTO PIDCOMPILATION(src:9-12).COMPILATION_DATE = SYSDATE;ISCANCELLEDprende il DEFAULT0. - Il nuovo id ritorna fino alla UI:
IdCompilation = ctrl.Save_XML(...)(:653). - Post-salvataggio (
CompilationView.ascx.cs:655-666): seisNew && IdCompilation > 0la UI notifica il salvataggio;ValidateRequiredQuestiondistingue solo tra messaggio "salvato" e "salvato con avviso" (domande obbligatorie non compilate) — non blocca il salvataggio (:657-660). Viene impostato_windowarg = 'true'e_forceLoadData = true(:662-663).
API / service
- Path interattivo: postback ASP.NET Web Forms sulla scheda (nessun SOAP/WCF diretto verso il DB).
- Confine di processo: fra web e BL c'è .NET Remoting (
Activator.GetObject,DAOFactory.cs:26-27), non una chiamata in-process a DLL. Il contratto remoto èICompilationBL(CensusInterface/ICompilationBL.cs). - Metodi del contratto:
Save_XML(create),Update_XML(update),LoadCompilations_XML(read),Delete_XML(delete logico/fisico).
Backend
- UI/Code-behind:
CompilationCreate.aspx.cs(wizard),CompilationView.ascx.cs(scheda + Salva). - Controller:
Descor.Census.CensusControllers.CompilationController(CensusControllers/CompilationController.cs), baseCtrl_EntityBase/Ctrl_Basecon proxy remotoDAO. - BL (servizio remoto):
Descor.Census.CensusBL.CompilationBL(CensusBL/CompilationBL.cs). - DAL:
Descor.Census.CensusDAL.OracleODP.CompilationDAL(CensusDAL/OracleODP/CompilationDAL.cs), factoryCensusDALFactory.GetCompilationDAL(). - Pattern DAL:
using (DataLayer dl = new DataLayer(ConnectionName))→dl.Parameters.Add(OracleParameter...)→dl.ExecuteNonQueryStoredProcedure("CNS_NEWCOMPILATION_XML"); id di ritorno via parametro OUTPIDCOMPILATION.
Query / stored procedure
| Passo | Stored procedure (Oracle) | Chiamata da (DAL) |
|---|---|---|
| Insert compilazione (nuova) | INFOCAD_TEST38.CNS_NEWCOMPILATION_XML (OUT PIDCOMPILATION) |
CompilationDAL.cs:42 |
| Update compilazione (path alternativo) | INFOCAD_TEST38.CNS_UPDATECOMPILATION_XML |
CompilationDAL.cs:79 |
| Load compilazione per id (READ) | INFOCAD_TEST38.CNS_LOADCOMPILATION_XML |
CompilationDAL.cs:111 |
| Load compilazioni per entità (READ) | INFOCAD_TEST38.CNS_LOADCOMPILATION_BYENTITY |
CompilationDAL.cs:146 |
| Cancellazione (path alternativo) | INFOCAD_TEST38.CNS_DELETECOMPILATION_XML |
CompilationDAL.cs:169 |
Tabelle lette (read)
- Nel path di salvataggio (
CNS_NEWCOMPILATION_XML): nessuna lettura — la procedura esegue solo l'INSERT. - A monte, per popolare il wizard (
CompilationCreate.aspx.cs): letture indirette via controller Property (DistrictController,BuildingController,FloorController,UIController) eEvalsheetController(fuori dal confine di questo flusso di WRITE).
Tabelle modificate (write)
INFOCAD_TEST38.CENSUS_XML— INSERT di una riga (nuova compilazione): colonneIDENTITY,ENTITY,IDUSER,COMPILATION_DATE(=SYSDATE),XML(XMLTYPE),DESCRIPTION;IDgenerato viaRETURNING ID;ISCANCELLED= DEFAULT0.
Validazione
- Autorizzazione: pulsante Salva reso/abilitato solo se
CanEdit(SuperAdmin o grant20200) —CompilationView.ascx.cs:132-138,:351. - Validazione dati: nel wizard
validateData()richiede la selezione di un'entità (Edificio/Piano/UI) e di una schedaEvalsheetprima di procedere (CompilationCreate.aspx.cs:348-351,:388). - Domande obbligatorie:
ValidateRequiredQuestion(CompilationView.ascx.cs:554-562) è non bloccante al salvataggio: evidenzia in rosso le domande obbligatorie mancanti e determina solo il messaggio ("salvato" vs "salvato con avviso"), ma la INSERT avviene comunque. - Lato DB: nessuna validazione applicativa nella procedura; vincoli garantiti da NOT NULL sulle
colonne
IDENTITY,ENTITY,IDUSER,COMPILATION_DATEdiCENSUS_XML.
Side effects
- Creazione di una nuova riga in
CENSUS_XMLcon timestamp server (SYSDATE). - Ritorno del nuovo
IDalla UI (IdCompilation), usato per eventualiUpdate_XML/note successive. - Refresh della UI (
_forceLoadData = true,_windowarg = 'true') e notifica utente. - Logging eccezioni via
Descor.Infrastructure.LogManager.ExceptionLogger.LogExceptionin caso di errore DAL.
Percorsi alternativi / errore
- Update: se
IdCompilation > 0(compilazione già esistente) →Update_XML(:651) →CNS_UPDATECOMPILATION_XML, che aggiorna in modo condizionale i soli campi valorizzati (IDUSER/IDENTITY/ENTITY/XML+COMPILATION_DATE/DESCRIPTION) suID = PID(src:9-41). - Salvataggio sola nota:
ucNote_onDescriptionSaved(:699-726) chiamaUpdate_XMLconPIDUSER=NULL,PIDENTITY=0,PENTITY=NULL,PXML=NULL→ aggiorna soloDESCRIPTION. - Errore DAL:
ExecuteNonQueryStoredProcedurefalso ⇒Save_XMLritorna-1; eccezioni loggate e rilanciate (CompilationDAL.cs:48-52). Lato UI, esito negativo ⇒ messaggioErrorCensusSaved(:666). - Copia di una compilazione: il wizard supporta
IDCOMPILATIONin querystring per precaricare l'XML di una compilazione esistente (CompilationCreate.aspx.cs:417-423), che viene poi salvata come nuova.
Diagramma di sequenza
sequenceDiagram
actor Op as Operatore Census
participant UI as CompilationView.ascx.cs
participant Ctrl as CompilationController
participant Rem as .NET Remoting
participant BL as CompilationBL (servizio)
participant DAL as CompilationDAL
participant DB as Oracle CNS_NEWCOMPILATION_XML
participant T as CENSUS_XML
Op->>UI: Click "Salva" (RadTB_ButtonClick / SAVE)
UI->>UI: CreateCensusXML() -> XML risposte
UI->>Ctrl: Save_XML(provUserKey, idEntity, entity, xml, note)
Ctrl->>Rem: Activator.GetObject(ICompilationBL)
Rem->>BL: Save_XML(...)
BL->>DAL: CensusDALFactory.GetCompilationDAL().Save_XML(...)
DAL->>DB: ExecuteNonQueryStoredProcedure("CNS_NEWCOMPILATION_XML")
DB->>T: INSERT ... RETURNING ID INTO PIDCOMPILATION
T-->>DB: ID nuovo
DB-->>DAL: PIDCOMPILATION (OUT)
DAL-->>BL: int idCompilation
BL-->>Ctrl: idCompilation
Ctrl-->>UI: idCompilation
UI-->>Op: Notifica "Documento salvato" + refresh
Matrice di tracciabilità (file:riga)
| # | Componente | File | Riga | Tipo evidenza |
|---|---|---|---|---|
| 1 | Trigger Salva | InfocadWeb/.../CensusCenterWeb/UserControls/Compilation/CompilationView.ascx.cs |
640-668 | Codice |
| 2 | Gate CanEdit (grant 20200) | idem | 132-138, 351 | Codice |
| 3 | Serializzazione XML risposte | idem | 572-633 | Codice |
| 4 | Chiamata Save_XML (create) | idem | 653 | Codice |
| 5 | Controller Save_XML | InfocadServer/CensusControllers/CompilationController.cs |
19-22 | Codice |
| 6 | DaoActivate (Ctrl_Compilation) | InfocadServer/CensusControllers/CompilationController.cs |
17 | Codice |
| 7 | Proxy Remoting (Activator.GetObject) | InfocadServer/CensusControllers/private/DAOFactory.cs |
26-27 | Codice |
| 8 | BL Save_XML | InfocadServer/CensusBL/CompilationBL.cs |
13-16 | Codice |
| 9 | DAL Save_XML + parametri + SP | InfocadServer/CensusDAL/OracleODP/CompilationDAL.cs |
22-53 (SP call :42) | Codice |
| 10 | SP INSERT su CENSUS_XML | Oracle USER_SOURCE CNS_NEWCOMPILATION_XML |
9-12 | DB (sorgente) |
| 11 | Schema tabella CENSUS_XML | Oracle USER_TAB_COLUMNS |
— | DB (schema) |
| 12 | SP Update (alternativo) | Oracle USER_SOURCE CNS_UPDATECOMPILATION_XML |
9-41 | DB (sorgente) |
Evidenza (INLINE)
Codice applicativo (InfocadWeb + InfocadServer)
CompilationView.ascx.cs:640-666 (trigger + create/update + XML):
protected void RadTB_ButtonClick(object sender, RadToolBarEventArgs e)
{
String cmdName = ((RadToolBarButton)e.Item).CommandName;
if (cmdName.Equals("SAVE"))
{
String xml = CreateCensusXML(pnlContentCenter);
Census.CensusControllers.CompilationController ctrl = new Census.CensusControllers.CompilationController();
bool result = false;
bool isNew = IdCompilation < 1;
if (IdCompilation > 0)
result = ctrl.Update_XML(IdCompilation, (Guid)WS.SessionLogin.ProviderUserKey, IdEntity, Entity, xml, Description);
else
IdCompilation = ctrl.Save_XML((Guid)WS.SessionLogin.ProviderUserKey, IdEntity, Entity, xml, Description);
if (result || (isNew && IdCompilation > 0)) { ... NotifyMessage(...DocumentSaved...) ... }
else NotifyMessage(...ErrorCensusSaved...);
}
}
CompilationView.ascx.cs:132-138 (autorizzazione):
public bool CanEdit
{
get { return WS.SessionProfile.SuperAdmin || HasUserGrant(20200); }
}
CompilationController.cs:19-22 (controller → BL via proxy):
public int Save_XML(Guid provUserKey, int idEntity, string entity, string xml, string note)
{
return ((ICompilationBL)base.DAO).Save_XML(provUserKey, idEntity, entity, xml, note);
}
DAOFactory.cs:26-27 (confine .NET Remoting):
case enControllers.Ctrl_Compilation:
return (IBase_BL)Activator.GetObject(typeof(ICompilationBL), SettingsManager.CHANNEL + "://" + SettingsManager.SERVERADDRESS + "/" + Properties.CensusDictionary.Service_Compilation);
CompilationBL.cs:13-16 (BL → DAL):
public int Save_XML(Guid provUserKey, int idEntity, string entity, string xml, string note)
{
return Census.CensusDAL.CensusDALFactory.GetCompilationDAL().Save_XML(provUserKey, idEntity, entity, xml, note);
}
CompilationDAL.cs:22-46 (parametri + chiamata SP + id di ritorno):
public int Save_XML(Guid provUserKey, int idEntity, string entity, string xml, string note)
{
OracleParameter idUserParam = new OracleParameter("PIDUSER", OracleDbType.Raw, provUserKey, ParameterDirection.Input);
OracleParameter idEntityParam = new OracleParameter("PIDENTITY", OracleDbType.Int32, idEntity, ParameterDirection.Input);
OracleParameter entityParam = new OracleParameter("PENTITY", OracleDbType.Varchar2, entity, ParameterDirection.Input);
OracleParameter xmlParam = new OracleParameter("PXML", OracleDbType.XmlType, xml, ParameterDirection.Input);
OracleParameter noteParam = new OracleParameter("PNOTE", OracleDbType.Varchar2, note, ParameterDirection.Input);
OracleParameter outparam = new OracleParameter("PIDCOMPILATION", OracleDbType.Int32, ParameterDirection.Output);
using (DataLayer dl = new DataLayer(ConnectionName))
{
dl.Parameters.Add(idUserParam); ... dl.Parameters.Add(outparam);
if (dl.ExecuteNonQueryStoredProcedure("CNS_NEWCOMPILATION_XML"))
return ((Oracle.DataAccess.Types.OracleDecimal)outparam.Value).ToInt32();
else return -1;
}
}
Sorgente DB (Oracle INFOCAD_TEST38, via USER_SOURCE / USER_TAB_COLUMNS — read-only bounded)
CNS_NEWCOMPILATION_XML (USER_SOURCE, 13 righe):
PROCEDURE "CNS_NEWCOMPILATION_XML" (PIDUSER IN RAW,
PIDENTITY IN NUMBER,
PENTITY IN VARCHAR2,
PXML IN XMLTYPE,
PNOTE IN VARCHAR2,
PIDCOMPILATION OUT NUMBER)
AS
BEGIN
INSERT INTO CENSUS_XML (
IDENTITY, ENTITY, IDUSER, COMPILATION_DATE, XML, DESCRIPTION
)
VALUES (PIDENTITY, PENTITY, PIDUSER, SYSDATE, PXML, PNOTE) RETURNING ID INTO PIDCOMPILATION;
END;
CENSUS_XML (USER_TAB_COLUMNS):
ID NUMBER NOT NULL
IDENTITY NUMBER NOT NULL
ENTITY VARCHAR2 NOT NULL
IDUSER RAW NOT NULL
COMPILATION_DATE DATE NOT NULL
XML XMLTYPE NULL
DESCRIPTION VARCHAR2 NULL
ISCANCELLED NUMBER NOT NULL DEFAULT 0
CNS_UPDATECOMPILATION_XML (USER_SOURCE, path alternativo — update condizionale per campo):
PROCEDURE "CNS_UPDATECOMPILATION_XML" (PID IN NUMBER, PIDUSER IN RAW, PIDENTITY IN NUMBER,
PENTITY IN VARCHAR2, PXML IN XMLTYPE, PNOTE IN VARCHAR2)
AS BEGIN
IF PIDUSER IS NOT NULL THEN UPDATE CENSUS_XML SET IDUSER=PIDUSER WHERE ID=PID; END IF;
IF PIDENTITY > 0 THEN UPDATE CENSUS_XML SET IDENTITY=PIDENTITY WHERE ID=PID; END IF;
IF PENTITY IS NOT NULL THEN UPDATE CENSUS_XML SET ENTITY=PENTITY WHERE ID=PID; END IF;
IF PXML IS NOT NULL THEN UPDATE CENSUS_XML SET XML=PXML, COMPILATION_DATE=SYSDATE WHERE ID=PID; END IF;
IF PNOTE IS NOT NULL THEN UPDATE CENSUS_XML SET DESCRIPTION=PNOTE WHERE ID=PID; END IF;
END;
Confidence
VERIFIED. Due tipi di evidenza indipendenti e concordanti:
- Codice applicativo (C#): catena completa UI → Controller → (Remoting) → BL → DAL con nome stored procedure e parametri.
- Sorgente/schema DB Oracle (
USER_SOURCE,USER_TAB_COLUMNS): corpo della proceduraCNS_NEWCOMPILATION_XMLche esegue l'INSERT suCENSUS_XML, e struttura della tabella.
Forward (UI→DB) e reverse (SP→tabella→parametri DAL) concordano: i 6 parametri del DAL
(PIDUSER/PIDENTITY/PENTITY/PXML/PNOTE/PIDCOMPILATION) corrispondono 1:1 alla firma della procedura,
e le colonne inserite corrispondono allo schema di CENSUS_XML.
Open questions
- Configurazione runtime del canale .NET Remoting (
SettingsManager.CHANNEL/SERVERADDRESS) e nome effettivo del servizioService_Compilation: non risolti a runtime (valori da config del server). - Semantica dei valori possibili di
ENTITYoltre aEDIFICIO/PIANO/UIe uso a valle dell'XML (mappinglinkedToField/linkedToTable) — fuori dallo scope del solo WRITE. ISCANCELLEDnon è toccato dalla INSERT/UPDATE: la cancellazione (CNS_DELETECOMPILATION_XML) non è stata ispezionata per confermare se sia logica (flag) o fisica.