Table of Contents

BR-PROP — Regole di business del dominio Property / Patrimonio

Regole di business estratte dal flusso pilota FLOW-PROP-001 (creazione/aggiornamento di un edificio/immobile) e dai sorgenti correlati. Il dominio Property gestisce la gerarchia spaziale Regione → Città → Comprensorio → Edificio → Piano → Vano (più Terreni, UI, OC, Asset, People). Il salvataggio (create-or-update) di TUTTE le entità spaziali passa dalla stessa procedura generica Oracle PRP_MANAGEENTITY (nessun ORM; accesso via DAO_GenericEntity.ManageEntity).

Sistema: Infocad (Descor) — backend Oracle INFOCAD_TEST38, ASP.NET Web Forms (VB.NET) + controller in-process (Descor.Property.PropertyControllers) e path WCF equivalente (EditingWCF.svc).

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/PropertyManager/DAO/DAO_GenericEntity.vb:315).
  • Evidenza DB: letta in sola lettura da USER_SOURCE (sorgente procedure/trigger), USER_CONSTRAINTS/USER_CONS_COLUMNS (vincoli), USER_TRIGGERS (trigger) su INFOCAD_TEST38, limitatamente a PRP_MANAGEENTITY, COD_GENERATECODE, CNT_EDIFICI e alla tabella EDIFICI_. Nessuna lettura di dati applicativi, nessuna DML/DDL. Le righe della procedura sono indicate come PRP_MANAGEENTITY:NNN (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 (vincoli e trigger) non visibili dal codice applicativo.

Registro delle regole (register)

id regola tipo enforcement conf
BR-PROP-001 La semantica create-vs-update è pilotata dall'id: id=0/NULL ⇒ INSERT, id>0 ⇒ UPDATE state-transition mixed VERIFIED
BR-PROP-002 Il nome tabella entità si ottiene aggiungendo il suffisso _ (EDIFICIEDIFICI_); eccezioni BLOCKS_DATA, TIPO_*, nomi già terminanti in _ config-flag BL VERIFIED
BR-PROP-003 Per l'entità VANI/VANI_ l'identity 0 viene forzata a -1 prima della chiamata validation BL VERIFIED
BR-PROP-004 La procedura verifica l'esistenza di tabella e colonna-id prima di eseguire DML; se assenti non esegue nulla e ritorna stringa d'errore validation DB VERIFIED
BR-PROP-005 In INSERT il codice entità (CODICE_EDIFICIO) è generato da COD_GENERATECODE, solo se una colonna-codice è configurata in GLOBAL_CODE_CONFIGURATION per il tenant calculation DB VERIFIED
BR-PROP-006 ID_EDIFICIO è assegnato dalla sequence SEQ_GLOBAL_GEOM se NULL (trigger CNT_EDIFICI) calculation DB VERIFIED
BR-PROP-007 ID_EDIFICIO è immutabile: un UPDATE che lo modifica solleva ORA-20000 validation DB VERIFIED
BR-PROP-008 Dismissione datata: su UPDATE di ID_ENDING_DATE, se la nuova data < SYSDATE e la vecchia > SYSDATE, CODICE_EDIFICIO viene prefissato con (DEL.<id>)_ date-logic DB VERIFIED
BR-PROP-009 Su INSERT viene creato il binding di tenant in GLOBAL_TENANCY_BINDINGS con PERMISSION=2 (solo se TENANCYID>0) permission DB VERIFIED
BR-PROP-010 Il tenant dell'operazione è dedotto dall'utente via GLOBAL_LOGIN_SETTINGS + ASPNET_TEST38; utente non risolto ⇒ fallimento permission DB VERIFIED
BR-PROP-011 Sul path WCF il salvataggio richiede grant ADD_DELETE (create) o EDIT (update) sull'entità permission BL VERIFIED
BR-PROP-012 Sul path griglia, permesso tenancy NONE/VIEW sull'entità blocca il salvataggio con alert NoGrant permission BL VERIFIED
BR-PROP-013 Il campo-chiave del livello (es. EDIFICIO) è obbligatorio: vuoto ⇒ errore di validazione validation mixed VERIFIED
BR-PROP-014 Il campo parent-id del livello (per l'edificio ID_COMPRENSORIO) è obbligatorio e ≠ 0 validation mixed VERIFIED
BR-PROP-015 Lock ottimistico applicativo: salvataggio consentito solo se l'elemento non è lockato da altri; il super-admin può forzare (rubare) il lock state-transition BL VERIFIED
BR-PROP-016 Il DAO aggiunge ID_CHANGED_BY = <username> ai campi da salvare se assente validation BL VERIFIED
BR-PROP-017 Su create via WCF/griglia ID_CREATED_BY è forzato al literal "WEB SERVICE" validation BL VERIFIED
BR-PROP-018 In AddItem il parent-key (ID_COMPRENSORIO) è aggiunto automaticamente dai valori se assente validation BL VERIFIED
BR-PROP-019 CODICE_EDIFICIO è unico per tenant (UC_EDIFICI su CODICE_EDIFICIO,ID_TENANT) e globalmente (UK_EDIFICI_ su CODICE_EDIFICIO) validation DB VERIFIED
BR-PROP-020 Integrità referenziale: ID_COMPRENSORIO deve riferire un comprensorio esistente; ID_TERRENO è FK validation DB VERIFIED
BR-PROP-021 Colonne DB obbligatorie non gestite dall'app (ID_CREATION_DATE, ID_LAST_UPDATE, ID_STARTING_DATE, ID_ENDING_DATE, DISMESSO, ID_LOCK_CAD, ID_LOCK_MANAGER, ID_NEGLECTED NOT NULL) validation DB VERIFIED
BR-PROP-022 Nel path Insert (DTO) l'edificio è dedotto per nome+parent (GetBuildingIdByName): id trovato ⇒ update, altrimenti create state-transition BL VERIFIED
BR-PROP-023 Solo i campi presenti nella struttura entità (filtrata per ruoli utente) vengono salvati; se il valore manca si applica il default della struttura validation BL VERIFIED
BR-PROP-024 Attorno alla DML dinamica la procedura forza le NLS di sessione (NLS_DATE_FORMAT='DD/MM/YYYY HH24:MI:SS', separatore decimale) e le ripristina date-logic DB VERIFIED
BR-PROP-025 Ogni statement SQL costruito è scritto in GLOBAL_DEBUG_LOG con COMMIT intermedio (log sempre attivo) config-flag DB VERIFIED
BR-PROP-026 La cancellazione logica dell'edificio usa il remover hardcoded "WEB" (PRP_LOGICALDELETEBUILDING) state-transition mixed VERIFIED
BR-PROP-027 Interpretazione del ritorno: numerico = successo (id nuovo se >0, update se =0); non numerico = errore DB state-transition BL VERIFIED
BR-PROP-028 Visibilità toolbar per permesso tenancy: VIEW nasconde Modifica/Elimina, MANAGE nasconde Elimina, NONE nasconde la scheda permission UI VERIFIED
BR-PROP-029 Su DELETE fisico il trigger CNT_EDIFICI archivia la riga in EDIFICI_CANCELLATI e rimuove il binding in GLOBAL_TENANCY_BINDINGS state-transition DB VERIFIED
BR-PROP-030 Il flag PREQUIREREFRESH (default 1) richiede il refresh cache/strutture dopo il salvataggio config-flag mixed SUPPORTED
BR-PROP-031 Numerosi trigger AFTER I/U/D per-campo (TK_EDIFICI_*) e DOCS_EDIFICI_UPD implementano storicizzazione/effetti su campi custom, specifici per schema/cliente customer-specific DB SUPPORTED

Dettaglio delle regole

BR-PROP-001 — Create vs Update pilotato dall'id

  • Regola: se l'id dell'entità è 0 o NULL si esegue una INSERT (nuovo edificio); se > 0 si esegue una UPDATE.
  • Tipo: state-transition · Enforcement: mixed (BL propaga l'id, DB decide) · Confidence: VERIFIED
  • Evidenza (BL): EntityBase.SaveObj inoltra SaveBuilding(UserName, ide, allFieldValues) con ide=0 ⇒ create / ide>0 ⇒ update — InfocadWeb/WebMachine/CASSANDRA/CommonWeb/PropertyCenter/Classes/EntityBase.vb:1067; dispatch griglia EditManager.vb:309.
  • Evidenza (DB): ISINSERT := TRUE se PID_INFOCAD IS NULL oppure NUMID_INFOCAD = 0PRP_MANAGEENTITY:59-73.

BR-PROP-002 — Convenzione nome tabella con suffisso _

  • Regola: il nome tabella fisico si ricava dal nome-entità aggiungendo _ (EDIFICIEDIFICI_). Eccezioni: BLOCKS_DATA, nomi che iniziano con TIPO_, o già terminanti in _.
  • Tipo: config-flag (convenzione) · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: Dim entityTableName As String = If(entity = "BLOCKS_DATA" OrElse entity.StartsWith("TIPO_") OrElse entity.EndsWith("_"), entity, entity & "_")InfocadServer/PropertyManager/DAO/DAO_GenericEntity.vb:315.
  • Nota: convenzione replicata (con variazioni: DRAWINGS_HOST_BIM) in DeleteEntity (:369) e FinalDeleteEntity (:817) — rischio di divergenza tra i rami.

BR-PROP-003 — Caso speciale VANI: identity 0 → -1

  • Regola: per l'entità VANI/VANI_, un identity "0" viene forzato a "-1" prima della chiamata alla procedura.
  • Tipo: validation (workaround) · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: If entityTableName = "VANI_" Or entityTableName = "VANI" Then If identity = "0" Then identity = "-1"DAO_GenericEntity.vb:322-326.
  • Flag: magic number hard-coded (-1) specifico dei locali/vani; non documentato lato DB.

BR-PROP-004 — Guardia di esistenza tabella/colonna (DB)

  • Regola: la procedura verifica in USER_TABLES/USER_VIEWS che la tabella esista e in USER_TAB_COLUMNS che la colonna-id esista; in caso negativo NON esegue alcuna DML e ritorna una stringa d'errore in PRETVALUE.
  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: SELECT COUNT(1) INTO EXISTTAB_INFOCAD FROM (... USER_TABLES UNION ... USER_VIEWS) WHERE TABLE_NAME = PTAB_INFOCAD e verifica colonna — PRP_MANAGEENTITY:77-96.
  • Flag: regola enforced solo in SQL (guardia difensiva della procedura generica).

BR-PROP-005 — Generazione codice entità (COD_GENERATECODE)

  • Regola: in INSERT, se per la tabella e il tenant esiste una CODECOLUMN configurata in GLOBAL_CODE_CONFIGURATION, la procedura genera il codice via COD_GENERATECODE(PTAB_INFOCAD, TENANCYID, V_CODEVALUE) e lo inietta nella INSERT.
  • Tipo: calculation · Enforcement: DB · Confidence: VERIFIED (chiamata) / SUPPORTED (interno di COD_GENERATECODE)
  • Evidenza: lookup colonna-codice SELECT CODECOLUMN INTO V_CODECOLUMN FROM GLOBAL_CODE_CONFIGURATION WHERE REPLACE(PTAB_INFOCAD,'_','')=REPLACE(TABLE_NAME,'_','') AND ID_TENANT = TENANCYIDPRP_MANAGEENTITY:130-138; chiamata generazione PRP_MANAGEENTITY:319,393,573.
  • Flag: comportamento tenant/cliente-dipendente (dipende dalla configurazione in GLOBAL_CODE_CONFIGURATION); COD_GENERATECODE usa DBMS_RANDOM (da dipendenze).

BR-PROP-006 — Assegnazione ID_EDIFICIO da sequence (trigger)

  • Regola: alla INSERT, se ID_EDIFICIO è NULL, il trigger CNT_EDIFICI lo valorizza da SEQ_GLOBAL_GEOM.
  • Tipo: calculation · Enforcement: DB (trigger BEFORE ROW) · Confidence: VERIFIED
  • Evidenza: IF INSERTING THEN IF (:new.ID_EDIFICIO IS NULL) THEN SELECT SEQ_GLOBAL_GEOM.NEXTVAL INTO :new.ID_EDIFICIO FROM dual; END IF; END IF; — trigger CNT_EDIFICI (USER_TRIGGERS, BEFORE INSERT OR DELETE OR UPDATE OF ID_ENDING_DATE ON EDIFICI_).
  • Flag: regola enforced solo in SQL. La INSERT ... RETURNING ID_EDIFICIO della procedura restituisce quindi l'id prodotto dal trigger/sequence, non un valore calcolato dall'app.

BR-PROP-007 — Immutabilità di ID_EDIFICIO

  • Regola: un UPDATE che cambia ID_EDIFICIO è vietato e solleva ORA-20000 ("Non posso cambiare il contatore per la tabella EDIFICI_").
  • Tipo: validation · Enforcement: DB (trigger) · Confidence: VERIFIED
  • Evidenza: IF UPDATING THEN IF NOT(:new.ID_EDIFICIO = :old.ID_EDIFICIO) THEN RAISE non_posso_cambiare; ... raise_application_error(-20000, ...) — trigger CNT_EDIFICI.
  • Flag: regola enforced solo in SQL; errore con codice hard-coded -20000.

BR-PROP-008 — Dismissione datata e prefisso codice (DEL.<id>)_

  • Regola: su UPDATE di ID_ENDING_DATE, se la nuova data di fine è < SYSDATE e la vecchia era > SYSDATE (transizione ad "dismesso/scaduto"), il trigger prefissa CODICE_EDIFICIO con (DEL.<ID_EDIFICIO>)_.
  • Tipo: date-logic · Enforcement: DB (trigger) · Confidence: VERIFIED
  • Evidenza: IF :NEW.ID_ENDING_DATE < SYSDATE AND :OLD.ID_ENDING_DATE > SYSDATE THEN :NEW.CODICE_EDIFICIO := '(DEL.' || :NEW.ID_EDIFICIO || ')_' || :NEW.CODICE_EDIFICIO; END IF; — trigger CNT_EDIFICI.
  • Flag: logica date-sensitive dipendente da SYSDATE; regola enforced solo in SQL. La riprova del comportamento dipende dalla data corrente (comportamento diverso prima/dopo la data di fine).

BR-PROP-009 — Binding di tenant su GLOBAL_TENANCY_BINDINGS (PERMISSION=2)

  • Regola: su INSERT, se TENANCYID > 0, viene inserita una riga in GLOBAL_TENANCY_BINDINGS con TAB_INFOCAD='EDIFICI', ID_INFOCAD=<nuovo id>, ID_TENANCY=<tenant>, PERMISSION=2, CODICE=<codice generato>.
  • Tipo: permission · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: IF TENANCYID > 0 THEN ... INSERT INTO GLOBAL_TENANCY_BINDINGS (TAB_INFOCAD, ID_INFOCAD, ID_TENANCY, PERMISSION, CODICE) VALUES ('EDIFICI', TO_NUMBER(PRETVALUE), TENANCYID, 2, V_CODEVALUE)PRP_MANAGEENTITY:634,660-663.
  • Flag: magic number hard-coded PERMISSION=2 (presumibilmente MANAGE/OWNER, non parametrico). Nessun binding se il tenant non è risolto.

BR-PROP-010 — Risoluzione tenant dell'utente (cross-schema)

  • Regola: il tenant (TENANCYID) è dedotto dall'utente tramite join GLOBAL_LOGIN_SETTINGS × ASPNET_TEST38.ORA_ASPNET_USERS × ORA_ASPNET_APPLICATIONS (filtro su username e su APPLICATIONNAME = USER). Se l'utente non è risolto, il SELECT ... INTO fallisce (NO_DATA_FOUND) e l'operazione termina in errore.
  • Tipo: permission · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: SELECT ID_TENANCY INTO TENANCYID FROM GLOBAL_LOGIN_SETTINGS GLS JOIN ASPNET_TEST38.ORA_ASPNET_USERS ... WHERE OAU.LOWEREDUSERNAME = LOWER(PUSERNAME) AND OAA.APPLICATIONNAME = USERPRP_MANAGEENTITY:48-56.
  • Flag: dipendenza cross-schema (ASPNET_TEST38); il legame applicazione↔tenant usa USER (schema Oracle corrente).

BR-PROP-011 — Grant WCF ADD_DELETE / EDIT

  • Regola: sul path programmatico WCF, AddItem richiede grant ADD_DELETE, EditItem/EditItems richiedono EDIT sull'entità; senza grant l'operazione ritorna False senza scrivere.
  • Tipo: permission · Enforcement: BL (WCF) · Confidence: VERIFIED
  • Evidenza: If HasUserGrant(...ADD_DELETE, EntityName) Then Return editMan.AddItem(...)InfocadWeb/WebMachine/CASSANDRA/CommonWeb/PropertyCenter/WebServices/EditingWCF.svc.vb:277; EDIT per EditItem/EditItems :303,329. Previo ValidateLoginKey(loginkey) :274,300,326.

BR-PROP-012 — Blocco tenancy sul path griglia (NONE/VIEW)

  • Regola: nel salvataggio multiplo da griglia, per utenti non super-admin e con tenancy abilitata, se anche uno solo degli elementi ha permesso NONE o VIEW l'intero salvataggio è bloccato con alert NoGrant.
  • Tipo: permission · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: If Not WS.SessionProfile.SuperAdmin AndAlso WS.IsTenantEnabled Then ... GetPermissionByEntity(...) ... Where(spx.Permission = NONE OrElse = VIEW).Count > 0 Then _errMsg = ...NoGrant... Return FalseInfocadWeb/WebMachine/CASSANDRA/CommonWeb/PropertyCenter/Classes/Editing/EditManager.vb:269-290.
  • Flag: controllo lato applicazione (BL server-side, non DB). Il path WCF ha invece il proprio grant (BR-PROP-011); i due controlli non coincidono nel dettaglio.

BR-PROP-013 — Campo-chiave obbligatorio

  • Regola: il campo-chiave del livello (per l'edificio EDIFICIO) non può essere vuoto; se vuoto il salvataggio ritorna VALIDATION_ERROR con alert.
  • Tipo: validation · Enforcement: mixed (UI/BL + DB NOT NULL) · Confidence: VERIFIED
  • Evidenza (BL): ciclo di validazione su DataSheetBase.GetLevelName(...) con String.IsNullOrEmpty(Trim(arr(1)))Return Result.VALIDATION_ERROREntityBase.vb:1003-1023.
  • Evidenza (DB): vincolo SYS_C001716813 "EDIFICIO" IS NOT NULL su EDIFICI_ (USER_CONSTRAINTS).

BR-PROP-014 — Parent-id obbligatorio e ≠ 0

  • Regola: il parent-key del livello (per l'edificio ID_COMPRENSORIO) non può essere vuoto né 0.
  • Tipo: validation · Enforcement: mixed · Confidence: VERIFIED
  • Evidenza (BL): If parentKey.ToLower().Equals(arr(0).ToLower()) Then If String.IsNullOrEmpty(Trim(arr(1))) OrElse Trim(arr(1)) = "0" Then ... Return Result.VALIDATION_ERROREntityBase.vb:1025-1035.
  • Evidenza (DB): vincolo SYS_C001716812 "ID_COMPRENSORIO" IS NOT NULL (USER_CONSTRAINTS); si veda anche BR-PROP-020 (FK).

BR-PROP-015 — Lock ottimistico applicativo

  • Regola: il salvataggio è consentito solo se l'elemento non è lockato da altri utenti (o il lock è dell'utente corrente). Il super-admin può forzare il "furto" del lock tramite conferma; l'utente normale riceve ItemLocked e il salvataggio è negato.
  • Tipo: state-transition · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: Case "Save": If LockedBy(EntityName, Identifier) = UserName OrElse Not IsLocked(...) Then Save(...) ... Else ... ItemLocked_StealedEntityBase.vb:689-705; blocco Edit/Delete :676-720.
  • Flag: lock a livello applicativo (Application state), non a livello DB — rischio: aggiornamenti concorrenti tramite path che non passano dal lock (WCF, integrazioni import) non sono soggetti a questo controllo.

BR-PROP-016 — Stamping ID_CHANGED_BY

  • Regola: il DAO aggiunge il campo ID_CHANGED_BY = <username> all'insieme dei campi da salvare, se non già presente.
  • Tipo: validation (audit) · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: If Not bFound Then Array.Resize(KeyValue,...) : KeyValue(...) = New String(1) {"ID_CHANGED_BY", username}InfocadServer/PropertyManager/DAO/DAO_Building.vb:469-479.

BR-PROP-017 — ID_CREATED_BY forzato a "WEB SERVICE"

  • Regola: in AddItem (create via griglia/WCF) il campo ID_CREATED_BY è impostato/forzato al literal "WEB SERVICE".
  • Tipo: validation (audit) · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: AllFieldValues(i) = New String(1) {"ID_CREATED_BY", "WEB SERVICE"} (e append se assente) — EditManager.vb:198-209.
  • Flag: valore hard-coded — l'utente reale creatore non è tracciato in ID_CREATED_BY su questo path.

BR-PROP-018 — Aggiunta automatica del parent-key in AddItem

  • Regola: se tra i campi manca il parent-key dell'entità, AddItem lo aggiunge con il valore ID_Parent corrente.
  • Tipo: validation · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: If Not bFoud AndAlso DataSheetBase.GetParentLevelKey(EntityName) <> String.Empty Then Array.Resize(...) : AllFieldValues(...) = New String(1) {GetParentLevelKey(EntityName), ID_Parent.ToString}EditManager.vb:179-191.

BR-PROP-019 — Unicità CODICE_EDIFICIO (per tenant e globale)

  • Regola: CODICE_EDIFICIO è soggetto a due vincoli di unicità: UC_EDIFICI sulla coppia (CODICE_EDIFICIO, ID_TENANT) e UK_EDIFICI_ sul solo CODICE_EDIFICIO.
  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: USER_CONSTRAINTS/USER_CONS_COLUMNS su EDIFICI_: UC_EDIFICI (U) → CODICE_EDIFICIO, ID_TENANT; UK_EDIFICI_ (U) → CODICE_EDIFICIO.
  • Flag: regola enforced solo in SQL. La coesistenza dei due unique è potenzialmente ridondante/conflittuale (l'unique globale su CODICE_EDIFICIO rende di fatto irrilevante la componente ID_TENANT del primo). Da chiarire con Descor.

BR-PROP-020 — Integrità referenziale (comprensorio, terreno)

  • Regola: ID_COMPRENSORIO deve riferire un comprensorio esistente; ID_TERRENO è vincolato da FK.
  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: FK su EDIFICI_ in USER_CONSTRAINTS: SYS_C001729012 (R) → ID_COMPRENSORIO; F_EDIFICI_TERRENI (R) → ID_TERRENO. PK SYS_C001727708 (P) → ID_EDIFICIO.
  • Flag: regola enforced solo in SQL.

BR-PROP-021 — Colonne NOT NULL non gestite dall'app

  • Regola: EDIFICI_ impone NOT NULL su un insieme di colonne che la scheda edificio tipicamente non valorizza: ID_CREATION_DATE, ID_LAST_UPDATE, ID_STARTING_DATE, ID_ENDING_DATE, DISMESSO, ID_LOCK_CAD, ID_LOCK_MANAGER, ID_NEGLECTED (oltre a ID_EDIFICIO, ID_COMPRENSORIO, EDIFICIO).
  • Tipo: validation · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: vincoli C in USER_CONSTRAINTS (SYS_C001716814SYS_C001716821).
  • Flag: regola enforced solo in SQL con rischio operativo: se un INSERT (via PRP_MANAGEENTITY o import) non fornisce questi campi e non esiste un DEFAULT di colonna o un trigger che li popoli, l'INSERT fallisce. Le date iniziali/finali sono presumibilmente gestite da default/trigger DB (non verificato riga per riga).

BR-PROP-022 — Dedup per nome+parent nel path Insert (DTO)

  • Regola: nel metodo Insert(DTO) l'id è risolto via GetBuildingIdByName(name, id_district): se un edificio con quel nome esiste nel comprensorio, si esegue un update su quell'id; altrimenti create.
  • Tipo: state-transition · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: Dim idObj As Integer = daoMan.GetBuildingIdByName(objBuilding.Name, objBuilding.Id_District) poi daoMan.SaveBuilding(username, idObj, entityFields)DAO_Building.vb:234,260; GetBuildingIdByNamePRP_GETBUILDINGIDBYNAME :935-956.
  • Nota: il metodo Update(DTO) richiede invece objBuilding.ID_DTO ≠ 0 (altrimenti ErrInvalidID) e verifica l'esistenza con SelectById (ErrNotFound) — DAO_Building.vb:288-296.

BR-PROP-023 — Filtro campi per struttura entità e ruoli

  • Regola: solo i campi (ExtraParameters) presenti nella EntityStructure (ottenuta per l'entità e per i ruoli dell'utente) vengono aggiunti al salvataggio; se il valore passato è vuoto si applica il default della struttura.
  • Tipo: validation (permission-driven) · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: Dim struct = New DAO_Metadata().GetEntityStructure(entityName, roleMan.GetRolesForUser(username).ToList()) ... Dim fld = struct.Fields.Find(...) If fld IsNot Nothing Then ... If(Not String.IsNullOrEmpty(attributes(1)), attributes(1), fld.ValueToString)DAO_Building.vb:247-258 (Insert) e :308-319 (Update).

BR-PROP-024 — Forzatura NLS di sessione attorno alla DML

  • Regola: prima della DML dinamica la procedura salva le NLS correnti e forza NLS_DATE_FORMAT='DD/MM/YYYY HH24:MI:SS' e il separatore decimale; al termine ripristina i valori originali.
  • Tipo: date-logic · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: SELECT VALUE INTO TMPNLSDATE FROM V$NLS_PARAMETERS WHERE PARAMETER='NLS_DATE_FORMAT' + EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = ''DD/MM/YYYY HH24:MI:SS'''PRP_MANAGEENTITY:542-551; ripristino :840-841.
  • Flag: formato data/decimali hard-coded; i valori serializzati in XML dai campi scheda sono interpretati con questo formato (rischio se un client invia date/decimali in formato diverso).

BR-PROP-025 — Debug log sempre attivo con COMMIT intermedio

  • Regola: ogni statement SQL costruito (TMPSQL) è scritto in GLOBAL_DEBUG_LOG con un COMMIT immediato.
  • Tipo: config-flag (side effect) · Enforcement: DB · Confidence: VERIFIED
  • Evidenza: EXECUTE IMMEDIATE 'insert into global_debug_log values(:1,:2,:3,:4)' USING 'INFOCAD','MANAGEENTITY',TMPSQL,SYSDATE; COMMIT;PRP_MANAGEENTITY:158-159.
  • Flag: logging non condizionato (nessun feature-flag): ogni upsert scrive nel log e forza un COMMIT intermedio (implicazioni transazionali). Da valutare in PROD (crescita tabella, transazione non atomica).

BR-PROP-026 — Cancellazione logica con remover "WEB"

  • Regola: la cancellazione logica dell'edificio invoca PRP_LOGICALDELETEBUILDING passando PREMOVER = "WEB" (valore fisso), poi solleva l'evento observable RaiseObjectLogicalDeleted.
  • Tipo: state-transition · Enforcement: mixed · Confidence: VERIFIED
  • Evidenza: Dim removerparam As New OracleParameter("PREMOVER", ..., "WEB", ...) + PRP_LOGICALDELETEBUILDINGDAO_Building.vb:353,358.
  • Flag: valore hard-coded "WEB" (il remover reale non è l'utente).

BR-PROP-027 — Interpretazione del valore di ritorno

  • Regola: il ritorno di PRP_MANAGEENTITY (in PRETVALUE) è interpretato così: numerico ⇒ successo (id nuovo se >0, update se =0); non numerico ⇒ messaggio d'errore DB, logga l'errore, nessuna persistenza segnalata all'utente.
  • Tipo: state-transition · Enforcement: BL · Confidence: VERIFIED
  • Evidenza: If IsNumeric(retValue) Then If CInt(retValue) > 0 Then ... Inserted Else ... Updated ... Else ... InfocadTraceWrapper.CreateError ... If IsDBError(retValue) Then DB_ERROR_MESSAGE = ParseDBError(retValue)EditManager.vb:343-361. Lato DB PRETVALUE := '0' iniziale/update — PRP_MANAGEENTITY:46.

BR-PROP-028 — Visibilità toolbar per permesso tenancy (UI)

  • Regola: sulla scheda, per utenti non super-admin con tenancy abilitata: NONE nasconde la scheda (con alert NoGrant), VIEW nasconde i pulsanti Modifica/Elimina, MANAGE nasconde solo Elimina.
  • Tipo: permission · Enforcement: UI · Confidence: VERIFIED
  • Evidenza: Select Case permission ... NONE: Me.Visible = False; VIEW: toolbar.Controls(2/0).Visible = False; MANAGE: toolbar.Controls(0).Visible = FalseEntityBase.vb:571-582; check parallelo CheckTenantPermission/CheckTenantParentPermission :597-663.
  • Flag: controllo UI-only (nasconde pulsanti): non è la barriera effettiva di scrittura — quella resta il grant WCF (BR-PROP-011), il check griglia (BR-PROP-012) e il binding tenant DB. Nasconde i comandi ma non impedisce di per sé una POST costruita ad hoc.

BR-PROP-029 — Archiviazione e pulizia binding su DELETE fisico

  • Regola: alla DELETE fisica di una riga EDIFICI_, il trigger CNT_EDIFICI inserisce lo storico in EDIFICI_CANCELLATI (id, comprensorio, edificio, data, utente) e rimuove la riga corrispondente in GLOBAL_TENANCY_BINDINGS.
  • Tipo: state-transition · Enforcement: DB (trigger) · Confidence: VERIFIED
  • Evidenza: IF DELETING THEN INSERT INTO EDIFICI_CANCELLATI(...) VALUES(:OLD..., SYSDATE, USER); DELETE FROM GLOBAL_TENANCY_BINDINGS WHERE TAB_INFOCAD='EDIFICI' AND ID_INFOCAD=:NEW.ID_EDIFICIO; — trigger CNT_EDIFICI.
  • Flag: regola enforced solo in SQL. Nota: la DELETE nel branch usa :NEW.ID_EDIFICIO (in un trigger DELETE :NEW è NULL) — potenziale difetto per cui il binding potrebbe non essere rimosso; da verificare con Descor.

BR-PROP-030 — Flag di refresh cache

  • Regola: il parametro PREQUIREREFRESH (default 1/True dal DAO) segnala alla procedura/all'applicazione di rinfrescare cache/strutture dopo il salvataggio.
  • Tipo: config-flag · Enforcement: mixed · Confidence: SUPPORTED
  • Evidenza: Dim bRefreshParam As New OracleParameter("PREQUIREREFRESH", OracleDbType.Int16, If(requireRefresh, 1, 0), ...) con Optional requireRefresh As Boolean = TrueDAO_GenericEntity.vb:298,304,333.

BR-PROP-031 — Trigger di storicizzazione/effetti su campi custom (cliente-specifici)

  • Regola: EDIFICI_ porta decine di trigger AFTER INSERT OR UPDATE OR DELETE per singolo campo (TK_EDIFICI_*, es. TK_EDIFICI_INDIRIZZO, TK_EDIFICI_MQ, TK_EDIFICI_DATA_COSTRUZIONE, TK_EDIFICI_LATITUDINE, …) e un DOCS_EDIFICI_UPD AFTER UPDATE, che implementano storicizzazione/effetti collaterali sui campi custom della scheda.
  • Tipo: customer-specific · Enforcement: DB · Confidence: SUPPORTED (elenco trigger da USER_TRIGGERS; corpi non ispezionati singolarmente)
  • Evidenza: USER_TRIGGERS su EDIFICI_ (≈40 trigger TK_EDIFICI_* più DOCS_EDIFICI_UPD, CNT_EDIFICI).
  • Flag: regole enforced solo in SQL e cliente/schema-specifiche — l'insieme dei campi custom (e quindi dei trigger) varia per installazione/tenant; non deducibili dal codice applicativo generico.

Sintesi dei rischi e flag

Regole enforced SOLO nell'UI (rischio: bypassabili da altri path)

  • BR-PROP-028 — la visibilità dei pulsanti in toolbar è puramente cosmetica; la scrittura è governata altrove (grant WCF / check griglia / binding DB).

Regole enforced SOLO in SQL (invisibili al codice applicativo)

  • BR-PROP-004 (guardia tabella/colonna), BR-PROP-006 (sequence id), BR-PROP-007 (id immutabile, ORA-20000), BR-PROP-008 (dismissione datata), BR-PROP-019 (unicità codice), BR-PROP-020 (FK), BR-PROP-021 (NOT NULL non gestiti dall'app), BR-PROP-029 (archiviazione su delete), BR-PROP-031 (trigger custom).

Regole enforced SOLO in BL (non presidiate dal DB)

  • BR-PROP-012 (blocco tenancy griglia) e BR-PROP-015 (lock ottimistico applicativo): non hanno contropartita a livello DB, quindi non proteggono i path che non passano dall'EditManager/ManageEditing (WCF, import). La coerenza dipende dalla disciplina del codice chiamante.

Magic number / valori e id hard-coded

  • VANI identity 0 → -1 (BR-PROP-003).
  • PERMISSION = 2 nel binding tenant (BR-PROP-009).
  • ORA-20000 per il cambio di ID_EDIFICIO (BR-PROP-007).
  • ID_CREATED_BY = "WEB SERVICE" (BR-PROP-017), PREMOVER = "WEB" (BR-PROP-026).
  • NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI:SS' (BR-PROP-024).
  • Prefisso codice (DEL.<id>)_ (BR-PROP-008).

Logica date-sensitive

  • BR-PROP-008 (dismissione basata sul confronto ID_ENDING_DATE con SYSDATE) e BR-PROP-024 (formato data forzato). La riproducibilità dipende dalla data corrente.

Feature flag / logging nascosto

  • BR-PROP-025GLOBAL_DEBUG_LOG scritto ad ogni upsert con COMMIT intermedio, senza flag di disattivazione; BR-PROP-030PREQUIREREFRESH.

Varianti cliente-specifiche

  • BR-PROP-005 (config codice per tenant in GLOBAL_CODE_CONFIGURATION), BR-PROP-031 (trigger custom per campo). L'insieme dei campi/trigger e la generazione codice variano per installazione.

Open questions

  • Chi popola le colonne NOT NULL ID_CREATION_DATE/ID_STARTING_DATE/ID_ENDING_DATE/DISMESSO/ID_LOCK_*/ID_NEGLECTED su INSERT (default di colonna vs trigger non ispezionato) — vedi BR-PROP-021.
  • Coesistenza dei due unique UC_EDIFICI (codice+tenant) e UK_EDIFICI_ (solo codice): è intenzionale? (BR-PROP-019).
  • Nel branch DELETING del trigger CNT_EDIFICI l'uso di :NEW.ID_EDIFICIO per pulire GLOBAL_TENANCY_BINDINGS sembra un difetto (dovrebbe essere :OLD) — impatto sulla pulizia dei binding (BR-PROP-029).
  • PERMISSION=2 in GLOBAL_TENANCY_BINDINGS: mappatura esatta sull'enum TenancyPermission (BR-PROP-009).
  • Comportamento in configurazioni PROD (osservato solo su ambiente TEST38); crescita/impatto di GLOBAL_DEBUG_LOG (BR-PROP-025).