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 viaDAO_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) suINFOCAD_TEST38, limitatamente aPRP_MANAGEENTITY,COD_GENERATECODE,CNT_EDIFICIe alla tabellaEDIFICI_. Nessuna lettura di dati applicativi, nessuna DML/DDL. Le righe della procedura sono indicate comePRP_MANAGEENTITY:NNN(numerazioneUSER_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 _ (EDIFICI→EDIFICI_); 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à è
0o NULL si esegue una INSERT (nuovo edificio); se> 0si esegue una UPDATE. - Tipo: state-transition · Enforcement: mixed (BL propaga l'id, DB decide) · Confidence: VERIFIED
- Evidenza (BL):
EntityBase.SaveObjinoltraSaveBuilding(UserName, ide, allFieldValues)conide=0⇒ create /ide>0⇒ update —InfocadWeb/WebMachine/CASSANDRA/CommonWeb/PropertyCenter/Classes/EntityBase.vb:1067; dispatch grigliaEditManager.vb:309. - Evidenza (DB):
ISINSERT := TRUEsePID_INFOCAD IS NULLoppureNUMID_INFOCAD = 0—PRP_MANAGEENTITY:59-73.
BR-PROP-002 — Convenzione nome tabella con suffisso _
- Regola: il nome tabella fisico si ricava dal nome-entità aggiungendo
_(EDIFICI→EDIFICI_). Eccezioni:BLOCKS_DATA, nomi che iniziano conTIPO_, 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) inDeleteEntity(:369) eFinalDeleteEntity(: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_VIEWSche la tabella esista e inUSER_TAB_COLUMNSche la colonna-id esista; in caso negativo NON esegue alcuna DML e ritorna una stringa d'errore inPRETVALUE. - Tipo: validation · Enforcement: DB · Confidence: VERIFIED
- Evidenza:
SELECT COUNT(1) INTO EXISTTAB_INFOCAD FROM (... USER_TABLES UNION ... USER_VIEWS) WHERE TABLE_NAME = PTAB_INFOCADe 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
CODECOLUMNconfigurata inGLOBAL_CODE_CONFIGURATION, la procedura genera il codice viaCOD_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 = TENANCYID—PRP_MANAGEENTITY:130-138; chiamata generazionePRP_MANAGEENTITY:319,393,573. - Flag: comportamento tenant/cliente-dipendente (dipende dalla configurazione in
GLOBAL_CODE_CONFIGURATION);COD_GENERATECODEusaDBMS_RANDOM(da dipendenze).
BR-PROP-006 — Assegnazione ID_EDIFICIO da sequence (trigger)
- Regola: alla INSERT, se
ID_EDIFICIOè NULL, il triggerCNT_EDIFICIlo valorizza daSEQ_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;— triggerCNT_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_EDIFICIOdella 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 sollevaORA-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, ...)— triggerCNT_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 è< SYSDATEe la vecchia era> SYSDATE(transizione ad "dismesso/scaduto"), il trigger prefissaCODICE_EDIFICIOcon(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;— triggerCNT_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 inGLOBAL_TENANCY_BINDINGSconTAB_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(presumibilmenteMANAGE/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 joinGLOBAL_LOGIN_SETTINGS×ASPNET_TEST38.ORA_ASPNET_USERS×ORA_ASPNET_APPLICATIONS(filtro su username e suAPPLICATIONNAME = USER). Se l'utente non è risolto, ilSELECT ... INTOfallisce (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 = USER—PRP_MANAGEENTITY:48-56. - Flag: dipendenza cross-schema (
ASPNET_TEST38); il legame applicazione↔tenant usaUSER(schema Oracle corrente).
BR-PROP-011 — Grant WCF ADD_DELETE / EDIT
- Regola: sul path programmatico WCF,
AddItemrichiede grantADD_DELETE,EditItem/EditItemsrichiedonoEDITsull'entità; senza grant l'operazione ritornaFalsesenza 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;EDITperEditItem/EditItems:303,329. PrevioValidateLoginKey(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
NONEoVIEWl'intero salvataggio è bloccato con alertNoGrant. - 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 False—InfocadWeb/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 ritornaVALIDATION_ERRORcon alert. - Tipo: validation · Enforcement: mixed (UI/BL + DB NOT NULL) · Confidence: VERIFIED
- Evidenza (BL): ciclo di validazione su
DataSheetBase.GetLevelName(...)conString.IsNullOrEmpty(Trim(arr(1)))⇒Return Result.VALIDATION_ERROR—EntityBase.vb:1003-1023. - Evidenza (DB): vincolo
SYS_C001716813"EDIFICIO" IS NOT NULLsuEDIFICI_(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_ERROR—EntityBase.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
ItemLockede 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_Stealed—EntityBase.vb:689-705; bloccoEdit/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 campoID_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_BYsu questo path.
BR-PROP-018 — Aggiunta automatica del parent-key in AddItem
- Regola: se tra i campi manca il parent-key dell'entità,
AddItemlo aggiunge con il valoreID_Parentcorrente. - 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_EDIFICIsulla coppia(CODICE_EDIFICIO, ID_TENANT)eUK_EDIFICI_sul soloCODICE_EDIFICIO. - Tipo: validation · Enforcement: DB · Confidence: VERIFIED
- Evidenza:
USER_CONSTRAINTS/USER_CONS_COLUMNSsuEDIFICI_: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_EDIFICIOrende di fatto irrilevante la componenteID_TENANTdel primo). Da chiarire con Descor.
BR-PROP-020 — Integrità referenziale (comprensorio, terreno)
- Regola:
ID_COMPRENSORIOdeve riferire un comprensorio esistente;ID_TERRENOè vincolato da FK. - Tipo: validation · Enforcement: DB · Confidence: VERIFIED
- Evidenza: FK su
EDIFICI_inUSER_CONSTRAINTS:SYS_C001729012(R) →ID_COMPRENSORIO;F_EDIFICI_TERRENI(R) →ID_TERRENO. PKSYS_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 aID_EDIFICIO,ID_COMPRENSORIO,EDIFICIO). - Tipo: validation · Enforcement: DB · Confidence: VERIFIED
- Evidenza: vincoli C in
USER_CONSTRAINTS(SYS_C001716814…SYS_C001716821). - Flag: regola enforced solo in SQL con rischio operativo: se un INSERT (via
PRP_MANAGEENTITYo 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 viaGetBuildingIdByName(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)poidaoMan.SaveBuilding(username, idObj, entityFields)—DAO_Building.vb:234,260;GetBuildingIdByName→PRP_GETBUILDINGIDBYNAME:935-956. - Nota: il metodo
Update(DTO)richiede inveceobjBuilding.ID_DTO ≠ 0(altrimentiErrInvalidID) e verifica l'esistenza conSelectById(ErrNotFound) —DAO_Building.vb:288-296.
BR-PROP-023 — Filtro campi per struttura entità e ruoli
- Regola: solo i campi (
ExtraParameters) presenti nellaEntityStructure(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 inGLOBAL_DEBUG_LOGcon unCOMMITimmediato. - 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
COMMITintermedio (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_LOGICALDELETEBUILDINGpassandoPREMOVER = "WEB"(valore fisso), poi solleva l'evento observableRaiseObjectLogicalDeleted. - Tipo: state-transition · Enforcement: mixed · Confidence: VERIFIED
- Evidenza:
Dim removerparam As New OracleParameter("PREMOVER", ..., "WEB", ...)+PRP_LOGICALDELETEBUILDING—DAO_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(inPRETVALUE) è 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 DBPRETVALUE := '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:
NONEnasconde la scheda (con alertNoGrant),VIEWnasconde i pulsanti Modifica/Elimina,MANAGEnasconde 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 = False—EntityBase.vb:571-582; check paralleloCheckTenantPermission/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 triggerCNT_EDIFICIinserisce lo storico inEDIFICI_CANCELLATI(id, comprensorio, edificio, data, utente) e rimuove la riga corrispondente inGLOBAL_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;— triggerCNT_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(default1/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), ...)conOptional requireRefresh As Boolean = True—DAO_GenericEntity.vb:298,304,333.
BR-PROP-031 — Trigger di storicizzazione/effetti su campi custom (cliente-specifici)
- Regola:
EDIFICI_porta decine di triggerAFTER INSERT OR UPDATE OR DELETEper singolo campo (TK_EDIFICI_*, es.TK_EDIFICI_INDIRIZZO,TK_EDIFICI_MQ,TK_EDIFICI_DATA_COSTRUZIONE,TK_EDIFICI_LATITUDINE, …) e unDOCS_EDIFICI_UPDAFTER 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_TRIGGERSsuEDIFICI_(≈40 triggerTK_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
VANIidentity0 → -1(BR-PROP-003).PERMISSION = 2nel binding tenant (BR-PROP-009).ORA-20000per il cambio diID_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_DATEconSYSDATE) e BR-PROP-024 (formato data forzato). La riproducibilità dipende dalla data corrente.
Feature flag / logging nascosto
- BR-PROP-025 —
GLOBAL_DEBUG_LOGscritto ad ogni upsert conCOMMITintermedio, senza flag di disattivazione; BR-PROP-030 —PREQUIREREFRESH.
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 NULLID_CREATION_DATE/ID_STARTING_DATE/ID_ENDING_DATE/DISMESSO/ID_LOCK_*/ID_NEGLECTEDsu INSERT (default di colonna vs trigger non ispezionato) — vedi BR-PROP-021. - Coesistenza dei due unique
UC_EDIFICI(codice+tenant) eUK_EDIFICI_(solo codice): è intenzionale? (BR-PROP-019). - Nel branch
DELETINGdel triggerCNT_EDIFICIl'uso di:NEW.ID_EDIFICIOper pulireGLOBAL_TENANCY_BINDINGSsembra un difetto (dovrebbe essere:OLD) — impatto sulla pulizia dei binding (BR-PROP-029). PERMISSION=2inGLOBAL_TENANCY_BINDINGS: mappatura esatta sull'enumTenancyPermission(BR-PROP-009).- Comportamento in configurazioni PROD (osservato solo su ambiente TEST38); crescita/impatto di
GLOBAL_DEBUG_LOG(BR-PROP-025).