FLOW-BLK-001 — Caricamento massivo (BulkLoader) — Import batch di Persone da Excel
Flusso end-to-end di import massivo (insert batch) di anagrafiche Persone a partire da un file Excel caricato dall'operatore. Operazione WRITE rappresentativa del dominio BulkLoader / Caricamento massivo. Path pilota: UserControl
UploadProcessControl.ascx→ opzioneIMP_PERSONE. Backend OracleINFOCAD_TEST38, accesso via stored procedure ODP.NET (nessun ORM). Le righe valide del file vengono persistite come entitàPERSONE(tabellaPERSONE_) tramite la stessa procedura generica di upsertPRP_MANAGEENTITYusata dal salvataggio interattivo; il ciclo di vita del processo di caricamento è tracciato suGLOBAL_UPLOAD_PROCESS/GLOBAL_UPLOAD_ALERT.
- Flow ID: FLOW-BLK-001
- Repository: InfocadWeb (ASP.NET Web Forms, VB.NET — CommonWeb/UploadProcessControl) + InfocadServer (BulkLoaderControllers/BulkLoaderManager + PropertyManager, VB.NET; servizio Windows via .NET Remoting)
- Confidence complessiva: VERIFIED (catena UI → controller remoting → BulkLoader server → PeopleBulkLoader → DAO → stored procedure, confermata su codice E su sorgente DB per le procedure di processo
RPS_*) · SUPPORTED (mappaPRP_MANAGEENTITY→PERSONE_, ereditata da FLOW-PROP-001 + verifica catalogo colonne)
Obiettivo di business
Consentire a un operatore di caricare in blocco un elenco di persone (anagrafica PERSONE) da un
foglio Excel, posizionandole nel vano corretto della gerarchia spaziale, evitando l'inserimento
manuale record per record. Ogni riga valida del file produce (in modalità insert) una nuova persona
nella tabella PERSONE_, con chiave di deduplica configurabile (strPeopleKey), collocazione
spaziale risolta a partire dai campi vano/edificio/comprensorio, e stamping di audit. Il processo è
asincrono/batch: viene registrato uno stato di avanzamento e, per ogni riga, un alert di esito
(successo / warning / errore), consultabile poi dall'operatore.
Attori
- Operatore (utente autenticato,
WS.SessionLogin.UserName) che apre il control di upload, seleziona l'entitàPersone(IMP_PERSONE), le chiavi di identificazione e il file Excel, e preme Carica (btnLoad). - InfocadServer / servizio BulkLoader (oggetto remoting
BulkLoader.rem) che esegue l'import lato server, riga per riga. - Oracle
INFOCAD_TEST38— procedure di processoRPS_STARTUPLOADPROCESS/RPS_WRITEUPLOADALERT/RPS_COMPLETEUPLOADPROCESS(tracciamento) ePRP_MANAGEENTITY(upsert dell'entitàPERSONE_), con letture cross-schemaASPNET_TEST38per la risoluzione tenant.
Trigger
Click sul pulsante Carica: evento btnLoad_Click
(UploadProcessControl.ascx.vb:388, Handles btnLoad.Click), che entra nello Select Case LoadOptions.SelectedValue (:405) e, sul ramo Case "IMP_PERSONE" (:453), costruisce la chiave
persone e invoca il controller BulkLoader (:460).
Frontend entry point
- Control di upload:
CommonWeb/Common/UserControls/UploadProcessControl.ascx(+ code-behindUploadProcessControl.ascx.vb), riusato da più moduli (Property/Global) come UI generica di caricamento massivo. - Selettore entità:
LoadOptions(dropdown) con valoreIMP_PERSONE(insert) /UPD_PERSONE(update). - Chiavi di deduplica: checklist
cmbPeopleKey→ stringastrPeopleKey(;-separated), passata cometableKeyal server. - Controller client:
Descor.BulkLoaders.BulkLoaderControllers.BulkLoadController(UploadProcessControl.ascx.vb:229istanzia;:460chiama).
Sequenza principale (main sequence)
- Operatore seleziona
Persone, spunta le chiavi, carica il file Excel e preme Carica. UploadProcessControl.ascx.vb→btnLoad_Click(:388) →Case "IMP_PERSONE"(:453): componestrPeopleKeydalle voci selezionate (:454-459) e chiamabulkCtrl.StartFileUploadProcess(New BulkEntity.GLOBAL(ENTITY.PERSONE), fileName, documentFile, UserName, strPeopleKey, isInsert:=True, evaluateLocation:=0, evaluateAction:=0)(:460).BulkLoadController.StartFileUploadProcess(...)inoltra al DAO remotingIBulkLoad(BulkLoadController.vb:83), risolto in costruttore viaActivator.GetObject(GetType(IBulkLoad), CHANNEL "://" SERVERADDRESS "/BulkLoader.rem")(BulkLoadController.vb:9) — il server è la classeBulkLoadernel servizio InfocadServer.BulkLoader.StartFileUploadProcess(entityType As Base, ..., tableKey, isInsert, evaluateLocation, evaluateAction)(BulkLoader.vb:199):- salva il file su disco
SaveUploadedFile(doc, fileName)(:203); - registra il processo:
StartProcess(username, tmpfilename, doc, entityType.getValue())(:205) → stored procedureRPS_STARTUPLOADPROCESS(:806), che faINSERT INTO GLOBAL_UPLOAD_PROCESS (... STATUS='RUNNING' ...) RETURNING ID_PROCESSe restituisce ilprocessid; - dispatch a
Import(entityType, processid, tmpfilename, username, tableKey, isInsert, evaluateLocation, evaluateAction)(:207).
- salva il file su disco
Import(...)(BulkLoader.vb:673): sul ramoGLOBAL.ENTITY.PERSONE(:677) istanziaNew PeopleBulkLoader(processid, tableKey, isInsert, evaluateLocation, evaluateAction)(:678), impostaUsernamee chiamaBLB.StartImport(filename, logs)(:687).PeopleBulkLoader.StartImport(PeopleBulkLoader.vb:69):LoadUploadedFile(filename)(:70) carica il DataTable dall'Excel;- risolve il tenant corrente
DAO_Tenancy.GetCurrentTenancyID(Username)(:76-77); ValidateFile(dt, log)(:86) →ValidateInsertingFile(:141) verifica presenza colonneVANO/CODICE_VANO, chiavi, colonneLOG_RES/LOG_DETe confronto con le colonne diPERSONE_(DAO_Db.getColumnsByTable(ENTITY),:189);- per ogni riga non vuota:
ValidateObject(obj, log)(:103) poiInsertObject(obj, log)(:105).
PeopleBulkLoader.InsertObject(:36) → (insert,evaluateLocation=0)InsertPeople(dr, idRoomNew, log)(:59), previa risoluzione del vanoValidateSpaceLocation(dr, log)(:57) che interrogaDAO_Asset.GetAssetLocationByParamAndTnt(param, tenantID)(:303) e ritornaID_VANO.PeopleBulkLoader.InsertPeople(:333):- deduplica: se la chiave esiste già per il tenant (
DAO_GenericEntity.existEntityByKeyAndTenant,:371) → riga rifiutata con alert; altrimenti - costruisce
entityFieldsa partire dalle colonne del file mappate sulla struttura entità (DAO_Metadata.GetEntityStructure("PERSONE_", roles),:383; loop:385-405), aggiungendoID_VANO = idRoom(:381); - persiste:
idPeople = New DAO_People().SavePeople(Username, 0, entityFields)(:406) (0= creazione).
- deduplica: se la chiave esiste già per il tenant (
DAO_People.SavePeople(DAO_People.vb:231): aggiunge la colonna di auditID_CHANGED_BY = usernamese assente (:241-244) e chiamaDAO_GenericEntity.ManageEntity(username, peopleID, "ID_N", "PERSONE", "", "", KeyValue)(:248).DAO_GenericEntity.ManageEntitycalcolaentityTableName = "PERSONE" & "_"=PERSONE_, serializzaKeyValuein XML e invocaPRP_MANAGEENTITY(stessa procedura generica documentata in FLOW-PROP-001):PID=0/NULL⇒ INSERTPERSONE_conRETURNING ID_N; scrive/aggiornaGLOBAL_TENANCY_BINDINGS; ritorna il nuovo id inPRETVALUE.- Alert per riga:
PeopleBulkLoaderchiamaWriteAlert(...)(es.:419successo /:423errore) →BulkLoaderBase.WriteAlert(BulkLoaderBase.vb:558) →BulkLoader.WriteUploadAlert(BulkLoader.vb:954) →RPS_WRITEUPLOADALERT(:976) →INSERT INTO GLOBAL_UPLOAD_ALERT. - Chiusura processo: al termine di
StartImport,ImportchiamaCompleteFileUploadProcess(processid, completion, TotalObjects, ValidObjects, CreatedObjects)(BulkLoader.vb:689) →RPS_COMPLETEUPLOADPROCESS(:1004) →UPDATE GLOBAL_UPLOAD_PROCESS SET STATUS=..., END_DATE=SYSDATE, TOTALOBJS/VALIDOBJS/CREATEDOBJS.
API / service
- UI → Server: nessun WCF/SOAP. Il
BulkLoadController(in-process nel web) delega a un oggetto .NET RemotingIBulkLoad(BulkLoader.rem) esposto dal servizio InfocadServer (BulkLoadController.vb:9). L'interfaccia di contratto èIBulkLoad(BulkLoaderControllers/IBulkLoad.vb, con overload tipizzati nell'implementazione server). - Metodo di ingresso:
StartFileUploadProcess(entityType, fileName, doc, username, tableKey, isInsert, evaluateLocation, evaluateAction)— overload dedicato al caso Persone. - Metodi correlati (stesso servizio):
RetryFileUploadProcess,GetUserFileUploadProcesses,GetFileUploadProcess,GetFileUploadAlertHistory,WriteUploadAlert.
Backend
- UI/Code-behind:
CommonWeb/Common/UserControls/UploadProcessControl.ascx.vb. - Controller (client remoting):
Descor.BulkLoaders.BulkLoaderControllers.BulkLoadController(InfocadServer/BulkLoaderControllers/BulkLoadController.vb). - Servizio server (implementazione
IBulkLoad):Descor.BulkLoaders.BulkLoaderManager.BulkLoader(InfocadServer/BulkLoaderManager/BulkLoader.vb) — orchestrazione processo, dispatch per entità, scritture di processo/alert via DAL. - Loader di dominio:
PeopleBulkLoader : BulkLoaderBase(InfocadServer/BulkLoaderManager/PeopleBulkLoader.vb) — validazione file/righe, risoluzione vano, costruzione campi, insert/update per riga. - Classe base:
BulkLoaderBase(BulkLoaderManager/BulkLoaderBase.vb) — caricamento file,WriteAlert, validazioni comuni, contrattoMustOverride(ValidateFile/ValidateObject/InsertObject/StartImport). - DAO entità:
PropertyManager.DAO.DAO_People(SavePeople) ePropertyManager.DAO.DAO_GenericEntity(ManageEntity,existEntityByKeyAndTenant). - Pattern DAL:
Using dl As New DataLayer(My.Settings.ConnectionName)→dl.Parameters.Add(OracleParameter...)→dl.ExecuteNonQueryStoredProcedure("RPS_..."); identity via parametro OUT (PNEWINDEX,PALERTID).
Query / stored procedure
| Passo | Stored procedure (Oracle INFOCAD_TEST38) |
Chiamata da (DAL) |
|---|---|---|
Apertura processo di caricamento (INSERT GLOBAL_UPLOAD_PROCESS, OUT PNEWINDEX) |
RPS_STARTUPLOADPROCESS |
BulkLoader.vb:806 |
Upsert entità Persona (INSERT/UPDATE dinamico su PERSONE_) |
PRP_MANAGEENTITY (OUT PRETVALUE CLOB) |
DAO_People.vb:248 → DAO_GenericEntity.ManageEntity |
Alert per riga (INSERT GLOBAL_UPLOAD_ALERT, OUT PALERTID) |
RPS_WRITEUPLOADALERT |
BulkLoader.vb:976 |
Chiusura processo (UPDATE GLOBAL_UPLOAD_PROCESS stato+contatori) |
RPS_COMPLETEUPLOADPROCESS |
BulkLoader.vb:1004 |
| Verifica esistenza persona per chiave+tenant (READ) | (SQL/proc via) DAO_GenericEntity.existEntityByKeyAndTenant |
PeopleBulkLoader.vb:371 |
| Risoluzione vano di collocazione (READ) | DAO_Asset.GetAssetLocationByParamAndTnt |
PeopleBulkLoader.vb:303 |
Tabelle lette (read)
INFOCAD_TEST38: struttura/colonnePERSONE_(DAO_Db.getColumnsByTable), metadati entità (DAO_Metadata.GetEntityStructure), gerarchia spaziale perGetAssetLocationByParamAndTnt(VANI_/EDIFICI_/…),GLOBAL_LOGIN_SETTINGS+ cataloghiUSER_TABLES/USER_TAB_COLUMNS(dentroPRP_MANAGEENTITY).ASPNET_TEST38:ORA_ASPNET_USERS,ORA_ASPNET_APPLICATIONS(risoluzione tenant, viaPRP_MANAGEENTITY, ereditato da FLOW-PROP-001).
Tabelle modificate (write)
INFOCAD_TEST38:GLOBAL_UPLOAD_PROCESS(RW — record di processo: INSERT su start conSTATUS='RUNNING'+RETURNING ID_PROCESS; UPDATE su completamento con stato/END_DATE/contatori; VERIFIED su sorgenteRPS_STARTUPLOADPROCESS/RPS_COMPLETEUPLOADPROCESS).GLOBAL_UPLOAD_ALERT(RW — un record di esito per riga elaborata: INSERT conRETURNING ALERTID; VERIFIED su sorgenteRPS_WRITEUPLOADALERT).PERSONE_(RW — tabella-radice della persona: INSERT dinamico conRETURNING ID_Nin creazione, UPDATEWHERE ID_N = :idin aggiornamento; viaPRP_MANAGEENTITY).GLOBAL_TENANCY_BINDINGS(RW — binding tenant dell'entità, dentroPRP_MANAGEENTITY; SUPPORTED, ereditato da FLOW-PROP-001).
Validazione
- Lato UI: composizione obbligatoria di
strPeopleKeydalle chiavi selezionate (UploadProcessControl.ascx.vb:454-459); disabilitazione opzioneIMP_PERSONEin contesti non ammessi (:898). - Lato loader (file):
ValidateInsertingFile(PeopleBulkLoader.vb:183) — richiede colonnaVANO/CODICE_VANO(:191), chiavi non vuote (:196), colonne di servizioLOG_RES/LOG_DET(:224-232), congruenza con le colonne DB diPERSONE_(:201). - Lato loader (riga):
ValidateObject(:152) richiede l'indicazione del vano in insert (:159-168);ValidateSpaceLocation(:285) impone collocazione univoca e appartenente al tenant (0/>1 risultati ⇒ scarto con alterActionError,:310-322). - Deduplica:
existEntityByKeyAndTenant(:371) blocca l'insert se la persona esiste già (per la commessa o per altra commessa) con la chiave data (:373-377). - Lato DB:
PRP_MANAGEENTITYverifica esistenza tabella/colonna id prima della DML dinamica (ereditato da FLOW-PROP-001); errori ritornati come stringa inPRETVALUE.
Side effects
- Persistenza di un record di processo di caricamento (
GLOBAL_UPLOAD_PROCESS) con statoRUNNING → Done/DoneWithWarnings/NotDonee contatoriTOTALOBJS/VALIDOBJS/CREATEDOBJS. - Persistenza del file sorgente (BLOB
DOCUMENT_FILE) nel record di processo (per retry:RetryFileUploadProcess/RPS_RETRYUPLOADPROCESS). - Alert per riga su
GLOBAL_UPLOAD_ALERT(esito e messaggio), consultabili viaGetFileUploadAlertHistory/RPS_GETUPLOADALERTHISTORY. - Assegnazione codice/identity
ID_Ne stampingID_CHANGED_BY(via DAO) per ogni persona creata; binding tenant suGLOBAL_TENANCY_BINDINGS(viaPRP_MANAGEENTITY). - Aggiornamento del foglio Excel elaborato con i log per riga (
UploadLogOnUploadedFile,PeopleBulkLoader.vb:129). - In update con cambio vano: trasferimento asset collegati alla persona
(
DAO_People.UpdatePeopleChangeROOM, ramoupdatePeople,:527) — non attivo nel path insert.
Percorsi alternativi / di errore
- Update massivo Persone:
Case "UPD_PERSONE"(UploadProcessControl.ascx.vb:461) →isInsert:=False,evaluateLocation/evaluateActionda checkbox →PeopleBulkLoader.updatePeople(:435) →DAO_People.SavePeople(Username, ID_N, ...)(:544,PID>0⇒ UPDATEPERSONE_). - Retry:
RetryFileUploadProcess(processID, username)(BulkLoader.vb:267) rilegge il record processo (RPS_RETRYUPLOADPROCESS) e rilanciaImport. - File non valido:
ValidateFilefallisce ⇒WriteAlert(..., NoAction)eStartImportritornaNotDone(PeopleBulkLoader.vb:122-124), nessuna riga persistita. - Riga non valida / collocazione ambigua / duplicato: alert
ActionError/NoAction, riga saltata, incrementowarns⇒ processo chiusoDoneWithWarnings(:131-135). - Errore DB su
PRP_MANAGEENTITY: ritorno non numerico ⇒IsNumeric(idPeople)=False⇒ alert di errore con il messaggio DB (PeopleBulkLoader.vb:421-426). - entityType non riconosciuto:
WriteUploadAlert(..., "ENTITY UNKNOW", ...)(BulkLoader.vb:680). - Altre entità dello stesso dominio (stessa meccanica di processo): Companies, Contacts, Contracts,
Managements, Providers, Costcentre, Asset, Spatial, Categories, Energy, Documenti — dispatch in
BulkLoader.Import(BulkLoader.vb:434-582).
Diagramma di sequenza
sequenceDiagram
actor Op as Operatore
participant UI as UploadProcessControl.ascx.vb (btnLoad)
participant CC as BulkLoadController (remoting client)
participant SV as BulkLoader (InfocadServer, BulkLoader.rem)
participant PBL as PeopleBulkLoader
participant DAOP as DAO_People.SavePeople
participant DAOG as DAO_GenericEntity.ManageEntity
participant DB as Oracle INFOCAD_TEST38
Op->>UI: seleziona Persone + file + chiavi, click Carica
UI->>CC: StartFileUploadProcess(GLOBAL.PERSONE, file, user, key, isInsert=True, 0,0)
CC->>SV: IBulkLoad.StartFileUploadProcess(...) [.NET Remoting]
SV->>DB: RPS_STARTUPLOADPROCESS -> INSERT GLOBAL_UPLOAD_PROCESS (RUNNING) RETURNING ID_PROCESS
DB-->>SV: processid
SV->>PBL: Import -> new PeopleBulkLoader; StartImport(file)
PBL->>PBL: LoadUploadedFile / ValidateFile
loop per ogni riga valida
PBL->>PBL: ValidateObject + ValidateSpaceLocation (idRoom)
PBL->>DAOP: SavePeople(user, 0, entityFields)
DAOP->>DAOG: ManageEntity(user, 0, "ID_N", "PERSONE", KeyValue)
DAOG->>DB: PRP_MANAGEENTITY (PTAB="PERSONE_") -> INSERT PERSONE_ RETURNING ID_N
DB-->>DAOG: nuovo ID_N
PBL->>DB: RPS_WRITEUPLOADALERT -> INSERT GLOBAL_UPLOAD_ALERT (esito riga)
end
PBL-->>SV: CompletionResults (Done/DoneWithWarnings)
SV->>DB: RPS_COMPLETEUPLOADPROCESS -> UPDATE GLOBAL_UPLOAD_PROCESS (stato+contatori)
SV-->>CC: processid
CC-->>Op: processo avviato/completato (storico alert consultabile)
Matrice di tracciabilità
| Layer | Artefatto | Evidenza (file:riga) |
|---|---|---|
| UI | UploadProcessControl.ascx (control upload) |
CommonWeb/Common/UserControls/UploadProcessControl.ascx.vb:1 |
| Code-behind | btnLoad_Click → Case "IMP_PERSONE" → StartFileUploadProcess |
UploadProcessControl.ascx.vb:388,405,453,460 |
| Controller (remoting client) | BulkLoadController.StartFileUploadProcess + risoluzione BulkLoader.rem |
BulkLoadController.vb:9,83 |
| Contratto | IBulkLoad |
BulkLoaderControllers/IBulkLoad.vb:1 |
| Server orchestratore | BulkLoader.StartFileUploadProcess (overload People) |
BulkLoader.vb:199,205,207 |
| Server — apertura processo | StartProcess → RPS_STARTUPLOADPROCESS |
BulkLoader.vb:791,806 |
| Server — dispatch | Import(...) → New PeopleBulkLoader → StartImport |
BulkLoader.vb:673,677,678,687,689 |
| Loader | PeopleBulkLoader.StartImport/InsertObject/InsertPeople |
PeopleBulkLoader.vb:69,36,333,406 |
| Loader — validazioni | ValidateInsertingFile/ValidateObject/ValidateSpaceLocation |
PeopleBulkLoader.vb:183,152,285,303 |
| Loader — dedup | existEntityByKeyAndTenant |
PeopleBulkLoader.vb:371 |
| Base — alert | BulkLoaderBase.WriteAlert → WriteUploadAlert |
BulkLoaderBase.vb:558,565 ; BulkLoader.vb:954,976 |
| Server — chiusura | CompleteFileUploadProcess → RPS_COMPLETEUPLOADPROCESS |
BulkLoader.vb:989,1004 |
| DAO entità | DAO_People.SavePeople → ManageEntity |
DAO_People.vb:231,241-244,248 |
| DB | RPS_STARTUPLOADPROCESS (INSERT GLOBAL_UPLOAD_PROCESS) |
USER_SOURCE RPS_STARTUPLOADPROCESS src:9-12 |
| DB | RPS_WRITEUPLOADALERT (INSERT GLOBAL_UPLOAD_ALERT) |
USER_SOURCE RPS_WRITEUPLOADALERT src:10-13 |
| DB | RPS_COMPLETEUPLOADPROCESS (UPDATE GLOBAL_UPLOAD_PROCESS) |
USER_SOURCE RPS_COMPLETEUPLOADPROCESS src:9-11 |
| DB | PRP_MANAGEENTITY (upsert PERSONE_, RETURNING ID_N) |
vedi FLOW-PROP-001 ; PERSONE_ col ID_N NUMBER (USER_TAB_COLUMNS) |
| DB (catalogo) | PRP_MANAGEENTITY PROCEDURE; PERSONE_/GLOBAL_UPLOAD_PROCESS/GLOBAL_UPLOAD_ALERT TABLE |
USER_OBJECTS |
Reverse trace (dal DB/servizio ai chiamanti)
RPS_STARTUPLOADPROCESS/RPS_WRITEUPLOADALERT/RPS_COMPLETEUPLOADPROCESSsono usate solo dalla classe serverBulkLoader(StartProcess/WriteUploadAlert/CompleteFileUploadProcess), ovvero il motore comune a tutti i loader del dominio (People, Companies, Contacts, Contracts, Managements, Providers, Costcentre, Asset, Spatial, Categories, Energy, Documenti) — dispatch inBulkLoader.Import(BulkLoader.vb:434-582,646-790). Quindi il ciclo processo/alert è condiviso da ogni import massivo.PRP_MANAGEENTITYconPTAB_INFOCAD='PERSONE_',PCOL_IDINFOCAD='ID_N'è raggiunta daDAO_People.SavePeople(DAO_People.vb:248), a sua volta invocata sia dal BulkLoader (PeopleBulkLoader.vb:406,544) sia dal salvataggio interattivo Persone (schedaPeopleDetails). La stessaPRP_MANAGEENTITYè l'upsert generico di tutte le entità anagrafiche/spaziali (vedi FLOW-PROP-001,SaveBuilding→EDIFICI_).- Forward e reverse concordano: UI
IMP_PERSONE→BulkLoader(People overload) →PeopleBulkLoader.InsertPeople→SavePeople→PRP_MANAGEENTITY(PERSONE_), con tracciamento suGLOBAL_UPLOAD_PROCESS/GLOBAL_UPLOAD_ALERT→ NO CONFLICTING.
Regole correlate (related rules)
- Convenzione nomi tabella entità: suffisso
_(PERSONE→PERSONE_), gestita inDAO_GenericEntity.ManageEntity(cfr. FLOW-PROP-001). - Semantica create vs update pilotata dal
peopleIDpassato aSavePeople(0⇒ INSERT;>0⇒ UPDATE) e daisInsertsul ramo UI (IMP_PERSONEvsUPD_PERSONE). - Multi-tenant: collocazione e deduplica sono sempre filtrate per
_currenttenantID(DAO_Tenancy.GetCurrentTenancyID,PeopleBulkLoader.vb:77); il binding tenant è propagato daPRP_MANAGEENTITY. - Il file caricato è persistito come BLOB nel processo per abilitare il retry senza ri-upload.
Evidenza (file:line)
Punti chiave (codice):
UploadProcessControl.ascx.vb:388,405,453,454-459,460,468,898;
BulkLoadController.vb:9,83; BulkLoaderControllers/IBulkLoad.vb:1;
BulkLoader.vb:199,203,205,207,267,673,677,678,687,689,791,806,954,976,989,1004;
BulkLoaderBase.vb:546-552,558,565;
PeopleBulkLoader.vb:34,36,59,69,70,86,103,105,183,152,285,303,333,371,381,383,406,544;
DAO_People.vb:231,241-244,248.
Punti chiave (DB, INFOCAD_TEST38, letti in sola lettura via USER_SOURCE/USER_OBJECTS/USER_TAB_COLUMNS):
RPS_STARTUPLOADPROCESS → INSERT INTO GLOBAL_UPLOAD_PROCESS (... STATUS='RUNNING' ...) RETURNING ID_PROCESS (src:9-12);
RPS_WRITEUPLOADALERT → INSERT INTO GLOBAL_UPLOAD_ALERT (...) RETURNING alertid (src:10-13);
RPS_COMPLETEUPLOADPROCESS → UPDATE GLOBAL_UPLOAD_PROCESS SET STATUS=..., END_DATE=SYSDATE, TOTALOBJS/VALIDOBJS/CREATEDOBJS (src:9-11);
catalogo: PRP_MANAGEENTITY = PROCEDURE, PERSONE_/GLOBAL_UPLOAD_PROCESS/GLOBAL_UPLOAD_ALERT = TABLE (USER_OBJECTS);
colonne: PERSONE_(ID_N NUMBER, ID_VANO NUMBER, ID_CHANGED_BY VARCHAR2),
GLOBAL_UPLOAD_PROCESS(ID_PROCESS,FILENAME,START_DATE,END_DATE,USERNAME,DOCUMENT_FILE,STATUS,ENTITY_TYPE,TOTALOBJS,VALIDOBJS,CREATEDOBJS),
GLOBAL_UPLOAD_ALERT(ALERTID,PROCESSID,ROWNUMBER,OBJECTCODE,MESSAGE,STATUS) (USER_TAB_COLUMNS).
Confidence
- VERIFIED: catena UI → controller remoting →
BulkLoaderserver →PeopleBulkLoader→DAO_People.SavePeople→DAO_GenericEntity.ManageEntity→ nome stored procedure (letta sui sorgenti VB.NET) e sorgente delle procedure di processoRPS_STARTUPLOADPROCESS/RPS_WRITEUPLOADALERT/RPS_COMPLETEUPLOADPROCESSletto daUSER_SOURCE(INSERT/UPDATE suGLOBAL_UPLOAD_PROCESS/GLOBAL_UPLOAD_ALERTconfermati); esistenza tabelle/colonne (PERSONE_,GLOBAL_UPLOAD_*) da catalogo. - SUPPORTED: contenuto della DML dinamica su
PERSONE_e scritturaGLOBAL_TENANCY_BINDINGSinterne aPRP_MANAGEENTITY— ereditati/riusati da FLOW-PROP-001 (stessa procedura), non ri-eseguiti a runtime. - INFERRED: comportamento esatto di
existEntityByKeyAndTenanteGetAssetLocationByParamAndTnt(procedure/SQL non ispezionati riga per riga; ruolo funzionale dedotto dal codice chiamante).
Open questions
- Colonne effettivamente scritte in
PERSONE_a runtime: dipendono dalla mappaturaDAO_Metadata.GetEntityStructure("PERSONE_", roles)e dalle colonne presenti nel file Excel (variabile per configurazione/tenant/ruoli). - Se il processo BulkLoader giri in modo sincrono nel thread della richiesta remoting o su thread/worker dedicato del servizio InfocadServer (non determinabile dal solo codice ispezionato).
- Dettaglio della procedura/SQL dietro
existEntityByKeyAndTenanteGetAssetLocationByParamAndTnt(nomi delle stored procedure non tracciati in questo flusso). - Configurazione remoting effettiva (
CHANNEL/SERVERADDRESS, endpointBulkLoader.rem) in ambienti reali; osservato solo ambiente TEST38.