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 OracleINFOCAD_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 procedureWKT_*via wrapperExecute*StoredProcedure).Struttura del dominio: cinque entità principali (
Line,Mobile,WorkerKitEvent, più le anagraficheLineState/LineType/ChargeType/ContractType/LetterType/CostCentre/Site) con lo stesso layeringSharedObjects → Interface → DAL → BL → Controllers. Le entità vivono in tabelleWKRKIT_*, l'ID è generato daSEQ_WKRKIT_*via trigger BEFORE INSERT, la cancellazione è logica (ISCANCELLED). Le assegnazioni sono storicizzate (tabelle-ponteWKRKIT_CONTACTS_LINE,WKRKIT_CONTACTS_MOBILE,WKRKIT_MOBILE_LINESconDATE_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 (codiciNVARCHAR2/VARCHAR2, join per codice, poche FK). L'estrazione ha inoltre rilevato diversi difetti probabili (pathRestoreverso procedure inesistenti, assegnazione linea↔apparato che non storicizza,WKT_UPDATEEVENTchiamata 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_CONTACT→GLOBAL_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 = -1 → ShowMessage(...)).
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 NULL → SEQ_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_CONTACT →
GLOBAL_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 (PIDEVENT
… PNOTE), 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/1730sono controlli di sola interfaccia. I BL sonoMarshalByRefObjectpass-through e i Controller non riverificano permessi: chi raggiunge un endpoint*_BL.remnon è soggetto ai grant. L'unico gate server-side è la licenza (GUID005C62DD-…, 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
RestoreversoWKT_RESTORE*inesistenti), BR-WK-020 (bind linea↔apparato che non storicizza → duplicati attivi), BR-WK-026 (WKT_UPDATEEVENTchiamata con 12 parametri su 13 richiesti → update evento rotto), BR-WK-027 (Line_DAL.SelectByIdListsenzaPIDLIST), BR-WK-025 (precedenzaAND/ORche bypassa il filtro eventi conPGETALL=1), BR-WK-008 (nessun anti-dup in update), BR-WK-017 (hard delete → associazioni orfane), BR-WK-014/015 (soft-delete che non valorizzaDATE_OFFsulle associazioni). - Magic number / hard-coded id / magic string: grant numerici (BR-WK-002), ritorno
-1(BR-WK-010), literal'LINE'/'MOBILE'comeOBJECT_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_LINESsenza FK/PK. NessunON DELETE CASCADE. - Incoerenze di tipo minori:
WKT_CREATELINEusaDATEperDATE_ON/DATE_OFFmentreWKT_UPDATELINEe le colonne tabella usanoTIMESTAMP(6); il DAL passaOracleDbType.Datein entrambi i casi.PIDLINEè dichiaratoOracleDbType.Varchar2nel 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.