Table of Contents

BR-PRJ — Regole di business del dominio Project / Commessa

Regole di business estratte dal flusso pilota FLOW-PRJ-001 (creazione di un nuovo progetto/commessa dal wizard ProjectInsert) e dai sorgenti correlati. Il dominio Project (ProjectCenter) gestisce il ciclo di vita della commessa: anagrafica progetto, codice, workflow di stato, storico, team, tag, categorie di costo, attività, allegati e campi custom.

La creazione passa dalla procedura Oracle standalone PRJ_INSERTPROJECT (INSERT su PROJECT, RETURNING ID_PROJECT), orchestrata lato BL da Project_BL.Insert, che invoca una serie di SP companion (PRJ_INSERTPROJECTSTATUS, PRJ_INSERTPROJECTHISTORY, PRJ_INSERTPROJECTTEAM, PRJ_INSERTPROJECTATTACHMENT, PRJ_ADDTAGSTOPROJECT, PRJ_UPDATEPROJECTCODE). Nessun ORM; accesso via ODP.NET (DataLayer + OracleParameter).

Sistema: Infocad (Descor) — backend Oracle INFOCAD_TEST38, UI ASP.NET Web Forms (code-behind C#, ProjectCenterWeb) + boundary .NET Remoting tra ProjectController (client) e Project_BL (server, MarshalByRefObject).

Le regole sono classificate per tipo, enforcement point (UI / BL / DB / mixed) e confidence (VERIFIED / SUPPORTED / INFERRED). Gli identificatori tecnici NON sono tradotti.

Note di metodo e provenienza dell'evidenza

  • Evidenza di codice: percorsi relativi alla radice del repository Documentation/ (es. InfocadServer/ProjectBL/Project_BL.vb:305).
  • Evidenza DB: letta in sola lettura da USER_SOURCE (sorgente procedure/trigger), USER_CONSTRAINTS (vincoli), USER_TRIGGERS (trigger), USER_TAB_COLUMNS (default colonne) su INFOCAD_TEST38, limitatamente a PRJ_INSERTPROJECT e SP companion, al trigger CNT_PROJECT e alla tabella PROJECT. Nessuna lettura di dati applicativi, nessuna DML/DDL. Le righe delle procedure/trigger sono indicate come PRJ_INSERTPROJECT src:NN (numerazione USER_SOURCE).
  • La verifica DB conferma diverse regole che nel flusso pilota erano solo SUPPORTED e ne emerge un gruppo di regole enforced SOLO in SQL (trigger CNT_PROJECT, vincoli NOT NULL, default colonna, workflow di stato hard-coded) non visibili dal codice applicativo.
  • Flag rilevanti: assenza di controlli di grant nel path di insert (boundary Remoting non ri-verificato, pattern TD-008), transazionalità non garantita, doppia generazione del codice (trigger DB + parametrico UI), magic number nel workflow di stato.

Registro delle regole (register)

id regola tipo enforcement conf
BR-PRJ-001 La creazione progetto è INSERT-only (PRJ_INSERTPROJECT); create e update sono path distinti (wizard ProjectInsert vs ProjectUpdate, SP PRJ_UPDATEPROJECT) process mixed VERIFIED
BR-PRJ-002 ID_PROJECT è assegnato dalla sequence SEQ_PRJ_PROJECT se NULL (trigger CNT_PROJECT BEFORE INSERT) calculation DB VERIFIED
BR-PRJ-003 Se il codice è NULL all'insert, il trigger CNT_PROJECT genera PRJ-<YYYY>-<NNNNN> (anno + currval seq a 5 cifre) calculation DB VERIFIED
BR-PRJ-004 Se Code è vuoto, dopo l'insert la UI genera il codice via motore parametrico (GenerateProjectCode + GetNewCode) e lo sovrascrive con PRJ_UPDATEPROJECTCODE calculation mixed SUPPORTED
BR-PRJ-005 CODE è obbligatorio a DB (SYS_C001719758 NOT NULL) validation DB VERIFIED
BR-PRJ-006 NAME è obbligatorio (constraint DB SYS_C001719759 + RequiredFieldValidator UI) validation mixed VERIFIED
BR-PRJ-007 EXPECTED_START_DATE e EXPECTED_END_DATE sono obbligatorie (constraint DB + RequiredFieldValidator UI) validation mixed VERIFIED
BR-PRJ-008 Se ExpectedEndDate non impostata, la BL la forza a ExpectedStartDate + 1 giorno date-logic BL VERIFIED
BR-PRJ-009 START_DATE/END_DATE sono inizializzate alle date "expected" (sia in UI sia dalla SP che copia i parametri expected) calculation mixed VERIFIED
BR-PRJ-010 Validazione lato client della conformità date (fine > inizio) via CustomValidator (validateExDate/validateDate) validation UI SUPPORTED
BR-PRJ-011 CREATED è impostata a SYSDATE all'insert del progetto calculation DB VERIFIED
BR-PRJ-012 EFFECTIVE_COST è NOT NULL con default DB 0 (la SP non lo valorizza) validation DB VERIFIED
BR-PRJ-013 Ogni progetto nasce con 8 stati standard hard-coded in PROJECT_STATUS (Bozza..Cancellato) e stato iniziale sempre "Bozza" (ID_STATUS=0) state-transition DB VERIFIED
BR-PRJ-014 L'ORDER_ID di visualizzazione degli stati NON coincide con ID_STATUS (mapping fisso Bozza=3, Cancellato=0, Annullato=1, Sospeso=2, Pubblicato=4, Approvato=5, In Corso=6, Eseguito=7) config-flag DB VERIFIED
BR-PRJ-015 Alla creazione viene scritta una riga di storico iniziale in PROJECT_HISTORY (MODIFIED=SYSDATE, stato = Bozza, ID_ACTIVITY omesso se attività = 0) process mixed VERIFIED
BR-PRJ-016 I membri del team sono inseriti in loop (PRJ_INSERTPROJECTTEAM); i due rami del confronto team.IdContact = idcontact producono lo stesso insert (logica ridondante) process BL VERIFIED
BR-PRJ-017 Il membro team senza ID_COMPANY (NULL) viene inserito senza la colonna azienda (ramo condizionale nella SP) config-flag DB VERIFIED
BR-PRJ-018 I tag sono associati da PRJ_ADDTAGSTOPROJECT dentro l'insert; se la lista è il sentinella {0} (COUNT=1 e valore 0) non viene inserito alcun tag validation DB VERIFIED
BR-PRJ-019 La lista id tag è passata come HELPERS.numberlist (associative array PL/SQL), non come stringa/XML process mixed VERIFIED
BR-PRJ-020 La categoria è opzionale: PID_CATEGORY <> 0 seleziona il ramo INSERT con ID_CATEGORY, altrimenti senza (0 = nessuna categoria) config-flag DB VERIFIED
BR-PRJ-021 Le categorie di costo sono gestite per Status del DTO: Empty→Delete, NewObject→Insert, OnDBModifiedOject→Update process BL VERIFIED
BR-PRJ-022 Gli allegati sono gestiti post-insert: upload dei file temporanei in GLOBAL_DOCUMENTS, PRJ_INSERTPROJECTATTACHMENT e cancellazione del file temporaneo process mixed SUPPORTED
BR-PRJ-023 I campi custom sono serializzati nella colonna FIELDS (CLOB) via createExtraField(prj.Fields) process BL SUPPORTED
BR-PRJ-024 Nel path di insert progetto NON esistono controlli di grant/autorizzazione (né UI code-behind né BL); il boundary Remoting non ri-verifica i grant permission none/UI INFERRED
BR-PRJ-025 L'orchestrazione BL usa overload DAL SENZA DataLayer condiviso: ogni SP gira su connessione propria, quindi un fallimento parziale (es. team) può lasciare progetto+stati committati process BL INFERRED
BR-PRJ-026 ID_PROJECT è immutabile: un UPDATE che lo modifica solleva ORA-20000 (trigger CNT_PROJECT) validation DB VERIFIED
BR-PRJ-027 In update progetto viene sempre scritta una riga di storico (InsertHistory) per storicizzare lo stato corrente process mixed VERIFIED

Dettaglio delle regole

BR-PRJ-001 — Creazione INSERT-only, path create/update distinti

  • Tipo: process · Enforcement: mixed (BL + DB) · Confidence: VERIFIED · Customer-specific: no
  • Statement: La creazione di una commessa è sempre un INSERT eseguito da PRJ_INSERTPROJECT; non esiste ramo di update nella procedura di insert. La modifica ha una SP dedicata (PRJ_UPDATEPROJECT) e un wizard distinto (ProjectUpdate). Create e update non condividono il codice.
  • Evidenza: Project_BL.vb:305 (ProjectDALFactory.GetProjectDAL.Insert), ProjectDAL.vb:253 (ExecuteNonQueryStoredProcedure("PRJ_INSERTPROJECT")); ProjectDAL.vb:512 (PRJ_UPDATEPROJECT); PRJ_INSERTPROJECT src:18-26 (solo INSERT).

BR-PRJ-002 — Identity da sequence via trigger

  • Tipo: calculation · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: ID_PROJECT non è passato dall'applicazione; il trigger CNT_PROJECT (BEFORE INSERT, FOR EACH ROW) lo popola da SEQ_PRJ_PROJECT.NEXTVAL se :new.ID_PROJECT IS NULL. L'id è restituito all'app via RETURNING ID_PROJECT INTO PNEWINDEX.
  • Evidenza: CNT_PROJECT src:11-15 (SEQ_PRJ_PROJECT.NEXTVAL); PRJ_INSERTPROJECT src:21,26 (RETURNING ID_PROJECT INTO PNEWINDEX); ProjectDAL.vb:254 (ritorno PNEWINDEX).

BR-PRJ-003 — Codice auto-generato dal trigger (magic format)

  • Tipo: calculation · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: Se CODE è NULL all'insert, il trigger CNT_PROJECT genera un codice nel formato PRJ-<YYYY>-<NNNNN> (letteralmente 'PRJ-' || EXTRACT(YEAR FROM SYSDATE) || '-' || TRIM(TO_CHAR(SEQ_PRJ_PROJECT.CURRVAL, '00000')), cioè seq corrente su 5 cifre con zero-padding). Magic: prefisso PRJ- e maschera 00000 hard-coded nel trigger.
  • Evidenza: CNT_PROJECT src:16-21.

BR-PRJ-004 — Codice parametrico UI sovrascrive il codice generato (interazione/ridondanza)

  • Tipo: calculation · Enforcement: mixed (UI + DB) · Confidence: SUPPORTED · Customer-specific: sì
  • Statement: Dopo l'insert, se Code è vuoto la UI chiama il motore parametrico (Parametric.Project.Project.GenerateProjectCode + prjCtrl.GetNewCode) e sovrascrive il codice con PRJ_UPDATEPROJECTCODE. Il motore parametrico è configurabile per cliente. Interazione / probabile ridondanza: poiché PCODE è passato NULL quando vuoto, il trigger CNT_PROJECT (BR-PRJ-003) ha già assegnato un codice PRJ-YYYY-NNNNN; la UI lo rimpiazza subito con quello parametrico. Il codice del trigger è quindi transitorio quando la UI genera il proprio.
  • Evidenza: ProjectInsert.ascx.cs:207-212; ProjectDAL.vb:532 (PRJ_UPDATEPROJECTCODE); PRJ_UPDATEPROJECTCODE src:5-7 (UPDATE PROJECT SET CODE = PCODE). Il motore parametrico non è tracciato fino al DB in questo documento (⇒ SUPPORTED).

BR-PRJ-005 — CODE obbligatorio (DB)

  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: La colonna CODE è NOT NULL. Un insert con codice NULL è ammesso solo perché il trigger CNT_PROJECT lo valorizza prima della scrittura (BR-PRJ-003).
  • Evidenza: constraint SYS_C001719758 ("CODE" IS NOT NULL) su PROJECT.

BR-PRJ-006 — NAME obbligatorio

  • Tipo: validation · Enforcement: mixed (UI + DB) · Confidence: VERIFIED · Customer-specific: no
  • Statement: Il nome progetto è obbligatorio, enforced sia a UI (RequiredFieldValidator con label NameLabelRequired) sia a DB (constraint NOT NULL).
  • Evidenza: ProjectInfoUpdate.ascx:180 (label required); constraint SYS_C001719759 ("NAME" IS NOT NULL) su PROJECT.

BR-PRJ-007 — Date previste obbligatorie

  • Tipo: validation · Enforcement: mixed (UI + DB) · Confidence: VERIFIED · Customer-specific: no
  • Statement: EXPECTED_START_DATE ed EXPECTED_END_DATE sono obbligatorie: RequiredFieldValidator a UI ("Data Inizio Prevista obbligatoria" / "Data Fine Prevista obbligatoria") e constraint NOT NULL a DB.
  • Evidenza: ProjectInfoUpdate.ascx:223-230,282-289; constraint SYS_C001719760 ("EXPECTED_START_DATE" IS NOT NULL), SYS_C001719761 ("EXPECTED_END_DATE" IS NOT NULL).

BR-PRJ-008 — Default ExpectedEndDate = start + 1 giorno (date-logic, magic number)

  • Tipo: date-logic · Enforcement: BL · Confidence: VERIFIED · Customer-specific: no
  • Statement: Se ExpectedEndDate è DateTime.MinValue (non impostata), la BL la forza a ExpectedStartDate.AddDays(1). Magic number: +1 giorno.
  • Evidenza: Project_BL.vb:300-302.

BR-PRJ-009 — START_DATE/END_DATE inizializzate alle date previste

  • Tipo: calculation · Enforcement: mixed (UI + DB) · Confidence: VERIFIED · Customer-specific: no
  • Statement: Le date effettive di inizio/fine sono inizializzate a quelle previste. La UI setta prj.InfoBase.StartDate = ExpectedStartDate e EndDate = ExpectedEndDate; la SP inserisce comunque START_DATE = PEXPECTED_START_DATE, END_DATE = PEXPECTED_END_DATE (copia dei parametri expected, ignora i valori Start/End passati nell'insert — la SP di insert non ha parametri Start/End dedicati).
  • Evidenza: ProjectInsert.ascx.cs:172-173; PRJ_INSERTPROJECT src:21,26 (VALUES usano PEXPECTED_START_DATE/PEXPECTED_END_DATE nelle posizioni START_DATE/END_DATE).

BR-PRJ-010 — Validazione client conformità date

  • Tipo: validation · Enforcement: UI (client-side) · Confidence: SUPPORTED · Customer-specific: no
  • Statement: La coerenza tra data inizio e fine (previste ed effettive) è controllata lato client da CustomValidator con ClientValidationFunction validateExDate/validateDate (messaggio "Data inizio e fine ... non conformi"). Flag UI-only: nessun controllo equivalente a BL/DB (nessun constraint CHECK end>start su PROJECT); un chiamante non-UI (es. import/WCF) può creare un progetto con date incoerenti.
  • Evidenza: ProjectInfoUpdate.ascx:216-222,246-252,275-281,308-314. Le funzioni JS non sono ispezionate in dettaglio (⇒ SUPPORTED).

BR-PRJ-011 — CREATED = SYSDATE

  • Tipo: calculation · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: La data di creazione è impostata dalla SP a SYSDATE (server-side, non dal client). La colonna è NOT NULL.
  • Evidenza: PRJ_INSERTPROJECT src:21,26 (... CREATED ... VALUES (... SYSDATE ...)); constraint SYS_C001719763 ("CREATED" IS NOT NULL).

BR-PRJ-012 — EFFECTIVE_COST NOT NULL con default 0 (DB-only)

  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: EFFECTIVE_COST è NOT NULL ma non è tra le colonne dell'INSERT della SP; il valore è fornito dal default di colonna 0. Rule enforced solo in SQL, invisibile dal codice applicativo.
  • Evidenza: constraint SYS_C001719762 ("EFFECTIVE_COST" IS NOT NULL); USER_TAB_COLUMNS PROJECT.EFFECTIVE_COST nullable=N, data_default=0; PRJ_INSERTPROJECT src:18-26 (colonna assente).

BR-PRJ-013 — Workflow di 8 stati standard + stato iniziale Bozza (magic numbers)

  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: PRJ_INSERTPROJECTSTATUS inserisce sempre 8 righe fisse in PROJECT_STATUS: Bozza(0), Pubblicato(1), In Corso(2), Approvato(3), Eseguito(4), Annullato(5), Sospeso(6), Cancellato(7). La riga "Bozza" restituisce ID_PROJECT_STATUS (OUT PNEWINDEX), usato per UPDATE PROJECT SET ID_PROJECT_STATUS = <Bozza>. Ogni progetto nasce in stato "Bozza". I nomi degli stati sono hard-coded (magic strings/numbers) nella procedura.
  • Evidenza: PRJ_INSERTPROJECTSTATUS src:6-9 (Bozza + RETURNING), src:11-44 (altri 7 stati), src:47-49 (UPDATE PROJECT SET ID_PROJECT_STATUS = PNEWINDEX); Project_BL.vb:309.

BR-PRJ-014 — ORDER_ID di visualizzazione disallineato da ID_STATUS (hidden mapping)

  • Tipo: config-flag · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: L'ordinamento di visualizzazione (ORDER_ID) non segue l'enum ID_STATUS. Mapping fisso: Bozza→3, Pubblicato→4, In Corso→6, Approvato→5, Eseguito→7, Annullato→1, Sospeso→2, Cancellato→0. Magic numbers hard-coded; l'ordine visuale (Cancellato=0 primo, Eseguito=7 ultimo) differisce dall'ordine logico dell'enum.
  • Evidenza: PRJ_INSERTPROJECTSTATUS src:9,14,19,24,29,34,39,44 (valori ORDER_ID).

BR-PRJ-015 — Storico iniziale alla creazione

  • Tipo: process · Enforcement: mixed (BL + DB) · Confidence: VERIFIED · Customer-specific: no
  • Statement: Subito dopo la creazione degli stati, la BL scrive una riga iniziale in PROJECT_HISTORY con InsertHistory(idPrj, 0, idPrjStatus, idcontact). La SP imposta MODIFIED = SYSDATE; con PID_ACTIVITY = 0 inserisce senza colonna ID_ACTIVITY, altrimenti la include. Registra lo stato Bozza e il contatto operatore.
  • Evidenza: Project_BL.vb:313; PRJ_INSERTPROJECTHISTORY src:8-21.

BR-PRJ-016 — Inserimento team in loop (ramo ridondante — probabile difetto)

  • Tipo: process · Enforcement: BL · Confidence: VERIFIED · Customer-specific: no
  • Statement: Ogni membro di prj.Team è inserito con PRJ_INSERTPROJECTTEAM. Il codice ramifica su If Not team.IdContact = idcontact ... Else ..., ma entrambi i rami chiamano InsertTeam con gli stessi identici argomenti (nel ramo Else idcontact coincide con team.IdContact). Probabile difetto/dead branch: la condizione non produce comportamento differente ed è logica ridondante.
  • Evidenza: Project_BL.vb:317-323.

BR-PRJ-017 — ID_COMPANY del team opzionale (ramo condizionale DB)

  • Tipo: config-flag · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: PRJ_INSERTPROJECTTEAM inserisce senza colonna ID_COMPANY quando PID_COMPANY IS NULL, altrimenti la include. L'azienda del membro è quindi opzionale.
  • Evidenza: PRJ_INSERTPROJECTTEAM src:13-24.

BR-PRJ-018 — Associazione tag con sentinella {0}

  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: PRJ_ADDTAGSTOPROJECT (chiamata dentro PRJ_INSERTPROJECT) inserisce le associazioni in PROJECT_TAG_ASS solo se la lista NON è il sentinella {0} (COUNT = 1 AND (1) = 0). Con lista {0} (nessun tag selezionato) non viene inserito alcun tag. Magic/sentinel: 0 = "nessun tag".
  • Evidenza: PRJ_INSERTPROJECT src:29; PRJ_ADDTAGSTOPROJECT src:7-9 (skip), src:11-16 (INSERT da TABLE(CAST(tmplist AS MYINTTABLE))).

BR-PRJ-019 — Lista tag come associative array PL/SQL

  • Tipo: process · Enforcement: mixed (BL + DB) · Confidence: VERIFIED · Customer-specific: no
  • Statement: La lista di id tag è passata come OracleCollectionType.PLSQLAssociativeArray mappato sul tipo Oracle HELPERS.numberlist, deserializzato in MYINTTABLE da HELPERS.numberlist2TBL; non è una stringa CSV/XML.
  • Evidenza: ProjectDAL.vb:194-195 (CollectionType = PLSQLAssociativeArray); PRJ_INSERTPROJECT src:10 (PIDTAGLIST IN HELPERS.numberlist); PRJ_ADDTAGSTOPROJECT src:4 (HELPERS.numberlist2TBL).

BR-PRJ-020 — Categoria opzionale (sentinella 0)

  • Tipo: config-flag · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: La procedura ramifica su PID_CATEGORY <> 0: se diverso da 0 esegue l'INSERT con colonna ID_CATEGORY, altrimenti l'INSERT senza categoria. Sentinel: 0 = nessuna categoria. Il parametro è alimentato da prj.Category.ID_DTO.
  • Evidenza: PRJ_INSERTPROJECT src:16-27; ProjectDAL.vb:233 (PID_CATEGORY = prj.Category.ID_DTO).

BR-PRJ-021 — Costi per categoria gestiti per Status del DTO

  • Tipo: process · Enforcement: BL · Confidence: VERIFIED · Customer-specific: no
  • Statement: Per ogni ProjectCategoryCost la BL sceglie l'operazione in base a cc.Status: Status.EmptyDeleteCategoryCost, Status.NewObjectInsertCategoryCost, Status.OnDBModifiedOjectUpdateCategoryCost. Stessa logica riusata in insert e update (in creazione ci si attende prevalentemente NewObject).
  • Evidenza: Project_BL.vb:331-343.

BR-PRJ-022 — Allegati gestiti post-insert

  • Tipo: process · Enforcement: mixed (UI + DB) · Confidence: SUPPORTED · Customer-specific: no
  • Statement: Dopo la creazione del progetto, la UI itera i file temporanei (~/App_Data/ProjectTmpAttachs/<UserName>), li carica in GLOBAL_DOCUMENTS (ctrDoc.UploadDocument), li associa con prjCtrl.InsertAttachmentPRJ_INSERTPROJECTATTACHMENT (INSERT in PROJECT_ATTACHMENTS), poi cancella il file temporaneo.
  • Evidenza: ProjectInsert.ascx.cs:181-203; ProjectDAL.vb:342; PRJ_INSERTPROJECTATTACHMENT src:5-8.

BR-PRJ-023 — Campi custom serializzati nel CLOB FIELDS

  • Tipo: process · Enforcement: BL · Confidence: SUPPORTED · Customer-specific: no
  • Statement: I campi custom (prj.Fields) sono serializzati da createExtraField(prj.Fields) e passati come parametro CLOB PFIELDS, memorizzato nella colonna FIELDS. Il formato di serializzazione non è ispezionato in dettaglio.
  • Evidenza: ProjectDAL.vb:191,232 (PFIELDS ... createExtraField(prj.Fields)); PRJ_INSERTPROJECT src:9 (PFIELDS IN CLOB).

BR-PRJ-024 — Assenza di controlli di grant nel path di insert (security flag)

  • Tipo: permission · Enforcement: none / UI-a-monte · Confidence: INFERRED · Customer-specific: no
  • Statement: Nel path di creazione progetto NON risultano check di autorizzazione/grant né nel code-behind (ProjectInsert.ascx.cs) né nella BL (Project_BL.Insert), a differenza del dominio Property (che richiede grant ADD_DELETE/tenancy). Flag: l'unica barriera è l'accesso alla pagina/menu (UI-a-monte, non verificato). Il boundary .NET Remoting tra ProjectController e Project_BL non ri-verifica i grant (pattern TD-008): un chiamante che raggiunge l'endpoint IProject_BL può creare progetti senza controllo di permessi lato server.
  • Evidenza: assenza di grep hit per grant|permission|authoriz in ProjectInsert.ascx.cs e AddProject.aspx.cs; Project_BL.vb:293-350 (nessun controllo grant); boundary Remoting DAOFactory.vb (Case Ctrl_Project, Activator.GetObject(GetType(IProject_BL), ...)); Project_BL.vb:22-24 (Inherits MarshalByRefObject).

BR-PRJ-025 — Transazionalità non garantita (probabile difetto)

  • Tipo: process · Enforcement: BL · Confidence: INFERRED · Customer-specific: no
  • Statement: Project_BL.Insert invoca gli overload DAL senza DataLayer condiviso (Insert, InsertProjectStatus, InsertHistory, InsertTeam aprono ciascuno Using dl As New DataLayer(...)), quindi ogni SP gira su una connessione/transazione propria. Probabile difetto: un fallimento parziale (es. durante l'inserimento del team o delle attività) può lasciare committati progetto + stati + storico, con stato incoerente. Esiste un overload transazionale (Insert(..., ByRef dl)) ma non è usato in questa orchestrazione.
  • Evidenza: Project_BL.vb:305,309,313,319 (overload senza dl); ProjectDAL.vb:223,287 (Using dl As New DataLayer(My.Settings.ConnectionName)); overload transazionale disponibile a ProjectDAL.vb:180,262,353.

BR-PRJ-026 — ID_PROJECT immutabile in update

  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED · Customer-specific: no
  • Statement: Il trigger CNT_PROJECT sul ramo UPDATE solleva RAISE_APPLICATION_ERROR(-20000, 'Non posso cambiare il contatore per la tabella PROJECT') se :new.ID_PROJECT <> :old.ID_PROJECT. La chiave primaria del progetto è quindi immutabile.
  • Evidenza: CNT_PROJECT src:25-33.

BR-PRJ-027 — Storicizzazione ad ogni update

  • Tipo: process · Enforcement: mixed (BL + DB) · Confidence: VERIFIED · Customer-specific: no
  • Statement: In Project_BL.Update, dopo la modifica del progetto viene sempre scritta una riga di storico (InsertHistory(prj.ID_DTO, 0, prj.InfoBase.InternalStatus.ID_DTO, idcontact)) per registrare lo stato corrente al momento della modifica. La BL rilegge prima lo stato precedente (SelectById) per diffare team e costi.
  • Evidenza: Project_BL.vb:363-370; PRJ_INSERTPROJECTHISTORY src:8-21.

Open questions / follow-up

  • Doppia generazione codice (BR-PRJ-003 vs BR-PRJ-004): verificare se il codice del trigger e quello parametrico possano divergere e se il parametrico è sempre attivo (dipende dalla config cliente del motore Parametric.Project).
  • Transazionalità (BR-PRJ-025): confermare la policy commit/rollback del DataLayer (autocommit per ExecuteNonQueryStoredProcedure?) per stabilire la reale estensione del rischio di stato parziale.
  • Grant (BR-PRJ-024): verificare se esiste un controllo di accesso a monte (menu/pagina) o se la creazione progetto è effettivamente priva di autorizzazione lato server.
  • Date incoerenti (BR-PRJ-010): assenza di constraint DB end>start; valutare se path non-UI possano introdurre date incoerenti.
  • BUDGET Int32: il parametro PBUDGET è passato come OracleDbType.Int32 mentre la colonna è NUMBER — potenziale troncamento di budget con decimali (ProjectDAL.vb:189). Da confermare il tipo di prj.Costs.Budget.