FLOW-RPT-001 — Salvataggio della definizione di un report XML (Report Builder) — Report
Flusso end-to-end di salvataggio (create) della definizione di un report XML del modulo Report / ReportCenter. Il reporting Infocad è prevalentemente in lettura (esecuzione di query e rendering); l'operazione di scrittura autonoma rappresentativa è il salvataggio della definizione di un report costruito dal Report Builder (query, layout, grafico, eventuale schedulazione). Path pilota: UserControl
XmlProcedure.ascx(Report Builder interattivo). Backend OracleINFOCAD_TEST38, accesso via stored procedure ODP.NETRPT_ADDXMLREPORT(nessun ORM). L'entità è persistita nella tabellaRPT_XMLREPORTSOURCE.
- Flow ID: FLOW-RPT-001
- Repository: InfocadWeb (ASP.NET Web Forms, ReportCenterWeb, code-behind C#) + InfocadServer (ReportControllers/ReportManager, VB.NET)
- Operazione WRITE rappresentativa:
AddReport→RPT_ADDXMLREPORT(INSERT suRPT_XMLREPORTSOURCE) - has_standalone_write:
true(il dominio Report possiede un percorso di scrittura autonomo pulito: salvataggio definizione report) - Confidence complessiva: VERIFIED (catena UI → code-behind → controller → DAO → stored procedure, confermata su codice E su sorgente DB
USER_SOURCE/USER_DEPENDENCIES/USER_TAB_COLUMNS)
Obiettivo di business
Consentire a un operatore del ReportCenter di creare (o aggiornare) la definizione di un report XML
costruito interattivamente: testo della query SQL, connessione dati (RC/DEM/default), provider,
layout di stampa, grafico, pivot ed eventuale schedulazione con salvataggio dati periodico.
Al termine la definizione esiste nella tabella RPT_XMLREPORTSOURCE (una riga per ID_ACTION),
con ID_REPORT surrogato generato da sequenza; se il report è schedulato viene inoltre creato un
job Oracle DBMS_SCHEDULER con relativa tabella di appoggio.
Attori
- Operatore ReportCenter (utente autenticato con applicazione
ReportCentero grantVIEW; la modifica delle azioni richiede grantINSCANC) — path interattivo Report Builder. - Oracle
INFOCAD_TEST38(hub reporting; procedureRPT_ADDXMLREPORT,RPT_CREATESCHEDULING; sequenzaSEQ_RPT_XMLRPTSOURCE; triggerTRG_RPT_XMLREPORTSOURCE; sottosistemaDBMS_SCHEDULER).
Trigger
Click sul pulsante Salva del Report Builder: evento btnSave_Click
(XmlProcedure.ascx.cs:1412), che invoca SetData() (:1414).
Frontend entry point
- Pagina host:
ReportCenterWeb/ReportBuilderPage.aspx(ReportBuilderPage.aspx.cs, deriva daReportCenterPortalPage); apre il builder viaopenXmlReportBuilder(actionID, mode)(ReportBuilderPage.aspx.cs:60). - UserControl builder:
ReportCenterWeb/UserControls/XmlProcedure.ascx(+Common/QueryBuilder.ascxper la query,Scheduler1per la schedulazione,PivotBuilder1). - Gate di accesso:
ReportCenterPortalPageverifica l'appartenenza all'applicazioneReportCenteroHasUserGrant(ReportSettings.VIEW)(ReportCenterPortalPage.cs:17); il tasto di editing azione è vincolato aHasUserGrant(ReportSettings.INSCANC)(ReportBuilderPage.aspx.cs:138).
Sequenza principale (main sequence)
- Operatore costruisce/modifica il report (query, layout, grafico, pivot, schedulazione) e preme Salva.
XmlProcedure.ascx.cs→btnSave_Click(:1412) →SetData()(:425) popola il DTO_report(XmlReport) dai campi UI:Title,Description,ConnectionName,QueryText, scheduling (Scheduled,ScheduleMode,ScheduleStart,ScheduleEmails,ScheduleDataReset), layout/chart/pivot (:429-541).- Decisione create-vs-update lato web:
ctrl.GetReport(_report.ActionID)(:548); se esiste →EditReport(:550), altrimenti →AddReport(WS.SessionLogin.UserName, _report)(:552); in caso di eccezione, fallback suAddReport(:558). XmlReportController.AddReport(XmlReportController.vb:44) inoltra al DAO:DirectCast(Me.DAO, IDAO_XmlReport).AddReport(username, rpt)(:46). Il DAO è risolto inNew XmlReportController()→DaoActivate(enControllers.Ctrl_XmlReport)(XmlReportController.vb:9) →DAOFactory.CreateDAO(DAOFactory.vb:25) che usa .NET Remoting (Activator.GetObject(GetType(IDAO_XmlReport), … Service_XmlReport),DAOFactory.vb:26) verso il servizio ReportManager.DAO_XmlReport.AddReport(DAO_XmlReport.vb:179) prepara i parametriPIDACTION=ActionID,PCONNECTION,PPROVIDER,PXML(CLOB =rpt.XmlString, XML serializzato inXmlReport.vb:831),PIDOUT(OUT NUMBER) ed esegueRPT_ADDXMLREPORTviadl.ExecuteNonQueryStoredProcedure("RPT_ADDXMLREPORT", False)(:200).- Oracle
RPT_ADDXMLREPORT(INFOCAD_TEST38):INSERT INTO RPT_XMLREPORTSOURCE (ID_ACTION, CONNECTION, PROVIDER, XML) VALUES (…) RETURNING ID_ACTION INTO PIDOUT(src:9-12). Il triggerTRG_RPT_XMLREPORTSOURCEBEFORE INSERT valorizzaID_REPORTdaSEQ_RPT_XMLRPTSOURCE.NEXTVALse NULL (trg:6-13). - Se
rpt.Scheduledè TRUE:DAO_XmlReportistanziaDAO_Schedulere chiamaCreateScheduling("XMLRPT_" & ActionID, QueryText, ScheduleMode, ScheduleDataReset, ScheduleStart)(DAO_XmlReport.vb:202-205) →RPT_CREATESCHEDULING(DAO_Scheduler.vb:29): droppa/crea la tabella di appoggioRPT_SCHED_XMLRPT_<ActionID>(CREATE TABLE … AS (SELECT * FROM (query)),src:16-21) e crea program/schedule/job viaDBMS_SCHEDULER(src:26-33). - Il DAO legge
PIDOUT(OracleDecimal.ToInt32) e lo restituisce comeretVal(DAO_XmlReport.vb:207); il controller lo propaga al code-behind. - Post-salvataggio:
btnSave_Clickrisolve l'azione (ActionsController.GetAction) e reindirizza alla pagina di visualizzazione del report (XmlProcedure.ascx.cs:1419-1430).
API / service
- Path interattivo: postback ASP.NET Web Forms diretto sul builder (nessun SOAP/WCF sul salvataggio).
- Layer server: invocazione dei controller Report tramite .NET Remoting (canale configurato in
SettingsManager.CHANNEL/SERVERADDRESS, dictionaryService_XmlReport), non in-process (DAOFactory.vb:26) — diversamente dai controller Property (in-process).
Backend
- UI/Code-behind:
ReportBuilderPage.aspx.cs(host),UserControls/XmlProcedure.ascx.cs(builder). - DTO:
Descor.BI.ReportSharedObjects.XmlReport(InfocadServer/ReportSharedObjects/XmlReport.vb) — serializzazioneXmlString(:831). - Controller server:
Descor.BI.ReportControllers.XmlReportController(InfocadServer/ReportControllers/XmlReportController.vb), deriva daCtrl_Base, inoltra al DAO. - DAO:
Descor.BI.ReportManager.DAO_XmlReport(InfocadServer/ReportManager/DAO_XmlReport.vb) eDAO_Scheduler(.../DAO_Scheduler.vb), baseDAO_Base(QueryExecutionCheck). - Pattern DAL:
Dim dl As New DataLayer(My.Settings.ConnectionName)→dl.Parameters.Add(OracleParameter…)→dl.ExecuteNonQueryStoredProcedure("RPT_ADDXMLREPORT", False); identity/ritorno via parametro OUTPIDOUT.
Query / stored procedure
| Passo | Stored procedure (Oracle) | Chiamata da (DAL) |
|---|---|---|
Insert definizione report (INSERT su RPT_XMLREPORTSOURCE, OUT PIDOUT) |
INFOCAD_TEST38.RPT_ADDXMLREPORT |
DAO_XmlReport.vb:200 |
| Update definizione report | INFOCAD_TEST38.RPT_EDITXMLREPORT |
DAO_XmlReport.vb:160 |
| Cancellazione definizione report | INFOCAD_TEST38.RPT_DELETEXMLREPORT |
DAO_XmlReport.vb:234 |
Creazione schedulazione (DDL + DBMS_SCHEDULER) |
INFOCAD_TEST38.RPT_CREATESCHEDULING |
DAO_Scheduler.vb:29 |
| Cancellazione schedulazione | INFOCAD_TEST38.RPT_DELETESCHEDULING |
DAO_Scheduler.vb:76 |
| Load definizione report (READ-ONLY) | query diretta SELECT * FROM RPT_XMLREPORTSOURCE WHERE ID_ACTION=… |
DAO_XmlReport.vb:26 |
Tabelle lette (read)
INFOCAD_TEST38:RPT_XMLREPORTSOURCE(verifica esistenza pre-insert viaXmlReportController.GetReport,DAO_XmlReport.vb:26);USER_TABLES(verifica tabella di appoggio inRPT_CREATESCHEDULING,src:11).
Tabelle modificate (write)
INFOCAD_TEST38:RPT_XMLREPORTSOURCE(RW — tabella-radice della definizione report: INSERT conRETURNING ID_ACTION; VERIFIED su sorgenteUSER_SOURCEe suUSER_TAB_COLUMNScolonneID_REPORT, ID_ACTION, CONNECTION, PROVIDER, XML).SEQ_RPT_XMLRPTSOURCE(sequenza —NEXTVALperID_REPORT, consumata dal trigger).- Se schedulato: tabella dinamica
RPT_SCHED_XMLRPT_<ActionID>(DDLCREATE/DROP TABLE) e oggettiDBMS_SCHEDULER(PRG_…,SCHED_…,JOB_…) creati daRPT_CREATESCHEDULING(src:16-33).
(La tabella RPT_XMLREPORTSOURCE è confermata come dipendenza statica di RPT_ADDXMLREPORT in
USER_DEPENDENCIES; RPT_CREATESCHEDULING dipende dal synonym DBMS_SCHEDULER e usa DDL dinamico
per le tabelle RPT_SCHED_*, che non compaiono nelle dipendenze statiche.)
Validazione
- Lato UI/pagina: gate applicazione
ReportCentero grantVIEW(ReportCenterPortalPage.cs:17); editing azioni vincolato a grantINSCANC(ReportBuilderPage.aspx.cs:138). - Lato business (esecuzione query, non salvataggio):
DAO_Base.QueryExecutionCheck(DAO_Base.vb:38) blocca query contenentiinsert/update/delete/alter/drop/exec/create— applicato nei path di esecuzione/anteprima (GetReport :46,ExecuteNonQuery/TestQuery), NON al momento del salvataggio della definizione:AddReportpersiste il testo query come XML senza validarne il contenuto (vedi Open questions). - Lato DB: trigger
TRG_RPT_XMLREPORTSOURCEimpedisce la modifica diID_REPORTin UPDATE (RAISE_APPLICATION_ERROR(-20000, …),trg:15-23).
Side effects
- Assegnazione
ID_REPORTsurrogato daSEQ_RPT_XMLRPTSOURCE(trigger). - Se schedulato: creazione tabella di appoggio
RPT_SCHED_XMLRPT_<ActionID>e di un job Oracle abilitato (DBMS_SCHEDULER.CREATE_JOB … enabled => TRUE,RPT_CREATESCHEDULING src:33), che materializza periodicamente il dataset; invio email programmato gestito dallo scheduler (ReportManager/Scheduler/ReportEmailSender.vb) sulla base diScheduleEmails. - Salvataggio logo tenant su filesystem/
SetPrintLogose caricata immagine (XmlProcedure.ascx.cs:568-577).
Percorsi alternativi / di errore
- Aggiornamento definizione: report già esistente →
XmlReportController.EditReport(XmlReportController.vb:36) →DAO_XmlReport.EditReport(:141) →RPT_EDITXMLREPORT(:160), con ricostruzione/eliminazione schedulazione (EditScheduling/DeleteScheduling,:162-168). - Cancellazione:
DAO_XmlReport.DeleteReport(:220) →RPT_DELETEXMLREPORT(:234), previaDeleteSchedulingse schedulato. - Pivot associato: se
chkPivotattivo, prima dell'insert report viene creato/aggiornato il pivot viaPivotController.AddReport/EditReport(XmlProcedure.ascx.cs:531-533) →RPT_ADDPIVOT/RPT_EDITPIVOT. - Errore DB: eccezione loggata da
LogManager.ExceptionLogger.LogExceptione ri-sollevata (DAO_XmlReport.vb:211-213); il code-behind intercetta l'eccezione dellaEditReporte ritenta conAddReport(XmlProcedure.ascx.cs:554-558).
Diagramma di sequenza
sequenceDiagram
actor Op as Operatore ReportCenter
participant UI as XmlProcedure.ascx (ReportBuilderPage)
participant CB as XmlProcedure.ascx.cs (btnSave_Click/SetData)
participant XC as XmlReportController.AddReport
participant DAO as DAO_XmlReport.AddReport
participant SCH as DAO_Scheduler.CreateScheduling
participant DB as Oracle INFOCAD_TEST38
Op->>UI: costruisce report + click Salva
UI->>CB: btnSave_Click -> SetData()
CB->>CB: popola _report (XmlReport) dai campi UI
CB->>XC: GetReport(ActionID) [test esistenza]
alt non esiste (create)
CB->>XC: AddReport(user, _report)
XC->>DAO: AddReport(user, rpt) [.NET Remoting]
DAO->>DB: RPT_ADDXMLREPORT (PXML CLOB, OUT PIDOUT)
DB->>DB: INSERT RPT_XMLREPORTSOURCE + TRG (ID_REPORT da SEQ)
opt rpt.Scheduled
DAO->>SCH: CreateScheduling("XMLRPT_"&ActionID, ...)
SCH->>DB: RPT_CREATESCHEDULING (CREATE TABLE RPT_SCHED_* + DBMS_SCHEDULER JOB)
end
DB-->>DAO: PIDOUT
else esiste (update)
CB->>XC: EditReport(_report)
XC->>DAO: EditReport -> RPT_EDITXMLREPORT
end
CB->>UI: Response.Redirect(pagina report)
Matrice di tracciabilità (file:riga)
| Layer | Artefatto | Evidenza |
|---|---|---|
| Trigger UI | btnSave_Click |
InfocadWeb/…/ReportCenterWeb/UserControls/XmlProcedure.ascx.cs:1412 |
| Raccolta dati | SetData() |
XmlProcedure.ascx.cs:425 |
| Create-vs-update | GetReport/AddReport |
XmlProcedure.ascx.cs:548,552,558 |
| Host page + grant | ReportBuilderPage |
ReportBuilderPage.aspx.cs:60,138; ReportCenterPortalPage.cs:17 |
| Controller | XmlReportController.AddReport |
InfocadServer/ReportControllers/XmlReportController.vb:44 |
| DAO factory (Remoting) | DAOFactory.CreateDAO |
InfocadServer/ReportControllers/DAOFactory.vb:25-26 |
| DAO write | DAO_XmlReport.AddReport |
InfocadServer/ReportManager/DAO_XmlReport.vb:179,200,204,207 |
| DAO scheduling | DAO_Scheduler.CreateScheduling |
InfocadServer/ReportManager/DAO_Scheduler.vb:29 |
| DTO serializzazione | XmlReport.XmlString |
InfocadServer/ReportSharedObjects/XmlReport.vb:831 |
| Validazione query | DAO_Base.QueryExecutionCheck |
InfocadServer/ReportManager/DAO_Base.vb:38 |
| Stored procedure | RPT_ADDXMLREPORT |
Oracle USER_SOURCE (INSERT RPT_XMLREPORTSOURCE RETURNING) |
| Trigger DB | TRG_RPT_XMLREPORTSOURCE |
Oracle USER_SOURCE/USER_TRIGGERS (ID_REPORT da SEQ_RPT_XMLRPTSOURCE) |
| Stored procedure | RPT_CREATESCHEDULING |
Oracle USER_SOURCE (CREATE TABLE + DBMS_SCHEDULER) |
Evidenza (INLINE)
Vedi la sezione dedicata restituita come evidence_markdown.
Confidence
VERIFIED per l'intera catena UI → code-behind → controller → DAO → stored procedure:
- Codice sorgente letto direttamente (web C# + server VB.NET).
- Sorgente stored procedure e trigger letti da Oracle
USER_SOURCE/USER_TRIGGERS. - Dipendenze confermate da
USER_DEPENDENCIES; struttura tabella daUSER_TAB_COLUMNS. - Forward e reverse concordano (
RPT_ADDXMLREPORTscrive soloRPT_XMLREPORTSOURCEed è chiamata solo daDAO_XmlReport.AddReport).
Open questions
PIDOUTrestituisceID_ACTION, nonID_REPORT:RPT_ADDXMLREPORTfaRETURNING ID_ACTION INTO PIDOUT, quindi il valore restituito al chiamante è l'ID_ACTIONin input, non il surrogatoID_REPORTgenerato dal triggerSEQ_RPT_XMLRPTSOURCE.NEXTVAL. Probabilmente intenzionale (chiave logica = azione), ma il nomePIDOUT/retValè fuorviante.- Nessuna protezione anti-duplicato a livello DB: l'unicità "una definizione per
ID_ACTION" è garantita solo dal controllo applicativoGetReportlato web; non è stata verificata l'esistenza di un vincolo UNIQUE suID_ACTIONinRPT_XMLREPORTSOURCE. QueryExecutionChecknon applicato al salvataggio: il testo della query viene persistito come XML senza il filtro anti-DML che è invece applicato nei path di esecuzione — potenziale superficie di rischio se la query viene poi eseguita con privilegi elevati (da approfondire con la sicurezza).- Modello di deployment:
DAOFactoryusa .NET Remoting verso il servizio ReportManager; non è stato verificato se in produzione il servizio sia co-locato (loopback) o remoto.