FLOW-PRJ-001 — Creazione di un progetto/commessa — Project (ProjectCenter)
Flusso end-to-end di creazione di un nuovo progetto (commessa) del modulo Project / ProjectCenter. Path pilota: wizard
ProjectInsert.ascx(inserimento interattivo da parte di un operatore) ospitato nella paginaAddProject.aspx. Backend OracleINFOCAD_TEST38, accesso via stored procedure ODP.NETPRJ_INSERTPROJECT(nessun ORM). L'entità è persistita nella tabellaPROJECT, con orchestrazione lato BL che crea anche stati, storico, team, tag, costi e attività associate.
- Flow ID: FLOW-PRJ-001
- Repository: InfocadWeb (ASP.NET Web Forms, code-behind C#, ProjectCenterWeb) + InfocadServer (ProjectControllers → ProjectBL → ProjectDAL, VB.NET)
- Confidence complessiva: VERIFIED (catena UI → code-behind → controller → BL → DAO → stored procedure, confermata su codice e su sorgente DB
USER_SOURCE/USER_DEPENDENCIES) - has_standalone_write:
true— esiste un path di scrittura autonomo e pulito (creazione progetto).
Obiettivo di business
Consentire a un operatore del ProjectCenter di creare una nuova commessa/progetto compilando un
wizard multi-step (Info, Costi, Allegati, Associazioni, Team, Campi custom). Al termine il progetto
esiste nella tabella PROJECT con un ID_PROJECT generato, il set standard di stati di workflow
(PROJECT_STATUS), la riga di storico iniziale (PROJECT_HISTORY), il team (PROJECT_TEAM),
i tag (PROJECT_TAG_ASS), i costi per categoria e le eventuali attività, oltre agli allegati caricati
e al codice progetto generato dai parametrici.
Attori
- Operatore ProjectCenter (utente autenticato,
WS.SessionLogin, conIdContactdi sessione) — path interattivo wizardProjectInsert.ascxinAddProject.aspx. - Oracle
INFOCAD_TEST38(hub anagrafico Project; procedurePRJ_*), con tipi helperHELPERS.numberlist/MYINTTABLEper il passaggio della lista di tag.
Trigger
Click sul pulsante Finish del wizard di inserimento: evento OnFinishButtonClick del
RadWizard InsertProjectRadWizard, dichiarato in ProjectInsert.ascx:55, gestito dal metodo
InsertProjectRadWizard_FinishButtonClick in ProjectInsert.ascx.cs:143.
Frontend entry point
- Pagina:
ProjectCenterWeb/WindowsPage/AddProject.aspx(registra e ospita il UserControl,AddProject.aspx:4,46); impostaProjectInsert.Modality = modality.Insert(AddProject.aspx.cs:36). - UserControl wizard:
ProjectCenterWeb/UserControls/Project/ProjectInsert.ascx(+ sub-controlProjectInfoUpdate,ProjectCategoriesCosts,AttachementsGrid,ProjectUpdateControlAss,ProjectSettingsUpdate,ProjectCustomFieldUpdateper i vari step). - Modalità:
modality.Insertpropagata a tutti i sub-control (ProjectInsert.ascx.cs:100-108).
Sequenza principale (main sequence)
- Operatore apre
AddProject.aspx, compila gli step del wizard e preme Finish. ProjectInsert.ascx.cs→InsertProjectRadWizard_FinishButtonClick(:143) raccoglie i dati dai sub-control nell'oggettoCurrentProject(InfoBase,Costs,Attachments,Tags,Team,Fields;:149-167), imposta le date di default (:172-173) e chiamaprjCtrl.Insert(ref prj, IdContact)(:175).ProjectController.Insert(ProjectController.vb:102) inoltra alla BL via proxy:DirectCast(Me.DAO, IProject_BL).Insert(prj, idcontact)(:105).Me.DAOè risolto daDAOFactory.CreateDAO(Ctrl_Project)(DAOFactory.vb) → endpoint remotingIProject_BL(serverProject_BL).
Project_BL.Insert(Project_BL.vb:293) orchestra la scrittura completa:- default
ExpectedEndDate= start+1g se non impostata (:300-302); - crea il progetto:
idPrj = ProjectDALFactory.GetProjectDAL.Insert(prj, idcontact)(:305) e assegnaprj.ID_DTO = idPrj(:306); - stati standard:
InsertProjectStatus(idPrj, idPrjStatus)(:309); - storico iniziale:
InsertHistory(idPrj, 0, idPrjStatus, idcontact)(:313); - team: loop su
prj.Team→InsertTeam(...)(:317-323); - attività:
insertActivity(prj.ActivityList, idPrj, idPrjStatus, idcontact)(:328); - costi per categoria: switch su
Status→Insert/Update/DeleteCategoryCost(:331-343).
- default
ProjectDAL.Insert(ProjectDAL.vb:221, overload senzadl) apreUsing dl As New DataLayer(...), prepara i parametriOracleParameter(PCODE, PNAME, PDESCRIPTION, PNOTE, PEXPECTED_START_DATE, PEXPECTED_END_DATE, PBUDGET, PEXPECTED_MANHOURS, PFIELDS CLOB, PIDTAGLIST comePLSQLAssociativeArray, PID_CATEGORY) + OUTPNEWINDEX(:224-251) e invocadl.ExecuteNonQueryStoredProcedure("PRJ_INSERTPROJECT")(:253); ritornaPNEWINDEXcome nuovo id (:254).- Oracle
PRJ_INSERTPROJECT(INFOCAD_TEST38, procedura standalone):- se
PID_CATEGORY <> 0→INSERT INTO PROJECT (... , ID_CATEGORY) VALUES (...) RETURNING ID_PROJECT INTO PNEWINDEX(src:16-21); - altrimenti
INSERT INTO PROJECT (...) ... RETURNING ID_PROJECT INTO PNEWINDEX(src:22-26); START_DATE/END_DATEsono inizializzate alle date "expected";CREATED = SYSDATE;- poi chiama
PRJ_ADDTAGSTOPROJECT(PIDTAGLIST, PNEWINDEX)(src:29) che, se la lista non è{0}, esegueINSERT INTO PROJECT_TAG_ASS (ID_TAG, ID_PROJECT)daTABLE(CAST(... AS MYINTTABLE))(ADDTAGS src:11-16).
- se
Project_BLprosegue con le SP companion:PRJ_INSERTPROJECTSTATUS: inserisce 8 righe di stato (Bozza..Cancellato) inPROJECT_STATUS,RETURNING ID_PROJECT_STATUSper lo stato "Bozza", e faUPDATE PROJECT SET ID_PROJECT_STATUS = ...(STATUS src:6-49);PRJ_INSERTPROJECTHISTORY:INSERT INTO PROJECT_HISTORY(con/senzaID_ACTIVITY) (HISTORY src:8-21);PRJ_INSERTPROJECTTEAM:INSERT INTO PROJECT_TEAM(con/senzaID_COMPANY) (TEAM src:13-24).
- Tornati alla UI (
ProjectInsert.ascx.cs): per ogni file temporaneo caricato →ctrDoc.UploadDocument(...)+prjCtrl.InsertAttachment(prj.ID_DTO, idAtt)(:186-203); seCodevuoto →GetNewCode(...)(parametrico) +UpdateCode(prj.ID_DTO, code)(:207-212). ScriptManager.RegisterStartupScript(... "CloseWindow()")chiude la finestra (:215). In caso di eccezione:InfocadTraceWrapper.CreateError(...)+RadAlertdi errore (:218-222).
API / service
- Path interattivo: nessun servizio SOAP/WCF sul lato client — postback ASP.NET Web Forms sul wizard.
- Boundary server: il
ProjectController(client) dialoga conProject_BL(server) via .NET Remoting (Activator.GetObject(GetType(IProject_BL), CHANNEL & "://" & SERVERADDRESS & "/" & Service_Project),DAOFactory.vb);Project_BLereditaMarshalByRefObject(Project_BL.vb:22-24).
Backend
- UI/Code-behind:
ProjectInsert.ascx/ProjectInsert.ascx.cs(wizard, C#),AddProject.aspx(.cs). - Controller:
Descor.Projects.ProjectControllers.ProjectController(ProjectController.vb) →IProject_BL. - BL (server, remoting):
Descor.Projects.ProjectBL.Project_BL(Project_BL.vb) — orchestratore multi-tabella. - DAL:
Descor.Projects.ProjectDAL.OracleODP.ProjectDAL(ProjectDAL.vb), viaProjectDALFactory.GetProjectDAL. - Pattern DAL:
Using dl As New DataLayer(My.Settings.ConnectionName)→dl.Parameters.Add(OracleParameter...)→dl.ExecuteNonQueryStoredProcedure("PRJ_INSERTPROJECT"); identity via parametro OUTPNEWINDEX. - Nota: la lista tag è passata come
OracleCollectionType.PLSQLAssociativeArraymappato sul tipo OracleHELPERS.numberlist(ProjectDAL.vb:194-195,PRJ_INSERTPROJECT src:10).
Query / stored procedure
| Passo | Stored procedure (Oracle) | Chiamata da (DAL) |
|---|---|---|
Insert progetto (INSERT su PROJECT, RETURNING ID_PROJECT) |
INFOCAD_TEST38.PRJ_INSERTPROJECT (OUT PNEWINDEX) |
ProjectDAL.vb:212,253 |
Associazione tag (dentro PRJ_INSERTPROJECT) |
INFOCAD_TEST38.PRJ_ADDTAGSTOPROJECT |
PRJ_INSERTPROJECT src:29 |
| Stati workflow standard + update stato iniziale | INFOCAD_TEST38.PRJ_INSERTPROJECTSTATUS (OUT PNEWINDEX) |
ProjectDAL.vb:272,295 |
| Storico progetto | INFOCAD_TEST38.PRJ_INSERTPROJECTHISTORY |
ProjectDAL.vb:366,390 |
| Team progetto | INFOCAD_TEST38.PRJ_INSERTPROJECTTEAM |
ProjectDAL.vb:426,462 |
| Allegato progetto (post-insert) | INFOCAD_TEST38.PRJ_INSERTPROJECTATTACHMENT |
ProjectDAL.vb:342 |
| Aggiornamento codice (parametrico) | INFOCAD_TEST38.PRJ_UPDATEPROJECTCODE |
ProjectDAL.vb:532 |
Tabelle lette (read)
INFOCAD_TEST38: tipo/oggettoHELPERS(PACKAGE) eMYINTTABLE(TYPE) usati per deserializzare la lista tag inPRJ_ADDTAGSTOPROJECT(daUSER_DEPENDENCIES).- Il progetto appena creato NON viene riletto nel path di insert (nessuna
SELECTsul progetto nel flusso).
Tabelle modificate (write)
INFOCAD_TEST38:PROJECT(RW — riga-radice del progetto: INSERT conRETURNING ID_PROJECT; UPDATE diID_PROJECT_STATUSdaPRJ_INSERTPROJECTSTATUS),PROJECT_TAG_ASS(INSERT associazioni tag),PROJECT_STATUS(INSERT 8 stati standard),PROJECT_HISTORY(INSERT storico iniziale),PROJECT_TEAM(INSERT membri del team).- Effetti collaterali applicativi (stessa transazione logica, SP separate): allegati
(
PRJ_INSERTPROJECTATTACHMENT→ tabella allegati progetto) e codice (PRJ_UPDATEPROJECTCODE→PROJECT). - Tutte le tabelle target sono VERIFIED via
USER_DEPENDENCIESdelle rispettive procedure.
Validazione
- Lato UI/BL: default applicativi —
ExpectedEndDateforzata aExpectedStartDate + 1gse non valorizzata (Project_BL.vb:300-302);StartDate/EndDate= date "expected" (ProjectInsert.ascx.cs:172-173). - Lato DB:
PRJ_INSERTPROJECTramifica suPID_CATEGORY <> 0(con/senzaID_CATEGORY,src:16-27);PRJ_ADDTAGSTOPROJECTsalta l'insert se la lista tag è il sentinella{0}(ADDTAGS src:7-9);PRJ_INSERTPROJECTHISTORY/TEAMramificano suPID_ACTIVITY=0/PID_COMPANY IS NULL. - Gestione errori UI: try/catch globale nel finish handler → log
InfocadTraceWrapper.CreateErrorRadAlert"Errore nell inserimento del progetto" (ProjectInsert.ascx.cs:218-222).
- Non risultano check di grant espliciti nel path di insert progetto (vedi Open questions).
Side effects
- Generazione identity
ID_PROJECT(sequenza/identity Oracle, esposta viaRETURNING ... INTO PNEWINDEX). - Popolamento del workflow di stato standard (8 stati) e impostazione dello stato iniziale "Bozza".
- Scrittura storico, team, tag, costi e attività associate nella stessa orchestrazione BL.
- Upload documenti in
GLOBAL_DOCUMENTS(viaDocumentController.UploadDocument) e associazione al progetto. - Generazione del codice progetto tramite motore parametrico (
Parametric.Project...GenerateProjectCode) quandoCodeè vuoto (ProjectInsert.ascx.cs:207-212).
Percorsi alternativi / di errore
- Aggiornamento progetto (path fratello, non insert): wizard/scheda
ProjectUpdate.ascx→ProjectController.Update(ProjectController.vb:111) →Project_BL.Update(Project_BL.vb:361) →ProjectDAL.Update(ProjectDAL.vb:473) →PRJ_UPDATEPROJECT(ProjectDAL.vb:512). - Overload transazionale:
ProjectDAL.Insert(prj, id_contact, ByRef dl)(ProjectDAL.vb:180) accetta unDataLayeresterno per condividere la connessione/transazione (usato in orchestrazioni composite). - Cancellazione logica (controprova non distruttiva):
PRJ_LOGICALDELETEPROJECT(ProjectDAL.vb:28). - Errore DB / eccezione: propagata da DAL (
LogException+Throw) fino al catch UI → alert, nessunCloseWindow(finestra resta aperta).
Diagramma di sequenza
sequenceDiagram
actor Op as Operatore ProjectCenter
participant UI as ProjectInsert.ascx (AddProject.aspx)
participant CB as ProjectInsert.ascx.cs (Finish)
participant PC as ProjectController.Insert
participant BL as Project_BL.Insert (remoting)
participant DAO as ProjectDAL.Insert
participant DB as Oracle INFOCAD_TEST38
Op->>UI: compila wizard + click Finish
UI->>CB: InsertProjectRadWizard_FinishButtonClick
CB->>CB: raccoglie CurrentProject (Info/Costs/Tags/Team/Fields)
CB->>PC: Insert(ref prj, IdContact)
PC->>BL: IProject_BL.Insert(prj, idcontact)
BL->>DAO: ProjectDAL.Insert(prj, idcontact)
DAO->>DB: PRJ_INSERTPROJECT (PCODE..PIDTAGLIST, OUT PNEWINDEX)
DB->>DB: INSERT INTO PROJECT RETURNING ID_PROJECT
DB->>DB: PRJ_ADDTAGSTOPROJECT -> INSERT PROJECT_TAG_ASS
DB-->>DAO: PNEWINDEX (nuovo ID_PROJECT)
DAO-->>BL: idPrj
BL->>DB: PRJ_INSERTPROJECTSTATUS (8 righe PROJECT_STATUS + UPDATE PROJECT)
BL->>DB: PRJ_INSERTPROJECTHISTORY (PROJECT_HISTORY)
BL->>DB: PRJ_INSERTPROJECTTEAM (PROJECT_TEAM) [per membro]
BL-->>PC: ok
PC-->>CB: ok
CB->>DB: UploadDocument + PRJ_INSERTPROJECTATTACHMENT [per file]
CB->>DB: GetNewCode + PRJ_UPDATEPROJECTCODE [se Code vuoto]
CB-->>Op: CloseWindow() (progetto creato)
Matrice di tracciabilità
| Layer | Artefatto | Evidenza (file:riga) |
|---|---|---|
| UI | AddProject.aspx (host) + ProjectInsert.ascx (wizard) |
AddProject.aspx:4,46 ; ProjectInsert.ascx:47,55 |
| Code-behind | InsertProjectRadWizard_FinishButtonClick → prjCtrl.Insert |
ProjectInsert.ascx.cs:143,169,175 |
| Controller | ProjectController.Insert → IProject_BL.Insert |
ProjectController.vb:102,105 |
| Factory DAO | DAOFactory.CreateDAO(Ctrl_Project) (remoting IProject_BL) |
DAOFactory.vb (Case Ctrl_Project) |
| BL (server) | Project_BL.Insert (orchestrazione multi-tabella) |
Project_BL.vb:293,305,309,313,317-323,328 |
| DAO | ProjectDAL.Insert → PRJ_INSERTPROJECT |
ProjectDAL.vb:221,224-251,253,254 |
| DAO (companion) | InsertProjectStatus/InsertHistory/InsertTeam |
ProjectDAL.vb:285,377,437 |
| DB | PRJ_INSERTPROJECT (INSERT PROJECT + tag) |
USER_SOURCE PRJ_INSERTPROJECT src:16-29 |
| DB | PRJ_ADDTAGSTOPROJECT (PROJECT_TAG_ASS) |
USER_SOURCE src:11-16 |
| DB | PRJ_INSERTPROJECTSTATUS (PROJECT_STATUS + UPDATE PROJECT) |
USER_SOURCE src:6-49 |
| DB | PRJ_INSERTPROJECTHISTORY (PROJECT_HISTORY) |
USER_SOURCE src:8-21 |
| DB | PRJ_INSERTPROJECTTEAM (PROJECT_TEAM) |
USER_SOURCE src:13-24 |
| DB (deps) | target tables via USER_DEPENDENCIES |
PROJECT, PROJECT_TAG_ASS, PROJECT_STATUS, PROJECT_HISTORY, PROJECT_TEAM |
Reverse trace (dal DB/BL ai chiamanti)
PRJ_INSERTPROJECTè invocata solo daProjectDAL.Insert(due overload,ProjectDAL.vb:212,253), a sua volta chiamato daProject_BL.Insert(Project_BL.vb:305) →ProjectController.Insert(ProjectController.vb:105) → wizardProjectInsert.ascx.cs:175.Project_BL.Insertè il punto di ingresso server della creazione progetto; non risultano altri chiamanti dell'insert progetto oltre alProjectController(grep su\.Insert(per il dominio Project).- Forward e reverse concordano: wizard
ProjectInsert→Insert→PRJ_INSERTPROJECTcon INSERT suPROJECTeRETURNING ID_PROJECT→ NO CONFLICTING.
Regole correlate (related rules)
- Semantica insert-only:
PRJ_INSERTPROJECTè sempre INSERT (nessun ramo update); l'update ha una SP dedicataPRJ_UPDATEPROJECT. Create vs update sono path distinti (wizardProjectInsertvsProjectUpdate). - Sentinella lista tag:
{0}= "nessun tag" (nessun insert inPROJECT_TAG_ASS,ADDTAGS src:7-9). - Workflow stati fisso: 8 stati standard hard-coded nella SP (
Bozza..Cancellato), progetto sempre creato inBozza. - Binding parametri: la lista id tag passa come
HELPERS.numberlist(associative array PL/SQL), non come stringa/XML.
Evidenza (file:line)
Punti chiave (codice):
AddProject.aspx:4,46; AddProject.aspx.cs:36; ProjectInsert.ascx:47,55;
ProjectInsert.ascx.cs:143,149-167,172-173,175,186-203,207-212,215,218-222;
ProjectController.vb:102,105,111; DAOFactory.vb (Case Ctrl_Project);
Project_BL.vb:22-24,293,300-302,305,306,309,313,317-323,328,361;
ProjectDAL.vb:180,194-195,221,224-251,253,254,285,377,437,473,512,532.
Punti chiave (DB, INFOCAD_TEST38, letti in sola lettura via USER_SOURCE/USER_DEPENDENCIES):
PRJ_INSERTPROJECT firma src:1-12; INSERT PROJECT con/senza categoria src:16-27;
RETURNING ID_PROJECT INTO PNEWINDEX src:21,26; chiamata tag src:29;
PRJ_ADDTAGSTOPROJECT INSERT PROJECT_TAG_ASS src:11-16;
PRJ_INSERTPROJECTSTATUS INSERT PROJECT_STATUS + UPDATE PROJECT src:6-49;
PRJ_INSERTPROJECTHISTORY INSERT PROJECT_HISTORY src:8-21;
PRJ_INSERTPROJECTTEAM INSERT PROJECT_TEAM src:13-24.
Dipendenze (USER_DEPENDENCIES): PRJ_INSERTPROJECT→PROJECT(TABLE),PRJ_ADDTAGSTOPROJECT(PROC),HELPERS(PKG);
PRJ_ADDTAGSTOPROJECT→PROJECT_TAG_ASS,MYINTTABLE,HELPERS; PRJ_INSERTPROJECTSTATUS→PROJECT,PROJECT_STATUS;
PRJ_INSERTPROJECTHISTORY→PROJECT_HISTORY; PRJ_INSERTPROJECTTEAM→PROJECT_TEAM.
Confidence
- VERIFIED: catena UI (C#) → controller → BL → DAO → nome stored procedure (letta sui sorgenti) e
sorgente di
PRJ_INSERTPROJECT(INSERT suPROJECT,RETURNING ID_PROJECT) letto daUSER_SOURCE; tabelle target confermate daUSER_DEPENDENCIES. Idem per le SP companion (status/history/team/tag). - SUPPORTED: boundary .NET Remoting tra
ProjectControllereProject_BL(dedotto daDAOFactory+MarshalByRefObject), non osservato a runtime; upload allegati e generazione codice parametrico (path presente nel code-behind, non tracciato fino al DB in questo documento). - INFERRED: appartenenza dell'intera orchestrazione BL a un'unica transazione DB (le SP companion
usano overload senza
dlconUsing dl As New DataLayer(...)→ connessioni potenzialmente distinte).
Open questions
- Transazionalità:
Project_BL.Insertusa gli overload DAL senzaDataLayercondiviso (Project_BL.vb:305,309,313,319), quindi ogni SP gira su una propria connessione — un fallimento parziale (es. team) potrebbe lasciare progetto+stati già committati. Da verificare la policy di commit/rollback delDataLayer. - Controlli di autorizzazione/grant sulla creazione progetto: non individuati nel path di insert (a differenza del path Property). Da verificare se applicati a monte (menu/pagina) o assenti.
- Sequenza/identity di
ID_PROJECTeID_PROJECT_STATUS: presumibilmente identity/trigger sulle tabellePROJECT/PROJECT_STATUS(non ispezionati i trigger). - Colonne
FIELDS(CLOBcreateExtraField): formato di serializzazione dei campi custom non ispezionato in dettaglio. - Comportamento in PROD (osservato solo ambiente TEST38 / service
dev).