Table of Contents

BR-WK — Regole di business del dominio WorkerKit / Dotazioni telefoniche

Regole estratte dal dominio WorkerKit / WorkerKitCenter di Infocad, ancorate al flusso pilota FLOW-WK-001 (creazione di una linea telefonica) e alla relativa evidenza. Il modulo gestisce le dotazioni telefoniche aziendali: linee/SIM (Line: prefisso, numero, PIN/PUK, stato, tipo, addebito, velocità, costo, sedi, centro di costo), cellulari (Mobile: IMEI, marca, tipo, contratto), le loro assegnazioni a contatti/dipendenti e agli apparati, e gli eventi/lettere di consegna (WorkerKitEvent). Sistema: Infocad (Descor), backend Oracle INFOCAD_TEST38, front-end ASP.NET Web Forms (VB.NET) WorkerKitWeb (famiglia CASSANDRA), server VB.NET (Controller → .NET Remoting → BL → DAL), nessun ORM (le DAL chiamano stored procedure WKT_* via wrapper Execute*StoredProcedure).

Struttura del dominio: cinque entità principali (Line, Mobile, WorkerKitEvent, più le anagrafiche LineState/LineType/ChargeType/ContractType/LetterType/CostCentre/Site) con lo stesso layering SharedObjects → Interface → DAL → BL → Controllers. Le entità vivono in tabelle WKRKIT_*, l'ID è generato da SEQ_WKRKIT_* via trigger BEFORE INSERT, la cancellazione è logica (ISCANCELLED). Le assegnazioni sono storicizzate (tabelle-ponte WKRKIT_CONTACTS_LINE, WKRKIT_CONTACTS_MOBILE, WKRKIT_MOBILE_LINES con DATE_ON/DATE_OFF/ISCANCELLED).

Aspetti centrali: l'intero modulo è attivabile a licenza (GUID ULM 005C62DD-1406-485E-9AEA-D40EC9C7161B); i grant applicativi sono verificati solo lato UI e mai ri-controllati oltre il confine .NET Remoting (pattern TD-008); l'unicità (linea/mobile) è imposta solo dentro le stored procedure di CREATE (nessun constraint dichiarativo); l'integrità referenziale verso le anagrafiche e verso linee/mobili è solo applicativa (codici NVARCHAR2/VARCHAR2, join per codice, poche FK). L'estrazione ha inoltre rilevato diversi difetti probabili (path Restore verso procedure inesistenti, assegnazione linea↔apparato che non storicizza, WKT_UPDATEEVENT chiamata con un parametro in meno, ecc.).

Legenda enforcement: UI = validato solo lato interfaccia/code-behind · BL = logica applicativa (controller/BL/DAL) · DB = logica in stored procedure/trigger o constraint · mixed = più livelli. Legenda confidence: VERIFIED = catena di codice + controprova indipendente (sorgente DB su USER_SOURCE/USER_TRIGGERS/USER_CONSTRAINTS) · SUPPORTED = evidenza coerente ma un anello non eseguito a runtime · INFERRED = dedotto dalla struttura, non testato.

Le stored procedure/trigger/constraint WKT_*/WKRKIT_* citati sono stati confermati con lookup read-only su USER_SOURCE/USER_TRIGGERS/USER_CONSTRAINTS/USER_CONS_COLUMNS/USER_TAB_COLUMNS dello schema INFOCAD_TEST38 (driver python-oracledb thin, sola lettura del dizionario — nessun accesso a dati di business, nessuna DML/DDL, nessuna credenziale stampata). I numeri di riga delle SP si riferiscono alla riga interna al testo della procedura in USER_SOURCE.


Registro regole

ID Regola Tipo Enforcement Conf.
BR-WK-001 Scrittura scheda Line consentita solo con grant 10020 o SuperAdmin; altrimenti scheda in sola visualizzazione permission UI ⚠️ VERIFIED
BR-WK-002 Grant per operazione/entità hard-coded (10020/10030/10120/10130/10230/10320/10330/1320/1730) e verificati solo in UI permission UI ⚠️ VERIFIED
BR-WK-003 L'intera superficie .NET Remoting WorkerKit (10 *_BL.rem SingleCall) è registrata solo se la licenza ULM abilita il GUID 005C62DD-… config-flag/permission mixed VERIFIED
BR-WK-004 I grant non sono ri-verificati oltre il Remoting (BL pass-through): un chiamante server-side bypassa i grant (TD-008) permission UI ⚠️ SUPPORTED
BR-WK-005 Creazione evento su un oggetto richiede 10230 e il grant di edit dell'oggetto (objectEditKey) permission UI ⚠️ VERIFIED
BR-WK-006 Unicità linea attiva = PREFIX+LINE_NUMBER con ISCANCELLED=0, imposta solo in WKT_CREATELINE (nessun constraint) validation DB VERIFIED
BR-WK-007 Unicità apparato attivo = IMEI con ISCANCELLED=0, imposta solo in WKT_CREATEMOBILE (nessun constraint) validation DB VERIFIED
BR-WK-008 L'anti-duplicato non è applicato in update (WKT_UPDATELINE/WKT_UPDATEMOBILE): collisione possibile via modifica validation/defect DB ⚠️ VERIFIED
BR-WK-009 WKT_CREATEEVENT non ha alcun controllo di unicità (INSERT diretto) validation DB VERIFIED
BR-WK-010 Convenzione di ritorno PNEWINDEX = -1 su duplicato → messaggio UI (magic number + stringa IT hard-coded) validation mixed VERIFIED
BR-WK-011 Nessuna validazione applicativa (InitValidators vuoto, BL pass-through): unica guardia = dup-check DB validation BL/UI ⚠️ VERIFIED
BR-WK-012 ID entità generati da SEQ_WKRKIT_* via trigger BEFORE INSERT; se ID fornito, il trigger risincronizza la sequence (ramo ELSE catch-up) calculation DB VERIFIED
BR-WK-013 ISCANCELLED default 0 (record attivo): cancellazione logica, non fisica, come stato base state-transition DB VERIFIED
BR-WK-014 Soft-delete linea (WKT_LOGICALDELETELINE) cancella a cascata associazioni contatto e apparato + la linea; non valorizza DATE_OFF state-transition DB ⚠️ VERIFIED
BR-WK-015 Soft-delete apparato (WKT_LOGICALDELETEMOBILE) simmetrico (cascata su contatti, mobile_lines, mobile) state-transition DB VERIFIED
BR-WK-016 Path Restore rotto: WKT_RESTORELINE/WKT_RESTOREMOBILE/WKT_RESTOREEVENT chiamate dal DAL non esistono in DB defect DB ⚠️ VERIFIED
BR-WK-017 WKT_FINALDELETE* (hard delete) cancella solo la riga entità: lascia orfane le righe di associazione (no FK/cascade) state-transition/defect DB ⚠️ VERIFIED
BR-WK-018 Assegnazione linea→contatto storicizza: chiude (ISCANCELLED=1,DATE_OFF=SYSDATE) le associazioni attive della linea, poi INSERT → una sola associazione-contatto attiva per linea state-transition DB VERIFIED
BR-WK-019 Assegnazione apparato→contatto simmetrica (chiusura + INSERT su WKRKIT_CONTACTS_MOBILE) state-transition DB VERIFIED
BR-WK-020 Assegnazione linea↔apparato non storicizza: la UPDATE di chiusura è commentata in WKT_ADDLINESTOMOBILE/WKT_ADDMOBILESTOLINE → righe attive duplicate defect DB ⚠️ VERIFIED
BR-WK-021 Rimozione associazioni (WKT_REMOVE*FROM*) storicizza correttamente: DATE_OFF=SYSDATE + ISCANCELLED=1, con scoping (per contatto / per linea / per apparato) state-transition DB VERIFIED
BR-WK-022 Disponibilità "for bind": una linea/apparato è selezionabile solo se non attivamente legata né ad apparato/linea né a un contatto validation DB VERIFIED
BR-WK-023 Integrità referenziale verso anagrafiche (COST_CENTRE NVARCHAR2, STATE_LINE/LINE_TYPE/CHARGE_TYPE/sedi VARCHAR2) è solo applicativa (codici, LEFT JOIN, nessuna FK) config-flag DB ⚠️ VERIFIED
BR-WK-024 Tabelle-ponte: FK solo su ID_CONTACTGLOBAL_CONTACTS; nessuna FK sul lato linea/apparato; WKRKIT_MOBILE_LINES senza FK config-flag/defect DB ⚠️ VERIFIED
BR-WK-025 WKT_GETEVENTSBYIDLINE/BYIDMOBILE: precedenza AND/OR fa ignorare il filtro OBJECT_TYPE/OBJECT_ID quando PGETALL=1 → ritorna tutti gli eventi defect DB ⚠️ VERIFIED
BR-WK-026 WorkerKitEvent_DAL.Update passa 12 parametri ma WKT_UPDATEEVENT ne richiede 13 (PISCANCELLED senza default) → update evento fallisce defect BL ⚠️ VERIFIED
BR-WK-027 Line_DAL.SelectByIdList costruisce PIDLIST ma non lo aggiunge ai parametri → WKT_GETLINESBYIDLIST invocata senza la lista (rotto) defect BL ⚠️ VERIFIED
BR-WK-028 Scheda Line in Insert preimposta DATE_ON e DATE_OFF a DateTime.Now; date lasciate vuote → DateTime.MinValue nel DTO date-logic UI VERIFIED

⚠️ = regola a rischio (solo-UI, solo-DB, magic number/hard-coded id, difetto probabile, integrità solo applicativa).

Nessuna regola risulta customer_specific: il modulo è prodotto standard; i progetti Reporting*/WorkerKitCenter/* in Customizations sono solo report/lettere (EventSheet), non percorsi di scrittura (cfr. FLOW-WK-001, Reverse trace).


Dettaglio regole

BR-WK-001 — Grant di scrittura sulla scheda Line

Tipo: permission · Enforcement: UI ⚠️ · Conf.: VERIFIED · customer_specific: no In BindPage() la scheda calcola canUpdate = HasUserGrant("10020") Or WS.SessionProfile.SuperAdmin; se falso, forza _operationType = View, e SetControlsState(View) disabilita tutti i controlli e trasforma il pulsante d'azione in "chiudi finestra" → nessun salvataggio possibile. ⚠️ solo-UI: il controllo è sulla resa/abilitazione dei controlli, non ripetuto a valle. 10020 è un magic id (etichetta funzionale non presente nel codice web — Open question di FLOW-WK-001). Evidenza: WorkerKitWeb/UserControls/LineDetail.ascx.vb:490-493 (gate), :334-386 (SetControlsState), :154-161 (PreRender → "chiudi").

BR-WK-002 — Mappa dei grant hard-coded del modulo (solo-UI)

Tipo: permission · Enforcement: UI ⚠️ · Conf.: VERIFIED · customer_specific: no Tutti i controlli d'accesso del WorkerKitCenter sono HasUserGrant("<id>") Or SuperAdmin con id numerici hard-coded, applicati alla visibilità/abilitazione di pulsanti e griglie: 10020 (crea/modifica linea + bind linea→apparato), 10030 (elimina linea), 10130 (crea/modifica apparato), 10120 (elimina apparato + bind apparato→linea), 10230 (crea/elimina evento), 10320 (bind linee/apparati a contatto), 10330 (crea/modifica contatto), 1320 (azione trasversale nelle griglie), 1730 (selector contatto in LinesManager/MobilesManager). ⚠️ magic id diffusi; nessun catalogo/enum centrale. Il menu di navigazione avrebbe grant di sola-vista (10010/10110/10210/10310) ma sono commentati (navMenu.ascx.vb:21-30). Evidenza: LinesManager.ascx.vb:171,180; MobilesManager.ascx.vb:164,173,185; MobileDetail.ascx.vb:357; MobileLinesGrid.ascx.vb:80,184; LineMobilesGrid.ascx.vb:81,189; EventsManager.ascx.vb:177; EventsGrid.ascx.vb:126,203; ContactLinesGrid.ascx.vb:95; ContactMobilesGrid.ascx.vb:91; ContactDetail.ascx.vb:361; LineDetail.ascx.vb:490.

BR-WK-003 — License gate ULM sull'intera superficie Remoting

Tipo: config-flag/permission · Enforcement: mixed · Conf.: VERIFIED · customer_specific: no Il Windows Service InfocadServer registra i wellknown SingleCall del WorkerKit solo dentro If enabledApplications.Contains(New Guid("005C62DD-1406-485E-9AEA-D40EC9C7161B")) Then: dieci endpoint *_BL.rem (Mobile_BL.rem, Line_BL.rem, WorkerKitEvent_BL.rem, ContractType_BL.rem, LineState_BL.rem, LineType_BL.rem, LetterType_BL.rem, ChargeType_BL.rem, CostCentre_BL.rem, Site_BL.rem). Se il GUID non è abilitato in licenza, nessun endpoint è registrato e ogni chiamata Activator.GetObject(...) del client fallisce a runtime. Lo stesso GUID registra l'app ULM WorkerKit/WorkerKitCenter (home ~/WorkerKitweb/default.aspx). Evidenza: InfocadServer/Business/Start.vb:841 (gate GUID), :843 (banner), :845-872 (10 RegisterWellKnownServiceType, Line_BL.rem a :848); InfocadServer/ULM/ApplicationFactory.vb:12,54.

BR-WK-004 — Grant non ri-verificati oltre il Remoting (TD-008)

Tipo: permission · Enforcement: UI ⚠️ · Conf.: SUPPORTED · customer_specific: no I grant (BR-WK-001/002) sono verificati esclusivamente nelle code-behind .ascx.vb. I BL server-side sono pass-through: Line_BL.Insert (e omologhi) si limita a DirectCast del DTO e a inoltrare al DAL, con il solo logging delle eccezioni; nessuna verifica di grant/utente. L'unico gate lato server è la licenza (BR-WK-003). Ne consegue che un chiamante che raggiunge l'endpoint Remoting non è soggetto ai grant 10020 &c. (pattern TD-008: grant controllato solo in UI, non riverificato attraverso .NET Remoting). SUPPORTED: dedotto dall'assenza di controlli server-side (non è stato eseguito un bypass a runtime). Evidenza: InfocadServer/WorkerKitBL/Line_BL.vb:9-11 (MarshalByRefObject/ILine_BL), :23-53 (Insert pass-through), :48-51 (solo logging); assenza di HasUserGrant/controlli utente in WorkerKitBL/* e nei Controller (WorkerKitControllers/LineController.vb).

BR-WK-005 — Creazione evento: doppio grant (evento + oggetto)

Tipo: permission · Enforcement: UI ⚠️ · Conf.: VERIFIED · customer_specific: no Nella griglia eventi il pulsante di inserimento/eliminazione è abilitato solo se (HasUserGrant("10230") And HasUserGrant(objectEditKey)) Or SuperAdmin: oltre al grant "eventi" (10230) serve anche il grant di edit dell'oggetto cui l'evento è legato (objectEditKey, es. 10020 per una linea, 10130 per un apparato). ⚠️ solo-UI + magic id; la logica AND rende la creazione evento subordinata al permesso sull'entità sottostante. Evidenza: WorkerKitWeb/UserControls/EventsGrid.ascx.vb:126.

BR-WK-006 — Unicità della linea attiva (solo in SP)

Tipo: validation · Enforcement: DB · Conf.: VERIFIED · customer_specific: no WKT_CREATELINE inizializza PNEWINDEX := -1, poi esegue SELECT COUNT(1) INTO EXISTLINE FROM WKRKIT_LINES WHERE PREFIX=PPREFIX AND LINE_NUMBER=PNUMBER AND ISCANCELLED=0; solo se EXISTLINE <= 0 esegue l'INSERT ... RETURNING ID_LINES INTO PNEWINDEX. L'unicità è quindi PREFIX+LINE_NUMBER limitata alle linee attive: una linea logicamente cancellata con lo stesso numero non blocca la ricreazione. ⚠️ regola solo-DB: WKRKIT_LINES ha PK solo su ID_LINES, nessun unique constraint su (PREFIX, LINE_NUMBER). Evidenza: WKT_CREATELINE USER_SOURCE:26 (init -1), :28-33 (dup-check ISCANCELLED=0), :35-40 (INSERT RETURNING); USER_CONSTRAINTS/USER_CONS_COLUMNS: PK_WKRKIT_LINES(ID_LINES), nessun UNIQUE; WorkerKitDAL/OracleODP/Line_DAL.vb:219.

BR-WK-007 — Unicità dell'apparato attivo per IMEI (solo in SP)

Tipo: validation · Enforcement: DB · Conf.: VERIFIED · customer_specific: no WKT_CREATEMOBILE replica esattamente il pattern di BR-WK-006 sull'IMEI: SELECT COUNT(1) INTO EXISTIMEI FROM WKRKIT_MOBILES WHERE IMEI=PIMEI AND ISCANCELLED=0; se <= 0, INSERT con RETURNING ID_MOBILES INTO PNEWINDEX, altrimenti PNEWINDEX resta -1. Nessun unique constraint su IMEI (PK solo su ID_MOBILES). Nota: il parametro PCONTACTID/contactId è commentato nel DAL e nella SP → la creazione dell'apparato non lega mai un contatto (il legame è un passo separato, cfr. BR-WK-019). Evidenza: WKT_CREATEMOBILE USER_SOURCE:15 (init -1), :17-21 (dup IMEI), :23-28 (INSERT RETURNING); WorkerKitDAL/OracleODP/Mobile_DAL.vb:173,185 (contactId commentato), :188.

BR-WK-008 — Nessun anti-duplicato in aggiornamento (difetto/asimmetria)

Tipo: validation/defect · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no WKT_UPDATELINE esegue un UPDATE WKRKIT_LINES SET ... WHERE ID_LINES = PIDLINE senza ricontrollare l'unicità di PREFIX+LINE_NUMBER; idem WKT_UPDATEMOBILE sull'IMEI. In assenza di unique constraint (BR-WK-006/007), una modifica può portare due linee/apparati attivi allo stesso numero/IMEI: la guardia anti-duplicato esiste solo nel path di creazione. ⚠️ difetto di coerenza. Evidenza: WKT_UPDATELINE USER_SOURCE:26-29; WKT_UPDATEMOBILE USER_SOURCE:15-17; Line_DAL.vb:301, Mobile_DAL.vb:239.

BR-WK-009 — Nessun controllo di unicità sugli eventi

Tipo: validation · Enforcement: DB · Conf.: VERIFIED · customer_specific: no WKT_CREATEEVENT esegue direttamente INSERT INTO WKRKIT_EVENTS (...) VALUES (...) RETURNING ID_EVENTS INTO PNEWINDEX, senza alcun COUNT/guardia: gli eventi/lettere non hanno vincolo di unicità (né su PREFIX+EVENT_NUMBER né su PROTOCOL). Coerente con la natura "log di consegna" dell'entità. Evidenza: WKT_CREATEEVENT USER_SOURCE:16-19; WorkerKitEvent_DAL.vb:224.

BR-WK-010 — Convenzione PNEWINDEX = -1 su duplicato

Tipo: validation · Enforcement: mixed · Conf.: VERIFIED · customer_specific: no Le SP di creazione ritornano -1 in PNEWINDEX quando il duplicato è rilevato (linea/apparato già attivo). Il DAL restituisce il valore invariato; il code-behind interpreta newID = -1 come duplicato e mostra il messaggio all'utente. ⚠️ magic number (-1) come canale di errore + stringa italiana hard-coded nel code-behind ("Esiste già una linea con questo numero!") invece di una risorsa localizzata. Evidenza: WKT_CREATELINE USER_SOURCE:26; WKT_CREATEMOBILE USER_SOURCE:15; LineDetail.ascx.vb:260-262 (newID = -1ShowMessage(...)).

BR-WK-011 — Nessuna validazione applicativa (BL/UI)

Tipo: validation · Enforcement: BL/UI ⚠️ · Conf.: VERIFIED · customer_specific: no InitValidators() della scheda è vuoto; CreateNew()/Update() mappano i controlli sul DTO senza controlli di dominio (solo IsNullOrEmpty prima di castare Speed/LineCost); i BL sono pass-through (BR-WK-004). L'unica guardia effettiva sui dati è il dup-check DB (BR-WK-006/007). Il doppio submit è invece prevenuto lato UI dai flag Created/Updated in ControlState. Evidenza: LineDetail.ascx.vb:482-484 (InitValidators vuoto), :207-257 (CreateNew, nessuna validazione di dominio), :83-116,538,542 (ControlState anti-doppio-submit); Line_BL.vb:23-53.

BR-WK-012 — Generazione ID via sequence e ramo di risincronizzazione

Tipo: calculation · Enforcement: DB · Conf.: VERIFIED · customer_specific: no I trigger BEFORE INSERT FOR EACH ROW su WKRKIT_LINES, WKRKIT_MOBILES, WKRKIT_EVENTS assegnano l'ID: se :NEW.<pk> IS NULLSEQ_WKRKIT_<x>.NEXTVAL; altrimenti (ID già valorizzato, es. import/migrazione) eseguono un catch-up: leggono Last_Number-1 da USER_SEQUENCES e ciclano NEXTVAL finché la sequence non supera l'ID fornito. ⚠️ il ramo ELSE è fragile: Last_Number in USER_SEQUENCES riflette l'high-water mark cache (con CACHE > 0 non è l'ultimo valore realmente usato), quindi la risincronizzazione può sovra/sotto-stimare. Il path normale (ID NULL) è pulito. Evidenza: USER_TRIGGERS: WKRKIT_LINES/WKRKIT_MOBILE/WKRKIT_EVENTS (BEFORE INSERT, ramo IF :NEW... IS NULL → NEXTVAL, ELSE → loop su User_Sequences.Last_Number).

BR-WK-013 — ISCANCELLED=0 come stato base (cancellazione logica)

Tipo: state-transition · Enforcement: DB · Conf.: VERIFIED · customer_specific: no La colonna ISCANCELLED ha default 0 su WKRKIT_LINES, WKRKIT_MOBILES, WKRKIT_EVENTS: i record nascono "attivi" (gli INSERT delle SP non impostano esplicitamente la colonna). La cancellazione è logica (set a 1), mai fisica sul path standard; tutte le GET filtrano PGETALL = 1 OR <tab>.ISCANCELLED = 0 (il parametro getAll consente il recupero dei cancellati). L'unicità (BR-WK-006/007) e i "for bind" (BR-WK-022) ragionano su ISCANCELLED=0. Evidenza: USER_TAB_COLUMNS: ISCANCELLED DEFAULT 0 su WKRKIT_LINES/WKRKIT_MOBILES/WKRKIT_EVENTS; WKT_GETALLLINES USER_SOURCE:55-56, WKT_GETALLMOBILES USER_SOURCE:29-30, WKT_GETALLEVENTS USER_SOURCE:27-28.

BR-WK-014 — Soft-delete linea con cascata applicativa

Tipo: state-transition · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no WKT_LOGICALDELETELINE(PIDLINE) esegue tre UPDATE: ISCANCELLED=1 su WKRKIT_CONTACTS_LINE (per ID_LINE), su WKRKIT_MOBILE_LINES (per ID_LINES) e su WKRKIT_LINES. Quindi la cancellazione logica di una linea annulla anche le sue assegnazioni a contatto e ad apparato. ⚠️ le UPDATE sulle associazioni non valorizzano DATE_OFF (a differenza di BR-WK-018/021), lasciando record cancellati ma con data di chiusura NULL → incoerenza nello storico. Evidenza: WKT_LOGICALDELETELINE USER_SOURCE:5-15; Line_DAL.vb:41.

BR-WK-015 — Soft-delete apparato con cascata simmetrica

Tipo: state-transition · Enforcement: DB · Conf.: VERIFIED · customer_specific: no WKT_LOGICALDELETEMOBILE(PIDMOBILE) è speculare: ISCANCELLED=1 su WKRKIT_CONTACTS_MOBILE (per ID_MOBILE), su WKRKIT_MOBILE_LINES (per ID_MOBILES) e su WKRKIT_MOBILES. Stessa nota sul DATE_OFF non valorizzato di BR-WK-014. Evidenza: WKT_LOGICALDELETEMOBILE USER_SOURCE:5-15; Mobile_DAL.vb:42.

BR-WK-016 — Path Restore verso procedure inesistenti (difetto)

Tipo: defect · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no I DAL espongono un Restore(id) che invoca WKT_RESTORELINE / WKT_RESTOREMOBILE / WKT_RESTOREEVENT. La verifica su ALL_OBJECTS/USER_OBJECTS (INFOCAD_TEST38) mostra che queste procedure non esistono (né come PROCEDURE standalone, né come synonym, né dentro package; sono presenti solo 48 procedure WKT_*, nessuna WKT_RESTORE*). Ogni chiamata di ripristino solleva quindi ORA-06550/PLS-00201 a runtime. ⚠️ difetto: funzionalità di ripristino della cancellazione logica non operativa su questo schema. Evidenza: Line_DAL.vb:59, Mobile_DAL.vb:60, WorkerKitEvent_DAL.vb:55 (chiamate WKT_RESTORE*); ALL_OBJECTS/USER_OBJECTS: nessun oggetto WKT_RESTORE% (48 WKT_* = tutte PROCEDURE, 0 package).

BR-WK-017 — Hard delete lascia associazioni orfane

Tipo: state-transition/defect · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no WKT_FINALDELETELINE/WKT_FINALDELETEMOBILE/WKT_FINALDELETEEVENT eseguono un DELETE secco della sola riga entità (WKRKIT_LINES/WKRKIT_MOBILES/WKRKIT_EVENTS), senza rimuovere le righe di associazione collegate. Poiché le tabelle-ponte non hanno FK verso linee/apparati (BR-WK-024) né ON DELETE CASCADE, la cancellazione definitiva di una linea/apparato lascia orfane le righe in WKRKIT_CONTACTS_LINE/WKRKIT_CONTACTS_MOBILE/ WKRKIT_MOBILE_LINES. ⚠️ rischio di dati orfani/incoerenti. Evidenza: WKT_FINALDELETELINE USER_SOURCE:5-6, WKT_FINALDELETEMOBILE USER_SOURCE:5-6, WKT_FINALDELETEEVENT USER_SOURCE:5-6; Line_DAL.vb:23, Mobile_DAL.vb:24.

BR-WK-018 — Assegnazione linea→contatto: storicizzazione e unicità

Tipo: state-transition · Enforcement: DB · Conf.: VERIFIED · customer_specific: no WKT_ADDLINESTOCONTACT(PIDLINESLIST, PIDCONTACT) prima chiude le associazioni attive delle linee indicate (UPDATE WKRKIT_CONTACTS_LINE SET ISCANCELLED=1, DATE_OFF=SYSDATE WHERE ID_LINE IN (lista)), poi inserisce i nuovi legami (ISCANCELLED=0, DATE_ON=SYSDATE, DATE_OFF=NULL, ID_CONTACT=PIDCONTACT). La chiusura è per ID_LINE (indipendente dal contatto precedente): ne discende l'invariante "al più un'associazione-contatto attiva per linea", con storico preservato in DATE_ON/DATE_OFF. La lista di ID arriva come tipo Oracle HELPERS.NUMBERLIST convertito in MYINTTABLE. Evidenza: WKT_ADDLINESTOCONTACT USER_SOURCE:8-11 (chiusura), :14-22 (INSERT); Line_DAL.vb:326-337; LineViewControl.ascx.vb:131-144 (attivazione su contatto selezionato).

BR-WK-019 — Assegnazione apparato→contatto (simmetrica)

Tipo: state-transition · Enforcement: DB · Conf.: VERIFIED · customer_specific: no WKT_ADDMOBILESTOCONTACT(PIDMOBILESLIST, PIDCONTACT) replica BR-WK-018 su WKRKIT_CONTACTS_MOBILE: chiude le associazioni attive per ID_MOBILE, poi inserisce il nuovo legame. Invariante "al più un contatto attivo per apparato". Evidenza: WKT_ADDMOBILESTOCONTACT USER_SOURCE:8-11 (chiusura), :14-22 (INSERT); Mobile_DAL.vb:249-260.

BR-WK-020 — Assegnazione linea↔apparato NON storicizza (difetto)

Tipo: defect · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no In WKT_ADDLINESTOMOBILE e WKT_ADDMOBILESTOLINE la UPDATE di chiusura delle associazioni precedenti è commentata: le procedure eseguono solo l'INSERT in WKRKIT_MOBILE_LINES. Poiché la tabella non ha unique constraint né PK, associare ripetutamente la stessa linea/apparato accumula più righe attive duplicate (ISCANCELLED=0), che poi compaiono duplicate nelle GET WKT_GET{MOBILE,LINE}BOUNDED{LINES,MOBILES} (filtrate su ISCANCELLED=0). ⚠️ asimmetria netta rispetto all'assegnazione a contatto (BR-WK-018/019) e alla rimozione (BR-WK-021), che invece storicizzano. Evidenza: WKT_ADDLINESTOMOBILE USER_SOURCE:10-12 (UPDATE commentata), :15-23 (solo INSERT); WKT_ADDMOBILESTOLINE USER_SOURCE:8-10 (UPDATE commentata), :12-20 (solo INSERT); Line_DAL.vb:358, Mobile_DAL.vb:304.

BR-WK-021 — Rimozione associazioni: storicizzazione con scoping

Tipo: state-transition · Enforcement: DB · Conf.: VERIFIED · customer_specific: no Le procedure di rimozione chiudono correttamente lo storico: WKT_REMOVELINESFROMCONTACT/ WKT_REMOVEMOBILESFROMCONTACT fanno SET ISCANCELLED=1, DATE_OFF=SYSDATE filtrando per contatto (ID_CONTACT = PIDCONTACT), così da non toccare associazioni di altri contatti; WKT_REMOVELINESFROMMOBILE/ WKT_REMOVEMOBILESFROMLINE eseguono due UPDATE (prima DATE_OFF=SYSDATE sui record attivi, poi ISCANCELLED=1) filtrando per apparato/linea. Corretta gestione della data di chiusura (a differenza del soft-delete, BR-WK-014). Evidenza: WKT_REMOVELINESFROMCONTACT USER_SOURCE:8-12; WKT_REMOVEMOBILESFROMCONTACT USER_SOURCE:8-12; WKT_REMOVELINESFROMMOBILE USER_SOURCE:9-21; WKT_REMOVEMOBILESFROMLINE USER_SOURCE:8-21; Line_DAL.vb:379, Mobile_DAL.vb:324,395.

BR-WK-022 — Disponibilità "for bind": elemento libero

Tipo: validation · Enforcement: DB · Conf.: VERIFIED · customer_specific: no WKT_GETALLLINESFORBIND restituisce le linee candidabili al legame solo se: attive (ISCANCELLED=0 o PGETALL=1) e non attualmente legate a un apparato (ID_LINES NOT IN (SELECT ID_LINES FROM WKRKIT_MOBILE_LINES WHERE ISCANCELLED=0)) e non assegnate a un contatto (WKRKIT_CONTACTS_LINE.ID_CONTACT IS NULL). WKT_GETALLMOBILESFORBIND applica la regola speculare agli apparati. Regola di business: un elemento è associabile solo se libero (né ad apparato/linea, né a contatto). Evidenza: WKT_GETALLLINESFORBIND USER_SOURCE:55-60; WKT_GETALLMOBILESFORBIND USER_SOURCE:28-33; Line_DAL.vb:400, Mobile_DAL.vb:370.

BR-WK-023 — Integrità verso le anagrafiche solo applicativa

Tipo: config-flag · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no WKRKIT_LINES non ha FK verso le anagrafiche: COST_CENTRE è NVARCHAR2 (codice), STATE_LINE, LINE_TYPE, CHARGE_TYPE, DEPARTURE_SITE, ARRIVAL_SITE sono VARCHAR2 (codici). Le GET risolvono i codici via LEFT JOIN sulle anagrafiche (WKRKIT_COST_CENTRE, WKRKIT_LINE_STATE, ...): un codice inesistente non è bloccato (join a NULL, non errore). L'integrità referenziale è quindi solo applicativa. Nota di modello: WKRKIT_LINE_STATE/WKRKIT_LINE_TYPE hanno solo CODE NOT NULL (check) e non una PK su CODE (a differenza di COST_CENTRE/CONTRACT_TYPE/LETTER_TYPE/SITES che hanno PK su CODE): stati/tipi linea potrebbero avere codici duplicati. (Curiosità: la PK di WKRKIT_CHARGE_TYPE è denominata PK_WKRKIT_LINE_TYPE — errore di naming, innocuo.) Evidenza: USER_TAB_COLUMNS WKRKIT_LINES.COST_CENTRE = NVARCHAR2; USER_CONSTRAINTS/USER_CONS_COLUMNS: WKRKIT_LINES FKS=∅; WKRKIT_LINE_STATE/WKRKIT_LINE_TYPE solo check CODE NOT NULL; WKT_GETALLLINES USER_SOURCE:38-49 (LEFT JOIN per codice).

BR-WK-024 — Tabelle-ponte: FK solo verso GLOBAL_CONTACTS

Tipo: config-flag/defect · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no WKRKIT_CONTACTS_LINE e WKRKIT_CONTACTS_MOBILE hanno FK solo su ID_CONTACTGLOBAL_CONTACTS.PK_GLOBAL_CONTACTS; nessuna FK sul lato ID_LINE/ID_MOBILE. WKRKIT_MOBILE_LINES non ha alcuna FK né PK (solo tre check NOT NULL). Nessuna delle tre tabelle-ponte ha una PK/unique che impedisca righe duplicate. Conseguenze: l'integrità linea/apparato è solo applicativa; si combinano con BR-WK-017 (orfani su hard delete) e BR-WK-020 (duplicati su bind apparato↔linea). Evidenza: USER_CONSTRAINTS/USER_CONS_COLUMNS: WKRKIT_CONTACTS_LINE FK FK_WKRKIT_CONTACTS_LINE_CNT(ID_CONTACT)GLOBAL_CONTACTS, 3 check NOT NULL, PK assente; WKRKIT_CONTACTS_MOBILE idem (FK_WKRKIT_CONTACTS_MOBILE1); WKRKIT_MOBILE_LINES FKS=∅, PK=∅.

BR-WK-025 — WKT_GETEVENTSBYIDLINE/BYIDMOBILE: filtro ignorato con PGETALL=1 (difetto)

Tipo: defect · Enforcement: DB ⚠️ · Conf.: VERIFIED · customer_specific: no La clausola è WHERE (PGETALL = 1 OR WKRKIT_EVENTS.ISCANCELLED = 0 AND OBJECT_TYPE = 'LINE' AND OBJECT_ID = PIDLINE). Poiché AND lega più di OR, l'espressione equivale a PGETALL=1 OR (ISCANCELLED=0 AND OBJECT_TYPE='LINE' AND OBJECT_ID=PIDLINE): con PGETALL=1 il filtro su oggetto/ID è completamente bypassato → la SP ritorna tutti gli eventi invece di quelli della linea (idem per l'apparato con 'MOBILE'). Sul path normale (getAll=0, default del DAL) la clausola funziona. ⚠️ difetto di precedenza + magic string 'LINE'/'MOBILE'. Evidenza: WKT_GETEVENTSBYIDLINE USER_SOURCE:25-28; WKT_GETEVENTSBYIDMOBILE USER_SOURCE:25-28; WorkerKitEvent_DAL.vb:144-156 (SelectByIdLine, getall default False).

BR-WK-026 — WKT_UPDATEEVENT chiamata con un parametro in meno (difetto)

Tipo: defect · Enforcement: BL ⚠️ · Conf.: VERIFIED · customer_specific: no La procedura WKT_UPDATEEVENT dichiara 13 parametri formali, incluso PISCANCELLED IN NUMBER (senza DEFAULT). Il chiamante WorkerKitEvent_DAL.Update aggiunge però solo 12 OracleParameter (PIDEVENTPNOTE), omettendo PISCANCELLED. Con parametro obbligatorio mancante, la chiamata solleva PLS-00306/ORA-06550 sia in binding posizionale sia per nome. ⚠️ difetto: l'aggiornamento di un evento via questo path fallisce (il set di ISCANCELLED da update non è comunque raggiungibile). Evidenza: WKT_UPDATEEVENT USER_SOURCE:1-13 (13 formali, PISCANCELLED a :13), :18-21 (UPDATE con ISCANCELLED=PISCANCELLED); WorkerKitEvent_DAL.vb:237-269 (solo 12 parametri aggiunti, :255-266).

BR-WK-027 — Line_DAL.SelectByIdList non aggiunge la lista ID (difetto)

Tipo: defect · Enforcement: BL ⚠️ · Conf.: VERIFIED · customer_specific: no In Line_DAL.SelectByIdList il parametro PIDLIST (associative array) viene costruito ma non aggiunto a dl.Parameters (sono aggiunti solo PGETALL e POUT). La SP WKT_GETLINESBYIDLIST richiede invece PIDLIST HELPERS.NUMBERLIST come primo argomento → la chiamata è priva della lista e fallisce/ritorna un cursore vuoto. Gli omologhi Mobile_DAL.SelectByIdList e WorkerKitEvent_DAL.SelectByIdList aggiungono correttamente il parametro. ⚠️ difetto isolato al DAL delle linee. Evidenza: Line_DAL.vb:123-124 (PIDLIST costruito), :128-129 (aggiunti solo PGETALL/POUT), :131 (WKT_GETLINESBYIDLIST); confronto Mobile_DAL.vb:129, WorkerKitEvent_DAL.vb:125; WKT_GETLINESBYIDLIST USER_SOURCE:1-6 (formale PIDLIST).

BR-WK-028 — Default date della scheda Line in inserimento

Tipo: date-logic · Enforcement: UI · Conf.: VERIFIED · customer_specific: no In SetControlsState, ramo Insert, la scheda preimposta sia dtpDateOn sia dtpDateOff a DateTime.Now: una nuova linea nasce con data di attivazione e di disattivazione uguali a "adesso" se l'operatore non le modifica. In CreateNew/Update, una data lasciata vuota è mappata a DateTime.MinValue nel DTO. ⚠️ date-logic app-side (nessun controllo di coerenza DATE_ON <= DATE_OFF). Evidenza: LineDetail.ascx.vb:350-354 (default DateTime.Now su Insert), :235-245 (vuoto → DateTime.MinValue).


Note trasversali e flag

  • Solo-UI / TD-008 (BR-WK-001/002/004/005): tutti i grant 10020/10030/10120/10130/10230/10320/ 10330/1320/1730 sono controlli di sola interfaccia. I BL sono MarshalByRefObject pass-through e i Controller non riverificano permessi: chi raggiunge un endpoint *_BL.rem non è soggetto ai grant. L'unico gate server-side è la licenza (GUID 005C62DD-…, BR-WK-003).
  • Solo-DB (BR-WK-006/007/012/013/014/015/018/019/021/022): unicità, generazione ID, soft-delete a cascata, storicizzazione delle assegnazioni e regole di disponibilità vivono interamente in stored procedure/trigger, invisibili al codice applicativo.
  • Difetti probabili (⚠️): BR-WK-016 (path Restore verso WKT_RESTORE* inesistenti), BR-WK-020 (bind linea↔apparato che non storicizza → duplicati attivi), BR-WK-026 (WKT_UPDATEEVENT chiamata con 12 parametri su 13 richiesti → update evento rotto), BR-WK-027 (Line_DAL.SelectByIdList senza PIDLIST), BR-WK-025 (precedenza AND/OR che bypassa il filtro eventi con PGETALL=1), BR-WK-008 (nessun anti-dup in update), BR-WK-017 (hard delete → associazioni orfane), BR-WK-014/015 (soft-delete che non valorizza DATE_OFF sulle associazioni).
  • Magic number / hard-coded id / magic string: grant numerici (BR-WK-002), ritorno -1 (BR-WK-010), literal 'LINE'/'MOBILE' come OBJECT_TYPE (BR-WK-025), stringa italiana hard-coded nel messaggio di duplicato (BR-WK-010).
  • Integrità solo applicativa (BR-WK-023/024): codici anagrafici senza FK, tabelle-ponte con FK solo verso GLOBAL_CONTACTS, WKRKIT_MOBILE_LINES senza FK/PK. Nessun ON DELETE CASCADE.
  • Incoerenze di tipo minori: WKT_CREATELINE usa DATE per DATE_ON/DATE_OFF mentre WKT_UPDATELINE e le colonne tabella usano TIMESTAMP(6); il DAL passa OracleDbType.Date in entrambi i casi. PIDLINE è dichiarato OracleDbType.Varchar2 nel DAL pur essendo un id numerico (Line_DAL.vb:256). Non bloccanti.
  • customer_specific: nessuna regola specifica per singolo cliente; comportamento di prodotto standard su INFOCAD_TEST38. Le personalizzazioni WorkerKit note (Reporting*/WorkerKitCenter/*) sono solo report/lettere.