Table of Contents

BR-DOC — Regole di business del dominio Document (documentale core / DocCenter)

Regole estratte dal dominio Document (entità core del documentale, tabelle DOCS_* dello schema Oracle INFOCAD_TEST38), ancorate al flusso pilota FLOW-DOC-001 (creazione di un documento con allegato principale, tag, attributi custom, protocollo di sistema) e ai percorsi di aggiornamento, rinnovo e revisione. Sistema: Infocad (Descor), backend Oracle, front-end ASP.NET Web Forms (VB.NET) su DocCenterWeb, server DocumentController → Document_BL → Document_DAL, comunicazione controller↔BL via .NET Remoting, nessun ORM (stored procedure DOC_* invocate via ExecuteNonQueryStoredProcedure).

Distinzione: qui si documenta la scrittura sull'entità documento core (DOCS_DOCUMENT e satelliti). Il salvataggio del file fisico su ECM esterno (Alfresco/OpenText/Docs) è un percorso separato coperto da BR-ECM; la relazione tra i due è nella regola BR-DOC-028.

Legenda enforcement: UI = validato solo lato interfaccia/code-behind · BL = logica applicativa (code-behind/BL) · DB = vincolo/logica in stored procedure, constraint o trigger · mixed = più livelli. Legenda confidence: VERIFIED = catena di codice + controprova indipendente (sorgente DB o secondo artefatto) · SUPPORTED = evidenza di codice coerente ma un anello non eseguibile/non isolato · INFERRED = dedotto.

Le stored procedure DOC_*, i vincoli, i default di colonna e i trigger citati sono stati confermati con lookup read-only bounded su USER_SOURCE, USER_TRIGGERS e sul catalogo colonne/constraint dello schema INFOCAD_TEST38 (driver oracledb thin, sola lettura del testo di procedure/trigger e dei metadati di tabella — nessun accesso a dati di business, nessuna DML/DDL).


Registro regole

ID Regola (sintesi) Tipo Enforcement Conf. Cust.
BR-DOC-001 Il protocollo di sistema è generato eseguendo una formula SQL dinamica letta da DOCS_PROTOCOLFORMAT, non da una sequence calculation mixed (DB/BL) VERIFIED no
BR-DOC-002 Il protocollo finale = CInt(numero).ToString(FORMAT) + SUFFIX; la colonna REGEXPRESSION è in realtà una stringa di formato .NET calculation BL VERIFIED no
BR-DOC-003 DOCS_PROTOCOLFORMAT è letta con SELECT INTO senza WHERE: attesa riga singola (>1 riga → TOO_MANY_ROWS) data-integrity DB VERIFIED no
BR-DOC-004 Nessun incremento atomico del progressivo di protocollo (SEQ_DOCS_PROTOCOL commentata) → rischio collisione su concorrenza defect/concurrency DB SUPPORTED no
BR-DOC-005 Anti-duplicato in creazione: confronto descrizione + nome file + data + categoria + scadenze; saltato se descrizione vuota validation UI-only VERIFIED no
BR-DOC-006 L'allegato principale viene creato solo se il BLOB non è nullo (IF NOT PDOCUMENTFILE IS NULL) state-transition DB VERIFIED no
BR-DOC-007 ID_DOCUMENT / ID_ATTACHMENT assegnati da trigger BEFORE INSERT via SEQ_DOCS_DOCUMENT / SEQ_DOCS_ATTACHMENT calculation DB VERIFIED no
BR-DOC-008 Colonne NOT NULL di DOCS_DOCUMENT: DESCRIPTION, IS_LAST_VERSION, RELATION_TYPE(def 0), ISVALID(def 0), VERSION(def 1), CREATED(def SYSDATE) data-integrity DB VERIFIED no
BR-DOC-009 Colonne NOT NULL di DOCS_ATTACHMENT: FILE_SIZE, FILE_EXTENSION, FILE_NAME, DOCUMENT_FILE data-integrity DB VERIFIED no
BR-DOC-010 La categoria non è obbligatoria a DB (ID_CATEGORY nullable); la DAL converte idCategory = 0 in NULL validation mixed (DB/BL) VERIFIED no
BR-DOC-011 I tag sono associati in blocco (bulk insert da array PL/SQL) via DOC_ADDTAGSTODOCUMENT state-transition DB VERIFIED no
BR-DOC-012 DOCS_TAG_DOCUMENT non ha PK né unique → possibili associazioni tag↔documento duplicate data-integrity DB VERIFIED no
BR-DOC-013 Il ricalcolo del peso tag (DOC_REFRESHTAGWEIGHT) è commentato → peso non aggiornato in creazione defect DB VERIFIED no
BR-DOC-014 Gli attributi custom sono inseriti fuori dalla transazione del documento (Try isolato, log-only): fallimento parziale = documento senza attributi error-handling BL VERIFIED no
BR-DOC-015 Attributi custom in 4 tipi (STRING/LIST/NUMBER/DATE); il valore DATE è letto dal campo RadDate_<id> calculation BL VERIFIED no
BR-DOC-016 Gli attributi specifici sono presi dalla categoria padre (GetAttributesByCategory(Category.IdParent)), non dalla categoria stessa calculation BL SUPPORTED no
BR-DOC-017 L'update del documento sostituisce integralmente i tag (DOC_REMOVEALLTAGSFROMDOCUMENT + DOC_ADDTAGSTODOCUMENT) state-transition DB VERIFIED no
BR-DOC-018 L'update non modifica SYS_PROTOCOLVERSION (protocollo e versione di sistema immutabili in update) data-integrity DB VERIFIED no
BR-DOC-019 In update, se non c'è nuovo file e PIDATTACHMENT è 0/NULL, ID_ATTACHMENT viene azzerato a NULL (sgancio allegato) data-integrity DB VERIFIED no
BR-DOC-020 Rinnovo (DOC_RENEWDOCUMENT): crea un documento figlio con ID_PARENT = vecchio, RELATION_TYPE = 0; il vecchio non viene toccato state-transition DB VERIFIED no
BR-DOC-021 Revisione (DOC_REVIEWDOCUMENT): nuova versione con ID_PREVIOUS_VERSION = vecchio, RELATION_TYPE = 1, VERSION = old+1; il vecchio → IS_LAST_VERSION = 0, ID_NEXT_VERSION = nuovo state-transition DB VERIFIED no
BR-DOC-022 Magic number RELATION_TYPE: 0 = creazione/rinnovo, 1 = revisione/versione magic-number DB VERIFIED no
BR-DOC-023 Il documento creato dal wizard ha IS_LAST_VERSION = 0 (DTO default False, mai impostato in creazione) defect mixed (BL/DB) SUPPORTED no
BR-DOC-024 Stamping alla creazione: START_DATE = SYSDATE, END_DATE = NULL, CREATEDBY = SessionContact.ID_DTO calculation mixed (BL/DB) VERIFIED no
BR-DOC-025 Se il workflow non trova il contatto, il documento appena creato viene cancellato fisicamente (DOC_PHYSICALDELETEDOCUMENT) + scadenze error-handling/state mixed VERIFIED no
BR-DOC-026 Inserimento "da cancellato": se InsertCancelled il documento è messo subito in delete logico dopo l'insert state-transition BL VERIFIED
BR-DOC-027 Tenancy del documento assegnata con permesso hard-coded 2 sul tenant corrente magic-number BL VERIFIED no
BR-DOC-028 La creazione core non invoca l'ECM esterno; l'aggancio ECM avviene solo in pubblicazione (vedi BR-ECM) integration mixed SUPPORTED no
BR-DOC-029 Il wiring DocumentController → IDocument_BL è via .NET Remoting: i grant/autorizzazioni UI non sono ri-verificati dal servizio (pattern TD-008) security BL SUPPORTED no

Dettaglio regole

BR-DOC-001 — Protocollo di sistema da formula dinamica (non da sequence)

  • Regola: il progressivo/protocollo di sistema non è generato da una sequence Oracle ma eseguendo dinamicamente (DBMS_SQL) la formula SQL memorizzata nella colonna PROTOCOLFORMULA di DOCS_PROTOCOLFORMAT; il risultato è il numero grezzo del protocollo. La stessa procedura è chiamata da Insert, Renew e Review.
  • Tipo: calculation · Enforcement: mixed (DB/BL) · Confidence: VERIFIED · customer_specific: false
  • Evidenza: Document_DAL.vb:359 (ExecuteNonQueryStoredProcedure("DOC_GETNEWDOCPROTOCOL")), analoghi :1680, :1816; controprova DB (USER_SOURCE) DOC_GETNEWDOCPROTOCOL: SELECT PROTOCOLFORMULA, REGEXPRESSION, SUFFIX INTO SQLSTR, PPROTOCOLREGEX, PSUFFIX FROM DOCS_PROTOCOLFORMAT; poi DBMS_SQL.PARSE(EXEC_CURSOR, SQLSTR, ...) / EXECUTE_AND_FETCHPPROTOCOL.
  • Note: il "numero" dipende interamente dalla query configurata in PROTOCOLFORMULA (tipicamente un MAX(...)+1 o simile): logica di numerazione spostata nei dati, non nel codice.

BR-DOC-002 — Composizione del protocollo (format .NET + suffisso)

  • Regola: il protocollo finale è composto lato DAL come String.Format("{0}{1}", CInt(numeroGrezzo).ToString(Expression), Suffix), dove Expression proviene dalla colonna REGEXPRESSION (usata come stringa di formato numerico .NET, es. padding/zeri) e Suffix dalla colonna SUFFIX.
  • Tipo: calculation · Enforcement: BL · Confidence: VERIFIED · customer_specific: false
  • Evidenza: Document_DAL.vb:361-364 (Protocol = String.Format("{0}{1}", CInt(Protocol).ToString(Expression), Suffix)); ripetuto identico in Renew :1685 e Review :1821.
  • Note: naming fuorviante — la colonna si chiama REGEXPRESSION ma è consumata come format string di Integer.ToString(...), non come regex. CInt(Protocol) presuppone che il numero grezzo sia un intero valido: una formula che restituisca non-numerico solleva eccezione.

BR-DOC-003 — DOCS_PROTOCOLFORMAT atteso come riga singola

  • Regola: la configurazione di protocollo è letta con SELECT ... INTO ... FROM DOCS_PROTOCOLFORMAT senza clausola WHERE: la procedura assume una sola riga di configurazione; con più di una riga Oracle solleva TOO_MANY_ROWS, con zero righe NO_DATA_FOUND.
  • Tipo: data-integrity · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_GETNEWDOCPROTOCOL (USER_SOURCE): SELECT PROTOCOLFORMULA, REGEXPRESSION, SUFFIX INTO ... FROM DOCS_PROTOCOLFORMAT; (nessun predicato).
  • Note: singleton di configurazione implicito, non protetto da vincolo.

BR-DOC-004 — Nessun incremento atomico del progressivo (rischio concorrenza)

  • Regola: l'incremento del progressivo tramite sequence dedicata (SEQ_DOCS_PROTOCOL.NEXTVAL) è commentato; il numero deriva dall'esecuzione della formula (BR-DOC-001). Non essendoci né sequence né lock, due creazioni concorrenti che eseguono la stessa formula (MAX+1) possono ottenere lo stesso protocollo.
  • Tipo: defect/concurrency · Enforcement: DB · Confidence: SUPPORTED · customer_specific: false
  • Evidenza: controprova DB DOC_GETNEWDOCPROTOCOL: --SELECT SEQ_DOCS_PROTOCOL.NEXTVAL INTO tmpNextVal FROM DUAL; (commentata) e --tmpNextVal NUMBER;.
  • Note: probable defect — nessun UNIQUE su SYS_PROTOCOL in DOCS_DOCUMENT (vedi elenco constraint BR-DOC-008) a difesa della collisione. Coerente con l'open question di FLOW-DOC-001.

BR-DOC-005 — Controllo anti-duplicato in creazione (solo UI)

  • Regola: prima dell'insert, se la descrizione è valorizzata, checkNoExistDocument recupera i documenti con stessa descrizione (SelectByDescription) e considera duplicato quello con stessa descrizione + stesso nome file (upper) + stessa DocumentDate + stesso codice categoria + stesse scadenze; se duplicato, l'insert non viene eseguito e si mostra DocExistMessage. Con descrizione vuota il controllo è saltato (noExistDocument = True).
  • Tipo: validation · Enforcement: UI-only · Confidence: VERIFIED · customer_specific: false
  • Evidenza: DocumentCreateControl.ascx.vb:321-323 (skip se descrizione vuota), :417-459 (checkNoExistDocument, confronto descrizione/filename/data/categoria/deadline), :326-327 (insert solo se noExistDocument), :396-398 (ramo duplicato).
  • Note: regola solo UI — bypassabile da percorsi non interattivi (upload massivo, custom): nessun vincolo DB impedisce documenti "gemelli".

BR-DOC-006 — Allegato principale creato solo con BLOB presente

  • Regola: DOC_CREATEDOCUMENT inserisce in DOCS_ATTACHMENT (via DOC_CREATEATTACHMENT) solo se il BLOB PDOCUMENTFILE non è nullo; altrimenti ID_ATTACHMENT del documento resta nullo. Stessa condizione in Renew, Review e (con logica estesa) Update.
  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_CREATEDOCUMENT: IF NOT PDOCUMENTFILE IS NULL THEN DOC_CREATEATTACHMENT(...); END IF;; identico in DOC_RENEWDOCUMENT, DOC_REVIEWDOCUMENT; DOC_UPDATEDOCUMENT IF PDOCUMENTFILE IS NOT NULL THEN ....

BR-DOC-007 — Chiavi surrogate da trigger BEFORE INSERT

  • Regola: ID_DOCUMENT e ID_ATTACHMENT sono assegnati da trigger BEFORE INSERT che, se la chiave arriva NULL, prende SEQ_DOCS_DOCUMENT.NEXTVAL / SEQ_DOCS_ATTACHMENT.NEXTVAL; se la chiave arriva valorizzata, il trigger fa avanzare la sequence fino a superare il valore inserito (protezione contro import con id espliciti).
  • Tipo: calculation · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB (USER_TRIGGERS) trigger DOCS_DOCUMENT: IF (:NEW."ID_DOCUMENT" IS NULL) THEN SELECT "SEQ_DOCS_DOCUMENT".NEXTVAL INTO :NEW."ID_DOCUMENT" FROM DUAL; ELSE ... WHILE (last_InsertID > last_Sequence) LOOP ... NEXTVAL ...; trigger analogo su DOCS_ATTACHMENT con SEQ_DOCS_ATTACHMENT. Le SP usano RETURNING ID_DOCUMENT/ID_ATTACHMENT INTO PNEWINDEX.
  • Note: il ciclo WHILE di riallineamento sequence è O(n) sul gap → costoso se si inserisce un id molto maggiore del corrente.

BR-DOC-008 — Vincoli NOT NULL e default di DOCS_DOCUMENT

  • Regola: DOCS_DOCUMENT impone NOT NULL su DESCRIPTION, IS_LAST_VERSION, RELATION_TYPE, ISVALID, VERSION, CREATED (oltre a ID_DOCUMENT). Default di colonna: RELATION_TYPE = 0, ISCANCELLED = 0, ID_DOC_SITE = 0, ISVALID = 0, VERSION = 1, CREATED = SYSDATE, NUM_ATTACH = 0.
  • Tipo: data-integrity · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: catalogo constraint INFOCAD_TEST38.DOCS_DOCUMENT — check "DESCRIPTION" IS NOT NULL, "IS_LAST_VERSION" IS NOT NULL, "RELATION_TYPE" IS NOT NULL, "ISVALID" IS NOT NULL, "VERSION" IS NOT NULL, "CREATED" IS NOT NULL; default colonne RELATION_TYPE=0, ISVALID=0, VERSION=1, CREATED=SYSDATE (da docs/_generated/db-detail.json, verificato su metadati DB).
  • Note: SYS_PROTOCOL/USER_PROTOCOL/USER_VERSION sono nullable e senza UNIQUE (rilevante per BR-DOC-004). Self-FK ID_PARENT, ID_PREVIOUS_VERSION, ID_NEXT_VERSION sostengono le relazioni di versione/rinnovo.

BR-DOC-009 — Vincoli NOT NULL di DOCS_ATTACHMENT

  • Regola: DOCS_ATTACHMENT impone NOT NULL su FILE_SIZE, FILE_EXTENSION, FILE_NAME, DOCUMENT_FILE (oltre a ID_ATTACHMENT). Un allegato senza estensione, nome, dimensione o contenuto binario è rifiutato a livello DB.
  • Tipo: data-integrity · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: catalogo constraint INFOCAD_TEST38.DOCS_ATTACHMENT — check "FILE_SIZE" IS NOT NULL, "FILE_EXTENSION" IS NOT NULL, "FILE_NAME" IS NOT NULL, "DOCUMENT_FILE" IS NOT NULL (da db-detail.json). CONTENT_TYPE è nullable.
  • Note: la creazione dell'attachment è condizionata alla presenza del BLOB (BR-DOC-006), quindi in pratica questi campi arrivano valorizzati; ma un allegato con FileSize = 0/estensione vuota fallirebbe qui.

BR-DOC-010 — Categoria non obbligatoria a DB; 0 → NULL

  • Regola: ID_CATEGORY è nullable in DOCS_DOCUMENT; la DAL, prima di invocare la SP, converte idCategory = 0 (o assente) in DBNull.Value. L'eventuale obbligatorietà della categoria è imposta solo lato UI (vedi BR-ECM-016).
  • Tipo: validation · Enforcement: mixed (DB/BL) · Confidence: VERIFIED · customer_specific: false
  • Evidenza: Document_DAL.vb:418-427 (Insert: If idCategory = 0 Then idcategoryparam.Value = DBNull.Value), analogo Renew :1732-1741; controprova DB DOC_RENEWDOCUMENT/DOC_REVIEWDOCUMENT/DOC_UPDATEDOCUMENT: IF PNULLABLECATEGORY IS NULL OR PNULLABLECATEGORY = 0 THEN PNULLABLECATEGORY := NULL;; colonna ID_CATEGORY nullable (catalogo).
  • Note: percorsi che bypassano la validazione UI possono creare documenti senza categoria.

BR-DOC-011 — Associazione tag in blocco

  • Regola: i tag selezionati sono passati come array PL/SQL (PIDTAGLIST, PLSQLAssociativeArray) e inseriti in blocco in DOCS_TAG_DOCUMENT da DOC_ADDTAGSTODOCUMENT con un unico INSERT ... SELECT dall'array; una riga (ID_TAG, ID_DOCUMENT) per ciascun tag.
  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: Document_DAL.vb:396-397 (PIDTAGLIST, CollectionType = OracleCollectionType.PLSQLAssociativeArray); controprova DB DOC_ADDTAGSTODOCUMENT: INSERT INTO DOCS_TAG_DOCUMENT (ID_TAG, ID_DOCUMENT) (SELECT ASR.*, PIDDOCUMENT FROM (SELECT * FROM TABLE(CAST(tmplist AS MYINTTABLE))) ASR);.

BR-DOC-012 — DOCS_TAG_DOCUMENT senza PK/unique (duplicati possibili)

  • Regola: la tabella di associazione DOCS_TAG_DOCUMENT non ha primary key né unique; le colonne ID_TAG/ID_DOCUMENT sono anche nullable. Nulla impedisce a livello DB associazioni tag↔documento duplicate.
  • Tipo: data-integrity · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: catalogo INFOCAD_TEST38.DOCS_TAG_DOCUMENTpk: [], uniques: [], colonne ID_TAG/ID_DOCUMENT nullable, con sole FK verso DOCS_TAG e DOCS_DOCUMENT (da db-detail.json).
  • Note: in update la pulizia integrale (BR-DOC-017) mitiga l'accumulo, ma un doppio invio in creazione o inserimenti concorrenti possono duplicare le righe.

BR-DOC-013 — Peso dei tag non ricalcolato in creazione

  • Regola: il ricalcolo del "peso" dei tag (DOC_REFRESHTAGWEIGHT) all'interno di DOC_ADDTAGSTODOCUMENT è commentato: creando/associando tag il loro peso non viene aggiornato.
  • Tipo: defect · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_ADDTAGSTODOCUMENT: blocco -- FOR I IN PIDTAGLIST.FIRST..PIDTAGLIST.LAST LOOP -- DOC_REFRESHTAGWEIGHT(PIDTAGLIST(I)); -- END LOOP; interamente commentato.
  • Note: coerente con l'open question di FLOW-DOC-001; comportamento probabilmente disattivato di proposito ma non documentato.

BR-DOC-014 — Attributi custom fuori transazione (log-only)

  • Regola: nel BL, l'inserimento degli attributi custom (generici e specifici) avviene in un Try/Catch separato rispetto all'insert del documento: un errore sugli attributi viene solo loggato (ExceptionLogger.LogException) e non annulla il documento già creato. Stesso pattern in Insert, Renew, Review.
  • Tipo: error-handling · Enforcement: BL · Confidence: VERIFIED · customer_specific: false
  • Evidenza: Document_BL.vb:57-79 (Insert: attributi in Try isolato, Catch ... LogException), :81 (Return idDoc); analoghi Renew :816-838, Review :881-903.
  • Note: probable data-integrity gap — documento persistito senza i suoi attributi in caso di errore parziale; nessuna atomicità con DOCS_DOCUMENT.

BR-DOC-015 — Tipizzazione degli attributi custom

  • Regola: gli attributi custom sono classificati per Type in quattro categorie (STRING, LIST, NUMBER, DATE, confronto in upper-case); per il tipo DATE il valore è letto da un campo di form denominato RadDate_<idAttributo>, per gli altri da un campo <idAttributo>. Per LIST un valore vuoto è salvato come Nothing.
  • Tipo: calculation · Enforcement: BL · Confidence: VERIFIED · customer_specific: false
  • Evidenza: DocumentCreateControl.ascx.vb:231-268 (attributi generici, RadDate_ a :267), :275-312 (attributi specifici, RadDate_ a :311).
  • Note: la SP DOC_ADDDOCATTRIBUTE dichiara PIDDOCUMENT IN VARCHAR2 (non NUMBER) — piccola incoerenza di tipo lato DB, l'id documento è passato come stringa e usato in INSERT INTO DOCS_DOCUMENT_ATTRIBUTE.

BR-DOC-016 — Attributi specifici presi dalla categoria padre

  • Regola: gli attributi custom "specifici" del documento sono caricati con docCtrl.GetAttributesByCategory(doc.Category.IdParent), cioè in base alla categoria padre della categoria selezionata, non alla categoria foglia direttamente.
  • Tipo: calculation · Enforcement: BL · Confidence: SUPPORTED · customer_specific: false
  • Evidenza: DocumentCreateControl.ascx.vb:273-274 (If doc.Category IsNot Nothing Then For Each attribute ... In docCtrl.GetAttributesByCategory(CInt(doc.Category.IdParent))).
  • Note: possibile anomalia o convenzione (attributi ereditati dal livello padre); da confermare con il modello categorie. Se la categoria selezionata è radice (IdParent = 0/nullo) il set specifico può risultare vuoto.

BR-DOC-017 — Update = sostituzione integrale dei tag

  • Regola: l'aggiornamento di un documento rimuove tutti i tag esistenti e reinserisce quelli passati dal client: DOC_UPDATEDOCUMENT chiama DOC_REMOVEALLTAGSFROMDOCUMENT(PIDDOCUMENT) seguito da DOC_ADDTAGSTODOCUMENT(PIDTAGLIST, PIDDOCUMENT). Analogamente nel BL gli attributi custom sono cancellati e reinseriti (DeleteDocAttribute + AddDocAttribute).
  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_UPDATEDOCUMENT: DOC_REMOVEALLTAGSFROMDOCUMENT(PIDDOCUMENT); DOC_ADDTAGSTODOCUMENT(PIDTAGLIST, PIDDOCUMENT);; BL attributi Document_BL.vb:135-154 (DeleteDocAttribute + re-AddDocAttribute).
  • Note: nessun merge — un tag non presente nella lista passata viene perso. (Coerente con BR-ECM-019.)

BR-DOC-018 — Update non tocca SYS_PROTOCOL né VERSION

  • Regola: la UPDATE DOCS_DOCUMENT di DOC_UPDATEDOCUMENT aggiorna descrizione, note, ubicazione, validità, categoria, USER_PROTOCOL e USER_VERSION, ma non modifica SYS_PROTOCOLVERSION: protocollo di sistema e numero di versione restano quelli assegnati alla creazione.
  • Tipo: data-integrity · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_UPDATEDOCUMENT: la SET ... elenca USER_PROTOCOL = PUSERPROTOCOL, USER_VERSION = PUSERVERSION ma non SYS_PROTOCOLVERSION. La DAL Update (Document_DAL.vb:1395-1500) non passa alcun parametro PSYSPROTOCOL.
  • Note: solo la revisione (BR-DOC-021) incrementa VERSION; l'update in-place è "silente" sulla versione di sistema.

BR-DOC-019 — Update: sgancio dell'allegato se assente

  • Regola: in DOC_UPDATEDOCUMENT, se non viene passato un nuovo BLOB e PIDATTACHMENT è 0/NULL, la colonna ID_ATTACHMENT del documento viene impostata a NULL (allegato scollegato). Il BL, quando il DTO non ha allegato, forza Attachment.ID_DTO = 0 e DocumentFile = Nothing, innescando questo ramo.
  • Tipo: data-integrity · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_UPDATEDOCUMENT: ELSIF PIDATTACHMENT = 0 OR PIDATTACHMENT IS NULL THEN IDATTACHMENT := NULL; e SET ... ID_ATTACHMENT = IDATTACHMENT; BL Document_BL.vb:99-103 (If doc.Attachment Is Nothing Then ... ID_DTO = 0 : DocumentFile = Nothing).
  • Note: probable defect — un update che non ri-carica l'allegato può sganciare silenziosamente il file dal documento; la riga in DOCS_ATTACHMENT non viene cancellata (resta orfana).

BR-DOC-020 — Rinnovo = nuovo documento figlio (RELATION_TYPE 0)

  • Regola: DOC_RENEWDOCUMENT inserisce un nuovo documento con ID_PARENT = PIDOLDDOCUMENT e RELATION_TYPE = 0, riprendendo anagrafica/allegato/tag dal DTO; il documento di partenza non viene modificato (nessun aggiornamento di IS_LAST_VERSION/ID_NEXT_VERSION). Il nuovo documento riceve un nuovo protocollo di sistema.
  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_RENEWDOCUMENT: INSERT INTO DOCS_DOCUMENT (... ID_PARENT, RELATION_TYPE ...) VALUES (... PIDOLDDOCUMENT, 0, ...) RETURNING ID_DOCUMENT INTO PNEWINDEX; DOC_ADDTAGSTODOCUMENT(PIDTAGLIST, PNEWINDEX);; DAL Document_DAL.vb:1649-1773, BL Document_BL.vb:785-814 (doc.ParentID).
  • Note: il rinnovo è una relazione padre-figlio (ID_PARENT), distinta dalla catena di versione della revisione (BR-DOC-021).

BR-DOC-021 — Revisione = nuova versione in catena (RELATION_TYPE 1)

  • Regola: DOC_REVIEWDOCUMENT calcola NEWVERSION = VERSION_vecchio + 1, inserisce un nuovo documento con ID_PREVIOUS_VERSION = PIDOLDDOCUMENT, RELATION_TYPE = 1, VERSION = NEWVERSION, poi aggiorna il documento precedente ponendo IS_LAST_VERSION = 0 e ID_NEXT_VERSION = <nuovo>. Il nuovo documento riceve un nuovo protocollo di sistema.
  • Tipo: state-transition · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: controprova DB DOC_REVIEWDOCUMENT: SELECT (VERSION + 1) INTO NEWVERSION FROM DOCS_DOCUMENT WHERE ID_DOCUMENT = PIDOLDDOCUMENT;INSERT ... (ID_PREVIOUS_VERSION, RELATION_TYPE, VERSION ...) VALUES (... PIDOLDDOCUMENT, 1, NEWVERSION ...)UPDATE DOCS_DOCUMENT SET IS_LAST_VERSION = 0, ID_NEXT_VERSION = PNEWINDEX WHERE ID_DOCUMENT = PIDOLDDOCUMENT;; DAL Document_DAL.vb:1785-1904, BL Document_BL.vb:849-905 (doc.PreviousVersionID).
  • Note: la catena di versione è una lista concatenata (ID_PREVIOUS_VERSION/ID_NEXT_VERSION). Il flag IS_LAST_VERSION del nuovo documento è quello passato dal client (PISLASTVERSION): se il client non lo imposta a 1, la catena può restare senza "ultima versione" valorizzata (vedi BR-DOC-023).

BR-DOC-022 — Magic number RELATION_TYPE

  • Regola: la colonna RELATION_TYPE codifica il tipo di relazione del documento: 0 = documento standalone / rinnovo (creazione e DOC_RENEWDOCUMENT), 1 = revisione/versione (DOC_REVIEWDOCUMENT).
  • Tipo: magic-number · Enforcement: DB · Confidence: VERIFIED · customer_specific: false
  • Evidenza: DOC_CREATEDOCUMENT non valorizza RELATION_TYPE → default 0; DOC_RENEWDOCUMENT inserisce RELATION_TYPE = 0; DOC_REVIEWDOCUMENT inserisce RELATION_TYPE = 1 (controprova DB USER_SOURCE); default colonna RELATION_TYPE = 0 (catalogo).
  • Note: valori numerici hard-coded nel PL/SQL senza tabella di lookup; il significato è desumibile solo dal codice.

BR-DOC-023 — Documento creato con IS_LAST_VERSION = 0

  • Regola: il wizard di creazione istanzia New Objects.Document e non imposta mai doc.IsLastVersion; la property VB.NET default è False, quindi la DAL passa PISLASTVERSION = 0 e il documento viene creato con IS_LAST_VERSION = 0.
  • Tipo: defect · Enforcement: mixed (BL/DB) · Confidence: SUPPORTED · customer_specific: false
  • Evidenza: DocumentCreateControl.ascx.vb:180 (Dim doc As New Objects.Document) — nessuna assegnazione a doc.IsLastVersion nel percorso InsertDocument (:174-320); DTO DocumentSharedObjects/Objects/Document.vb:13 (Private _IsLastVersion As Boolean, default False); DAL Document_DAL.vb:372 (PISLASTVERSION da isLastVersion).
  • Note: probable defect — un documento appena creato risulterebbe "non ultima versione". Da verificare se un percorso a valle (workflow/pubblicazione) corregge il flag; altrimenti le viste che filtrano IS_LAST_VERSION = 1 non mostrerebbero i documenti nuovi.

BR-DOC-024 — Stamping alla creazione

  • Regola: alla creazione il documento riceve START_DATE = SYSDATE, END_DATE = NULL e CREATEDBY = WS.SessionContact.ID_DTO (l'utente autenticato). CREATED è valorizzata dal default di colonna (SYSDATE).
  • Tipo: calculation · Enforcement: mixed (BL/DB) · Confidence: VERIFIED · customer_specific: false
  • Evidenza: DocumentCreateControl.ascx.vb:181 (doc.CreatedBy = WS.SessionContact.ID_DTO); controprova DB DOC_CREATEDOCUMENT: INSERT ... (START_DATE, END_DATE, ... CREATEDBY ...) VALUES (... SYSDATE(), NULL, ... PCREATEDBY ...); default colonna CREATED = SYSDATE (catalogo).

BR-DOC-025 — Rollback fisico se manca il contatto workflow

  • Regola: dopo l'insert, l'ingresso in workflow (CreateWorkFlowEntryPoint) può fallire se non trova il contatto; in tal caso il documento appena creato viene cancellato fisicamente (docCtrl.FinalDeleteDOC_PHYSICALDELETEDOCUMENT) e le relative scadenze eliminate.
  • Tipo: error-handling/state · Enforcement: mixed · Confidence: VERIFIED · customer_specific: false
  • Evidenza: DocumentCreateControl.ascx.vb:358 (CreateWorkFlowEntryPoint), :360 (check ActionResult), :378-384 (ramo else: docCtrl.FinalDelete(newDocID) + deadCtrl.DeleteByIdDocument(newDocID)); DAL Document_DAL.vb:21-28 (FinalDeleteDOC_PHYSICALDELETEDOCUMENT).
  • Note: cancellazione fisica (non logica) del documento e dell'allegato; compensazione applicativa, non transazione DB.

BR-DOC-026 — Inserimento "da cancellato"

  • Regola: se la proprietà InsertCancelled è vera (accesso da RequestCenter/link al documentale o esigenze custom da property), subito dopo l'insert riuscito il documento viene messo in cancellazione logica (docCtrl.LogicalDeleteDOC_LOGICALDELETEDOCUMENT).
  • Tipo: state-transition · Enforcement: BL · Confidence: VERIFIED · customer_specific: true
  • Evidenza: DocumentCreateControl.ascx.vb:364-365 (commento "gestione di inserimento da cancellato se effettuo da RequestCenter…" + If InsertCancelled Then docCtrl.LogicalDelete(newDocID)); property :161 (Public Property InsertCancelled As Boolean); DAL Document_DAL.vb:38-45 (DOC_LOGICALDELETEDOCUMENT).
  • Note: variante di comportamento cliente-specifica (integrazione RequestCenter); il documento nasce già cancellato logicamente.

BR-DOC-027 — Tenancy con permesso hard-coded 2

  • Regola: alla creazione, il documento è assegnato al tenant corrente (WS.CurrentTenant.ID_DTO) con livello di permesso 2 codificato in modo fisso, tramite SetDocumentTenancies("DOCUMENT", newDocID, ...).
  • Tipo: magic-number · Enforcement: BL · Confidence: VERIFIED · customer_specific: false
  • Evidenza: DocumentCreateControl.ascx.vb:347-351 (tenancyIDs.Add(WS.CurrentTenant.ID_DTO), perms.Add(2), docCtrl.SetDocumentTenancies("DOCUMENT", newDocID, tenancyIDs, perms, True)); DAL Document_DAL.vb:2606 (DOC_SETDOCUMENTTENANTS).
  • Note: magic number 2 (significato del livello permesso non esplicitato) e stringa entità "DOCUMENT" hard-coded.

BR-DOC-028 — Relazione con l'ECM esterno

  • Regola: la creazione dell'entità core (DOC_CREATEDOCUMENT) persiste il file come BLOB in Oracle (DOCS_ATTACHMENT) e non invoca alcun ECM esterno. La delega del file a un ECM esterno (Alfresco/OpenText/Docs) e la scrittura di USER_PROTOCOL con l'ID esterno avvengono solo nel flusso di pubblicazione (vedi BR-ECM, BR-ECM-001/003/007), condizionati al flag SaveAttachExtMode.
  • Tipo: integration · Enforcement: mixed · Confidence: SUPPORTED · customer_specific: false
  • Evidenza: DOC_CREATEDOCUMENT (controprova DB) inserisce l'allegato solo localmente via DOC_CREATEATTACHMENT; nel percorso InsertDocument (DocumentCreateControl.ascx.vb:174-399) non c'è alcuna chiamata a provider ECM; cross-ref BR-ECM-001 (SaveAttachExtMode) e BR-ECM-007 (USER_PROTOCOL).
  • Note: la colonna USER_PROTOCOL (nullable) è il punto di aggancio riusato dall'ECM in pubblicazione; alla creazione contiene il "protocollo utente" digitato dall'operatore o resta vuota.

BR-DOC-029 — Wiring via .NET Remoting, grant UI non ri-verificati

  • Regola: DocumentController.Insert delega a IDocument_BL risolto a runtime via DAOFactory con Activator.GetObject(...) sul canale Remoting Service_Document; l'implementazione Document_BL eredita MarshalByRefObject. I controlli di autorizzazione/grant applicati lato UI non risultano ri-verificati dal servizio server (pattern TD-008).
  • Tipo: security · Enforcement: BL · Confidence: SUPPORTED · customer_specific: false
  • Evidenza: DocumentController.vb:16-17 (Return DirectCast(Me.DAO, IDocument_BL).Insert(dto)); DAOFactory.vb:14-15 (Case enControllers.Ctrl_Document ... Activator.GetObject(GetType(IDocument_BL), ... Service_Document)); Document_BL.vb:12-14 (Inherits MarshalByRefObject, Implements IDocument_BL).
  • Note: flag UI-only — un chiamante che raggiunga direttamente il canale Remoting/BL non passa per la validazione del wizard (BR-DOC-005, categoria obbligatoria, ecc.).

Rischi trasversali (sintesi)

  • Regole solo-UI (bypassabili da percorsi non-UI, upload massivo, Remoting diretto): BR-DOC-005 (anti-duplicato), obbligatorietà categoria (BR-ECM-016), e in generale i controlli del wizard non ri-verificati dal BL (BR-DOC-029).
  • Regole solo-DB (logica interna alle procedure/trigger, non visibile dal codice VB): BR-DOC-006, BR-DOC-007, BR-DOC-011, BR-DOC-017, BR-DOC-018, BR-DOC-019, BR-DOC-020, BR-DOC-021.
  • Magic number: RELATION_TYPE 0/1 (BR-DOC-022), permesso tenancy 2 (BR-DOC-027), default VERSION = 1, ISVALID = 0 (BR-DOC-008).
  • Numerazione/protocollo: formula dinamica in dati (BR-DOC-001/002), singleton implicito (BR-DOC-003), assenza di sequence e di UNIQUE su SYS_PROTOCOL → rischio collisione (BR-DOC-004).
  • Integrità dati / probable defect: attributi fuori transazione (BR-DOC-014), sgancio allegato in update (BR-DOC-019), IS_LAST_VERSION = 0 alla creazione (BR-DOC-023), duplicati tag (BR-DOC-012), peso tag non aggiornato (BR-DOC-013).
  • Date logic: START_DATE/CREATED = SYSDATE, END_DATE = NULL (BR-DOC-024); DATE_DOCUMENT opzionale (nullable).
  • Varianti cliente: inserimento da cancellato (BR-DOC-026, RequestCenter/custom).
  • Hidden flag / dipendenze: InsertCancelled (BR-DOC-026), autoPublish (Salva vs Salva e pubblica), relazione con SaveAttachExtMode dell'ECM (BR-DOC-028).

Domande aperte

  • Come viene effettivamente incrementato il progressivo di protocollo, se SEQ_DOCS_PROTOCOL è commentata? La formula in DOCS_PROTOCOLFORMAT fa MAX+1 (soggetto a race) o altro? (BR-DOC-001/004)
  • Il documento appena creato con IS_LAST_VERSION = 0 viene corretto da un passo a valle (workflow/pubblicazione) o è un difetto? (BR-DOC-023)
  • Perché gli attributi specifici sono letti dalla categoria padre e non dalla categoria selezionata? È eredità voluta? (BR-DOC-016)
  • In caso di update senza ri-upload dell'allegato, lo sgancio di ID_ATTACHMENT è intenzionale? Chi ripulisce la riga orfana in DOCS_ATTACHMENT? (BR-DOC-019)
  • Il canale .NET Remoting Service_Document applica una qualche autorizzazione lato server o si affida interamente alla UI? (BR-DOC-029, TD-008)