Files
zentral/site/search/search_index.json
2025-11-28 10:59:10 +01:00

1 line
557 KiB
JSON

{"config":{"lang":["it"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Apollinare Catering - Documentazione Completa","text":"<p>Questa documentazione contiene l'estrazione completa di tutti gli oggetti del database Oracle e dell'applicazione APEX di Apollinare Catering &amp; Banqueting.</p>"},{"location":"#application-overview","title":"Application Overview","text":"<p>Apollinare Catering &amp; Banqueting Management Software \u00e8 un gestionale completo per aziende di catering che gestisce l'intero ciclo di vita di un evento: dalla richiesta del cliente, al preventivo, alla conferma, fino all'esecuzione.</p>"},{"location":"#funzionalita-principali","title":"Funzionalit\u00e0 Principali","text":"Area Descrizione Gestione Eventi Creazione, workflow stati, versioning Gestione Ospiti Tipologie ospiti, conteggi, coefficienti Lista Prelievo Calcolo automatico quantit\u00e0 materiale Risorse/Staff Pianificazione personale per evento Acconti/Pagamenti Sistema caparre 30%-50%-20%, solleciti Calendario Vista eventi, limiti giornalieri, conflitti Reporting Schede evento, preventivi, report cucina"},{"location":"#proposta-saas-caterpro","title":"Proposta SaaS: CaterPro","text":"<p>La documentazione include una proposta per trasformare Apollinare in CaterPro, una piattaforma SaaS multi-tenant:</p> <ul> <li>Target: Piccole, medie e grandi aziende di catering</li> <li>Stack: .NET 8 + React TypeScript + PostgreSQL/Oracle</li> <li>Pricing: Da \u20ac49/mese (Basic) a \u20ac399/mese (Enterprise)</li> <li>Roadmap: 10-14 mesi per feature parity + SaaS</li> </ul> <p>Leggi la documentazione completa per dettagli su architettura, funzionalit\u00e0 e roadmap.</p>"},{"location":"#struttura-della-documentazione","title":"Struttura della Documentazione","text":"<pre><code>docs/\n\u251c\u2500\u2500 apex/ # Applicazione APEX\n\u2502 \u251c\u2500\u2500 README.md # Overview applicazione\n\u2502 \u251c\u2500\u2500 pages/ # 56 pagine\n\u2502 \u251c\u2500\u2500 processes/ # 98 processi\n\u2502 \u251c\u2500\u2500 lovs/ # 12 List of Values\n\u2502 \u251c\u2500\u2500 javascript/ # Librerie JavaScript\n\u2502 \u251c\u2500\u2500 authorization/ # 5 schemi autorizzazione\n\u2502 \u251c\u2500\u2500 dynamic-actions/ # Azioni dinamiche\n\u2502 \u251c\u2500\u2500 items/ # Items condivisi\n\u2502 \u251c\u2500\u2500 regions/ # Regioni condivise\n\u2502 \u2514\u2500\u2500 navigation/ # Navigazione\n\u251c\u2500\u2500 tables/ # 32 tabelle\n\u251c\u2500\u2500 views/ # 26 viste\n\u251c\u2500\u2500 procedures/ # 11 stored procedures\n\u251c\u2500\u2500 functions/ # 23 funzioni\n\u251c\u2500\u2500 packages/ # 17 packages\n\u251c\u2500\u2500 triggers/ # 19 triggers\n\u251c\u2500\u2500 sequences/ # 22 sequences\n\u2514\u2500\u2500 types/ # 10 tipi custom\n</code></pre>"},{"location":"#apex-application-documentation","title":"APEX Application Documentation","text":""},{"location":"#apex-application-overview","title":"APEX Application Overview","text":"<p>Application: APCB Project (ID: 112) APEX Version: 21.1.0 Schema: APOLLINARECATERINGPROD</p> Component Count Pages 56 Items 302 Processes 98 Regions 151 Buttons 119 Dynamic Actions 62 LOVs 12"},{"location":"#key-apex-documentation","title":"Key APEX Documentation","text":"<ul> <li>APEX README - Application overview and navigation</li> <li>Processes Documentation - All 98 processes with PL/SQL code</li> <li>LOVs Documentation - 12 List of Values definitions</li> <li>JavaScript Libraries - Custom ajaxUtils.js and iframeObj.js</li> <li>Authorization Schemes - 5 security schemes</li> </ul>"},{"location":"#critical-apex-pages","title":"Critical APEX Pages","text":"Page Name Description 1 Home Dashboard principale 22 Nuovo Evento Pagina pi\u00f9 complessa (108 items, 32 processi) 9 Liste Lista eventi 12 Calendario Calendario eventi 35 Schede Schede evento"},{"location":"#indice-per-categoria","title":"Indice per Categoria","text":""},{"location":"#tabelle-32","title":"Tabelle (32)","text":"<p>Tabelle principali del dominio business:</p> <ul> <li>EVENTI - Tabella principale eventi</li> <li>EVENTI_DET_PREL - Liste prelievo</li> <li>EVENTI_DET_OSPITI - Dettaglio ospiti</li> <li>EVENTI_DET_RIS - Risorse assegnate</li> <li>EVENTI_DET_DEGUST - Degustazioni</li> <li>EVENTI_ACCONTI - Gestione acconti/pagamenti</li> <li>EVENTI_ALTRICOSTI - Altri costi</li> <li>EVENTI_ALLEG - Allegati</li> <li>ARTICOLI - Catalogo articoli</li> <li>COSTI_ARTICOLI - Storico costi</li> <li>CLIENTI - Anagrafica clienti</li> <li>LOCATION - Location eventi</li> <li>RISORSE - Personale</li> </ul> <p>Tabelle di lookup:</p> <ul> <li>TB_TIPI_MAT - Tipi materiale</li> <li>TB_CODICI_CATEG - Categorie</li> <li>TB_TIPI_EVENTO - Tipi evento</li> <li>TB_TIPI_OSPITI - Tipi ospiti</li> <li>TB_TIPI_RISORSA - Tipi risorsa</li> <li>TB_TIPI_PASTO - Tipi pasto</li> <li>TB_CALENDAR_LOCKS - Limiti calendario</li> <li>TB_CONFIG - Configurazioni</li> </ul> <p>Tabelle di sistema:</p> <ul> <li>USERS_READONLY - Permessi utenti</li> <li>XLIB_LOGS - Log applicazione</li> <li>XLIB_COMPONENTS - Componenti</li> <li>XLIB_JASPERREPORTS_CONF - Config report</li> <li>XLIB_JASPERREPORTS_DEMOS - Demo report</li> </ul>"},{"location":"#viste-26","title":"Viste (26)","text":"<p>Viste per calcolo costi:</p> <ul> <li>GET_COSTO_ART_BY_EVT - Costo articoli per evento</li> <li>GET_COSTO_ART_EVT - Costo articoli aggregato</li> <li>GET_COSTO_CATEG_EVT - Costo per categoria</li> <li>GET_COSTO_DEGUS_EVT - Costo degustazioni</li> <li>GET_COSTO_OSPITI_EVT - Costo ospiti</li> <li>GET_COSTO_RIS_EVT - Costo risorse</li> <li>GET_COSTO_TIPI_EVT - Costo per tipo</li> <li>GET_ULTIMI_COSTI - Ultimi costi articoli</li> </ul> <p>Viste per eventi:</p> <ul> <li>GET_EVT_DATA - Dati evento completi</li> <li>GET_EVT_DATA_PRINT - Dati per stampa</li> <li>GET_PREL_ART_TOT - Totali prelievo</li> <li>GET_PREL_BY_EVT - Prelievi per evento</li> </ul> <p>Viste per calendario e stato:</p> <ul> <li>VW_CALENDARIO_EVENTI - Vista calendario</li> <li>VW_EVENT_COLOR - Colori stati</li> <li>VW_EVENTI_STATUSES - Stati eventi</li> </ul> <p>Viste per giacenze:</p> <ul> <li>V_IMPEGNI_ARTICOLI - Impegni articoli</li> <li>V_IMPEGNI_ARTICOLI_LOC - Impegni per location</li> </ul> <p>Viste per report:</p> <ul> <li>V_REP_ALLESTIMENTI - Report allestimenti</li> <li>VW_REP_DEGUSTAZIONI - Report degustazioni</li> <li>V_GRIGLIA - Vista griglia</li> <li>GET_REPORT_CONSUNTIVO_PER_DATA - Consuntivo</li> </ul> <p>Viste per utenti/permessi:</p> <ul> <li>GET_CONSUNTIVI_USERS - Utenti consuntivi</li> <li>GET_GESTORI_USERS - Utenti gestori</li> <li>GET_USERS_LIST - Lista utenti</li> </ul> <p>Viste per pagamenti:</p> <ul> <li>GET_EVENTI_DA_PAGARE_ENTRO_65GG - Eventi da sollecitare</li> </ul>"},{"location":"#stored-procedures-11","title":"Stored Procedures (11)","text":"<p>Business logic principale:</p> <ul> <li>EVENTI_AGGIORNA_QTA_LISTA - Ricalcolo quantit\u00e0 lista prelievo</li> <li>EVENTI_AGGIORNA_TOT_OSPITI - Aggiorna totale ospiti</li> <li>EVENTI_COPIA - Duplicazione evento</li> <li>EVENTI_RICALCOLA_ACCONTI - Ricalcolo acconti</li> <li>EVENTO_ELIMINA_PRELIEVI - Elimina prelievi</li> <li>LISTE_COPIA - Copia liste tra eventi</li> <li>P_CANCEL_SAME_LOCATION_EVENTS - Annulla eventi stessa location</li> </ul> <p>Utility:</p> <ul> <li>ROWSORT_TIPI - Ordinamento tipi</li> <li>HTPPRN - Stampa HTTP</li> <li>SEND_DATA_TO_DROPBOX - Export Dropbox</li> <li>XLOG - Logging</li> </ul>"},{"location":"#funzioni-23","title":"Funzioni (23)","text":"<p>Calcolo quantit\u00e0 e disponibilit\u00e0:</p> <ul> <li>F_GET_QTA_IMPEGNATA - Quantit\u00e0 impegnata</li> <li>F_GET_TOT_OSPITI - Totale ospiti</li> <li>F_GET_OSPITI - Dettaglio ospiti (pipelined)</li> <li>F_LIST_PRELIEVO_ADD_ARTICOLO - Aggiunta articolo</li> </ul> <p>Calcolo costi:</p> <ul> <li>F_GET_COSTO_ARTICOLO - Costo articolo a data</li> </ul> <p>Validazioni:</p> <ul> <li>F_EVENTO_SCADUTO - Verifica scadenza</li> <li>F_MAX_NUMERO_EVENTI_RAGGIUNTO - Limite eventi</li> <li>F_MAX_NUM_EVENTI_CONFERMATI - Limite confermati</li> <li>F_CI_SONO_EVENTI_CONFERMATI - Check confermati</li> </ul> <p>Report:</p> <ul> <li>F_REP_ALLESTIMENTI - Report allestimenti</li> <li>F_REP_CUCINA - Report cucina</li> <li>F_GET_ANGOLO_ALLESTIMENTO - Angolo allestimento</li> <li>F_GET_ANGOLO_ALLESTIMENTO_OB - Angolo open bar</li> <li>F_GET_TOVAGLIATO_ALLESTIMENTO - Tovagliato</li> </ul> <p>Autorizzazioni:</p> <ul> <li>F_USER_IN_ROLE - Verifica ruolo utente</li> <li>F_USER_IN_ROLE_STR - Ruolo utente (stringa)</li> </ul> <p>Utility:</p> <ul> <li>F_DAY_TO_NAME - Giorno in italiano</li> <li>STRING_TO_TABLE_ENUM - Stringa a tabella</li> <li>GET_PARAM_VALUE - Valore parametro</li> <li>SPLIT - Split stringa</li> <li>MY_INSTR - Instr custom</li> <li>CLOB2BLOB - Conversione CLOB</li> <li>EXTDATE_GET_ITA - Data in italiano</li> </ul>"},{"location":"#packages-17","title":"Packages (17)","text":"<p>Business:</p> <ul> <li>MAIL_PKG - Gestione invio email automatiche</li> </ul> <p>Utility esterne:</p> <ul> <li>UTL_BASE64 - Encoding Base64</li> </ul> <p>JasperReports:</p> <ul> <li>XLIB_JASPERREPORTS - Integrazione JasperReports</li> <li>XLIB_JASPERREPORTS_IMG - Immagini report</li> </ul> <p>HTTP/Componenti:</p> <ul> <li>XLIB_HTTP - Chiamate HTTP</li> <li>XLIB_COMPONENT - Componenti</li> <li>XLIB_LOG - Logging</li> </ul> <p>JSON (libreria PLJSON):</p> <ul> <li>PLJSON_DYN</li> <li>PLJSON_EXT</li> <li>PLJSON_HELPER</li> <li>PLJSON_ML</li> <li>PLJSON_OBJECT_CACHE</li> <li>PLJSON_PARSER</li> <li>PLJSON_PRINTER</li> <li>PLJSON_UT</li> <li>PLJSON_UTIL_PKG</li> <li>PLJSON_XML</li> </ul>"},{"location":"#triggers-19","title":"Triggers (19)","text":"<p>Generazione ID:</p> <ul> <li>EVENTI_TRG - ID eventi + inizializzazione</li> <li>EVENTI_AI_TRG - Creazione ospiti default</li> <li>EVENTI_DET_PREL_TRG - ID prelievi</li> <li>EVENTI_DET_RIS_TRG - ID risorse</li> <li>EVENTI_DET_DEGUST_TRG - ID degustazioni</li> <li>EVENTI_ACCONTI_TRG - ID acconti</li> <li>EVENTI_ALTRICOSTI_TRG - ID altri costi</li> <li>EVENTI_ALLEG_TRG - ID allegati</li> <li>CLIENTI_TRG - ID clienti</li> <li>LOCATION_TRG - ID location</li> <li>RISORSE_TRG - ID risorse</li> <li>ARTICOLI_DET_REGOLE_TRG - ID regole articoli</li> <li>TB_TIPI_PASTO_TRG - ID tipi pasto</li> </ul> <p>Business logic:</p> <ul> <li>EVENTI_DET_OSPITI_TRG_AI - Aggiornamento ospiti</li> <li>EVENTI_DET_PREL_QTA_TOT_TRG - Calcolo quantit\u00e0 totale</li> </ul> <p>Ordinamento:</p> <ul> <li>ADD_COD_STEP - Ordine tipi materiale</li> <li>ON_DELETE_REORDER - Riordino dopo delete</li> </ul> <p>Sistema:</p> <ul> <li>BI_GL_SCHEMA_CHANGES - Log modifiche schema</li> <li>XLIB_LOGS_BI_TRG - Log applicazione</li> </ul>"},{"location":"#sequences-22","title":"Sequences (22)","text":"<p>Tutte le sequence del database.</p>"},{"location":"#types-10","title":"Types (10)","text":"<p>Tipi custom:</p> <ul> <li>T_DET_OSPITI_ROW / T_DET_OSPITI_TAB - Tipo per F_GET_OSPITI</li> <li>T_REP_ALLESTIMENTI_ROW / T_REP_ALLESTIMENTI_TAB - Tipo per F_REP_ALLESTIMENTI</li> <li>T_REP_CUCINA_ROW / T_REP_CUCINA_TAB - Tipo per F_REP_CUCINA</li> <li>STRING_LIST - Lista stringhe</li> <li>ENUM_TABLE_OBJECT / ENUM_TABLE_TYPE - Tipi per STRING_TO_TABLE_ENUM</li> <li>XLIB_VC2_ARRAY_T - Array varchar2</li> </ul>"},{"location":"#schema-er-semplificato","title":"Schema ER Semplificato","text":"<pre><code> \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 CLIENTI \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 LOCATION \u2502\u25c4\u2500\u2500\u2500\u2500\u2502 EVENTI \u2502\u2500\u2500\u2500\u2500\u25ba\u2502TB_TIPI_EVENTO\u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 \u2502 \u2502\n \u25bc \u25bc \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502EVENTI_DET_OSPITI\u2502 \u2502 EVENTI_DET_PREL \u2502 \u2502 EVENTI_DET_RIS \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502 \u2502 \u2502\n \u25bc \u25bc \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 TB_TIPI_OSPITI \u2502 \u2502 ARTICOLI \u2502 \u2502 RISORSE \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 TB_CODICI_CATEG \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 TB_TIPI_MAT \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 \u2502 \u2502\n \u25bc \u25bc \u25bc\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502EVENTI_DET_DEGUST\u2502 \u2502 EVENTI_ACCONTI \u2502 \u2502EVENTI_ALTRICOSTI\u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n</code></pre>"},{"location":"#workflow-stati-evento","title":"Workflow Stati Evento","text":"<pre><code> \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 PREVENTIVO \u2502 (100) - Bianco\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502 Degustazione\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502SCHEDA EVENTO \u2502 (200) - Celeste\n \u2502(preparazione)\u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502 Prima caparra\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 SCHEDA \u2502 (300) - Giallo\n \u2502 CONFERMATA \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502 Quasi confermato\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502SCHEDA QUASI \u2502 (350) - Arancio\n \u2502 CONFERMATA \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502 Conferma definitiva\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 CONFERMATO \u2502 (400) - Verde\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n \u2502 Rifiuto/Scadenza\n \u25bc\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502NON ACCETTATO/\u2502 (900) - Viola\n \u2502 SUPERATO \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n</code></pre>"},{"location":"#note-per-lo-sviluppo","title":"Note per lo Sviluppo","text":"<ol> <li> <p>Packages PLJSON_*: Libreria esterna per parsing JSON, pu\u00f2 essere sostituita con funzionalit\u00e0 native .NET</p> </li> <li> <p>Packages XLIB_*: Componenti per integrazione JasperReports, da valutare sostituzione con report .NET</p> </li> <li> <p>Trigger per ID: In .NET usare Identity columns o GUID</p> </li> <li> <p>Calcolo quantit\u00e0: La logica in <code>EVENTI_AGGIORNA_QTA_LISTA</code> \u00e8 critica e deve essere portata fedelmente</p> </li> <li> <p>Sistema acconti: Le percentuali 30%-50%-20% sono hardcoded, valutare parametrizzazione</p> </li> </ol>"},{"location":"APPLICATION_OVERVIEW/","title":"Apollinare Catering &amp; Banqueting - Application Overview","text":""},{"location":"APPLICATION_OVERVIEW/#descrizione-applicazione-attuale","title":"Descrizione Applicazione Attuale","text":""},{"location":"APPLICATION_OVERVIEW/#cose-apollinare","title":"Cos'\u00e8 Apollinare","text":"<p>Apollinare Catering &amp; Banqueting Management Software \u00e8 un gestionale completo per aziende di catering e banqueting che gestisce l'intero ciclo di vita di un evento, dalla prima richiesta del cliente fino all'esecuzione finale.</p> <p>L'applicazione \u00e8 attualmente in uso presso Apollinare Catering (Italia) ed \u00e8 stata sviluppata su piattaforma Oracle APEX 21.1.0.</p>"},{"location":"APPLICATION_OVERVIEW/#funzionalita-principali","title":"Funzionalit\u00e0 Principali","text":""},{"location":"APPLICATION_OVERVIEW/#1-gestione-eventi","title":"1. Gestione Eventi","text":"<p>Il cuore dell'applicazione \u00e8 la gestione degli eventi di catering:</p> <ul> <li>Creazione Evento: Wizard guidato per la creazione di nuovi eventi</li> <li>Dati Evento: Data, orario cerimonia, orario evento, location, cliente</li> <li>Tipologie: Matrimoni, battesimi, comunioni, cresime, eventi aziendali, feste private</li> <li>Tipo Pasto: Pranzo, cena, pranzo buffet, cena buffet</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#2-workflow-stati-evento","title":"2. Workflow Stati Evento","text":"<p>L'evento attraversa diverse fasi:</p> <pre><code>PREVENTIVO (100) \u2192 Cliente interessato, preventivo in preparazione\n \u2193\nSCHEDA (200) \u2192 Degustazione effettuata, scheda evento in preparazione\n \u2193\nCONFERMATA (300) \u2192 Prima caparra ricevuta\n \u2193\nQUASI CONFERMATO (350) \u2192 In attesa conferma definitiva\n \u2193\nCONFERMATO (400) \u2192 Evento confermato, in esecuzione\n \u2193\nSUPERATO (900) \u2192 Evento concluso o annullato\n</code></pre>"},{"location":"APPLICATION_OVERVIEW/#3-gestione-ospiti","title":"3. Gestione Ospiti","text":"<p>Sistema sofisticato per la gestione degli ospiti:</p> <ul> <li>Tipi Ospiti: Adulti, bambini, staff, fornitori esterni</li> <li>Conteggi Separati: Seduti vs buffet, adulti vs bambini</li> <li>Coefficienti: Ogni tipo ospite ha coefficienti per il calcolo quantit\u00e0</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#4-lista-prelievo-pick-list","title":"4. Lista Prelievo (Pick List)","text":"<p>Gestione automatizzata del materiale necessario:</p> <ul> <li>Articoli: Catalogo completo con immagini, quantit\u00e0 standard, coefficienti</li> <li>Categorie: Posate, piatti, bicchieri, tovagliato, decorazioni, attrezzature cucina</li> <li>Calcolo Automatico: Le quantit\u00e0 vengono calcolate automaticamente in base a:</li> <li>Numero ospiti per tipo</li> <li>Coefficienti categoria (A=Adulti, S=Seduti, B=Buffet)</li> <li>Quantit\u00e0 standard articolo</li> <li>Disponibilit\u00e0: Verifica impegni articoli su altri eventi nella stessa data</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#5-gestione-risorse-staff","title":"5. Gestione Risorse (Staff)","text":"<p>Pianificazione del personale:</p> <ul> <li>Tipi Risorsa: Camerieri, cuochi, barman, responsabili sala</li> <li>Assegnazione: Assegnazione risorse per evento</li> <li>Report: Riepilogo impegni risorse per data</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#6-sistema-acconti-e-pagamenti","title":"6. Sistema Acconti e Pagamenti","text":"<p>Gestione finanziaria completa:</p> <ul> <li>Caparre Automatiche: Sistema 30% - 50% - 20%</li> <li>Tracking Pagamenti: Monitoraggio stato pagamenti</li> <li>Solleciti: Identificazione eventi con pagamenti in scadenza (65 giorni)</li> <li>Email Automatiche: Notifiche automatiche per pagamenti</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#7-reporting","title":"7. Reporting","text":"<p>Sistema di reportistica integrato:</p> <ul> <li>Scheda Evento: PDF completo per cliente</li> <li>Preventivo: Documento commerciale</li> <li>Riepilogo Cucina: Per lo staff di cucina</li> <li>Riepilogo Allestimenti: Per team setup</li> <li>Griglia Eventi: Vista calendario operativa</li> <li>Report Costi: Analisi costi per evento/categoria</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#8-calendario","title":"8. Calendario","text":"<p>Vista calendario interattiva:</p> <ul> <li>Visualizzazione: Eventi per giorno/settimana/mese</li> <li>Colori Stati: Codifica colore per stato evento</li> <li>Limiti: Controllo numero massimo eventi per data</li> <li>Conflitti: Verifica location gi\u00e0 impegnate</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#9-gestione-degustazioni","title":"9. Gestione Degustazioni","text":"<p>Per eventi come matrimoni:</p> <ul> <li>Pianificazione: Data e dettagli degustazione</li> <li>Tracking: Stato degustazione</li> <li>Note: Preferenze e allergie</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#10-template-eventi","title":"10. Template Eventi","text":"<p>Sistema di template per velocizzare la creazione:</p> <ul> <li>Template Predefiniti: Configurazioni standard per tipologie evento</li> <li>Duplicazione: Copia evento esistente come base</li> <li>Versionamento: Sistema di versioni per tracciare modifiche</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#proposta-saas-caterpro","title":"Proposta SaaS: CaterPro","text":""},{"location":"APPLICATION_OVERVIEW/#vision","title":"Vision","text":"<p>Trasformare Apollinare in CaterPro, una piattaforma SaaS multi-tenant per la gestione di aziende di catering e banqueting, mantenendo le funzionalit\u00e0 core ma aggiungendo caratteristiche enterprise.</p>"},{"location":"APPLICATION_OVERVIEW/#target-market","title":"Target Market","text":"<ol> <li>Piccole Aziende di Catering (1-10 dipendenti)</li> <li>Piano Basic</li> <li>Gestione eventi semplificata</li> <li> <p>Fino a 50 eventi/mese</p> </li> <li> <p>Medie Aziende di Catering (10-50 dipendenti)</p> </li> <li>Piano Professional</li> <li>Multi-location</li> <li> <p>Fino a 200 eventi/mese</p> </li> <li> <p>Grandi Aziende / Catene (50+ dipendenti)</p> </li> <li>Piano Enterprise</li> <li>Multi-brand, multi-country</li> <li>Eventi illimitati</li> </ol>"},{"location":"APPLICATION_OVERVIEW/#architettura-saas","title":"Architettura SaaS","text":"<pre><code>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 CaterPro Cloud \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n\u2502 \u2502 Tenant A \u2502 \u2502 Tenant B \u2502 \u2502 Tenant C \u2502 ... \u2502\n\u2502 \u2502 (Catering \u2502 \u2502 (Wedding \u2502 \u2502 (Corporate \u2502 \u2502\n\u2502 \u2502 Roma) \u2502 \u2502 Planner) \u2502 \u2502 Events) \u2502 \u2502\n\u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Shared Services \u2502\n\u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n\u2502 \u2502 Auth/IAM \u2502 \u2502 Billing \u2502 \u2502Analytics \u2502 \u2502 API \u2502 \u2502\n\u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Infrastructure \u2502\n\u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n\u2502 \u2502 .NET 8 \u2502 \u2502 React \u2502 \u2502PostgreSQL\u2502 \u2502 Azure \u2502 \u2502\n\u2502 \u2502 API \u2502 \u2502 SPA \u2502 \u2502 /Oracle \u2502 \u2502 Cloud \u2502 \u2502\n\u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n</code></pre>"},{"location":"APPLICATION_OVERVIEW/#funzionalita-saas-aggiuntive","title":"Funzionalit\u00e0 SaaS Aggiuntive","text":""},{"location":"APPLICATION_OVERVIEW/#multi-tenancy","title":"Multi-Tenancy","text":"<ul> <li>Isolamento Dati: Ogni cliente ha i propri dati completamente isolati</li> <li>Customizzazione: Logo, colori, branding personalizzabile</li> <li>Subdomain: cliente.caterpro.com</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#gestione-utenti-avanzata","title":"Gestione Utenti Avanzata","text":"<ul> <li>Ruoli Predefiniti: Admin, Manager, Operatore, Cucina, Solo Lettura</li> <li>Ruoli Custom: Creazione ruoli personalizzati</li> <li>SSO: Integrazione Azure AD, Google Workspace</li> <li>2FA: Autenticazione a due fattori</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#integrazioni","title":"Integrazioni","text":"<ul> <li>Calendario: Google Calendar, Outlook, Apple Calendar</li> <li>Pagamenti: Stripe, PayPal, bonifici SEPA</li> <li>Contabilit\u00e0: Export per Fatture in Cloud, QuickBooks, Xero</li> <li>CRM: Salesforce, HubSpot</li> <li>E-commerce: Preventivi online, pagamenti online</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#mobile-app","title":"Mobile App","text":"<ul> <li>App iOS/Android: Per staff in mobilit\u00e0</li> <li>Check-in Ospiti: QR code per eventi</li> <li>Inventario Mobile: Scansione barcode articoli</li> <li>Foto Evento: Upload diretto da app</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#analytics-bi","title":"Analytics &amp; BI","text":"<ul> <li>Dashboard Real-time: KPI principali</li> <li>Report Avanzati: Analisi trend, stagionalit\u00e0</li> <li>Forecasting: Previsioni ricavi</li> <li>Export: Excel, PDF, API</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#automazioni","title":"Automazioni","text":"<ul> <li>Email Marketing: Campagne automatiche</li> <li>Reminder: Notifiche scadenze, follow-up</li> <li>Workflow: Automazione processi custom</li> <li>Webhooks: Integrazione con sistemi esterni</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#pricing-model","title":"Pricing Model","text":""},{"location":"APPLICATION_OVERVIEW/#basic-49mese","title":"Basic - \u20ac49/mese","text":"<ul> <li>1 utente admin + 2 operatori</li> <li>50 eventi/mese</li> <li>500 articoli catalogo</li> <li>Report base</li> <li>Email support</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#professional-149mese","title":"Professional - \u20ac149/mese","text":"<ul> <li>5 utenti inclusi (+\u20ac15/utente aggiuntivo)</li> <li>200 eventi/mese</li> <li>Articoli illimitati</li> <li>Multi-location (fino a 3)</li> <li>Report avanzati</li> <li>Integrazioni base</li> <li>Chat support</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#enterprise-399mese","title":"Enterprise - \u20ac399/mese","text":"<ul> <li>Utenti illimitati</li> <li>Eventi illimitati</li> <li>Location illimitate</li> <li>API access</li> <li>Integrazioni premium</li> <li>White-label option</li> <li>SLA garantito</li> <li>Account manager dedicato</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#add-ons","title":"Add-ons","text":"<ul> <li>Mobile App: +\u20ac29/mese</li> <li>E-commerce Module: +\u20ac49/mese</li> <li>Advanced Analytics: +\u20ac39/mese</li> <li>Custom Integrations: Su richiesta</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#stack-tecnologico-proposto","title":"Stack Tecnologico Proposto","text":""},{"location":"APPLICATION_OVERVIEW/#backend-net-8","title":"Backend (.NET 8)","text":"<pre><code>\u251c\u2500\u2500 CaterPro.API # Web API REST\n\u251c\u2500\u2500 CaterPro.Core # Domain models, interfaces\n\u251c\u2500\u2500 CaterPro.Application # Business logic, CQRS\n\u251c\u2500\u2500 CaterPro.Infrastructure # Data access, external services\n\u251c\u2500\u2500 CaterPro.Identity # Authentication/Authorization\n\u2514\u2500\u2500 CaterPro.Workers # Background jobs\n</code></pre>"},{"location":"APPLICATION_OVERVIEW/#frontend-react-typescript","title":"Frontend (React TypeScript)","text":"<pre><code>\u251c\u2500\u2500 src/\n\u2502 \u251c\u2500\u2500 components/ # Reusable UI components\n\u2502 \u251c\u2500\u2500 features/ # Feature-based modules\n\u2502 \u2502 \u251c\u2500\u2500 events/ # Event management\n\u2502 \u2502 \u251c\u2500\u2500 inventory/ # Article/inventory\n\u2502 \u2502 \u251c\u2500\u2500 calendar/ # Calendar views\n\u2502 \u2502 \u251c\u2500\u2500 reports/ # Reporting\n\u2502 \u2502 \u2514\u2500\u2500 settings/ # Configuration\n\u2502 \u251c\u2500\u2500 hooks/ # Custom React hooks\n\u2502 \u251c\u2500\u2500 services/ # API services\n\u2502 \u251c\u2500\u2500 store/ # Redux/Zustand state\n\u2502 \u2514\u2500\u2500 utils/ # Utilities\n</code></pre>"},{"location":"APPLICATION_OVERVIEW/#database","title":"Database","text":"<ul> <li>Primary: PostgreSQL (per SaaS cost-efficiency)</li> <li>Alternative: Oracle (per clienti enterprise on-premise)</li> <li>Cache: Redis</li> <li>Search: Elasticsearch (per ricerca articoli/eventi)</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#infrastructure","title":"Infrastructure","text":"<ul> <li>Cloud: Azure / AWS</li> <li>Container: Docker + Kubernetes</li> <li>CI/CD: GitHub Actions / Azure DevOps</li> <li>Monitoring: Application Insights / DataDog</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#roadmap-migrazione","title":"Roadmap Migrazione","text":""},{"location":"APPLICATION_OVERVIEW/#fase-1-core-migration-3-4-mesi","title":"Fase 1: Core Migration (3-4 mesi)","text":"<ul> <li>[ ] Setup architettura .NET 8</li> <li>[ ] Migrazione modelli dati</li> <li>[ ] API REST per entit\u00e0 principali</li> <li>[ ] Frontend React base</li> <li>[ ] Autenticazione JWT</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#fase-2-feature-parity-2-3-mesi","title":"Fase 2: Feature Parity (2-3 mesi)","text":"<ul> <li>[ ] Gestione eventi completa</li> <li>[ ] Sistema calcolo quantit\u00e0</li> <li>[ ] Workflow stati</li> <li>[ ] Report PDF</li> <li>[ ] Calendario</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#fase-3-saas-features-2-3-mesi","title":"Fase 3: SaaS Features (2-3 mesi)","text":"<ul> <li>[ ] Multi-tenancy</li> <li>[ ] Billing integration</li> <li>[ ] User management avanzato</li> <li>[ ] Customization engine</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#fase-4-advanced-features-3-4-mesi","title":"Fase 4: Advanced Features (3-4 mesi)","text":"<ul> <li>[ ] Mobile app</li> <li>[ ] Integrazioni terze parti</li> <li>[ ] Analytics avanzati</li> <li>[ ] E-commerce module</li> </ul>"},{"location":"APPLICATION_OVERVIEW/#vantaggi-competitivi","title":"Vantaggi Competitivi","text":"<ol> <li>Esperienza Reale: Basato su software in produzione da anni</li> <li>Specifico per Settore: Non un gestionale generico adattato</li> <li>Calcolo Automatico: Algoritmo quantit\u00e0 unico nel settore</li> <li>Workflow Collaudato: Processo testato su centinaia di eventi</li> <li>Localizzazione: Gi\u00e0 disponibile in italiano, facilmente estendibile</li> </ol>"},{"location":"APPLICATION_OVERVIEW/#competitor-analysis","title":"Competitor Analysis","text":"Feature CaterPro Caterease Total Party Planner Better Cater Gestione Eventi \u2705 \u2705 \u2705 \u2705 Calcolo Auto Quantit\u00e0 \u2705 \u274c \u274c Parziale Multi-tenant \u2705 \u274c \u274c \u2705 Mobile App \u2705 \u2705 \u274c \u2705 Italiano \u2705 \u274c \u274c \u274c API Pubbliche \u2705 Parziale \u274c \u2705 Prezzo Entry \u20ac49 $75 $50 $99"},{"location":"APPLICATION_OVERVIEW/#conclusioni","title":"Conclusioni","text":"<p>L'applicazione Apollinare rappresenta un'eccellente base per lo sviluppo di una soluzione SaaS nel settore catering. Le funzionalit\u00e0 core sono mature e testate, la business logic \u00e8 ben documentata, e l'architettura pu\u00f2 essere modernizzata mantenendo la compatibilit\u00e0 con i processi esistenti.</p> <p>La migrazione a .NET + React TypeScript permetter\u00e0: - Scalabilit\u00e0 orizzontale per SaaS - Developer experience moderna - Ecosystem di librerie pi\u00f9 ampio - Deployment cloud-native - Costi operativi ridotti</p> <p>Il mercato italiano del catering \u00e8 frammentato e sottosevito da soluzioni software moderne, rappresentando un'opportunit\u00e0 significativa per un prodotto SaaS verticale ben eseguito.</p>"},{"location":"apex/","title":"APEX Application Documentation","text":""},{"location":"apex/#application-overview","title":"Application Overview","text":"Property Value Application ID 112 Application Name APCB Project Application Alias F_110112 APEX Version 21.1.0 Owner/Schema APOLLINARECATERINGPROD Language Italian (it) Date Format DD-MM-YYYY DateTime Format DD-MM-YYYY HH24:MI:SS Logo Text Apollinare Catering &amp; Banqueting - Management Software Last Updated By MONIA Last Update 2025-11-24 14:06:02"},{"location":"apex/#application-statistics","title":"Application Statistics","text":"Component Count Pages 56 Items 302 Processes 98 Regions 151 Buttons 119 Dynamic Actions 62 LOVs 12 Authorization Schemes 5 Computations 2 Breadcrumb Entries 22 List Entries 2 Templates 64 Plug-ins 2 Messages 464"},{"location":"apex/#navigation-structure","title":"Navigation Structure","text":""},{"location":"apex/#desktop-navigation-menu","title":"Desktop Navigation Menu","text":"<pre><code>Home (Page 1)\n\u251c\u2500\u2500 Articoli (Page 2)\n\u2502 \u2514\u2500\u2500 Impegni Articoli (Page 39)\n\u251c\u2500\u2500 Categorie (Page 4)\n\u251c\u2500\u2500 Tipi (Page 6)\n\u251c\u2500\u2500 Clienti (Page 17)\n\u251c\u2500\u2500 Location (Page 15)\n\u251c\u2500\u2500 Risorse (Page 31)\n\u251c\u2500\u2500 Permessi (Page 47) [Admin Only]\n\u251c\u2500\u2500 Gestione Dati (Page 45) [Admin Only]\n\u251c\u2500\u2500 Job Schedulati (Page 49)\n\u251c\u2500\u2500 Mail Inviate (Page 50)\n\u2514\u2500\u2500 Mail In Attesa (Page 51)\n\nEventi\n\u251c\u2500\u2500 Tipi Evento (Page 13) [Admin Only]\n\u251c\u2500\u2500 Nuovo Evento (Page 22) [Admin Only]\n\u251c\u2500\u2500 Schede/Schede Confermate (Page 35)\n\u251c\u2500\u2500 Liste (Page 9) [Admin Only]\n\u251c\u2500\u2500 Calendario Eventi (Page 12)\n\u251c\u2500\u2500 Degustazioni (Page 27)\n\u2514\u2500\u2500 Template Eventi (Page 48) [Admin Only]\n\nRiepiloghi/Report\n\u251c\u2500\u2500 Griglia (Page 16) [Admin Only]\n\u251c\u2500\u2500 Riepilogo Cucina (Page 25)\n\u251c\u2500\u2500 Torte e Costi Extra (Page 28) [Admin Only]\n\u251c\u2500\u2500 Riepilogo Allestimenti (Page 30)\n\u2514\u2500\u2500 Riepilogo Risorse (Page 38)\n</code></pre>"},{"location":"apex/#page-categories","title":"Page Categories","text":""},{"location":"apex/#master-data-pages","title":"Master Data Pages","text":"Page ID Name Description 2 Articoli Rpt Article list report 3 Articoli Article detail form 4 Categorie Rpt Categories list report 5 Categorie Category detail form 6 Tipi Rpt Types list report 7 Tipi Type detail form 17 Clienti Rpt Clients list report 18 Clienti Client detail form 15 Location Rpt Locations list report 20 Location Location detail form 31 Risorse Resources (staff) management"},{"location":"apex/#event-management-pages","title":"Event Management Pages","text":"Page ID Name Description 1 Home Dashboard 8 Nuovo Evento Wizard Event creation wizard 9 Lista Eventi Event list 12 Calendario Event calendar 13 Tipi Evento Rpt Event types list 14 Tipi Evento Event type detail form 22 Nuovo Evento Main event form (most complex) 27 Lista Degustazioni Tastings list 32 Degustazione Tasting detail 35 Schede/Schede Confermate Event cards 48 Template Eventi Event templates"},{"location":"apex/#report-pages","title":"Report Pages","text":"Page ID Name Description 16 Griglia Grid view 25 Riepilogo Cucina Kitchen summary 28 Torte e Costi Extra Cakes and extra costs 30 Riepilogo Allestimenti Setup summary 38 Riepilogo Risorse Resources summary 39 Impegni Articoli Article commitments"},{"location":"apex/#administration-pages","title":"Administration Pages","text":"Page ID Name Description 45 Gestione Dati Data management 46 Max Eventi Max events configuration 47 Permessi Permissions management 49 Job Schedulati Scheduled jobs 50 Mail Inviate Sent emails 51 Mail In Attesa Pending emails"},{"location":"apex/#page-22-nuovo-evento-most-complex-page","title":"Page 22 (Nuovo Evento) - Most Complex Page","text":"<p>Page 22 is the main event management page with the highest complexity:</p> Component Count Items 108 Regions 33 Buttons 32 Processes 32 Dynamic Actions Multiple"},{"location":"apex/#key-features","title":"Key Features:","text":"<ul> <li>Multiple Interactive Grids (master-detail)</li> <li>Guest type management with quantity recalculations</li> <li>Resource assignments</li> <li>Pick list management with coefficient-based calculations</li> <li>Event status workflow management</li> <li>Template support</li> <li>Versioning system</li> </ul>"},{"location":"apex/#documentation-structure","title":"Documentation Structure","text":"<pre><code>docs/apex/\n\u251c\u2500\u2500 README.md (this file)\n\u251c\u2500\u2500 pages/ # Individual page documentation\n\u251c\u2500\u2500 processes/ # Process documentation\n\u251c\u2500\u2500 lovs/ # List of Values documentation\n\u251c\u2500\u2500 javascript/ # JavaScript libraries\n\u251c\u2500\u2500 authorization/ # Authorization schemes\n\u251c\u2500\u2500 dynamic-actions/ # Dynamic actions\n\u251c\u2500\u2500 items/ # Shared items\n\u251c\u2500\u2500 regions/ # Shared regions\n\u2514\u2500\u2500 navigation/ # Navigation components\n</code></pre>"},{"location":"apex/#key-files","title":"Key Files","text":"<ul> <li>LOVs Documentation - List of Values definitions</li> <li>Processes Documentation - PL/SQL processes</li> <li>JavaScript Libraries - Custom JavaScript</li> <li>Authorization Schemes - Security settings</li> <li>Page 22 Documentation - Main event form</li> </ul>"},{"location":"apex/#event-status-workflow","title":"Event Status Workflow","text":"<pre><code>100 (Preventivo/Quote)\n \u2193 [Continue Event]\n200 (Scheda/Preparazione)\n \u2193 [Return to Preparazione]\n300 (Confermata/Quasi)\n \u2193 [Almost Continue Event]\n350 (Quasi Confermato)\n \u2193 [Confirm Event]\n400 (Confermato/Confirmed)\n \u2193 [Set Obsoleto]\n900 (Superato/Expired)\n</code></pre>"},{"location":"apex/#authorization-schemes","title":"Authorization Schemes","text":"Scheme Name Description Admin_auth_schema Full admin access User Read/Write Controlled by USERS_READONLY table Consuntivi Financial summaries access Gestori Manager-level permissions Solo Admins Highest level (admin, monia only)"},{"location":"apex/authorization/","title":"Authorization Schemes Documentation","text":"<p>This document describes the 5 authorization schemes used in the APEX application for access control.</p>"},{"location":"apex/authorization/#overview","title":"Overview","text":"Scheme Name Type Users/Condition Error Message Admin_auth_schema NATIVE_EXISTS Specific user list Utente non autorizzato User Read/Write NATIVE_FUNCTION_BODY USERS_READONLY table Utente abilitato in sola lettura Consuntivi NATIVE_EXISTS GET_CONSUNTIVI_USERS view Autorizzazione necessaria... Gestori NATIVE_EXISTS GET_GESTORI_USERS view Non possiedi i permessi... Solo Admins NATIVE_EXISTS admin, monia only Non possiedi i permessi..."},{"location":"apex/authorization/#admin_auth_schema","title":"Admin_auth_schema","text":"<p>Type: NATIVE_EXISTS Caching: BY_USER_BY_PAGE_VIEW</p> <p>SQL Query: <pre><code>select 1 from dual\nwhere lower(:APP_USER) in ('admin','monia','andrea','maria','sabrina','nicole','cucina','developer','elia.ballarani');\n</code></pre></p> <p>Authorized Users: - admin - monia - andrea - maria - sabrina - nicole - cucina - developer - elia.ballarani</p> <p>Usage: General administrative access to most management pages.</p>"},{"location":"apex/authorization/#user-readwrite","title":"User Read/Write","text":"<p>Type: NATIVE_FUNCTION_BODY Caching: BY_USER_BY_PAGE_VIEW</p> <p>PL/SQL Function: <pre><code>declare\n v_readonly number;\nbegin\n select 1\n into v_readonly\n from users_readonly\n where username = :APP_USER\n and flgwrite = 0;\n\n return false;\nexception when no_data_found then\n return true;\nend;\n</code></pre></p> <p>Logic: - Checks <code>USERS_READONLY</code> table - If user exists with <code>FLGWRITE = 0</code> \u2192 Returns FALSE (read-only mode) - If user not found \u2192 Returns TRUE (write access)</p> <p>Usage: Controls whether user can modify data or only view.</p>"},{"location":"apex/authorization/#consuntivi","title":"Consuntivi","text":"<p>Type: NATIVE_EXISTS Caching: BY_USER_BY_PAGE_VIEW</p> <p>SQL Query: <pre><code>select 1 from dual \nwhere :APP_USER in (select users from get_consuntivi_users);\n</code></pre></p> <p>Data Source: <code>GET_CONSUNTIVI_USERS</code> view</p> <p>Usage: Access to financial summary pages and cost management.</p>"},{"location":"apex/authorization/#gestori","title":"Gestori","text":"<p>Type: NATIVE_EXISTS Caching: BY_USER_BY_PAGE_VIEW</p> <p>SQL Query: <pre><code>select 1 from dual \nwhere :APP_USER in (select users from get_gestori_users);\n</code></pre></p> <p>Data Source: <code>GET_GESTORI_USERS</code> view</p> <p>Usage: Manager-level access. Applied to: - Home page - Nuovo Evento (Page 22) - Liste (Page 9) - Griglia (Page 16) - Torte e Costi Extra (Page 28) - Template Eventi (Page 48) - Tipi Evento (Page 13)</p>"},{"location":"apex/authorization/#solo-admins","title":"Solo Admins","text":"<p>Type: NATIVE_EXISTS Caching: BY_USER_BY_PAGE_VIEW</p> <p>SQL Query: <pre><code>select 1 from dual \nwhere lower(:APP_USER) in ('admin', 'monia');\n</code></pre></p> <p>Authorized Users: - admin - monia</p> <p>Usage: Highest level of access. Reserved for: - Permessi (Page 47) - Gestione Dati (Page 45) - Critical configuration pages</p>"},{"location":"apex/authorization/#application-level-processes","title":"Application-Level Processes","text":""},{"location":"apex/authorization/#set_user_readonly","title":"SET_USER_READONLY","text":"<p>Process Point: Before Header (runs on every page) Sequence: 1</p> <pre><code>begin\n select 1\n into :APP_READ_ONLY\n from users_readonly\n where username = :APP_USER\n and flgwrite = 0;\nexception when no_data_found then\n :APP_READ_ONLY := 0;\nend;\n</code></pre> <p>Sets: <code>APP_READ_ONLY</code> application item - Value <code>1</code> = Read-only mode - Value <code>0</code> = Full access</p> <p>This is checked in page processes with condition: <pre><code>:APP_READ_ONLY = 0\n</code></pre></p>"},{"location":"apex/authorization/#set_item_session","title":"SET_ITEM_SESSION","text":"<p>Process Point: On Demand Security: MUST_NOT_BE_PUBLIC_USER</p> <pre><code>declare\n v_itemList varchar2(32000);\nbegin\n v_itemList := APEX_UTIL.TABLE_TO_STRING(APEX_APPLICATION.G_F01);\n\n for c in (\n select\n (select result from table(STRING_TO_TABLE_ENUM(a.result, 1, '='))) as item,\n (select result from table(STRING_TO_TABLE_ENUM(a.result, 2, '='))) as val\n from table(STRING_TO_TABLE_ENUM(v_itemList)) a\n )\n loop\n APEX_UTIL.set_session_state(\n p_name =&gt; c.item,\n p_value =&gt; c.val\n );\n end loop;\nend;\n</code></pre> <p>Usage: Called by <code>setSessionState()</code> JavaScript function to update APEX session state for multiple items.</p>"},{"location":"apex/authorization/#application-items","title":"Application Items","text":""},{"location":"apex/authorization/#app_read_only","title":"APP_READ_ONLY","text":"<p>Protection Level: Internal Escape on HTTP Output: No</p> <p>Stores the read-only flag for the current user session.</p>"},{"location":"apex/authorization/#app_version","title":"APP_VERSION","text":"<p>Application version identifier.</p>"},{"location":"apex/authorization/#authorization-hierarchy","title":"Authorization Hierarchy","text":"<pre><code>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Solo Admins \u2502\n\u2502 (admin, monia) \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Admin_auth_schema \u2502\n\u2502 (admin, monia, andrea, maria, sabrina, nicole, \u2502\n\u2502 cucina, developer, elia.ballarani) \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Gestori \u2502\n\u2502 (from GET_GESTORI_USERS view) \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Consuntivi \u2502\n\u2502 (from GET_CONSUNTIVI_USERS view) \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 User Read/Write \u2502\n\u2502 (based on USERS_READONLY.FLGWRITE flag) \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Authenticated Users \u2502\n\u2502 (basic application access) \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n</code></pre>"},{"location":"apex/authorization/#database-objects-for-authorization","title":"Database Objects for Authorization","text":""},{"location":"apex/authorization/#users_readonly-table","title":"USERS_READONLY Table","text":"Column Type Description USERNAME VARCHAR2 APEX username FLGWRITE NUMBER 0 = read-only, 1 = write"},{"location":"apex/authorization/#get_gestori_users-view","title":"GET_GESTORI_USERS View","text":"<p>Returns list of users with manager permissions.</p>"},{"location":"apex/authorization/#get_consuntivi_users-view","title":"GET_CONSUNTIVI_USERS View","text":"<p>Returns list of users with financial access.</p>"},{"location":"apex/authorization/#migration-notes","title":"Migration Notes","text":"<p>When migrating to .NET + React:</p> <ol> <li>Authentication</li> <li>Implement JWT or cookie-based authentication</li> <li> <p>Consider integration with existing Oracle users or migrate to new system</p> </li> <li> <p>Authorization</p> </li> <li>Map authorization schemes to .NET roles/claims</li> <li> <p>Implement policy-based authorization in .NET</p> </li> <li> <p>Role Mapping <pre><code>public enum UserRole\n{\n User, // Basic authenticated user\n ReadOnly, // Read-only access\n Consuntivi, // Financial access\n Gestori, // Manager level\n Admin, // Admin_auth_schema equivalent\n SuperAdmin // Solo Admins equivalent\n}\n</code></pre></p> </li> <li> <p>Frontend Authorization</p> </li> <li>Store user roles in JWT/session</li> <li>Implement route guards in React</li> <li> <p>Conditionally render UI elements based on permissions</p> </li> <li> <p>Backend Authorization <pre><code>[Authorize(Policy = \"Gestori\")]\npublic class EventController : Controller\n{\n [Authorize(Policy = \"SoloAdmins\")]\n public IActionResult DeleteEvent(int id) { ... }\n}\n</code></pre></p> </li> </ol>"},{"location":"apex/javascript/","title":"JavaScript Libraries Documentation","text":"<p>This document describes the custom JavaScript libraries used in the APEX application.</p>"},{"location":"apex/javascript/#static-application-files","title":"Static Application Files","text":"File Name Description ajaxUtils.js AJAX utilities for dynamic updates and server communication iframeObj.js Jasper Reports integration wrapper"},{"location":"apex/javascript/#ajaxutilsjs","title":"ajaxUtils.js","text":"<p>Custom AJAX utility library for managing server-side communication and UI feedback.</p>"},{"location":"apex/javascript/#functions","title":"Functions","text":""},{"location":"apex/javascript/#notificaptext-ptype-null","title":"<code>notifica(pText, pType = null)</code>","text":"<p>Central dynamic notification function.</p> <p>Parameters: - <code>pText</code> (string): Message text to display - <code>pType</code> (string, optional): Notification type - 'alert', 'success', 'error', 'warning', 'info'</p> <p>Behavior: - Clears existing errors - If <code>pType</code> is provided, shows error notification at page level - If <code>pType</code> is null, shows success message</p> <p>Example: <pre><code>notifica(\"Record saved successfully\"); // Success message\nnotifica(\"Error occurred\", \"error\"); // Error message\n</code></pre></p>"},{"location":"apex/javascript/#setsessionstateelemlist-pcallback-null","title":"<code>setSessionState(elemList, pCallback = null)</code>","text":"<p>Sets APEX session state for multiple items.</p> <p>Parameters: - <code>elemList</code> (string): Comma-separated list of item IDs (without P prefix) - <code>pCallback</code> (function, optional): Callback function after session state is set</p> <p>How it works: 1. Splits the element list by comma 2. Gets values for each element using jQuery 3. Creates a dictionary of item-value pairs 4. Calls APEX process <code>SET_ITEM_SESSION</code> to update session state 5. Executes callback with data and elements dictionary</p> <p>Example: <pre><code>setSessionState(\"P22_EVENT_ID,P22_CLIENTE\", function(pData, elems) {\n console.log(\"Session state updated\");\n});\n</code></pre></p>"},{"location":"apex/javascript/#ajaxexecpname-clickobj-pparams-pcallback-pconfirm-ploading-pasync-ptype","title":"<code>ajaxExec(pName, clickObj, pParams, pCallback, pConfirm, pLoading, pAsync, pType)</code>","text":"<p>Generic AJAX execution wrapper for APEX server processes.</p> <p>Parameters: - <code>pName</code> (string): APEX process name to execute - <code>clickObj</code> (jQuery object): Button/element that triggered the action - <code>pParams</code> (object): Parameters to pass to the process - <code>pCallback</code> (function): Callback function on success/error - <code>pConfirm</code> (string): Confirmation message (uses native confirm dialog) - <code>pLoading</code> (boolean): Show loading popup - <code>pAsync</code> (boolean): Execute asynchronously - <code>pType</code> (string): Response data type (default: 'text')</p> <p>Features: - Prevents page unload during execution - Shows loading spinner on clicked element - Handles confirmation dialogs - Parses response and removes quotes - Executes callback with parsed data</p> <p>Example: <pre><code>ajaxExec(\"SAVE_EVENT\", clickBtn, {x01: eventId}, function(data, btn, params) {\n notifica(\"Event saved\");\n}, \"Are you sure?\", true);\n</code></pre></p>"},{"location":"apex/javascript/#execprocessasyncpname-pparams-ppreexec-pcallback-pitems-null-clickobj-null-pconfirm-null-ploading-null","title":"<code>execProcessAsync(pName, pParams, pPreExec, pCallback, pItems = null, clickObj = null, pConfirm = null, pLoading = null)</code>","text":"<p>Wrapper for async process execution with optional session state update.</p> <p>Parameters: - <code>pName</code> (string): Process name - <code>pParams</code> (object): Process parameters - <code>pPreExec</code> (function): Function to execute before AJAX call - <code>pCallback</code> (function): Callback after process execution - <code>pItems</code> (string): Items to set in session state first - <code>clickObj</code>: Clicked element - <code>pConfirm</code> (string): Confirmation message - <code>pLoading</code> (boolean): Show loading indicator</p> <p>Example: <pre><code>execProcessAsync(\"UPDATE_QTY\", {x01: itemId}, null, function(data) {\n apex.region(\"LIST_PREL\").refresh();\n}, \"P22_EVENT_ID\");\n</code></pre></p>"},{"location":"apex/javascript/#execqueryasyncpquery-ppreexec-pcallback-clickobj-null-pconfirm-null-pitems-null-ploading-null","title":"<code>execQueryAsync(pQuery, pPreExec, pCallback, clickObj = null, pConfirm = null, pItems = null, pLoading = null)</code>","text":"<p>Executes a SQL query asynchronously.</p> <p>Parameters: - <code>pQuery</code> (string): SQL query to execute - <code>pPreExec</code> (function): Pre-execution function - <code>pCallback</code> (function): Callback with query results - <code>clickObj</code>: Clicked element - <code>pConfirm</code> (string): Confirmation message - <code>pItems</code> (string): Items to set in session state - <code>pLoading</code> (boolean): Show loading indicator</p> <p>Note: Calls the <code>EXEC_QUERY</code> APEX process with the query in <code>x01</code> parameter.</p>"},{"location":"apex/javascript/#iframeobjjs","title":"iframeObj.js","text":"<p>JavaScript wrapper for embedding Jasper Reports in iframes.</p>"},{"location":"apex/javascript/#configuration","title":"Configuration","text":"<pre><code>var j_datasource = \"default\"; // Jasper datasource name\nvar j_username = \"jasperadmin\"; // Jasper server username\nvar j_password = \"jasperadmin\"; // Jasper server password\nvar j_def_outp = \"pdf\"; // Default output format (HTML, PDF)\n</code></pre>"},{"location":"apex/javascript/#iframe-class","title":"Iframe Class","text":""},{"location":"apex/javascript/#constructor","title":"Constructor","text":"<pre><code>var Iframe = function(parentObj, id, attr) { ... }\n</code></pre> <p>Parameters: - <code>parentObj</code>: Parent DOM element - <code>id</code>: Iframe element ID - <code>attr</code>: Additional attributes</p>"},{"location":"apex/javascript/#methods","title":"Methods","text":""},{"location":"apex/javascript/#setcsscss","title":"<code>setCss(css)</code>","text":"<p>Sets CSS styles on the iframe.</p> <p>Parameters: - <code>css</code> (object): CSS properties dictionary</p> <p>Example: <pre><code>iframe.setCss({ width: \"100%\", height: \"600px\", border: \"none\" });\n</code></pre></p>"},{"location":"apex/javascript/#seturlurl","title":"<code>setUrl(Url)</code>","text":"<p>Sets the iframe source URL.</p>"},{"location":"apex/javascript/#geturl","title":"<code>getUrl()</code>","text":"<p>Returns the current iframe URL.</p>"},{"location":"apex/javascript/#refresh","title":"<code>refresh()</code>","text":"<p>Reloads the iframe content.</p>"},{"location":"apex/javascript/#hide","title":"<code>hide()</code>","text":"<p>Hides the iframe (display: none).</p>"},{"location":"apex/javascript/#show","title":"<code>show()</code>","text":"<p>Shows the iframe (display: block).</p>"},{"location":"apex/javascript/#jasperreportdir-datasource-params-output-username-password","title":"<code>jasperReport(dir, datasource, params, output, username, password)</code>","text":"<p>Generates a Jasper Reports URL and loads it in the iframe.</p> <p>Parameters: - <code>dir</code> (string, required): Report path in Jasper server - <code>datasource</code> (string): Data source name (default: \"default\") - <code>params</code> (object): Report parameters as key-value pairs - <code>output</code> (string): Output format - 'pdf' or 'html' (default: 'pdf') - <code>username</code> (string): Jasper server username - <code>password</code> (string): Jasper server password</p> <p>URL Format: <pre><code>/jri/report?_repName={dir}&amp;_repFormat={output}&amp;_dataSource={datasource}&amp;_repLocale=it_IT&amp;_repTimeZone=Europe/Rome&amp;{params}\n</code></pre></p> <p>Example: <pre><code>var rptFrame = new Iframe(container, \"reportFrame\");\nrptFrame.jasperReport(\n \"apcb/scheda_evento_rpt\",\n \"default\",\n { P_EVENT_ID: eventId, P_TIPO: \"PREVENTIVO\" },\n \"pdf\"\n);\n</code></pre></p>"},{"location":"apex/javascript/#usage-in-apex-pages","title":"Usage in APEX Pages","text":""},{"location":"apex/javascript/#time-input-masks","title":"Time Input Masks","text":"<p>The application uses inputmask library for time fields:</p> <pre><code>Inputmask(\"99:99\", {\n placeholder: \"HH:MM\"\n}).mask($(\"#P22_ORA_INI_EVENTO\"));\n</code></pre>"},{"location":"apex/javascript/#sweetalert2-integration","title":"SweetAlert2 Integration","text":"<p>Used for enhanced confirmation dialogs:</p> <pre><code>Swal.fire({\n title: 'Conferma',\n text: 'Vuoi continuare?',\n icon: 'warning',\n showCancelButton: true\n}).then((result) =&gt; {\n if (result.isConfirmed) {\n // proceed\n }\n});\n</code></pre>"},{"location":"apex/javascript/#interactive-grid-refresh","title":"Interactive Grid Refresh","text":"<pre><code>// Refresh a specific interactive grid\napex.region(\"LISTA_PRELIEVO\").refresh();\n\n// Refresh with callback\napex.region(\"OSPITI\").widget().interactiveGrid(\"getViews\", \"grid\").model.fetchRecords();\n</code></pre>"},{"location":"apex/javascript/#migration-notes","title":"Migration Notes","text":"<p>When migrating to React TypeScript:</p> <ol> <li>AJAX Utilities - Replace with:</li> <li>Axios or fetch for HTTP requests</li> <li>React Query or SWR for data fetching</li> <li> <p>Toast library (react-toastify) for notifications</p> </li> <li> <p>Session State - Replace with:</p> </li> <li>React Context or Redux for state management</li> <li>URL parameters for shareable state</li> <li> <p>Session storage for persistence</p> </li> <li> <p>Jasper Reports - Options:</p> </li> <li>Keep Jasper and embed via iframe</li> <li>Migrate to SSRS, Crystal Reports</li> <li>Use PDF libraries (QuestPDF, iTextSharp)</li> <li> <p>Use React-PDF for client-side PDF generation</p> </li> <li> <p>Input Masks - Use:</p> </li> <li>react-input-mask</li> <li>@react-input/mask</li> <li> <p>Material-UI TextField with InputProps</p> </li> <li> <p>SweetAlert2 - Replace with:</p> </li> <li>MUI Dialog components</li> <li>react-confirm-alert</li> <li>Custom modal component</li> </ol>"},{"location":"apex/javascript/#example-react-migration","title":"Example React Migration","text":"<pre><code>// ajaxUtils.js equivalent in React\nimport { toast } from 'react-toastify';\nimport axios from 'axios';\n\nexport const notifica = (text: string, type?: 'success' | 'error' | 'warning' | 'info') =&gt; {\n if (type) {\n toast[type](text);\n } else {\n toast.success(text);\n }\n};\n\nexport const executeProcess = async &lt;T&gt;(\n processName: string,\n params: Record&lt;string, any&gt;\n): Promise&lt;T&gt; =&gt; {\n const response = await axios.post(`/api/processes/${processName}`, params);\n return response.data;\n};\n</code></pre>"},{"location":"apex/lovs/","title":"List of Values (LOVs) Documentation","text":"<p>This document contains all 12 List of Values defined in the APEX application.</p>"},{"location":"apex/lovs/#overview","title":"Overview","text":"LOV Name Source Type Description ARTICOLI SQL Query Article selection CATEGORIE SQL Query Category selection CLIENTI SQL Query Client selection LOCATION SQL Query Location selection RISORSE SQL Query Resource (staff) selection STATO_EVENTO Static Event status values TIPI MAT SQL Query Material type selection TIPI RISORSE SQL Query Resource type selection TIPO_EVENTO SQL Query Event type selection TIPO_OSPITI SQL Query Guest type selection TIPO_PASTO Static Meal type values USERS SQL Query User selection"},{"location":"apex/lovs/#articoli","title":"ARTICOLI","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>select /*a.cod_categ || ' - ' || c.descrizione || ' - ' ||*/ a.DESCRIZIONE as descrizione, a.COD_ARTICOLO\nfrom articoli a\njoin tb_codici_categ c on a.cod_categ = c.cod_categ\norder by 1\n</code></pre></p> <p>Usage: Selecting articles in pick lists and event details.</p>"},{"location":"apex/lovs/#categorie","title":"CATEGORIE","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>SELECT descrizione as d,\n cod_categ as r\nFROM tb_codici_categ\nORDER BY 1\n</code></pre></p> <p>Usage: Filtering articles by category, category selection in forms.</p>"},{"location":"apex/lovs/#clienti","title":"CLIENTI","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>select CLIENTE, ID\nfrom clienti\n</code></pre></p> <p>Usage: Client selection in event forms.</p>"},{"location":"apex/lovs/#location","title":"LOCATION","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>select location || ' - ' || indirizzo, id \nfrom location\n</code></pre></p> <p>Usage: Location selection in event forms. Displays location name with address.</p>"},{"location":"apex/lovs/#risorse","title":"RISORSE","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>select NOME || ' ' || COGNOME d, id r\nfrom risorse\n</code></pre></p> <p>Usage: Resource (staff) assignment in events. Displays full name.</p>"},{"location":"apex/lovs/#stato_evento","title":"STATO_EVENTO","text":"<p>Source Type: Static</p> <p>Values:</p> Display Value Return Value Sequence Scheda Evento (Preparazione) 0 10 Preventivo 10 20 Confermato 20 30 <p>Note: The actual status values in the database have been expanded: - 100 = Preventivo - 200 = Scheda - 300 = Confermata - 350 = Quasi Confermato - 400 = Confermato - 900 = Superato</p> <p>Usage: Event status display and selection.</p>"},{"location":"apex/lovs/#tipi-mat","title":"TIPI MAT","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>SELECT descrizione as d,\n cod_tipo as r\nFROM tb_tipi_mat\nORDER BY 1\n</code></pre></p> <p>Usage: Material type filtering in pick lists. Controls the step-by-step wizard flow.</p>"},{"location":"apex/lovs/#tipi-risorse","title":"TIPI RISORSE","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>select descrizione, cod_tipo\nfrom tb_tipi_risorsa\n</code></pre></p> <p>Usage: Resource type classification (camerieri, cuochi, etc.).</p>"},{"location":"apex/lovs/#tipo_evento","title":"TIPO_EVENTO","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>select trim(DESCRIZIONE) || decode(tipo_pasto, 'C', ' - Cena', 'P', ' - Pranzo', null) as d, \n COD_TIPO as r\nfrom tb_tipi_evento\n</code></pre></p> <p>Usage: Event type selection. Displays description with meal type indicator (Pranzo/Cena).</p>"},{"location":"apex/lovs/#tipo_ospiti","title":"TIPO_OSPITI","text":"<p>Source Type: SQL Query (LEGACY_SQL)</p> <p>Query: <pre><code>select descrizione as d,\n cod_tipo as r\nfrom tb_tipi_ospiti\norder by 1\n</code></pre></p> <p>Usage: Guest type selection in event guest details.</p>"},{"location":"apex/lovs/#tipo_pasto","title":"TIPO_PASTO","text":"<p>Source Type: Static</p> <p>Values:</p> Display Value Return Value Sequence Pranzo P 1 Cena C 2 Pranzo Buffet A 3 Cena Buffet B 4 <p>Usage: Meal type classification for events and event types.</p>"},{"location":"apex/lovs/#users","title":"USERS","text":"<p>Source Type: SQL Query</p> <p>Query: <pre><code>select user_name D, user_name R\nfrom WWV_FLOW_USERS\n</code></pre></p> <p>Return Column: R Display Column: D</p> <p>Usage: User selection for permissions and assignments.</p>"},{"location":"apex/lovs/#migration-notes","title":"Migration Notes","text":"<p>When migrating to React TypeScript:</p> <ol> <li>Static LOVs (STATO_EVENTO, TIPO_PASTO) can be implemented as TypeScript enums or const objects</li> <li>SQL-based LOVs should be converted to API endpoints</li> <li>Consider caching strategy for frequently used LOVs (CATEGORIE, TIPI MAT, etc.)</li> <li>TIPO_EVENTO uses Oracle <code>decode()</code> function - convert to CASE WHEN or handle in API</li> </ol>"},{"location":"apex/lovs/#example-typescript-implementation","title":"Example TypeScript Implementation","text":"<pre><code>// Static LOV - TIPO_PASTO\nexport const TIPO_PASTO = {\n PRANZO: { value: 'P', label: 'Pranzo' },\n CENA: { value: 'C', label: 'Cena' },\n PRANZO_BUFFET: { value: 'A', label: 'Pranzo Buffet' },\n CENA_BUFFET: { value: 'B', label: 'Cena Buffet' },\n} as const;\n\n// Dynamic LOV - API endpoint\n// GET /api/lovs/articoli\n// GET /api/lovs/categorie\n// GET /api/lovs/clienti\n// etc.\n</code></pre>"},{"location":"apex/pages/PAGE_002/","title":"Page 2 - Articoli Rpt","text":""},{"location":"apex/pages/PAGE_002/#items-1","title":"Items (1)","text":"<ul> <li><code>P2_IMMAGINE</code></li> </ul>"},{"location":"apex/pages/PAGE_003/","title":"Page 3 - Articoli","text":""},{"location":"apex/pages/PAGE_003/#items-21","title":"Items (21)","text":"<ul> <li><code>P3_COD_ARTICOLO</code></li> <li><code>P3_COD_CATEG</code></li> <li><code>P3_COD_RELATIVO</code></li> <li><code>P3_COEFF</code></li> <li><code>P3_COEFF_A</code></li> <li><code>P3_COEFF_B</code></li> <li><code>P3_COEFF_S</code></li> <li><code>P3_DESCRIZIONE</code></li> <li><code>P3_FLG_CUCINA</code></li> <li><code>P3_IMMAGINE</code></li> <li><code>P3_IMMAGINE_DISPLAY</code></li> <li><code>P3_PERC_IVA</code></li> <li><code>P3_PERC_OSPITI</code></li> <li><code>P3_QTAGIAC</code></li> <li><code>P3_QTAIMP</code></li> <li><code>P3_QTA_STD_A</code></li> <li><code>P3_QTA_STD_B</code></li> <li><code>P3_QTA_STD_S</code></li> <li><code>P3_RANK</code></li> <li><code>P3_ROWID</code></li> <li><code>P3_TIPO_QTA</code></li> </ul>"},{"location":"apex/pages/PAGE_005/","title":"Page 5 - Categorie","text":""},{"location":"apex/pages/PAGE_005/#items-9","title":"Items (9)","text":"<ul> <li><code>P5_COD_CATEG</code></li> <li><code>P5_COD_TIPO</code></li> <li><code>P5_COEFF_A</code></li> <li><code>P5_COEFF_B</code></li> <li><code>P5_COEFF_S</code></li> <li><code>P5_DESCRIZIONE</code></li> <li><code>P5_ROWID</code></li> <li><code>P5_SHOW_PRINT</code></li> <li><code>P5_TIPO_RIEPILOGO</code></li> </ul>"},{"location":"apex/pages/PAGE_007/","title":"Page 7 - Tipi","text":""},{"location":"apex/pages/PAGE_007/#items-3","title":"Items (3)","text":"<ul> <li><code>P7_COD_TIPO</code></li> <li><code>P7_DESCRIZIONE</code></li> <li><code>P7_ROWID</code></li> </ul>"},{"location":"apex/pages/PAGE_008/","title":"Page 8 - Creazione Evento","text":""},{"location":"apex/pages/PAGE_008/#items-35","title":"Items (35)","text":"<ul> <li><code>P8_ALLERGIE</code></li> <li><code>P8_CATEG</code></li> <li><code>P8_CATEG_FILTER</code></li> <li><code>P8_CLIENTE</code></li> <li><code>P8_CLIENTE_DISPLAY</code></li> <li><code>P8_COD_TIPO</code></li> <li><code>P8_COD_TIPO_DISPLAY</code></li> <li><code>P8_COD_TIPO_FILTER</code></li> <li><code>P8_CONFETTATA</code></li> <li><code>P8_DATA</code></li> <li><code>P8_DATA_DISPLAY</code></li> <li><code>P8_DESCRIZIONE</code></li> <li><code>P8_DESCRIZIONE_DISPLAY</code></li> <li><code>P8_EVENT_ID</code></li> <li><code>P8_FLG_TEMPLATE</code></li> <li><code>P8_ID_IMAGE_SHOW</code></li> <li><code>P8_INDIRIZZO</code></li> <li><code>P8_INDIRIZZO_DISPLAY</code></li> <li><code>P8_LOCATION</code></li> <li><code>P8_LOCATION_DISPLAY</code></li> <li><code>P8_MAXSTEP</code></li> <li><code>P8_NOTE</code></li> <li><code>P8_NOTE_DISPLAY</code></li> <li><code>P8_ORA_INI_CER</code></li> <li><code>P8_ORA_INI_EVT</code></li> <li><code>P8_PERC_SEDUTE</code></li> <li><code>P8_STAMPA_MENU</code></li> <li><code>P8_STEP</code></li> <li><code>P8_TAVOLI_NR</code></li> <li><code>P8_TORTA</code></li> <li><code>P8_TORTA_DISPLAY</code></li> <li><code>P8_TOT_ADULTI</code></li> <li><code>P8_TOT_BABY</code></li> <li><code>P8_TOT_KINDER</code></li> <li><code>P8_TOT_OSPITI</code></li> </ul>"},{"location":"apex/pages/PAGE_010/","title":"Page 10 - Anteprima Immagine","text":""},{"location":"apex/pages/PAGE_010/#items-2","title":"Items (2)","text":"<ul> <li><code>P10_IMMAGINE</code></li> <li><code>P10_ROWID</code></li> </ul>"},{"location":"apex/pages/PAGE_011/","title":"Page 11 - Stampa Riepilogo","text":""},{"location":"apex/pages/PAGE_011/#items-1","title":"Items (1)","text":"<ul> <li><code>P11_EVENT_ID</code></li> </ul>"},{"location":"apex/pages/PAGE_014/","title":"Page 14 - Tipi Evento","text":""},{"location":"apex/pages/PAGE_014/#items-5","title":"Items (5)","text":"<ul> <li><code>P14_COD_TIPO</code></li> <li><code>P14_DESCRIZIONE</code></li> <li><code>P14_LIVELLO</code></li> <li><code>P14_ROWID</code></li> <li><code>P14_TIPO_PASTO</code></li> </ul>"},{"location":"apex/pages/PAGE_016/","title":"Page 16 - Griglia","text":""},{"location":"apex/pages/PAGE_016/#items-1","title":"Items (1)","text":"<ul> <li><code>P16_SETTIMANA</code></li> </ul>"},{"location":"apex/pages/PAGE_018/","title":"Page 18 - Clienti","text":""},{"location":"apex/pages/PAGE_018/#items-10","title":"Items (10)","text":"<ul> <li><code>P18_CLIENTE</code></li> <li><code>P18_COGNOME_RIF</code></li> <li><code>P18_INDIRIZZO</code></li> <li><code>P18_MAIL</code></li> <li><code>P18_NOME_RIF</code></li> <li><code>P18_PIVA</code></li> <li><code>P18_RAGSOC</code></li> <li><code>P18_ROWID</code></li> <li><code>P18_TEL1</code></li> <li><code>P18_TEL2</code></li> </ul>"},{"location":"apex/pages/PAGE_019/","title":"Page 19 - Articoli Popup","text":""},{"location":"apex/pages/PAGE_019/#items-16","title":"Items (16)","text":"<ul> <li><code>P19_COD_ARTICOLO</code></li> <li><code>P19_COD_CATEG</code></li> <li><code>P19_COD_RELATIVO</code></li> <li><code>P19_COEFF</code></li> <li><code>P19_COEFF_A</code></li> <li><code>P19_COEFF_B</code></li> <li><code>P19_COEFF_S</code></li> <li><code>P19_DESCRIZIONE</code></li> <li><code>P19_FLG_CUCINA</code></li> <li><code>P19_IMMAGINE</code></li> <li><code>P19_IMMAGINE_DISPLAY</code></li> <li><code>P19_QTA_STD_A</code></li> <li><code>P19_QTA_STD_B</code></li> <li><code>P19_QTA_STD_S</code></li> <li><code>P19_ROWID</code></li> <li><code>P19_TIPO_QTA</code></li> </ul>"},{"location":"apex/pages/PAGE_020/","title":"Page 20 - Location","text":""},{"location":"apex/pages/PAGE_020/#items-7","title":"Items (7)","text":"<ul> <li><code>P20_ID</code></li> <li><code>P20_INDIRIZZO</code></li> <li><code>P20_LOCATION</code></li> <li><code>P20_NOTE</code></li> <li><code>P20_NOTE2</code></li> <li><code>P20_REFERENTE</code></li> <li><code>P20_ROWID</code></li> </ul>"},{"location":"apex/pages/PAGE_021/","title":"Page 21 - Costi Articolo","text":""},{"location":"apex/pages/PAGE_021/#items-1","title":"Items (1)","text":"<ul> <li><code>P21_COD_ARTICOLO</code></li> </ul>"},{"location":"apex/pages/PAGE_022/","title":"Page 22 - Evento","text":""},{"location":"apex/pages/PAGE_022/#items-108","title":"Items (108)","text":"<ul> <li><code>P22_ALLERGIE</code></li> <li><code>P22_ALLEST_BUFF</code></li> <li><code>P22_ALTRO</code></li> <li><code>P22_ALTRO_A</code></li> <li><code>P22_ALTRO_B</code></li> <li><code>P22_ARTICOLO_ADD</code></li> <li><code>P22_ARTICOLO_REMOVE</code></li> <li><code>P22_BICCHIERI</code></li> <li><code>P22_BUFFET_DOLCI_A</code></li> <li><code>P22_BUFFET_DOLCI_B</code></li> <li><code>P22_BUFFET_FINALE</code></li> <li><code>P22_BUFFET_FINALE_DISPLAY</code></li> <li><code>P22_BUFFET_INIZIALE</code></li> <li><code>P22_BUFFET_INIZIALE_DISPLAY</code></li> <li><code>P22_CARICOAPOLL</code></li> <li><code>P22_CARICOSPOSI</code></li> <li><code>P22_CATEG</code></li> <li><code>P22_CATEG_FILTER</code></li> <li><code>P22_CLIENTE</code></li> <li><code>P22_CLIENTE_EMAIL</code></li> <li><code>P22_CLIENTE_TEL</code></li> <li><code>P22_COD_TIPO</code></li> <li><code>P22_COD_TIPO_FILTER</code></li> <li><code>P22_COLOR</code></li> <li><code>P22_CONSUNTIVO_MORE_DETAILS</code></li> <li><code>P22_CONTRATTO_FIRMATO</code></li> <li><code>P22_DATA</code></li> <li><code>P22_DATA_DOC</code></li> <li><code>P22_DATA_SCAD_PREVENTIVO</code></li> <li><code>P22_DATORASCARICO</code></li> <li><code>P22_DATORASCARICO_NOTE</code></li> <li><code>P22_DELETED</code></li> <li><code>P22_DELETED_BY</code></li> <li><code>P22_DELETED_DATE</code></li> <li><code>P22_DESCRIZIONE</code></li> <li><code>P22_DISABLED</code></li> <li><code>P22_DISTANZA_LOCATION</code></li> <li><code>P22_EVENT_ID</code></li> <li><code>P22_EVENT_ID_DISPLAY</code></li> <li><code>P22_EXTRA</code></li> <li><code>P22_EXTRA_COSTI</code></li> <li><code>P22_FLG_SUPERATO</code></li> <li><code>P22_FLG_TEMPLATE</code></li> <li><code>P22_GGSETT</code></li> <li><code>P22_GRAN_BUFFET_A</code></li> <li><code>P22_GRAN_BUFFET_B</code></li> <li><code>P22_ID_EVT_FIGLIO</code></li> <li><code>P22_ID_EVT_PADRE</code></li> <li><code>P22_ID_IMAGE_SHOW</code></li> <li><code>P22_INDIRIZZO</code></li> <li><code>P22_IS_TEMPLATE</code></li> <li><code>P22_LISTA_PRINT</code></li> <li><code>P22_LOCATION</code></li> <li><code>P22_LOCATION_DESCRI</code></li> <li><code>P22_MAIL_ENABLED</code></li> <li><code>P22_MAXSTEP</code></li> <li><code>P22_NEW</code></li> <li><code>P22_NEW_EVENT_ID</code></li> <li><code>P22_NOTE</code></li> <li><code>P22_NOTE_INVIO</code></li> <li><code>P22_NUMALTRI</code></li> <li><code>P22_NUMDEGUSTAZIONI</code></li> <li><code>P22_NUM_LISTA</code></li> <li><code>P22_ORA_CERIMONIA</code></li> <li><code>P22_ORA_EVENTO</code></li> <li><code>P22_ORA_FINE_CERIMONIA</code></li> <li><code>P22_ORA_FINE_EVENTO</code></li> <li><code>P22_ORA_FI_CER</code></li> <li><code>P22_ORA_FI_EVENTO</code></li> <li><code>P22_ORA_INI_CER</code></li> <li><code>P22_ORA_INI_EVENTO</code></li> <li><code>P22_PERC_SEDUTE</code></li> <li><code>P22_PERMES_CONSUNTIVI_REPORT</code></li> <li><code>P22_PIATTI</code></li> <li><code>P22_PIATTINO_PANE</code></li> <li><code>P22_POSATE</code></li> <li><code>P22_PRE_BOUV_A</code></li> <li><code>P22_PRE_BOUV_B</code></li> <li><code>P22_PRIMI</code></li> <li><code>P22_PRIMI_DISPLAY</code></li> <li><code>P22_REFERENTE_TEL</code></li> <li><code>P22_RISORSA_ADD</code></li> <li><code>P22_RISORSA_REMOVE</code></li> <li><code>P22_RUNNER</code></li> <li><code>P22_SCADUTO</code></li> <li><code>P22_SECONDI</code></li> <li><code>P22_SEDIA</code></li> <li><code>P22_SERVIZIO_TAVOLO_A</code></li> <li><code>P22_SERVIZIO_TAVOLO_B</code></li> <li><code>P22_SOTTOPIATTI</code></li> <li><code>P22_STATO</code></li> <li><code>P22_STATUS</code></li> <li><code>P22_STEP</code></li> <li><code>P22_STILE_COLORI</code></li> <li><code>P22_TIPOL_TAV_OSPITI</code></li> <li><code>P22_TIPOL_TAV_SPOSI</code></li> <li><code>P22_TIPORIS_FILTER</code></li> <li><code>P22_TORTA</code></li> <li><code>P22_TORTA_A</code></li> <li><code>P22_TORTA_B</code></li> <li><code>P22_TOT_OSPITI</code></li> <li><code>P22_TOVAGLIA</code></li> <li><code>P22_TOVAGLIOLO</code></li> <li><code>P22_VERSION_DISPLAY</code></li> <li><code>P22_VERS_NUMBER</code></li> <li><code>P22_VERS_TOKEN</code></li> <li><code>P22_VINI</code></li> <li><code>P22_VINI_DISPLAY</code></li> </ul>"},{"location":"apex/pages/PAGE_024/","title":"Page 24 - Stampa Riepilogo Extra","text":""},{"location":"apex/pages/PAGE_024/#items-2","title":"Items (2)","text":"<ul> <li><code>P24_DATA_FI</code></li> <li><code>P24_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_025/","title":"Page 25 - Cucina","text":""},{"location":"apex/pages/PAGE_025/#items-2","title":"Items (2)","text":"<ul> <li><code>P25_DATA_FI</code></li> <li><code>P25_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_026/","title":"Page 26 - Stampa Riepilogo Cucina","text":""},{"location":"apex/pages/PAGE_026/#items-2","title":"Items (2)","text":"<ul> <li><code>P26_DATA_FI</code></li> <li><code>P26_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_027/","title":"Page 27 - Degustazioni_Lista","text":""},{"location":"apex/pages/PAGE_027/#items-2","title":"Items (2)","text":"<ul> <li><code>P27_DATA_FI</code></li> <li><code>P27_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_028/","title":"Page 28 - Torte e Costi Extra","text":""},{"location":"apex/pages/PAGE_028/#items-2","title":"Items (2)","text":"<ul> <li><code>P28_DATA_FI</code></li> <li><code>P28_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_029/","title":"Page 29 - Stampa Riepilogo Allestimenti","text":""},{"location":"apex/pages/PAGE_029/#items-2","title":"Items (2)","text":"<ul> <li><code>P29_DATA_FI</code></li> <li><code>P29_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_030/","title":"Page 30 - Riepilogo Allestimenti","text":""},{"location":"apex/pages/PAGE_030/#items-2","title":"Items (2)","text":"<ul> <li><code>P30_DATA_FI</code></li> <li><code>P30_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_032/","title":"Page 32 - Degustazioni","text":""},{"location":"apex/pages/PAGE_032/#items-14","title":"Items (14)","text":"<ul> <li><code>P32_DATA</code></li> <li><code>P32_EMAIL</code></li> <li><code>P32_ID</code></li> <li><code>P32_ID_EVENTO</code></li> <li><code>P32_LOCATION</code></li> <li><code>P32_MENU</code></li> <li><code>P32_NOME</code></li> <li><code>P32_NOTE</code></li> <li><code>P32_N_DEGUSTAZIONE</code></li> <li><code>P32_N_PAGANTI</code></li> <li><code>P32_N_PERSONE</code></li> <li><code>P32_ORA</code></li> <li><code>P32_ROWID</code></li> <li><code>P32_TELEFONO</code></li> </ul>"},{"location":"apex/pages/PAGE_033/","title":"Page 33 - Stampa Scheda Evento","text":""},{"location":"apex/pages/PAGE_033/#items-2","title":"Items (2)","text":"<ul> <li><code>P33_EVENT_ID</code></li> <li><code>P33_LISTA</code></li> </ul>"},{"location":"apex/pages/PAGE_035/","title":"Page 35 - Lista Schede Evento","text":""},{"location":"apex/pages/PAGE_035/#items-2","title":"Items (2)","text":"<ul> <li><code>P35_DATEFROM</code></li> <li><code>P35_DATETO</code></li> </ul>"},{"location":"apex/pages/PAGE_036/","title":"Page 36 - Stampa Riepilogo Degustazioni","text":""},{"location":"apex/pages/PAGE_036/#items-2","title":"Items (2)","text":"<ul> <li><code>P36_DATA_FI</code></li> <li><code>P36_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_038/","title":"Page 38 - Riepilogo Risorse","text":""},{"location":"apex/pages/PAGE_038/#items-3","title":"Items (3)","text":"<ul> <li><code>P38_COD_AZIENDA</code></li> <li><code>P38_DATA_FI</code></li> <li><code>P38_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_039/","title":"Page 39 - Impegni Articoli","text":""},{"location":"apex/pages/PAGE_039/#items-4","title":"Items (4)","text":"<ul> <li><code>P39_COD_ARTICOLO</code></li> <li><code>P39_DATA_FI</code></li> <li><code>P39_DATA_IN</code></li> <li><code>P39_SHOW_HISTORY</code></li> </ul>"},{"location":"apex/pages/PAGE_040/","title":"Page 40 - Stampa Riepilogo Risorse","text":""},{"location":"apex/pages/PAGE_040/#items-3","title":"Items (3)","text":"<ul> <li><code>P40_COD_AZIENDA</code></li> <li><code>P40_DATA_FI</code></li> <li><code>P40_DATA_IN</code></li> </ul>"},{"location":"apex/pages/PAGE_041/","title":"Page 41 - Backup","text":""},{"location":"apex/pages/PAGE_041/#items-1","title":"Items (1)","text":"<ul> <li><code>P41_BCKPASSWORD</code></li> </ul>"},{"location":"apex/pages/PAGE_042/","title":"Page 42 - Nuovo Allegato Evento","text":""},{"location":"apex/pages/PAGE_042/#items-8","title":"Items (8)","text":"<ul> <li><code>P42_CHARSET</code></li> <li><code>P42_EVENT_ID</code></li> <li><code>P42_FILENAME</code></li> <li><code>P42_FILESIZELIMITKB</code></li> <li><code>P42_ID</code></li> <li><code>P42_LAST_UPDATE</code></li> <li><code>P42_MIME_TYPE</code></li> <li><code>P42_RAW_DATA</code></li> </ul>"},{"location":"apex/pages/PAGE_043/","title":"Page 43 - Registro Acconti Evento","text":""},{"location":"apex/pages/PAGE_043/#items-1","title":"Items (1)","text":"<ul> <li><code>P43_ID_EVENTO</code></li> </ul>"},{"location":"apex/pages/PAGE_044/","title":"Page 44 - Registro Altri Costi","text":""},{"location":"apex/pages/PAGE_044/#items-1","title":"Items (1)","text":"<ul> <li><code>P44_ID_EVENTO</code></li> </ul>"},{"location":"apex/pages/PAGE_045/","title":"Page 45 - GestioneDati","text":""},{"location":"apex/pages/PAGE_045/#items-4","title":"Items (4)","text":"<ul> <li><code>P45_CONSUNTIVI_A</code></li> <li><code>P45_CONSUNTIVI_DA</code></li> <li><code>P45_EVENTI_A</code></li> <li><code>P45_EVENTI_DA</code></li> </ul>"},{"location":"apex/pages/PAGE_046/","title":"Page 46 - Imposta Blocco Calendario","text":""},{"location":"apex/pages/PAGE_046/#items-2","title":"Items (2)","text":"<ul> <li><code>P46_GIORNO</code></li> <li><code>P46_MAX_EVENTI</code></li> </ul>"},{"location":"apex/pages/PAGE_047/","title":"Page 47 - Permessi","text":""},{"location":"apex/pages/PAGE_047/#items-2","title":"Items (2)","text":"<ul> <li><code>P47_CONSUNTIVI_USERS</code></li> <li><code>P47_GESTORI_USERS</code></li> </ul>"},{"location":"apex/pages/PAGE_052/","title":"Page 52 - send_mail_modal","text":""},{"location":"apex/pages/PAGE_052/#items-6","title":"Items (6)","text":"<ul> <li><code>P52_DATA_FROM</code></li> <li><code>P52_DATA_FROM_DISPLAY</code></li> <li><code>P52_DATA_TO</code></li> <li><code>P52_DATA_TO_DISPLAY</code></li> <li><code>P52_MAIL_BODY</code></li> <li><code>P52_MAIL_SUBJECT</code></li> </ul>"},{"location":"apex/pages/PAGE_053/","title":"Page 53 - COPIA_LISTA_PAGE","text":""},{"location":"apex/pages/PAGE_053/#items-7","title":"Items (7)","text":"<ul> <li><code>P53_COPIA_ACCONTI</code></li> <li><code>P53_COPIA_ALTRICOSTI</code></li> <li><code>P53_COPIA_DEGUSTAZIONI</code></li> <li><code>P53_COPIA_PRELIEVI</code></li> <li><code>P53_COPIA_RISORSE</code></li> <li><code>P53_EVENTO_FROM</code></li> <li><code>P53_EVENTO_TO</code></li> </ul>"},{"location":"apex/pages/PAGE_101/","title":"Page 101 - Login Page","text":""},{"location":"apex/pages/PAGE_101/#items-2","title":"Items (2)","text":"<ul> <li><code>P101_PASSWORD</code></li> <li><code>P101_USERNAME</code></li> </ul>"},{"location":"apex/pages/PAGE_999/","title":"Page 999 - Stampa Preventivo","text":""},{"location":"apex/pages/PAGE_999/#items-3","title":"Items (3)","text":"<ul> <li><code>P999_EVENT_ID</code></li> <li><code>P999_MORE_DETAILS</code></li> <li><code>P999_SHOW_ECONOMICS</code></li> </ul>"},{"location":"apex/processes/","title":"APEX Processes Documentation","text":"<p>This document contains all 98 processes defined in the APEX application, organized by page.</p>"},{"location":"apex/processes/#process-overview","title":"Process Overview","text":"Process Type Count NATIVE_FORM_INIT Multiple NATIVE_FORM_DML Multiple NATIVE_PLSQL Multiple NATIVE_IG_DML Multiple NATIVE_SESSION_STATE Multiple"},{"location":"apex/processes/#shared-application-level-processes","title":"Shared (Application-Level) Processes","text":""},{"location":"apex/processes/#set_user_readonly","title":"SET_USER_READONLY","text":"<p>Process Point: Before Header (runs on every page) Type: NATIVE_PLSQL</p> <p>Sets the <code>APP_READ_ONLY</code> application item based on user permissions.</p> <pre><code>begin\n if F_USER_IN_ROLE(:APP_USER, 'READONLY') then\n :APP_READ_ONLY := 1;\n else\n :APP_READ_ONLY := 0;\n end if;\nend;\n</code></pre>"},{"location":"apex/processes/#page-3-articoli-article-form","title":"Page 3 - Articoli (Article Form)","text":""},{"location":"apex/processes/#fetch-row-from-articoli","title":"Fetch Row from ARTICOLI","text":"<p>Process Point: After Header Type: NATIVE_FORM_INIT</p> <p>Initializes form with article data.</p>"},{"location":"apex/processes/#process-row-of-articoli","title":"Process Row of ARTICOLI","text":"<p>Process Point: After Submit Type: NATIVE_FORM_DML</p> <p>Saves/updates article record.</p>"},{"location":"apex/processes/#delete-image","title":"Delete Image","text":"<p>Process Point: After Submit Type: NATIVE_PLSQL Button: Delete Image</p> <pre><code>begin\n update articoli\n set\n raw_data = null,\n last_update = null,\n charset = null,\n mimetype = null,\n filename = null\n where rowid = :P3_ROWID;\nend;\n</code></pre>"},{"location":"apex/processes/#page-22-nuovo-evento-main-event-form","title":"Page 22 - Nuovo Evento (Main Event Form)","text":"<p>Page 22 is the most complex page with 32 processes.</p>"},{"location":"apex/processes/#after-header-processes","title":"After Header Processes","text":""},{"location":"apex/processes/#get-event-details","title":"Get Event Details","text":"<p>Sequence: 10 Type: NATIVE_FORM_INIT</p> <p>Fetches event record into form items.</p>"},{"location":"apex/processes/#set-ospiti-on-load","title":"Set Ospiti on load","text":"<p>Sequence: 20 Type: NATIVE_PLSQL</p> <pre><code>begin\n EVENTI_AGGIORNA_TOT_OSPITI(:P22_EVENT_ID);\nend;\n</code></pre>"},{"location":"apex/processes/#default-values","title":"Default Values","text":"<p>Sequence: 40 Type: NATIVE_PLSQL</p> <pre><code>begin\n select trim(l.location)\n into :P22_LOCATION_DESCRI\n from eventi e\n join location l on l.id = e.id_location\n where e.id = :P22_EVENT_ID;\nexception when no_data_found then\n null;\nend;\n</code></pre>"},{"location":"apex/processes/#normalizza-dati","title":"Normalizza dati","text":"<p>Sequence: 50 Type: NATIVE_PLSQL</p> <p>Formats time values for display:</p> <pre><code>:P22_ORA_INI_CER := to_char(to_date(:P22_ORA_CERIMONIA, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');\n:P22_ORA_INI_EVENTO := to_char(to_date(:P22_ORA_EVENTO, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');\n:P22_ORA_FI_CER := to_char(to_date(:ORA_FINE_CERIMONIA, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');\n:P22_ORA_FI_EVENTO := to_char(to_date(:ORA_FINE_EVENTO, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');\n</code></pre>"},{"location":"apex/processes/#new-template-default-data","title":"New Template Default Data","text":"<p>Sequence: 60 Condition: P22_IS_TEMPLATE is not null</p> <pre><code>:P22_DATA := sysdate;\n</code></pre>"},{"location":"apex/processes/#after-submit-processes","title":"After Submit Processes","text":""},{"location":"apex/processes/#set-date-default-if-template","title":"Set Date Default if Template","text":"<p>Sequence: 10 Condition: P22_IS_TEMPLATE is not null</p> <pre><code>:P22_DATA := sysdate;\n</code></pre>"},{"location":"apex/processes/#delete-template","title":"Delete Template","text":"<p>Sequence: 20 Button: Delete Template Condition: P22_IS_TEMPLATE is not null</p> <pre><code>delete from eventi where id = :P22_EVENT_ID;\n</code></pre>"},{"location":"apex/processes/#genera-evento-da-template","title":"Genera Evento da Template","text":"<p>Sequence: 30 Button: Generate from Template Condition: P22_IS_TEMPLATE is not null</p> <pre><code>EVENTI_COPIA\n(\n ID_EVENTO_OLD =&gt; :P22_EVENT_ID,\n NUOVA_VERSIONE =&gt; 0,\n ID_EVENTO_NEW =&gt; :P22_EVENT_ID\n);\n</code></pre>"},{"location":"apex/processes/#formatta-ore-inizio","title":"Formatta Ore Inizio","text":"<p>Sequence: 40</p> <p>Combines date and time for storage:</p> <pre><code>:P22_ORA_EVENTO := :P22_DATA || ' ' || :P22_ORA_INI_EVENTO;\n:P22_ORA_CERIMONIA := :P22_DATA || ' ' || :P22_ORA_INI_CER;\n</code></pre>"},{"location":"apex/processes/#prepara-acconti-automatici","title":"Prepara Acconti Automatici","text":"<p>Sequence: 50 Condition: REQUEST in ('PREPARA_ACCONTI', 'PRINT_PREVENTIVO')</p> <pre><code>EVENTI_RICALCOLA_ACCONTI(p_event_id =&gt; :P22_EVENT_ID);\n</code></pre> <p>Comment: Default 3 deposits: 30%, 50%, 20%</p>"},{"location":"apex/processes/#go-forward","title":"Go Forward","text":"<p>Sequence: 60 Button: NEXT</p> <p>Navigates to next wizard step:</p> <pre><code>declare\n v_step number;\nbegin\n begin\n select min(cod_step)\n into v_step\n from tb_tipi_mat\n where cod_step &gt; TO_NUMBER(:P22_STEP);\n end;\n\n begin\n select cod_tipo\n into :P22_COD_TIPO_FILTER\n from tb_tipi_mat\n where cod_step = v_step;\n exception when no_data_found\n then raise_application_error(-20001, 'Errore sconosciuto');\n end;\n\n :P22_STEP := v_step;\nend;\n</code></pre>"},{"location":"apex/processes/#go-backward","title":"Go Backward","text":"<p>Sequence: 70 Button: PREVIOUS</p> <p>Navigates to previous wizard step.</p>"},{"location":"apex/processes/#tipo-ospiti-save-interactive-grid-data","title":"Tipo Ospiti - Save Interactive Grid Data","text":"<p>Sequence: 80 Region: Guest Types Grid Type: NATIVE_IG_DML Condition: APP_READ_ONLY = 0</p> <p>Saves guest type records.</p>"},{"location":"apex/processes/#tipo-ospiti-aggiorna-lista-prelievo","title":"Tipo Ospiti - Aggiorna Lista Prelievo","text":"<p>Sequence: 90 Type: NATIVE_PLSQL Condition: APP_READ_ONLY = 0</p> <p>Recalculates pick list quantities after guest changes:</p> <pre><code>EVENTI_AGGIORNA_QTA_LISTA(\n P_ID_EVENTO =&gt; :P22_EVENT_ID\n);\n</code></pre>"},{"location":"apex/processes/#degustazioni-save-interactive-grid-data","title":"Degustazioni - Save Interactive Grid Data","text":"<p>Sequence: 100 Region: Tastings Grid Type: NATIVE_IG_DML</p>"},{"location":"apex/processes/#delete-eventi-childs","title":"Delete Eventi Childs","text":"<p>Sequence: 110 Button: DELETE Condition: NEVER (disabled)</p> <pre><code>begin\n delete from eventi_det_ospiti\n where id_evento = :P22_EVENT_ID;\n\n delete from eventi_det_prel\n where id_evento = :P22_EVENT_ID;\n\n delete from eventi_det_ris\n where id_evento = :P22_EVENT_ID;\n\n delete from eventi_det_degust\n where id_evento = :P22_EVENT_ID;\nend;\n</code></pre>"},{"location":"apex/processes/#set-obsoleto","title":"Set Obsoleto","text":"<p>Sequence: 120 Button: Set Obsolete Condition: APP_READ_ONLY = 0</p> <p>Marks event as expired/cancelled:</p> <pre><code>begin\n UPDATE EVENTI\n SET FLG_SUPERATO = 1, STATO = 900, MAIL_ENABLED = 0\n WHERE ID = :P22_EVENT_ID;\nend;\n</code></pre>"},{"location":"apex/processes/#salva-evento","title":"Salva Evento","text":"<p>Sequence: 130 Condition: Complex (handles CREATE, SAVE, DELETE)</p> <p>Main event save process. Full implementation handles: - All event fields mapping - Email validation - Status-based logic - Versioning support - Soft delete</p> <p>Key excerpts:</p> <pre><code>declare\n r_eventi eventi%rowtype;\nbegin\n if :REQUEST = 'PREVIOUS' or :REQUEST = 'NEXT'\n then\n return;\n end if;\n\n if(:P22_DATA is null)\n then\n raise_application_error(-20001, 'Inserire la data evento');\n end if;\n\n -- Set all row fields\n r_eventi.\"ID\" := :P22_EVENT_ID;\n r_eventi.DESCRIZIONE := :P22_DESCRIZIONE;\n r_eventi.COD_TIPO := :P22_COD_TIPO;\n -- ... (all other fields)\n\n -- Email validation\n IF REGEXP_LIKE(:P22_CLIENTE_EMAIL, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$') \n OR :P22_CLIENTE_EMAIL IS NULL THEN\n r_eventi.CLIENTE_EMAIL := :P22_CLIENTE_EMAIL;\n ELSE\n RAISE_APPLICATION_ERROR(-20005, 'Formato email cliente non valido');\n END IF;\n\n -- Versioning\n r_eventi.VERS_NUMBER := nvl(:P22_VERS_NUMBER, 0);\n r_eventi.VERS_TOKEN := :P22_VERS_TOKEN;\n\n case :REQUEST\n when 'SAVE' then\n update eventi set row = r_eventi where id = :P22_EVENT_ID;\n when 'CREATE' then\n insert into eventi values r_eventi returning id into :P22_EVENT_ID;\n when 'DELETE' then\n if r_eventi.ID_EVT_FIGLIO is not null or r_eventi.ID_EVT_PADRE is not null\n then\n raise_application_error(-20001, 'Impossibile eliminare un evento...');\n end if;\n update eventi\n set deleted = 1,\n deleted_by = :APP_USER,\n deleted_date = sysdate\n where id = r_eventi.\"ID\";\n else\n null;\n end case;\nend;\n</code></pre>"},{"location":"apex/processes/#nuova-versione","title":"Nuova Versione","text":"<p>Sequence: 140 Button: New Version</p> <p>Creates a new version of the event:</p> <pre><code>EVENTI_COPIA\n(\n ID_EVENTO_OLD =&gt; :P22_EVENT_ID,\n NUOVA_VERSIONE =&gt; 1,\n ID_EVENTO_NEW =&gt; :P22_NEW_EVENT_ID\n);\n</code></pre>"},{"location":"apex/processes/#lista-prelievo-save-interactive-grid-data","title":"Lista Prelievo - Save Interactive Grid Data","text":"<p>Sequence: 150 Type: NATIVE_IG_DML Table: EVENTI_DET_PREL</p> <p>Saves pick list records.</p>"},{"location":"apex/processes/#continue-event","title":"Continue Event","text":"<p>Sequence: 160 Button: Continue</p> <p>Advances event to \"Confermata\" status (300):</p> <pre><code>declare\n v_count number;\n v_count_evt number;\nbegin\n -- Check if confirmed event exists for same location/date\n select count(*) into v_count\n from eventi\n where data = (select data from eventi where id = :P22_EVENT_ID)\n and stato = 300\n and id_location = (select id_location from eventi where id = :P22_EVENT_ID); \n\n if v_count &gt; 0 then \n raise_application_error(-20001, 'Esiste un evento Confermato per la location - Impossibile proseguire'); \n return;\n end if;\n\n -- Update status\n update eventi\n set stato = 300 \n where id = :P22_EVENT_ID;\n\n -- Check total confirmed events for date\n select count(*) into v_count_evt\n from eventi\n where data = (select data from eventi where id = :P22_EVENT_ID)\n and stato = 300; \n\n if v_count_evt &gt; 6 then \n RAISE_APPLICATION_ERROR(-20000, 'Ci sono gi\u00e0 6 eventi Confermati per la data'); \n end if; \nend;\n</code></pre>"},{"location":"apex/processes/#almost-continue-event","title":"Almost Continue Event","text":"<p>Sequence: 170 Button: Almost Continue</p> <p>Sets status to \"Quasi Confermato\" (350):</p> <pre><code>begin\n update eventi\n set stato = 350 \n where id = :P22_EVENT_ID;\nend;\n</code></pre>"},{"location":"apex/processes/#confirm-event","title":"Confirm Event","text":"<p>Sequence: 180 Button: Confirm Condition: APP_READ_ONLY = 0</p> <p>Final confirmation (status 400) and cancels competing events:</p> <pre><code>begin\n update eventi\n set stato = 400\n where id = :P22_EVENT_ID;\n\n -- Cancel events with same date and location\n p_cancel_same_location_events(\n p_good_event_id =&gt; :P22_EVENT_ID\n );\nend;\n</code></pre>"},{"location":"apex/processes/#unconfirm-event","title":"Unconfirm Event","text":"<p>Sequence: 190 Button: Unconfirm</p> <p>Returns event to initial status (100):</p> <pre><code>begin\n update eventi\n set stato = 100\n where id = :P22_EVENT_ID;\nend;\n</code></pre>"},{"location":"apex/processes/#reopen-event","title":"Reopen Event","text":"<p>Sequence: 200 Button: Reopen</p> <p>Clears the expired flag:</p> <pre><code>begin\n update eventi\n set flg_superato = 0\n where id = :P22_EVENT_ID;\nend;\n</code></pre>"},{"location":"apex/processes/#return-to-preparazione","title":"Return to Preparazione","text":"<p>Sequence: 210 Button: Return to Preparation</p> <p>Sets status back to preparation (200):</p> <pre><code>begin\n update eventi\n set stato = 200\n where id = :P22_EVENT_ID;\nend;\n</code></pre>"},{"location":"apex/processes/#risorse-save-interactive-grid-data","title":"Risorse - Save Interactive Grid Data","text":"<p>Sequence: 220 Type: NATIVE_IG_DML</p> <p>Saves resource assignments.</p>"},{"location":"apex/processes/#aggiorna-qta-lista","title":"Aggiorna QTA Lista","text":"<p>Sequence: 230 Condition: APP_READ_ONLY = 0 AND REQUEST = 'AGGIORNA_QTA'</p> <p>Manual quantity recalculation:</p> <pre><code>EVENTI_AGGIORNA_QTA_LISTA(\n P_ID_EVENTO =&gt; :P22_EVENT_ID\n);\n</code></pre>"},{"location":"apex/processes/#restore-deleted-event","title":"Restore Deleted Event","text":"<p>Sequence: 240</p> <p>Restores soft-deleted event.</p>"},{"location":"apex/processes/#event-status-workflow-summary","title":"Event Status Workflow Summary","text":"Status Code Status Name Italian Next Action 100 Preventivo Quote Continue Event \u2192 300 200 Scheda Preparation - 300 Confermata Confirmed (Pending) Almost Continue \u2192 350 350 Quasi Almost Confirmed Confirm \u2192 400 400 Confermato Confirmed - 900 Superato Expired/Cancelled Reopen \u2192 clears flag"},{"location":"apex/processes/#common-process-patterns","title":"Common Process Patterns","text":""},{"location":"apex/processes/#read-only-check","title":"Read-Only Check","text":"<p>All write processes include this condition: <pre><code>:APP_READ_ONLY = 0\n</code></pre></p>"},{"location":"apex/processes/#error-handling","title":"Error Handling","text":"<p>Standard error pattern: <pre><code>exception when no_data_found then\n raise_application_error(-20001, 'Error message in Italian');\n</code></pre></p>"},{"location":"apex/processes/#interactive-grid-save","title":"Interactive Grid Save","text":"<p>Standard IG DML process: - Type: NATIVE_IG_DML - Attributes: REGION_SOURCE, Allow Insert (Y), Allow Update (Y), Allow Delete (Y)</p>"},{"location":"apex/processes/#migration-notes","title":"Migration Notes","text":"<p>When migrating these processes to .NET:</p> <ol> <li>Form Initialization - Use API endpoints to fetch entity data</li> <li>Form DML - Implement CRUD endpoints with proper validation</li> <li>Custom PL/SQL - Convert to C# methods or stored procedures</li> <li>IG DML - Implement batch update endpoints for grid data</li> <li>Session State - Use application state management (Redux, Context)</li> <li>Validation - Implement in both frontend and backend</li> <li>Workflow - Consider state machine pattern for event status</li> </ol>"},{"location":"functions/","title":"Funzioni Database","text":"<p>Questa cartella contiene la documentazione di tutte le 23 funzioni del database.</p>"},{"location":"functions/#funzioni-calcolo-quantita-e-disponibilita","title":"Funzioni Calcolo Quantit\u00e0 e Disponibilit\u00e0","text":"Funzione Ritorno Descrizione F_GET_QTA_IMPEGNATA NUMBER Quantit\u00e0 impegnata di un articolo in un range di date F_GET_TOT_OSPITI NUMBER Totale ospiti per evento (opzionale per tipo) F_GET_OSPITI TABLE Dettaglio ospiti per evento (funzione pipelined) F_LIST_PRELIEVO_ADD_ARTICOLO VARCHAR2 (JSON) Aggiunge articolo alla lista prelievo con validazioni"},{"location":"functions/#funzioni-calcolo-costi","title":"Funzioni Calcolo Costi","text":"Funzione Ritorno Descrizione F_GET_COSTO_ARTICOLO NUMBER Costo unitario articolo a una data specifica"},{"location":"functions/#funzioni-validazione","title":"Funzioni Validazione","text":"Funzione Ritorno Descrizione F_EVENTO_SCADUTO NUMBER (0/1) Verifica se preventivo \u00e8 scaduto F_MAX_NUMERO_EVENTI_RAGGIUNTO NUMBER (-1/0/1) Verifica limite eventi giornaliero F_MAX_NUM_EVENTI_CONFERMATI NUMBER (0/1) Verifica limite eventi confermati F_CI_SONO_EVENTI_CONFERMATI NUMBER (0/1) Check esistenza eventi confermati in data/location"},{"location":"functions/#funzioni-report","title":"Funzioni Report","text":"Funzione Ritorno Descrizione F_REP_ALLESTIMENTI TABLE Dati per report allestimenti (pipelined) F_REP_CUCINA TABLE Dati per report cucina (pipelined) F_GET_ANGOLO_ALLESTIMENTO VARCHAR2 Descrizione angolo allestimento F_GET_ANGOLO_ALLESTIMENTO_OB VARCHAR2 Descrizione angolo open bar F_GET_TOVAGLIATO_ALLESTIMENTO VARCHAR2 Descrizione tovagliato"},{"location":"functions/#funzioni-autorizzazione","title":"Funzioni Autorizzazione","text":"Funzione Ritorno Descrizione F_USER_IN_ROLE NUMBER (0/1) Verifica appartenenza utente a ruolo F_USER_IN_ROLE_STR VARCHAR2 Verifica ruolo (ritorna stringa)"},{"location":"functions/#funzioni-utility","title":"Funzioni Utility","text":"Funzione Ritorno Descrizione F_DAY_TO_NAME VARCHAR2 Converte numero giorno in nome italiano STRING_TO_TABLE_ENUM TABLE Converte stringa delimitata in tabella GET_PARAM_VALUE VARCHAR2 Recupera valore parametro da TB_CONFIG SPLIT TABLE Split stringa in elementi MY_INSTR NUMBER Funzione INSTR personalizzata CLOB2BLOB BLOB Conversione CLOB \u2192 BLOB EXTDATE_GET_ITA VARCHAR2 Formatta data in italiano esteso"},{"location":"functions/#dettaglio-funzioni-critiche","title":"Dettaglio Funzioni Critiche","text":""},{"location":"functions/#f_get_qta_impegnata","title":"F_GET_QTA_IMPEGNATA","text":"<pre><code>FUNCTION F_GET_QTA_IMPEGNATA(\n p_codart VARCHAR2,\n p_data_from DATE,\n p_data_to DATE DEFAULT NULL\n) RETURN NUMBER\n</code></pre> <p>Logica: - Interroga <code>V_IMPEGNI_ARTICOLI</code> - Somma quantit\u00e0 impegnate nel range di date - Se <code>p_data_to</code> \u00e8 NULL, usa <code>p_data_from</code></p>"},{"location":"functions/#f_event0_scaduto","title":"F_EVENT0_SCADUTO","text":"<pre><code>FUNCTION F_EVENTO_SCADUTO(\n DATA_SCADENZA IN DATE,\n STATO_EVENTO IN NUMBER,\n STATO_FROM IN NUMBER,\n STATO_TO IN NUMBER\n) RETURN NUMBER\n</code></pre> <p>Logica: - Ritorna 1 se <code>TRUNC(DATA_SCADENZA) &lt;= TRUNC(SYSDATE)</code> AND <code>STATO_EVENTO BETWEEN STATO_FROM AND STATO_TO</code> - Altrimenti ritorna 0</p>"},{"location":"functions/#f_list_prelievo_add_articolo","title":"F_LIST_PRELIEVO_ADD_ARTICOLO","text":"<pre><code>FUNCTION F_LIST_PRELIEVO_ADD_ARTICOLO(\n p_event_id NUMBER,\n p_articolo_add VARCHAR2,\n p_qta_aperitivo NUMBER := 0,\n p_qta_seduto NUMBER := 0,\n p_qta_dolci NUMBER := 0\n) RETURN VARCHAR2\n</code></pre> <p>Logica: 1. Verifica esistenza evento 2. Verifica esistenza articolo 3. Recupera giacenza articolo 4. Controlla impegni in date vicine (\u00b12 giorni) 5. Inserisce record in <code>EVENTI_DET_PREL</code> 6. Chiama <code>EVENTI_AGGIORNA_QTA_LISTA</code> 7. Ritorna JSON con esito: - <code>{\"type\":\"success\",\"message\":\"...\"}</code> - <code>{\"type\":\"warning\",\"message\":\"...\"}</code> - <code>{\"type\":\"error\",\"code\":\"...\",\"stack\":\"...\",\"message\":\"...\"}</code></p>"},{"location":"functions/#f_get_costo_articolo","title":"F_GET_COSTO_ARTICOLO","text":"<pre><code>FUNCTION F_GET_COSTO_ARTICOLO(\n p_cod_articolo VARCHAR2,\n p_date DATE\n) RETURN NUMBER\n</code></pre> <p>Logica: 1. Cerca costo in <code>COSTI_ARTICOLI</code> alla data esatta 2. Se non trovato, prende ultimo costo disponibile 3. Se non trovato nulla, ritorna 0</p>"},{"location":"functions/CLOB2BLOB/","title":"CLOB2BLOB","text":""},{"location":"functions/CLOB2BLOB/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>FUNCTION \"CLOB2BLOB\" (AClob CLOB) return BLOB is\n Result BLOB;\n o1 integer;\n o2 integer;\n c integer;\n w integer;\nbegin\n o1 := 1;\n o2 := 1;\n c := 0;\n w := 0;\n DBMS_LOB.CreateTemporary(Result, true);\n DBMS_LOB.ConvertToBlob(Result, AClob, length(AClob), o1, o2, 0, c, w);\n return(Result);\nend clob2blob;\n</code></pre>"},{"location":"functions/EXTDATE_GET_ITA/","title":"EXTDATE_GET_ITA","text":""},{"location":"functions/EXTDATE_GET_ITA/#codice-sorgente","title":"Codice Sorgente","text":"<p><code>sql function extdate_get_ita( p_date date ) return varchar2 as begin return REGEXP_REPLACE(TO_CHAR(p_date, 'Day dd Month yyyy', 'NLS_DATE_LANGUAGE = ITALIAN'), ' [ ]+', ' '); end;</code></p>"},{"location":"functions/F_CI_SONO_EVENTI_CONFERMATI/","title":"F_CI_SONO_EVENTI_CONFERMATI","text":""},{"location":"functions/F_CI_SONO_EVENTI_CONFERMATI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION F_CI_SONO_EVENTI_CONFERMATI ( P_EVT_DATE IN DATE , P_LOCATION_ID IN NUMBER , P_BYPASS IN NUMBER ) RETURN NUMBER AS </p> <pre><code>v_evt_cnt number;\n</code></pre> <p>BEGIN</p> <pre><code>-- function bypass\nif P_BYPASS &gt; 0 then\n return 0;\nend if;\n\nselect\ncount(e.id) as evt_cnt\ninto v_evt_cnt\nfrom eventi e\njoin vw_event_color c on c.id = e.id\nwhere e.data = P_EVT_DATE\nand e.id_location = P_LOCATION_ID\nand c.status = 'Confermato';\n\nif v_evt_cnt &gt; 0 then\n return 1;\nelse\n return 0;\nend if;\n</code></pre> <p>END F_CI_SONO_EVENTI_CONFERMATI;```</p>"},{"location":"functions/F_DAY_TO_NAME/","title":"F_DAY_TO_NAME","text":""},{"location":"functions/F_DAY_TO_NAME/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION F_DAY_TO_NAME ( DAY_NUMBER IN NUMBER ) RETURN VARCHAR2 AS v_day_number number := DAY_NUMBER; v_language varchar2(255); BEGIN with t as ( select DECODE(parameter, 'NLS_CHARACTERSET', 'CHARACTER SET', 'NLS_LANGUAGE', 'LANGUAGE', 'NLS_TERRITORY', 'TERRITORY') name, value from v$nls_parameters WHERE parameter IN ( 'NLS_CHARACTERSET', 'NLS_LANGUAGE', 'NLS_TERRITORY') ) select value into v_language from t where name = 'LANGUAGE';</p> <pre><code>if v_language = 'AMERICAN' then\n case v_day_number\n when 1 then return 'Domenica';\n when 2 then return 'Luned\u00ec';\n when 3 then return 'Marted\u00ec';\n when 4 then return 'Mercoled\u00ec';\n when 5 then return 'Gioved\u00ec';\n when 6 then return 'Venerd\u00ec';\n when 7 then return 'Sabato';\n end case;\nelse\n case v_day_number\n when 1 then return 'Luned\u00ec';\n when 2 then return 'Marted\u00ec';\n when 3 then return 'Mercoled\u00ec';\n when 4 then return 'Gioved\u00ec';\n when 5 then return 'Venerd\u00ec';\n when 6 then return 'Sabato';\n when 7 then return 'Domenica';\n end case;\nend if;\n</code></pre> <p>END F_DAY_TO_NAME;```</p>"},{"location":"functions/F_EVENTO_SCADUTO/","title":"F_EVENTO_SCADUTO","text":""},{"location":"functions/F_EVENTO_SCADUTO/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>FUNCTION F_EVENTO_SCADUTO\n(\n DATA_SCADENZA IN DATE,\n STATO_EVENTO IN NUMBER,\n STATO_FROM IN NUMBER,\n STATO_TO IN NUMBER\n) RETURN NUMBER AS \nBEGIN\n if trunc(DATA_SCADENZA) &lt;= trunc(sysdate)\n and STATO_EVENTO between STATO_FROM and STATO_TO\n then\n return 1;\n else\n return 0;\n end if;\nEND F_EVENTO_SCADUTO;\n</code></pre>"},{"location":"functions/F_GET_ANGOLO_ALLESTIMENTO/","title":"F_GET_ANGOLO_ALLESTIMENTO","text":""},{"location":"functions/F_GET_ANGOLO_ALLESTIMENTO/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_GET_ANGOLO_ALLESTIMENTO\" ( p_filtro VARCHAR2, p_id NUMBER ) RETURN VARCHAR2 AS</p> <pre><code>TYPE ref_cur IS REF CURSOR;\nc_data ref_cur;\nv_val VARCHAR2(1000);\nv_filtro VARCHAR2(100);\nv_id NUMBER;\n</code></pre> <p>BEGIN v_filtro := p_filtro; v_id := p_id; OPEN c_data FOR ' select substr(a.descrizione || '' - '' || p.note ,1,1000) from eventi e left join location l on e.id_location = l.id join eventi_det_prel p on e.id=p.id_evento join articoli a on p.cod_articolo=a.cod_articolo where p.COD_ARTICOLO = :filtro -- AN-GELAT and e.id = to_number(:id)' USING v_filtro, v_id;</p> <pre><code>FETCH c_data INTO v_val;\nCLOSE c_data;\nRETURN v_val;\n</code></pre> <p>END;```</p>"},{"location":"functions/F_GET_ANGOLO_ALLESTIMENTO_OB/","title":"F_GET_ANGOLO_ALLESTIMENTO_OB","text":""},{"location":"functions/F_GET_ANGOLO_ALLESTIMENTO_OB/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_GET_ANGOLO_ALLESTIMENTO_OB\" ( p_filtro VARCHAR2, p_id NUMBER ) RETURN VARCHAR2 --ANGOLI OPEN BAR AS</p> <pre><code>TYPE ref_cur IS REF CURSOR;\nc_data ref_cur;\nv_val VARCHAR2(1000);\nv_filtro VARCHAR2(100);\nv_id NUMBER;\n</code></pre> <p>BEGIN v_filtro := p_filtro; v_id := p_id; OPEN c_data FOR ' select substr(a.descrizione || '' - '' || p.note ,1,1000) from eventi e left join location l on e.id_location = l.id join eventi_det_prel p on e.id=p.id_evento join articoli a on p.cod_articolo=a.cod_articolo where a.cod_categ = ''AN-FIN'' and a.descrizione like :filtro -- AN-GELAT and e.id = to_number(:id)' USING v_filtro, v_id;</p> <pre><code>FETCH c_data INTO v_val;\nCLOSE c_data;\nRETURN v_val;\n</code></pre> <p>END;```</p>"},{"location":"functions/F_GET_COSTO_ARTICOLO/","title":"F_GET_COSTO_ARTICOLO","text":""},{"location":"functions/F_GET_COSTO_ARTICOLO/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>function f_get_costo_articolo(p_cod_articolo varchar2, p_date date)\nreturn number\nas\n v_costo number := null;\nbegin\n\n -- Cerco il costo alla data\n begin\n SELECT a.costo_uni\n into v_costo\n FROM COSTI_ARTICOLI a\n where a.data_costo = p_date\n and a.cod_articolo = p_cod_articolo;\n exception when no_data_found then\n v_costo := null;\n end;\n\n -- Se non lo trovo prendo l'ultimo costo\n begin\n SELECT a.costo_uni\n into v_costo\n FROM COSTI_ARTICOLI a\n WHERE a.DATA_COSTO = (SELECT max(b.DATA_COSTO) FROM COSTI_ARTICOLI b where b.cod_articolo = a.cod_articolo)\n and a.cod_articolo = p_cod_articolo;\n exception when no_data_found then\n v_costo := null;\n end;\n\n -- se non trovo niente torno 0\n return nvl(v_costo, 0);\nend;\n</code></pre>"},{"location":"functions/F_GET_OSPITI/","title":"F_GET_OSPITI","text":""},{"location":"functions/F_GET_OSPITI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_GET_OSPITI\" ( p_id_evento IN NUMBER ) RETURN t_det_ospiti_tab PIPELINED AS</p> <pre><code>v_data DATE;\nv_location VARCHAR2(100);\nv_cliente VARCHAR2(100);\nv_descrizione VARCHAR2(100);\nv_ora_cerimonia VARCHAR2(10);\nv_ora_evento VARCHAR2(10);\nv_tot_adulti NUMBER;\nv_tot_kinder NUMBER;\nv_tot_baby NUMBER;\nv_tot_staff NUMBER;\nv_tot_invitati NUMBER;\nv_allergie VARCHAR2(4000);\nv_torta VARCHAR2(1000);\nv_confettata VARCHAR2(100);\nv_stampa_menu VARCHAR2(100);\nv_angoli VARCHAR2(1000);\nv_extra_info VARCHAR2(1000);\nv_note_adulti VARCHAR2(1000);\nv_note_kinder VARCHAR2(1000);\nv_note_baby VARCHAR2(1000);\nv_note_staff VARCHAR2(1000);\n</code></pre> <p>BEGIN BEGIN v_tot_adulti := 0; v_tot_kinder := 0; v_tot_baby := 0; v_tot_staff := 0; v_tot_invitati := 0; v_angoli := 0; v_note_adulti := ''; v_note_kinder := ''; v_note_baby := ''; v_note_staff := ''; </p> <pre><code> --ospiti\n SELECT\n nvl(SUM(o.numero),\n 0)\n INTO v_tot_adulti\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 8; -- adulti\n\n BEGIN\n SELECT\n o.note\n INTO v_note_adulti\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 8; -- adulti\n\n EXCEPTION\n WHEN no_data_found THEN\n NULL;\n END;\n\n SELECT\n nvl(SUM(o.numero),\n 0)\n INTO v_tot_kinder\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 5; --Kinder\n\n BEGIN\n SELECT\n o.note\n INTO v_note_kinder\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 5; --Kinder\n\n EXCEPTION\n WHEN no_data_found THEN\n NULL;\n END;\n\n SELECT\n nvl(SUM(o.numero),\n 0)\n INTO v_tot_baby\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 6; -- Baby\n\n BEGIN\n SELECT\n o.note\n INTO v_note_baby\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 6; -- Baby\n\n EXCEPTION\n WHEN no_data_found THEN\n NULL;\n END;\n\n SELECT\n nvl(SUM(o.numero),\n 0)\n INTO v_tot_staff\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 7; -- Staff\n\n BEGIN\n SELECT\n o.note\n INTO v_note_staff\n FROM\n eventi_det_ospiti o\n WHERE\n o.id_evento = p_id_evento\n AND o.cod_tipo_ospite = 7; -- Staff\n\n EXCEPTION\n WHEN no_data_found THEN\n NULL;\n END;\n\n SELECT\n nvl(e.tot_ospiti, 0)\n INTO v_tot_invitati\n FROM\n eventi e\n WHERE\n e.id = p_id_evento;\n\n PIPE ROW ( t_det_ospiti_row(p_id_evento, v_tot_adulti, v_tot_kinder, v_tot_baby, v_tot_staff,\n v_tot_invitati, v_note_adulti, v_note_kinder, v_note_baby, v_note_staff) );\n\nEXCEPTION\n WHEN OTHERS THEN\n NULL;\nEND;\n\nRETURN;\n</code></pre> <p>END;```</p>"},{"location":"functions/F_GET_QTA_IMPEGNATA/","title":"F_GET_QTA_IMPEGNATA","text":""},{"location":"functions/F_GET_QTA_IMPEGNATA/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_GET_QTA_IMPEGNATA\" ( p_codart VARCHAR2, p_data_from DATE, p_data_to DATE DEFAULT NULL ) RETURN NUMBER AS v_qta NUMBER; v_data_to DATE := p_data_to; BEGIN v_qta := 0; IF ( p_data_to IS NULL ) THEN v_data_to := p_data_from; END IF; BEGIN SELECT nvl(SUM(qta_imp), 0) INTO v_qta FROM v_impegni_articoli WHERE cod_articolo = p_codart --and data &lt;= p_data -- AND data BETWEEN p_data_from AND v_data_to; -- qta impegnata per quella data</p> <pre><code>EXCEPTION\n WHEN OTHERS THEN\n v_qta := 0;\nEND;\n\nRETURN v_qta;\n</code></pre> <p>END;```</p>"},{"location":"functions/F_GET_TOT_OSPITI/","title":"F_GET_TOT_OSPITI","text":""},{"location":"functions/F_GET_TOT_OSPITI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_GET_TOT_OSPITI\" ( p_id_evento IN NUMBER, p_tipo_ospite IN NUMBER := -1 ) RETURN NUMBER AS v_tot NUMBER; BEGIN v_tot := 0; BEGIN SELECT nvl(SUM(numero), 0) INTO v_tot FROM eventi_det_ospiti WHERE id_evento = p_id_evento AND ( cod_tipo_ospite = p_tipo_ospite OR p_tipo_ospite = - 1 );</p> <pre><code>EXCEPTION\n WHEN OTHERS THEN\n v_tot := 0;\nEND;\n\nRETURN v_tot;\n</code></pre> <p>END;```</p>"},{"location":"functions/F_GET_TOVAGLIATO_ALLESTIMENTO/","title":"F_GET_TOVAGLIATO_ALLESTIMENTO","text":""},{"location":"functions/F_GET_TOVAGLIATO_ALLESTIMENTO/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_GET_TOVAGLIATO_ALLESTIMENTO\" ( p_filtro VARCHAR2, p_id NUMBER ) RETURN VARCHAR2 AS</p> <pre><code>TYPE ref_cur IS REF CURSOR;\nc_data ref_cur;\nv_val VARCHAR2(1000);\nv_filtro VARCHAR2(100);\nv_id NUMBER;\n</code></pre> <p>BEGIN v_filtro := p_filtro; v_id := p_id; OPEN c_data FOR ' select substr(a.descrizione || '' - '' || p.note ,1,1000) as dato from eventi e left join location l on e.id_location = l.id join eventi_det_prel p on e.id=p.id_evento join articoli a on p.cod_articolo=a.cod_articolo join TB_CODICI_CATEG c on a.cod_categ=c.cod_categ --where c.COD_TIPO = ''TVB'' -- dividere tovagliolo da tovagliato con i codici categ where c.COD_TIPO = :filtro and rownum = 1 -- se esistono pi\u00f9 articoli fare list_agg op loop and e.id = to_number(:id)' USING v_filtro, v_id;</p> <pre><code>FETCH c_data INTO v_val;\nCLOSE c_data;\nRETURN v_val;\n</code></pre> <p>END;```</p>"},{"location":"functions/F_LIST_PRELIEVO_ADD_ARTICOLO/","title":"F_LIST_PRELIEVO_ADD_ARTICOLO","text":""},{"location":"functions/F_LIST_PRELIEVO_ADD_ARTICOLO/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql function f_list_prelievo_add_articolo( p_event_id number, p_articolo_add varchar2, p_qta_aperitivo NUMBER := 0, p_qta_seduto NUMBER := 0, p_qta_dolci NUMBER := 0 ) return varchar2 as v_qta_imp number; v_qta_giac number; v_data_evento date; v_cod_art varchar2(10); v_error_json varchar2(4000); v_qta_da_imp NUMBER; v_qta_da_imp_test NUMBER; v_num_evt_imp number; BEGIN</p> <pre><code>v_cod_art := p_articolo_add;\nv_qta_da_imp := nvl(p_qta_aperitivo, 0) + nvl(p_qta_seduto, 0) + nvl(p_qta_dolci, 0);\n\nbegin\n\n select trunc(data) as data\n into v_data_evento\n from eventi where id = p_event_id;\n exception when no_data_found then\n rollback;\n RETURN '{\"type\":\"error\",\"code\":\"'||SQLCODE||'\",\"stack\":\"'||SQLERRM||'\",\"message\":\"Evento non trovato\"}';\nend;\nbegin\n select qta_giac \n into v_qta_giac\n from articoli\n where COD_ARTICOLO = v_cod_art; \n exception when no_data_found then\n rollback;\n RETURN '{\"type\":\"error\",\"code\":\"'||SQLCODE||'\",\"stack\":\"'||SQLERRM||'\",\"message\":\"Articolo non trovato\"}';\nend;\n\n\nselect count(*) \ninto v_num_evt_imp\nfrom V_IMPEGNI_ARTICOLI\nwhere COD_ARTICOLO = v_cod_art\n and data between v_data_evento - 2 and v_data_evento + 2;\n\nv_qta_imp := nvl(f_get_qta_impegnata (v_cod_art, v_data_evento - 2, v_data_evento + 2 ) , 0);\n\n--insert impegno articolo\nbegin \n insert into eventi_det_prel (id_evento, cod_articolo,QTA_MAN_APE,QTA_MAN_SEDU,QTA_MAN_BUFDOL, COSTO_ARTICOLO)\n values (p_event_id, p_articolo_add, p_qta_aperitivo, p_qta_seduto, p_qta_dolci, f_get_costo_articolo(v_cod_art, v_data_evento));\n\n -- aggiorna liste prelievo\n EVENTI_AGGIORNA_QTA_LISTA(\n P_ID_EVENTO =&gt; p_event_id\n );\n\n -- Controlla banalmente se sono stati prelevati su altri eventi\n if v_qta_imp + v_qta_da_imp &gt; v_qta_giac then\n RETURN '{\"type\":\"warning\",\"message\":\"Attenzione: Non hai abbastanza articoli di questo tipo a magazzino\"}';\n end if;\n\n -- Se trovo articoli gi\u00e0 impegnati in quel giorno mostro un messaggio - 16/11/2022\n -- Continuo lo stesso ma do un messaggio di errore anzich\u00e8 di successo\n if(v_qta_imp &gt; 0 and v_num_evt_imp &gt; 0) then\n RETURN '{\"type\":\"warning\",\"code\":\"'||SQLCODE||'\",\"stack\":\"'||SQLERRM||'\",\"message\":\"Attenzione! Articolo '||p_articolo_add||' gi\u00e0 impegnato '||v_num_evt_imp||' '||(case when v_num_evt_imp &gt; 1 then 'volte' else 'volta' end)||' dal '||to_char(v_data_evento - 2, 'dd-mm-yyyy')||' al '||to_char(v_data_evento + 2, 'dd-mm-yyyy')||'\"}';\n end if;\n\n RETURN '{\"type\":\"success\",\"message\":\"Articolo aggiunto con successo\"}';\nexception when others then\n RETURN '{\"type\":\"success\",\"message\":\"Articolo aggiunto con errori: '||replace(replace(SQLERRM, 'ORA-20000: Errore:', ''), '-20000 - ', '')||'\"}';\nend;\n\nrollback;\nreturn '{\"type\":\"error\",\"code\":\"\",\"stack\":\"\",\"message\":\"Errore sconosciuto\"}';\n</code></pre> <p>end f_list_prelievo_add_articolo;```</p>"},{"location":"functions/F_MAX_NUMERO_EVENTI_RAGGIUNTO/","title":"F_MAX_NUMERO_EVENTI_RAGGIUNTO","text":""},{"location":"functions/F_MAX_NUMERO_EVENTI_RAGGIUNTO/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION F_MAX_NUMERO_EVENTI_RAGGIUNTO ( P_GIORNO IN DATE ) RETURN NUMBER AS v_max_eventi TB_CALENDAR_LOCKS.max_eventi%TYPE; -- Variable to hold the max_eventi value from TB_CALENDAR_LOCKS v_event_count NUMBER; -- Variable to hold the count of events from EVENTI BEGIN -- Step 1: Check if P_GIORNO is present in TB_CALENDAR_LOCKS and get the max_eventi value for that day BEGIN SELECT max_eventi INTO v_max_eventi FROM TB_CALENDAR_LOCKS WHERE giorno = P_GIORNO; EXCEPTION WHEN NO_DATA_FOUND THEN -- If the date is not found in TB_CALENDAR_LOCKS, return -1 (or some other code to indicate the absence) RETURN -1; END;</p> <p>-- Step 2: Count how many events occurred on P_GIORNO in the EVENTI table SELECT COUNT(*) INTO v_event_count FROM EVENTI WHERE TRUNC(DATA) = TRUNC(P_GIORNO); -- Use TRUNC to compare only the date part</p> <p>-- Step 3: Compare the event count with the max_eventi and return the appropriate result IF v_event_count &gt;= v_max_eventi THEN RETURN 1; -- Maximum number of events has been reached or exceeded ELSE RETURN 0; -- Maximum number of events has not been reached END IF;</p> <p>END F_MAX_NUMERO_EVENTI_RAGGIUNTO;```</p>"},{"location":"functions/F_MAX_NUM_EVENTI_CONFERMATI/","title":"F_MAX_NUM_EVENTI_CONFERMATI","text":""},{"location":"functions/F_MAX_NUM_EVENTI_CONFERMATI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION F_MAX_NUM_EVENTI_CONFERMATI ( P_EVT_DATE IN DATE , P_MAX_EVT_NUM NUMBER , P_BYPASS IN NUMBER ) RETURN NUMBER AS </p> <pre><code>v_evt_cnt number;\n</code></pre> <p>BEGIN</p> <pre><code>-- function bypass\nif P_BYPASS &gt; 0 then\n return 0;\nend if;\n\nselect\ncount(e.id) as evt_cnt\ninto v_evt_cnt\nfrom eventi e\njoin vw_event_color c on c.id = e.id\nwhere e.data = P_EVT_DATE\nand c.status = 'Confermato';\n\nif v_evt_cnt &gt;= P_MAX_EVT_NUM then\n return 1;\nelse\n return 0;\nend if;\n</code></pre> <p>END F_MAX_NUM_EVENTI_CONFERMATI;```</p>"},{"location":"functions/F_REP_ALLESTIMENTI/","title":"F_REP_ALLESTIMENTI","text":""},{"location":"functions/F_REP_ALLESTIMENTI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_REP_ALLESTIMENTI\" ( p_data_in IN varchar2 default to_char(sysdate,'YYYYMMD'), p_data_fi IN varchar2 default to_char(sysdate + 30,'YYYYMMD') ) RETURN t_rep_allestimenti_tab PIPELINED AS</p> <pre><code>v_data_in varchar2(100);\nv_data_fi varchar2(100);\n</code></pre> <p>cursor c_evento is with t as (--select e.id, e.data, l.location, e.torta, e.confettata, e.stampa_menu select e.id, e.data, l.location, e.torta, e.altro_a as confettata, e.sedia as stampa_menu from eventi e left join location l on e.id_location = l.id --where data &gt;= sysdate where e.data between to_date(v_data_in,'YYYYMMDD') and to_date(v_data_fi,'YYYYMMDD') and e.stato in (300, 400) -- 300 Scheda Confermata, 400 Confermato (Lista) and e.disabled = 0 and e.deleted = 0 order by data, to_number(to_char(e.ora_evento,'HH24MI')) ) , q as (select t.* , rownum as order_id from t order by data ) , r as (select case when order_id =1 then id else null end as id1, case when order_id =2 then id else null end as id2, case when order_id =3 then id else null end as id3, case when order_id =4 then id else null end as id4, case when order_id =5 then id else null end as id5, case when order_id =6 then id else null end as id6, case when order_id =7 then id else null end as id7, case when order_id =8 then id else null end as id8, case when order_id =9 then id else null end as id9, case when order_id =10 then id else null end as id10, case when order_id =11 then id else null end as id11, case when order_id =12 then id else null end as id12,</p> <pre><code> case when order_id =1 then data else null end as data1,\n case when order_id =2 then data else null end as data2,\n case when order_id =3 then data else null end as data3,\n case when order_id =4 then data else null end as data4,\n case when order_id =5 then data else null end as data5,\n case when order_id =6 then data else null end as data6,\n case when order_id =7 then data else null end as data7,\n case when order_id =8 then data else null end as data8,\n case when order_id =9 then data else null end as data9,\n case when order_id =10 then data else null end as data10,\n case when order_id =11 then data else null end as data11,\n case when order_id =12 then data else null end as data12,\n\n case when order_id =1 then location else null end as location1,\n case when order_id =2 then location else null end as location2,\n case when order_id =3 then location else null end as location3,\n case when order_id =4 then location else null end as location4,\n case when order_id =5 then location else null end as location5,\n case when order_id =6 then location else null end as location6,\n case when order_id =7 then location else null end as location7,\n case when order_id =8 then location else null end as location8,\n case when order_id =9 then location else null end as location9,\n case when order_id =10 then location else null end as location10,\n case when order_id =11 then location else null end as location11,\n case when order_id =12 then location else null end as location12,\n\n case when order_id =1 then torta else null end as torta1,\n case when order_id =2 then torta else null end as torta2,\n case when order_id =3 then torta else null end as torta3,\n case when order_id =4 then torta else null end as torta4,\n case when order_id =5 then torta else null end as torta5,\n case when order_id =6 then torta else null end as torta6,\n case when order_id =7 then torta else null end as torta7,\n case when order_id =8 then torta else null end as torta8,\n case when order_id =9 then torta else null end as torta9,\n case when order_id =10 then torta else null end as torta10,\n case when order_id =11 then torta else null end as torta11,\n case when order_id =12 then torta else null end as torta12,\n\n case when order_id =1 then confettata else null end as confettata1,\n case when order_id =2 then confettata else null end as confettata2,\n case when order_id =3 then confettata else null end as confettata3,\n case when order_id =4 then confettata else null end as confettata4,\n case when order_id =5 then confettata else null end as confettata5,\n case when order_id =6 then confettata else null end as confettata6,\n case when order_id =7 then confettata else null end as confettata7,\n case when order_id =8 then confettata else null end as confettata8,\n case when order_id =9 then confettata else null end as confettata9,\n case when order_id =10 then confettata else null end as confettata10,\n case when order_id =11 then confettata else null end as confettata11,\n case when order_id =12 then confettata else null end as confettata12,\n\n case when order_id =1 then stampa_menu else null end as stampa_menu1,\n case when order_id =2 then stampa_menu else null end as stampa_menu2,\n case when order_id =3 then stampa_menu else null end as stampa_menu3,\n case when order_id =4 then stampa_menu else null end as stampa_menu4,\n case when order_id =5 then stampa_menu else null end as stampa_menu5,\n case when order_id =6 then stampa_menu else null end as stampa_menu6,\n case when order_id =7 then stampa_menu else null end as stampa_menu7,\n case when order_id =8 then stampa_menu else null end as stampa_menu8,\n case when order_id =9 then stampa_menu else null end as stampa_menu9,\n case when order_id =10 then stampa_menu else null end as stampa_menu10,\n case when order_id =11 then stampa_menu else null end as stampa_menu11,\n case when order_id =12 then stampa_menu else null end as stampa_menu12 \n from q\n )\n</code></pre> <p>select min(id1) as id1, min(id2) as id2, min(id3) as id3, min(id4) as id4, min(id5) as id5, min(id6) as id6, min(id7) as id7, min(id8) as id8, min(id9) as id9, min(id10) as id10, min(id11) as id11, min(id12) as id12,</p> <pre><code> min(data1) as d1,\n min(data2) as d2,\n min(data3) as d3,\n min(data4) as d4,\n min(data5) as d5,\n min(data6) as d6,\n min(data7) as d7,\n min(data8) as d8,\n min(data9) as d9,\n min(data10) as d10,\n min(data11) as d11,\n min(data12) as d12,\n\n min(location1) as l1,\n min(location2) as l2,\n min(location3) as l3,\n min(location4) as l4,\n min(location5) as l5,\n min(location6) as l6,\n min(location7) as l7,\n min(location8) as l8,\n min(location9) as l9,\n min(location10) as l10,\n min(location11) as l11,\n min(location12) as l12,\n\n min(torta1) as t1,\n min(torta2) as t2,\n min(torta3) as t3,\n min(torta4) as t4,\n min(torta5) as t5,\n min(torta6) as t6,\n min(torta7) as t7,\n min(torta8) as t8,\n min(torta9) as t9,\n min(torta10) as t10,\n min(torta11) as t11,\n min(torta12) as t12,\n\n min(confettata1) as c1,\n min(confettata2) as c2,\n min(confettata3) as c3,\n min(confettata4) as c4,\n min(confettata5) as c5,\n min(confettata6) as c6,\n min(confettata7) as c7,\n min(confettata8) as c8,\n min(confettata9) as c9,\n min(confettata10) as c10,\n min(confettata11) as c11,\n min(confettata12) as c12,\n\n min(stampa_menu1) as SM1,\n min(stampa_menu2) as SM2,\n min(stampa_menu3) as SM3,\n min(stampa_menu4) as SM4,\n min(stampa_menu5) as SM5,\n min(stampa_menu6) as SM6,\n min(stampa_menu7) as SM7,\n min(stampa_menu8) as SM8,\n min(stampa_menu9) as SM9,\n min(stampa_menu10) as SM10,\n min(stampa_menu11) as SM11,\n min(stampa_menu12) as SM12\n</code></pre> <p>from r; </p> <pre><code>c_evt c_evento%ROWTYPE;\n\ntype v_TOVAGLIATO_AR IS VARRAY(12) OF VARCHAR2(4000); \nv_TOVAGLIATO v_TOVAGLIATO_AR;\n\nC1 varchar2(100); \nC2 varchar2(100); \nC3 varchar2(100); \nC4 varchar2(100); \nC5 varchar2(100); \nC6 varchar2(100); \nC7 varchar2(100); \nC8 varchar2(100); \nC9 varchar2(100); \nC10 varchar2(100); \nC11 varchar2(100); \nC12 varchar2(100);\n\ntype v_TOVAGLIOLO_AR IS VARRAY(12) OF VARCHAR2(1000);\nv_TOVAGLIOLO v_TOVAGLIOLO_AR;\n\ntype v_AN_GELATO_AR IS VARRAY(12) OF VARCHAR2(1000); \nv_AN_GELATO v_AN_GELATO_AR;\ntype v_AN_GELATO2_AR IS VARRAY(12) OF VARCHAR2(1000); \nv_AN_GELATO2 v_AN_GELATO2_AR;\n\ntype v_AN_OPENBAR_AR IS VARRAY(12) OF VARCHAR2(1000); \nv_AN_OPENBAR v_AN_OPENBAR_AR;\ntype v_AN_RUM_AR IS VARRAY(12) OF VARCHAR2(1000); \nv_AN_RUM v_AN_RUM_AR;\n\nT1 varchar2(100); \nT2 varchar2(100); \nT3 varchar2(100); \nT4 varchar2(100); \nT5 varchar2(100); \nT6 varchar2(100); \nT7 varchar2(100); \nT8 varchar2(100); \nT9 varchar2(100); \nT10 varchar2(100); \nT11 varchar2(100); \nT12 varchar2(100);\n\nv_appo varchar2(100);\n\nv_dato varchar2(100);\nv_id_str varchar2(100);\nv_id number;\nv_qry varchar2(1000);\n\ntype v_IDEVT_AR IS VARRAY(12) OF number;\nv_IDEVT v_IDEVT_AR;\n</code></pre> <p>BEGIN --default su date if p_data_in is null then v_data_in := to_char(sysdate,'YYYYMMD'); else v_data_in := p_data_in; end if; if p_data_fi is null then v_data_fi := to_char(sysdate + 30,'YYYYMMD'); else v_data_fi := p_data_fi; end if;</p> <pre><code>v_TOVAGLIATO := v_TOVAGLIATO_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);\nv_TOVAGLIOLO := v_TOVAGLIOLO_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);\nv_AN_GELATO := v_AN_GELATO_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);\nv_AN_GELATO2 := v_AN_GELATO2_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);\nv_AN_OPENBAR := v_AN_OPENBAR_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);\nv_AN_RUM := v_AN_RUM_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);\nv_IDEVT := v_IDEVT_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);\n\nopen c_evento;\nfetch c_evento into c_evt;\n--exit when c_evento%NOTFOUND;\n\n--caricare su vettore gli id:\nv_IDEVT(1) := c_evt.id1;\nv_IDEVT(2) := c_evt.id2;\nv_IDEVT(3) := c_evt.id3;\nv_IDEVT(4) := c_evt.id4;\nv_IDEVT(5) := c_evt.id5;\nv_IDEVT(6) := c_evt.id6;\nv_IDEVT(7) := c_evt.id7;\nv_IDEVT(8) := c_evt.id8;\nv_IDEVT(9) := c_evt.id9;\nv_IDEVT(10) := c_evt.id10;\nv_IDEVT(11) := c_evt.id11;\nv_IDEVT(12) := c_evt.id12;\n\nFOR i in 1 .. 12 LOOP \n v_dato := '';\n\n v_id := to_char(v_IDEVT(i));\n\n v_TOVAGLIATO(i) := f_get_tovagliato_allestimento ('TVB', v_IDEVT(i) ) ;\n v_AN_GELATO(i) := f_get_angolo_allestimento ('AN-GELAT', v_IDEVT(i) ) ;\n v_AN_GELATO2(i) := f_get_angolo_allestimento ('AN-GEL-BOM', v_IDEVT(i) ) ;\n --v_AN_OPENBAR(i) := f_get_angolo_allestimento ('OPEN-B', v_IDEVT(i) ) ;\n v_AN_OPENBAR(i) := f_get_angolo_allestimento_OB ('%OPEN BAR%', v_IDEVT(i) ) ;\n v_AN_RUM(i) := f_get_angolo_allestimento ('AN-RUM-CI', v_IDEVT(i) ) ;\n\nEND LOOP;\n\nPIPE ROW(t_rep_allestimenti_row(c_evt.D1 ,\n c_evt.D2 ,\n c_evt.D3 ,\n c_evt.D4 ,\n c_evt.D5 , \n c_evt.D6 , \n c_evt.D7 , \n c_evt.D8 , \n c_evt.D9 , \n c_evt.D10 , \n c_evt.D11 , \n c_evt.D12 ,\n\n c_evt.L1 , \n c_evt.L2 , \n c_evt.L3 , \n c_evt.L4 , \n c_evt.L5 , \n c_evt.L6 , \n c_evt.L7 , \n c_evt.L8 , \n c_evt.L9 , \n c_evt.L10 , \n c_evt.L11 , \n c_evt.L12 ,\n\n v_TOVAGLIATO(1),\n v_TOVAGLIATO(2),\n v_TOVAGLIATO(3),\n v_TOVAGLIATO(4),\n v_TOVAGLIATO(5),\n v_TOVAGLIATO(6),\n v_TOVAGLIATO(7),\n v_TOVAGLIATO(8),\n v_TOVAGLIATO(9),\n v_TOVAGLIATO(10),\n v_TOVAGLIATO(11),\n v_TOVAGLIATO(12),\n\n c_evt.C1 , \n c_evt.C2 , \n c_evt.C3 , \n c_evt.C4 , \n c_evt.C5 , \n c_evt.C6 , \n c_evt.C7 , \n c_evt.C8 , \n c_evt.C9 , \n c_evt.C10 , \n c_evt.C11 , \n c_evt.C12 ,\n\n v_TOVAGLIOLO(1),\n v_TOVAGLIOLO(2),\n v_TOVAGLIOLO(3),\n v_TOVAGLIOLO(4),\n v_TOVAGLIOLO(5),\n v_TOVAGLIOLO(6),\n v_TOVAGLIOLO(7),\n v_TOVAGLIOLO(8),\n v_TOVAGLIOLO(9),\n v_TOVAGLIOLO(10),\n v_TOVAGLIOLO(11),\n v_TOVAGLIOLO(12),\n\n v_AN_GELATO(1) || ', ' || v_AN_GELATO2(1),\n v_AN_GELATO(2) || ', ' || v_AN_GELATO2(2),\n v_AN_GELATO(3) || ', ' || v_AN_GELATO2(3),\n v_AN_GELATO(4) || ', ' || v_AN_GELATO2(4),\n v_AN_GELATO(5) || ', ' || v_AN_GELATO2(5),\n v_AN_GELATO(6) || ', ' || v_AN_GELATO2(6),\n v_AN_GELATO(7) || ', ' || v_AN_GELATO2(7),\n v_AN_GELATO(8) || ', ' || v_AN_GELATO2(8),\n v_AN_GELATO(9) || ', ' || v_AN_GELATO2(9),\n v_AN_GELATO(10) || ', ' || v_AN_GELATO2(10),\n v_AN_GELATO(11) || ', ' || v_AN_GELATO2(11),\n v_AN_GELATO(12) || ', ' || v_AN_GELATO2(12),\n\n v_AN_OPENBAR(1),\n v_AN_OPENBAR(2),\n v_AN_OPENBAR(3),\n v_AN_OPENBAR(4),\n v_AN_OPENBAR(5),\n v_AN_OPENBAR(6),\n v_AN_OPENBAR(7),\n v_AN_OPENBAR(8),\n v_AN_OPENBAR(9),\n v_AN_OPENBAR(10),\n v_AN_OPENBAR(11),\n v_AN_OPENBAR(12),\n\n v_AN_RUM(1),\n v_AN_RUM(2),\n v_AN_RUM(3),\n v_AN_RUM(4),\n v_AN_RUM(5),\n v_AN_RUM(6),\n v_AN_RUM(7),\n v_AN_RUM(8),\n v_AN_RUM(9),\n v_AN_RUM(10),\n v_AN_RUM(11),\n v_AN_RUM(12),\n\n c_evt.T1 , \n c_evt.T2 , \n c_evt.T3 , \n c_evt.T4 , \n c_evt.T5 , \n c_evt.T6 , \n c_evt.T7 , \n c_evt.T8 , \n c_evt.T9 , \n c_evt.T10 , \n c_evt.T11 , \n c_evt.T12 ,\n\n c_evt.SM1 ,\n c_evt.SM2 ,\n c_evt.SM3 ,\n c_evt.SM4 ,\n c_evt.SM5 , \n c_evt.SM6 , \n c_evt.SM7 , \n c_evt.SM8 , \n c_evt.SM9 , \n c_evt.SM10 , \n c_evt.SM11 , \n c_evt.SM12 \n ));\n\nclose c_evento;\n</code></pre> <p>RETURN;</p> <p>END;```</p>"},{"location":"functions/F_REP_CUCINA/","title":"F_REP_CUCINA","text":""},{"location":"functions/F_REP_CUCINA/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION \"F_REP_CUCINA\" (p_data_in IN varchar2,p_data_fi IN varchar2) RETURN t_rep_cucina_tab PIPELINED AS</p> <p>cursor c_evento is select e.id, e.data, l.LOCATION, e.cliente, t.DESCRIZIONE, e.ORA_CERIMONIA, e.ORA_EVENTO, e.ALLERGIE, e.torta, e.CONFETTATA, e.STAMPA_MENU, e.extra_info, e.cliente_email, e.cliente_tel, e.referente_tel, e.distanza_location, e.buffet_iniziale, e.buffet_finale, e.primi, e.secondi, e.vini, e.extra_costi from eventi e left join location l on e.id_location = l.id join tb_tipi_evento t on e.cod_tipo = t.cod_tipo where e.data between to_date(p_data_in,'YYYYMMDD') and to_date(p_data_fi,'YYYYMMDD') and e.stato = 300 -- Considero soltanto le schede confermate and e.disabled = 0 and e.deleted = 0;</p> <p>v_data date; v_LOCATION varchar2(4000); v_cliente varchar2(4000); v_DESCRIZIONE varchar2(4000); v_ORA_CERIMONIA varchar2(4000); v_ORA_EVENTO varchar2(4000); v_TOT_ADULTI number; v_TOT_KINDER number; v_TOT_BABY number; v_TOT_STAFF number; v_TOT_INVITATI number; v_ALLERGIE varchar2(4000); v_TORTA varchar2(4000); v_CONFETTATA varchar2(4000); v_STAMPA_MENU varchar2(4000); v_angoli varchar2(4000); v_EXTRA_INFO varchar2(4000); v_NOTE_ADULTI varchar2(4000); v_NOTE_KINDER varchar2(4000); v_NOTE_BABY varchar2(4000); v_NOTE_STAFF varchar2(4000); v_cliente_email varchar2(4000) := ''; v_cliente_tel varchar2(4000) := ''; v_referente_tel varchar2(4000) := ''; v_distanza_location varchar2(4000) := ''; v_buffet_iniziale varchar2(4000) := ''; v_buffet_finale varchar2(4000) := ''; v_primi varchar2(4000) := ''; v_secondi varchar2(4000) := ''; v_vini varchar2(4000) := ''; v_extra_costi varchar2(4000) := ''; v_event_id number;</p> <p>BEGIN</p> <pre><code>for c in c_evento\nloop\n\n begin\n\n v_TOT_ADULTI := 0;\n v_TOT_KINDER := 0;\n v_TOT_BABY := 0; \n v_TOT_STAFF := 0;\n v_TOT_INVITATI := 0;\n v_angoli := 0; \n v_NOTE_ADULTI := '';\n v_NOTE_KINDER := '';\n v_NOTE_BABY := '';\n v_NOTE_STAFF := '';\n\n v_cliente_email := c.cliente_email;\n v_cliente_tel := c.cliente_tel;\n v_referente_tel := c.referente_tel;\n v_distanza_location := c.distanza_location;\n v_buffet_iniziale := c.buffet_iniziale;\n v_buffet_finale := c.buffet_finale;\n v_primi := c.primi;\n v_secondi := c.secondi;\n v_vini := c.vini;\n v_extra_costi := c.extra_costi;\n v_event_id := c.id;\n\n --ospiti\n select nvl(sum(o.NUMERO),0)\n into v_TOT_ADULTI\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n --join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO\n where e.id = c.id\n and o.cod_tipo_ospite = 8; -- adulti\n\n begin\n select o.NOTE\n into v_NOTE_ADULTI\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n where e.id = c.id\n and o.cod_tipo_ospite = 8; -- adulti\n\n exception when no_data_found then null;\n end;\n\n select nvl(sum(o.NUMERO),0)\n into v_TOT_KINDER\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n --join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO\n where e.id = c.id\n and o.cod_tipo_ospite = 5; --Kinder\n\n begin\n select o.NOTE\n into v_NOTE_KINDER\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n where e.id = c.id\n and o.cod_tipo_ospite = 5; --Kinder\n\n exception when no_data_found then null;\n end;\n\n select nvl(sum(o.NUMERO),0)\n into v_TOT_BABY\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n --join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO\n where e.id = c.id\n and o.cod_tipo_ospite = 6; -- Baby\n\n begin\n select o.NOTE\n into v_NOTE_BABY\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n where e.id = c.id\n and o.cod_tipo_ospite = 6; -- Baby\n\n exception when no_data_found then null;\n end;\n\n select nvl(sum(o.NUMERO),0)\n into v_TOT_STAFF\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n --join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO\n where e.id = c.id\n and o.cod_tipo_ospite = 7; -- Staff\n\n begin\n select o.NOTE\n into v_NOTE_STAFF\n from eventi e\n join eventi_det_ospiti o on e.id = o.id_evento \n where e.id = c.id\n and o.cod_tipo_ospite = 7; -- Staff\n\n exception when no_data_found then null;\n end;\n\n select nvl(e.tot_ospiti,0)\n into v_TOT_INVITATI\n from eventi e \n where e.id = c.id;\n\n --angoli \"speciali\"\n v_angoli := '';\n for a in ( select trim(substr(a.descrizione || ' - ' || p.note,1,1000)) descrizione from eventi e\n join eventi_det_prel p on e.id=p.id_evento \n join articoli a on p.cod_articolo=a.cod_articolo \n where a.flg_cucina = 1\n and e.id = c.id\n )\n loop\n v_angoli := a.descrizione || ', ' || v_angoli ; \n end loop;\n\n PIPE ROW(t_rep_cucina_row( c.data,c.location,c.cliente,\n c.DESCRIZIONE,\n to_char(c.ORA_CERIMONIA,'HH24:MI'), \n to_char(c.ORA_EVENTO,'HH24:MI'), \n v_TOT_ADULTI ,\n v_TOT_KINDER ,\n v_TOT_BABY , \n v_TOT_STAFF , \n v_TOT_INVITATI ,\n c.ALLERGIE ,\n c.TORTA ,\n c.CONFETTATA ,\n c.STAMPA_MENU ,\n v_angoli,\n c.extra_info ,\n\n v_NOTE_ADULTI ,\n v_NOTE_KINDER ,\n v_NOTE_BABY ,\n v_NOTE_STAFF ,\n v_cliente_email ,\n v_cliente_tel ,\n v_referente_tel ,\n v_distanza_location ,\n v_buffet_iniziale ,\n v_buffet_finale ,\n v_primi ,\n v_secondi ,\n v_vini ,\n v_extra_costi ,\n v_event_id\n ));\n\n --exception when others\n -- then null;\n\n exception when others\n then\n RAISE_APPLICATION_ERROR(-20000, 'Errore: ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64));\n\n end;\n\nend loop;\n</code></pre> <p>RETURN;</p> <p>END;```</p>"},{"location":"functions/F_USER_IN_ROLE/","title":"F_USER_IN_ROLE","text":""},{"location":"functions/F_USER_IN_ROLE/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql FUNCTION F_USER_IN_ROLE ( P_USER IN VARCHAR2 , P_ROLE IN VARCHAR2 ) RETURN NUMBER AS v_has_role number := 0; BEGIN select count(column_value) into v_has_role from tb_config, table(split(strvalue, ':')) where upper(name) = upper(P_ROLE) and upper(column_value) = upper(P_USER);</p> <pre><code>return case when v_has_role &gt; 0 then 1 else 0 end;\n</code></pre> <p>END F_USER_IN_ROLE;```</p>"},{"location":"functions/F_USER_IN_ROLE_STR/","title":"F_USER_IN_ROLE_STR","text":""},{"location":"functions/F_USER_IN_ROLE_STR/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>FUNCTION F_USER_IN_ROLE_STR\n(\n P_USER IN VARCHAR2 \n, P_ROLE IN VARCHAR2 \n) RETURN VARCHAR2 AS \n v_has_role number := 0;\nBEGIN\n return case when F_USER_IN_ROLE(P_USER, P_ROLE) &gt; 0 then 'true' else 'false' end;\nEND F_USER_IN_ROLE_STR;\n</code></pre>"},{"location":"functions/GET_PARAM_VALUE/","title":"GET_PARAM_VALUE","text":""},{"location":"functions/GET_PARAM_VALUE/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>function get_param_value(p_name varchar2)\nreturn varchar2 as\n v_result varchar2(255);\nbegin\n select strvalue\n into v_result\n from tb_config\n where upper(name) = upper(p_name);\n\n return v_result;\nexception when others then\n return null;\nend;\n</code></pre>"},{"location":"functions/MY_INSTR/","title":"MY_INSTR","text":""},{"location":"functions/MY_INSTR/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>function my_instr( p_value varchar2,\n p_delim varchar2 )\nreturn number\nas\n\n i number;\n\n l_length number;\n\nbegin\n\n if p_value is null then\n return null;\n end if;\n\n i := 1;\n\n l_length := length(p_value);\n\n for i in 1..l_length\n loop\n if substr(p_value, i, length(p_delim)) = p_delim then\n return i;\n end if;\n end loop;\n\n\n return 0;\n\nend;\n</code></pre>"},{"location":"functions/SPLIT/","title":"SPLIT","text":""},{"location":"functions/SPLIT/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>FUNCTION \"SPLIT\" \n(\n p_list varchar2,\n p_del varchar2 := ','\n) return string_list\nis\n l_idx integer;\n l_list varchar2(32767) := p_list;\n\n l_value varchar2(32767);\n\n l_retval string_list;\nbegin\n\n l_retval := string_list();\n\n loop\n\n --l_idx := instr(l_list,p_del);\n l_idx := my_instr(l_list,p_del);\n\n l_retval.extend; \n\n if l_idx &gt; 0 then\n --pipe row(substr(l_list,1,l_idx-1));\n --l_list := substr(l_list,l_idx+length(p_del));\n l_retval(l_retval.count) := substr(l_list, 1, l_idx - 1);\n l_list := substr(l_list,l_idx+length(p_del));\n else\n --pipe row(l_list);\n --exit;\n l_retval(l_retval.count) := l_list;\n exit;\n end if;\n\n end loop;\n\n return l_retval;\n\nend split;\n</code></pre>"},{"location":"functions/STRING_TO_TABLE_ENUM/","title":"STRING_TO_TABLE_ENUM","text":""},{"location":"functions/STRING_TO_TABLE_ENUM/#codice-sorgente","title":"Codice Sorgente","text":"<p><code>sql FUNCTION \"STRING_TO_TABLE_ENUM\" (p_string VARCHAR2, v_level in number default 0, p_separator varchar2 default ':') RETURN ENUM_TABLE_TYPE pipelined IS conta number := 0; BEGIN FOR c IN ( select ROW_NUMBER() OVER (ORDER BY ROWNUM) id, result from ( with test as ( select p_string col from dual ) select nvl(regexp_substr(col, '[^' || p_separator || ']+', 1, level), '') result from test connect by level &lt;= length(regexp_replace(col, '[^' || p_separator || ']+')) + 1) ) LOOP conta := conta + 1; if v_level = 0 or ( v_level = conta ) then pipe row(enum_table_object(c.id,c.result)); end if; END LOOP; RETURN; END STRING_TO_TABLE_ENUM;</code></p>"},{"location":"packages/","title":"Packages Database","text":"<p>Questa cartella contiene la documentazione di tutti i 17 packages del database.</p>"},{"location":"packages/#packages-business","title":"Packages Business","text":"Package Descrizione MAIL_PKG Gestione invio email automatiche (solleciti, reminder)"},{"location":"packages/#packages-utility","title":"Packages Utility","text":"Package Descrizione UTL_BASE64 Encoding/decoding Base64"},{"location":"packages/#packages-jasperreports-xlib","title":"Packages JasperReports (XLIB)","text":"Package Descrizione XLIB_JASPERREPORTS Integrazione con JasperReports server XLIB_JASPERREPORTS_IMG Gestione immagini nei report XLIB_HTTP Chiamate HTTP/REST XLIB_COMPONENT Gestione componenti XLIB_LOG Sistema di logging"},{"location":"packages/#packages-json-pljson-library","title":"Packages JSON (PLJSON Library)","text":"<p>Libreria esterna per parsing e generazione JSON. In .NET pu\u00f2 essere sostituita con <code>System.Text.Json</code> o <code>Newtonsoft.Json</code>.</p> Package Descrizione PLJSON_DYN Query dinamiche JSON PLJSON_EXT Estensioni JSON PLJSON_HELPER Helper functions PLJSON_ML Multi-line JSON PLJSON_OBJECT_CACHE Cache oggetti JSON PLJSON_PARSER Parser JSON PLJSON_PRINTER Output JSON formattato PLJSON_UT Unit test JSON PLJSON_UTIL_PKG Utility JSON PLJSON_XML Conversione JSON \u2194 XML"},{"location":"packages/#dettaglio-package-mail_pkg","title":"Dettaglio Package MAIL_PKG","text":""},{"location":"packages/#procedures-disponibili","title":"Procedures Disponibili","text":"Procedura Descrizione <code>send_custom_mail</code> Invio email generica <code>send_richiesta_riscontro_preventivo</code> Sollecito per preventivi in stato 100/200 <code>send_richiesta_riscontro_preventivo_job</code> Job: 10 giorni dopo DATA_DOC <code>send_richiesta_riscontro_post_degustazione</code> Sollecito post-degustazione <code>send_richiesta_riscontro_post_degustazione_job</code> Job: 15 giorni dopo prima degustazione <code>send_reminder_seconda_caparra</code> Reminder pagamento seconda caparra <code>send_reminder_seconda_caparra_job</code> Job: ogni 5 giorni da 65gg prima evento"},{"location":"packages/#configurazione-email","title":"Configurazione Email","text":"<ul> <li>From: <code>noreply@apollinarecatering.it</code></li> <li>BCC: <code>monia@apollinarecatering.it, matrimonio@apollinarecatering.it</code></li> <li>Usa <code>APEX_MAIL</code> per invio</li> <li>Richiede <code>CMN_MAIL_HTMLUTILS</code> per costruzione body HTML</li> </ul>"},{"location":"packages/#migrazione-net","title":"Migrazione .NET","text":"<pre><code>// Esempio implementazione con SendGrid o SMTP\npublic interface IMailService\n{\n Task SendCustomMailAsync(string recipients, string subject, string body);\n Task SendRichiestaRiscontroPreventivo(int eventoId);\n Task SendReminderSecondaCaparra(int eventoId);\n}\n\n// Jobs con Hangfire\n[RecurringJob(\"0 9 * * *\")]\npublic async Task SendReminderSecondaCaparraJob()\n{\n var eventi = await GetEventiDaPagareEntro65gg();\n foreach (var evento in eventi.Where(e =&gt; ShouldSendReminder(e)))\n {\n await _mailService.SendReminderSecondaCaparra(evento.Id);\n }\n}\n</code></pre>"},{"location":"packages/#note-per-migrazione","title":"Note per Migrazione","text":"<ol> <li> <p>MAIL_PKG: Sostituire con servizio email .NET (SendGrid, SMTP, Azure Communication Services)</p> </li> <li> <p>PLJSON_*: Non necessari in .NET, usare <code>System.Text.Json</code></p> </li> <li> <p>XLIB_JASPERREPORTS: Valutare alternative:</p> </li> <li>SSRS (SQL Server Reporting Services)</li> <li>DevExpress Reports</li> <li>Telerik Reporting</li> <li> <p>QuestPDF / iTextSharp per PDF</p> </li> <li> <p>XLIB_HTTP: Sostituire con <code>HttpClient</code></p> </li> <li> <p>UTL_BASE64: Usare <code>Convert.ToBase64String</code> / <code>Convert.FromBase64String</code></p> </li> </ol>"},{"location":"packages/MAIL_PKG/","title":"MAIL_PKG","text":""},{"location":"packages/MAIL_PKG/#package-specification","title":"Package Specification","text":"<pre><code>PACKAGE MAIL_PKG AS\n --==================================================================================\n -- SPECIFICA DEL PACKAGE\n -- Aggiunta delle nuove procedure per il reminder della seconda caparra.\n -- Ultima modifica: 26/07/2024\n --==================================================================================\n\n -- Procedura generica per inviare email\n procedure send_custom_mail(p_recipients varchar2, p_subject varchar2, p_body varchar2);\n\n -- Procedure esistenti\n PROCEDURE send_richiesta_riscontro_preventivo (\n p_style_id NUMBER DEFAULT 1,\n p_evento_id NUMBER\n );\n PROCEDURE send_richiesta_riscontro_preventivo_job;\n\n PROCEDURE send_richiesta_riscontro_post_degustazione (\n p_style_id NUMBER DEFAULT 1,\n p_evento_id NUMBER\n );\n PROCEDURE send_richiesta_riscontro_post_degustazione_job;\n\n -- ===============================================================================\n -- NUOVE PROCEDURE PER IL REMINDER DELLA SECONDA CAPARRA\n -- Data creazione: 26/07/2024\n -- ===============================================================================\n\n /**\n * @descr Costruisce e invia la mail di sollecito per la seconda caparra per un dato evento.\n * @param p_style_id ID dello stile HTML da applicare alla mail.\n * @param p_evento_id ID dell'evento per cui inviare la notifica.\n */\n PROCEDURE send_reminder_seconda_caparra (\n p_style_id NUMBER DEFAULT 1,\n p_evento_id NUMBER\n );\n\n /**\n * @descr Job che seleziona gli eventi per cui inviare il sollecito della seconda caparra.\n * Il primo invio avviene 65 giorni prima dell'evento.\n * Gli invii successivi avvengono ogni 5 giorni fino alla data dell'evento,\n * se la seconda caparra non risulta ancora pagata.\n */\n PROCEDURE send_reminder_seconda_caparra_job;\n\nEND MAIL_PKG;\n</code></pre>"},{"location":"packages/MAIL_PKG/#package-body","title":"Package Body","text":"<p>```sql PACKAGE BODY MAIL_PKG AS --================================================================================== -- BODY DEL PACKAGE -- Implementazione delle nuove procedure e mantenimento di quelle esistenti. -- Ultima modifica: 25/07/2024 --==================================================================================</p> <pre><code>/**\n * @descr Procedura di utility generica per inviare una mail tramite APEX_MAIL.\n * @param p_recipients Lista di destinatari separati da virgola.\n * @param p_subject Oggetto della mail.\n * @param p_body Corpo della mail (pu\u00f2 contenere HTML).\n */\nprocedure send_custom_mail(p_recipients varchar2, p_subject varchar2, p_body varchar2) AS\nBEGIN\n -- Se non ci sono destinatari, interrompe l'esecuzione.\n if trim(p_recipients) is null\n then\n return;\n end if;\n\n -- Utilizza il package APEX_MAIL per comporre e inviare l'email.\n APEX_MAIL.SEND(\n p_to =&gt; p_recipients,\n p_from =&gt; 'noreply@apollinarecatering.it',\n p_bcc =&gt; 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',\n --p_bcc =&gt; 'monia@apollinarecatering.it, maria@apollinarecatering.it', -- Copia conoscenza nascosta\n p_subj =&gt; p_subject,\n p_body =&gt; p_body,\n p_body_html =&gt; p_body -- Il corpo viene inviato sia come testo che come HTML.\n );\n\n -- Forza l'invio immediato delle mail presenti nella coda di APEX.\n APEX_MAIL.PUSH_QUEUE;\nEND send_custom_mail;\n\n/**\n * @descr Invia una mail di sollecito per avere un riscontro su un preventivo inviato per eventi in stato preventivo (100) o scheda confermata (200).\n * @param p_style_id ID dello stile HTML da usare per il corpo della mail.\n * @param p_evento_id ID dell'evento a cui la mail fa riferimento.\n */\nPROCEDURE send_richiesta_riscontro_preventivo (\n p_style_id NUMBER DEFAULT 1,\n p_evento_id NUMBER\n) AS\n v_evento eventi%ROWTYPE;\n v_location location%ROWTYPE;\nBEGIN\n -- Imposta la lingua e il formato della data della sessione per garantire la corretta formattazione.\n EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE=\"ITALIAN\"';\n EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT=\"DD-MON-YYYY\"';\n\n -- Recupera i dettagli dell'evento e della location.\n BEGIN\n -- Seleziona i dati dell'evento solo se le mail sono abilitate (mail_enabled &gt; 0).\n SELECT e.* INTO v_evento\n FROM eventi e\n WHERE e.id = p_evento_id\n AND e.stato in (100, 200)\n AND e.mail_enabled &gt; 0;\n\n -- Seleziona i dati della location associata all'evento.\n SELECT l.* INTO v_location\n FROM location l\n WHERE l.id = v_evento.id_location;\n EXCEPTION\n -- Se l'evento non viene trovato (o ha le mail disabilitate), la procedura termina.\n WHEN NO_DATA_FOUND THEN RETURN;\n END;\n\n -- Inizializza il corpo della mail e imposta lo stile HTML.\n CMN_MAIL_HTMLUTILS.mailbody := '';\n CMN_MAIL_HTMLUTILS.set_style(p_style_id);\n\n -- Costruisce il corpo della mail paragrafo per paragrafo utilizzando il package di utility.\n CMN_MAIL_HTMLUTILS.create_paragraph('Gentilissimi,');\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'in seguito all''invio della nostra proposta per il vostro evento, '||\n 'desideriamo sapere se avete avuto modo di valutarla e se siete interessati ai nostri servizi.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'Saremmo lieti di incontrarvi per una degustazione, cos\u00ec da potervi presentare al meglio le nostre offerte. '||\n 'Potete prenotare una delle date disponibili direttamente tramite il nostro sito: '||\n '&lt;a href=\"https://www.apollinarecatering.it/degustazioni/\"&gt;Degustazioni&lt;/a&gt;.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'Per qualsiasi ulteriore informazione o chiarimento potete scriverci a '||\n '&lt;a href=\"mailto:info@apollinarecatering.it\"&gt;info@apollinarecatering.it&lt;/a&gt;.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Si prega di non rispondere direttamente a questa email.&lt;/b&gt;');\n CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Ufficio Commerciale&lt;/b&gt;');\n CMN_MAIL_HTMLUTILS.create_paragraph('\ud83d\udcde +39 0743 45 449');\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Apollinare Catering&lt;/b&gt;');\n\n -- Invia la mail usando APEX_MAIL, componendo un oggetto dinamico.\n APEX_MAIL.SEND(\n p_to =&gt; v_evento.cliente_email,\n p_from =&gt; 'noreply@apollinarecatering.it',\n p_bcc =&gt; 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',\n --p_bcc =&gt; 'monia@apollinarecatering.it, maria@apollinarecatering.it',\n p_subj =&gt; 'Apollinare \u2013 richiesta riscontro per evento del '||\n TO_CHAR(v_evento.data, 'DD/MM/YYYY')||' presso '||v_location.location,\n p_body =&gt; CMN_MAIL_HTMLUTILS.mailbody,\n p_body_html =&gt; CMN_MAIL_HTMLUTILS.mailbody\n );\n\n -- Forza l'invio immediato dalla coda di APEX.\n APEX_MAIL.PUSH_QUEUE;\nEND send_richiesta_riscontro_preventivo;\n\n/**\n * @descr Invia una mail di sollecito dopo che il cliente ha partecipato a una degustazione.\n * @param p_style_id ID dello stile HTML da usare per il corpo della mail.\n * @param p_evento_id ID dell'evento a cui la mail fa riferimento.\n */\nPROCEDURE send_richiesta_riscontro_post_degustazione (\n p_style_id NUMBER DEFAULT 1,\n p_evento_id NUMBER\n) AS\n v_evento eventi%ROWTYPE;\n v_location location%ROWTYPE;\nBEGIN\n -- Imposta la lingua e il formato della data della sessione.\n EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE=\"ITALIAN\"';\n EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT=\"DD-MON-YYYY\"';\n\n -- Recupera i dettagli dell'evento e della location.\n BEGIN\n -- Seleziona i dati dell'evento solo se le mail sono abilitate.\n SELECT e.* INTO v_evento\n FROM eventi e\n WHERE e.id = p_evento_id\n AND e.stato in (200)\n AND e.mail_enabled &gt; 0;\n\n -- Seleziona i dati della location.\n SELECT l.* INTO v_location\n FROM location l\n WHERE l.id = v_evento.id_location;\n EXCEPTION\n -- Se non trova l'evento, esce dalla procedura.\n WHEN NO_DATA_FOUND THEN RETURN;\n END;\n\n -- Inizializza il corpo della mail e imposta lo stile HTML.\n CMN_MAIL_HTMLUTILS.mailbody := '';\n CMN_MAIL_HTMLUTILS.set_style(p_style_id);\n\n -- Costruisce il corpo della mail.\n CMN_MAIL_HTMLUTILS.create_paragraph('Gentilissimi,');\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'in seguito alla degustazione effettuata per il vostro evento, '||\n 'desideriamo sapere se la nostra proposta risponde alle vostre aspettative '||\n 'e se intendete procedere con la conferma dei servizi.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'Per ogni ulteriore chiarimento siamo a vostra completa disposizione: '||\n '&lt;a href=\"mailto:info@apollinarecatering.it\"&gt;info@apollinarecatering.it&lt;/a&gt;.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Si prega di non rispondere direttamente a questa email.&lt;/b&gt;');\n CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Ufficio Commerciale&lt;/b&gt;');\n CMN_MAIL_HTMLUTILS.create_paragraph('\ud83d\udcde +39 0743 45 449');\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Apollinare Catering&lt;/b&gt;');\n\n -- Invia la mail, componendo un oggetto dinamico con data e location.\n APEX_MAIL.SEND(\n p_to =&gt; v_evento.cliente_email,\n p_from =&gt; 'noreply@apollinarecatering.it',\n p_bcc =&gt; 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',\n --p_bcc =&gt; 'monia@apollinarecatering.it, maria@apollinarecatering.it',\n p_subj =&gt; 'Apollinare \u2013 riscontro post-degustazione evento del '||\n TO_CHAR(v_evento.data, 'DD/MM/YYYY')||' presso '||v_location.location,\n p_body =&gt; CMN_MAIL_HTMLUTILS.mailbody,\n p_body_html =&gt; CMN_MAIL_HTMLUTILS.mailbody\n );\n\n -- Forza l'invio immediato.\n APEX_MAIL.PUSH_QUEUE;\nEND send_richiesta_riscontro_post_degustazione;\n\n/**\n * @descr Procedura schedulabile (job) che invia solleciti per i preventivi non confermati.\n */\nPROCEDURE send_richiesta_riscontro_preventivo_job AS\nBEGIN\n -- Itera su tutti gli eventi che soddisfano i criteri per il sollecito.\n FOR evt IN (\n SELECT e.*\n FROM eventi e\n WHERE e.stato in (100) -- Stato: Preventivo non confermato\n AND e.mail_enabled = 1 -- Mail abilitate\n AND TRUNC(e.data_doc) = TRUNC(SYSDATE) - 10 -- Sono passati 10 giorni dalla data del documento.\n )\n LOOP\n -- Per ogni evento trovato, chiama la procedura di invio mail.\n send_richiesta_riscontro_preventivo(\n p_style_id =&gt; 1,\n p_evento_id =&gt; evt.id\n );\n END LOOP;\nEND send_richiesta_riscontro_preventivo_job;\n\n/**\n * @descr Procedura schedulabile (job) che invia solleciti dopo una degustazione.\n */\nPROCEDURE send_richiesta_riscontro_post_degustazione_job AS\nBEGIN\n -- Itera su tutti gli eventi che soddisfano i criteri per il sollecito post-degustazione.\n FOR evt IN (\n SELECT e.*\n FROM eventi e\n JOIN ( -- Sottoquery per trovare la data della prima degustazione per ogni evento.\n SELECT id_evento,\n MIN(TRUNC(data)) AS min_data\n FROM eventi_det_degust\n GROUP BY id_evento ) dm\n ON dm.id_evento = e.id\n WHERE e.stato = 200 -- Stato: Scheda evento in preparazione\n AND e.mail_enabled = 1 -- Mail abilitate\n AND dm.min_data = TRUNC(SYSDATE) - 15 -- Sono passati 15 giorni dalla prima degustazione.\n )\n LOOP\n -- Per ogni evento trovato, chiama la procedura di invio mail.\n send_richiesta_riscontro_post_degustazione(\n p_style_id =&gt; 1,\n p_evento_id =&gt; evt.id\n );\n END LOOP;\nEND send_richiesta_riscontro_post_degustazione_job;\n\n\n-- ===============================================================================\n-- IMPLEMENTAZIONE NUOVE PROCEDURE\n-- Data creazione: 26/07/2024\n-- ===============================================================================\n\nPROCEDURE send_reminder_seconda_caparra (\n p_style_id NUMBER DEFAULT 1,\n p_evento_id NUMBER\n) AS\n v_evento eventi%ROWTYPE;\n v_location location%ROWTYPE;\nBEGIN\n EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE=\"ITALIAN\"';\n EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT=\"DD-MON-YYYY\"';\n\n -- Recupero i dati dell'evento e della location\n BEGIN\n SELECT e.* INTO v_evento\n FROM eventi e\n WHERE e.id = p_evento_id\n AND e.mail_enabled &gt; 0;\n\n SELECT l.* INTO v_location\n FROM location l\n WHERE l.id = v_evento.id_location;\n EXCEPTION\n WHEN NO_DATA_FOUND THEN\n -- Se l'evento non esiste o le mail sono disabilitate, esco.\n RETURN;\n END;\n\n -- Costruzione del corpo della mail\n CMN_MAIL_HTMLUTILS.mailbody := '';\n CMN_MAIL_HTMLUTILS.set_style(p_style_id);\n\n CMN_MAIL_HTMLUTILS.create_paragraph('Gentilissimi,');\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'sperando che tutto proceda per il meglio, desideriamo cortesemente ricordarvi la scadenza relativa alla seconda tranche di pagamento per il vostro evento.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'Qualora non fosse ancora stato effettuato, vi invitiamo a procedere con il versamento della seconda caparra, previsto 60 giorni prima della data dell\u2019evento, come da accordi e indicato nel preventivo.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph(\n 'Rimaniamo a disposizione per qualsiasi chiarimento e vi ringraziamo sin da ora per la preziosa collaborazione.'\n );\n CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Ufficio Commerciale&lt;/b&gt;');\n CMN_MAIL_HTMLUTILS.create_paragraph('\ud83d\udcde +39 0743 45 449');\n CMN_MAIL_HTMLUTILS.create_paragraph('&lt;b&gt;Apollinare Catering&lt;/b&gt;');\n\n -- Invio della mail\n APEX_MAIL.SEND(\n --p_to =&gt; v_evento.cliente_email,\n p_to =&gt; 'amministrazione@apollinarecatering.it',\n p_from =&gt; 'noreply@apollinarecatering.it',\n p_bcc =&gt; 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',\n --p_bcc =&gt; 'monia@apollinarecatering.it, maria@apollinarecatering.it',\n p_subj =&gt; 'Apollinare \u2013 Promemoria pagamento per evento del '||\n TO_CHAR(v_evento.data, 'DD/MM/YYYY'),\n p_body =&gt; CMN_MAIL_HTMLUTILS.mailbody,\n p_body_html =&gt; CMN_MAIL_HTMLUTILS.mailbody\n );\n\n -- Invio immediato dalla coda\n APEX_MAIL.PUSH_QUEUE;\n\nEND send_reminder_seconda_caparra;\n\n\nPROCEDURE send_reminder_seconda_caparra_job AS\nBEGIN\n -- Scorro tutti gli eventi che necessitano del reminder.\n -- La logica ora utilizza la vista GET_EVENTI_DA_PAGARE_ENTRO_65GG\n -- per identificare gli eventi che non hanno saldato la caparra.\n FOR evt IN (\n SELECT\n v.id,\n v.data -- Seleziono la data per il calcolo del MOD\n FROM\n GET_EVENTI_DA_PAGARE_ENTRO_65GG v\n JOIN\n eventi e ON v.id = e.id -- Join per recuperare il flag mail_enabled\n WHERE\n -- La vista gi\u00e0 filtra per stato, importi e finestra di 65 giorni.\n -- Aggiungo solo le condizioni specifiche del job.\n\n -- Le mail automatiche devono essere abilitate.\n e.mail_enabled = 1\n\n -- La logica MOD assicura l'invio periodico ogni 5 giorni.\n AND MOD(65 - (TRUNC(v.data) - TRUNC(SYSDATE)), 5) = 0\n )\n LOOP\n -- Per ogni evento trovato, chiamo la procedura di invio mail.\n send_reminder_seconda_caparra(\n p_style_id =&gt; 1,\n p_evento_id =&gt; evt.id\n );\n END LOOP;\nEND send_reminder_seconda_caparra_job;\n</code></pre> <p>END MAIL_PKG;```</p>"},{"location":"packages/PLJSON_DYN/","title":"PLJSON_DYN","text":""},{"location":"packages/PLJSON_DYN/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_dyn authid current_user as /* Copyright (c) 2010 Jonas Krogsboell</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */</p> <p>null_as_empty_string boolean not null := true; --varchar2 include_dates boolean not null := true; --date include_clobs boolean not null := true; include_blobs boolean not null := false; include_arrays boolean not null := true; -- pljson_varray or pljson_narray</p> <p>/ list with objects / function executeList(stmt varchar2, bindvar pljson default null, cur_num number default null, bindvardateformats pljson default null) return pljson_list;</p> <p>/ object with lists / function executeObject(stmt varchar2, bindvar pljson default null, cur_num number default null) return pljson;</p> <p>/ usage example: * declare * res json_list; * begin * res := json_dyn.executeList( * 'select :bindme as one, :lala as two from dual where dummy in :arraybind', * json('{bindme:\"4\", lala:123, arraybind:[1, 2, 3, \"X\"]}') * ); * res.print; * end; /</p> <p>/ --11g functions function executeList(stmt in out sys_refcursor) return json_list; function executeObject(stmt in out sys_refcursor) return json; / end pljson_dyn;```</p>"},{"location":"packages/PLJSON_DYN/#package-body","title":"Package Body","text":"<p>```sql package body pljson_dyn as /* -- 11gR2 function executeList(stmt in out sys_refcursor) return json_list as l_cur number; begin l_cur := dbms_sql.to_cursor_number(stmt); return json_dyn.executeList(null, null, l_cur); end;</p> <p>-- 11gR2 function executeObject(stmt in out sys_refcursor) return json as l_cur number; begin l_cur := dbms_sql.to_cursor_number(stmt); return json_dyn.executeObject(null, null, l_cur); end; */</p> <p>procedure bind_json(l_cur number, bindvar pljson, bindvardateformats pljson default null) as keylist pljson_list := bindvar.get_keys(); begin for i in 1 .. keylist.count loop if (bindvar.get(i).is_number()) then dbms_sql.bind_variable(l_cur, ':'||keylist.get(i).get_string(), bindvar.get(i).get_number()); elsif (bindvar.get(i).is_array()) then declare v_bind dbms_sql.varchar2_table; v_arr pljson_list := pljson_list(bindvar.get(i)); begin for j in 1 .. v_arr.count loop v_bind(j) := v_arr.get(j).value_of(); end loop; dbms_sql.bind_array(l_cur, ':'||keylist.get(i).get_string(), v_bind); end; else if bindvardateformats is not null then if bindvardateformats.exist(keylist.get(i).get_string()) then dbms_sql.bind_variable(l_cur, ':'||keylist.get(i).get_string(), to_date(bindvar.get(i).value_of(), bindvardateformats.get(keylist.get(i).get_string()).get_string() )); else dbms_sql.bind_variable(l_cur, ':'||keylist.get(i).get_string(), bindvar.get(i).value_of()); end if; else dbms_sql.bind_variable(l_cur, ':'||keylist.get(i).get_string(), bindvar.get(i).value_of()); end if; end if; end loop; end bind_json;</p> <p>/ list with objects / function executeList(stmt varchar2, bindvar pljson, cur_num number, bindvardateformats pljson default null) return pljson_list as l_cur number; l_dtbl dbms_sql.desc_tab3; l_cnt number; l_status number; l_val varchar2(4000); outer_list pljson_list := pljson_list(); inner_obj pljson; conv number; read_date date; read_clob clob; read_blob blob; col_type number; read_varray pljson_varray; read_narray pljson_narray; begin if (cur_num is not null) then l_cur := cur_num; else l_cur := dbms_sql.open_cursor; dbms_sql.parse(l_cur, stmt, dbms_sql.native); if (bindvar is not null) then bind_json(l_cur, bindvar, bindvardateformats); end if; end if; / E.I.Sarmas (github.com/dsnz) 2018-05-01 handling of varray, narray in select / dbms_sql.describe_columns3(l_cur, l_cnt, l_dtbl); for i in 1..l_cnt loop col_type := l_dtbl(i).col_type; --dbms_output.put_line(col_type); if (col_type = 12) then dbms_sql.define_column(l_cur, i, read_date); elsif (col_type = 112) then dbms_sql.define_column(l_cur, i, read_clob); elsif (col_type = 113) then dbms_sql.define_column(l_cur, i, read_blob); elsif (col_type in (1, 2, 96)) then dbms_sql.define_column(l_cur, i, l_val, 4000); / E.I.Sarmas (github.com/dsnz) 2018-05-01 handling of pljson_varray in select / elsif (col_type = 109 and l_dtbl(i).col_type_name = 'PLJSON_VARRAY') then dbms_sql.define_column(l_cur, i, read_varray); / E.I.Sarmas (github.com/dsnz) 2018-05-01 handling of pljson_narray in select / elsif (col_type = 109 and l_dtbl(i).col_type_name = 'PLJSON_NARRAY') then dbms_sql.define_column(l_cur, i, read_narray); / E.I.Sarmas (github.com/dsnz) 2018-05-01 record unhandled col_type / else dbms_output.put_line('unhandled col_type =' || col_type); end if; end loop;</p> <pre><code>if (cur_num is null) then l_status := dbms_sql.execute(l_cur); end if;\n\n--loop through rows\nwhile ( dbms_sql.fetch_rows(l_cur) &gt; 0 ) loop\n inner_obj := pljson(); --init for each row\n inner_obj.check_for_duplicate := 0;\n --loop through columns\n for i in 1..l_cnt loop\n case true\n --handling string types\n when l_dtbl(i).col_type in (1, 96) then -- varchar2\n dbms_sql.column_value(l_cur, i, l_val);\n if (l_val is null) then\n if (null_as_empty_string) then\n inner_obj.put(l_dtbl(i).col_name, ''); --treat as emptystring?\n else\n inner_obj.put(l_dtbl(i).col_name, pljson_null()); --null\n end if;\n else\n inner_obj.put(l_dtbl(i).col_name, pljson_string(l_val)); --null\n end if;\n --dbms_output.put_line(l_dtbl(i).col_name||' --&gt; '||l_val||'varchar2' ||l_dtbl(i).col_type);\n --handling number types\n when l_dtbl(i).col_type = 2 then -- number\n dbms_sql.column_value(l_cur, i, l_val);\n conv := l_val;\n inner_obj.put(l_dtbl(i).col_name, conv);\n -- dbms_output.put_line(l_dtbl(i).col_name||' --&gt; '||l_val||'number ' ||l_dtbl(i).col_type);\n when l_dtbl(i).col_type = 12 then -- date\n if (include_dates) then\n dbms_sql.column_value(l_cur, i, read_date);\n inner_obj.put(l_dtbl(i).col_name, pljson_ext.to_json_string(read_date));\n end if;\n --dbms_output.put_line(l_dtbl(i).col_name||' --&gt; '||l_val||'date ' ||l_dtbl(i).col_type);\n when l_dtbl(i).col_type = 112 then --clob\n if (include_clobs) then\n dbms_sql.column_value(l_cur, i, read_clob);\n inner_obj.put(l_dtbl(i).col_name, pljson_string(read_clob));\n end if;\n when l_dtbl(i).col_type = 113 then --blob\n if (include_blobs) then\n dbms_sql.column_value(l_cur, i, read_blob);\n if (dbms_lob.getlength(read_blob) &gt; 0) then\n inner_obj.put(l_dtbl(i).col_name, pljson_ext.encode(read_blob));\n else\n inner_obj.put(l_dtbl(i).col_name, pljson_null());\n end if;\n end if;\n /* E.I.Sarmas (github.com/dsnz) 2018-05-01 handling of pljson_varray in select */\n when l_dtbl(i).col_type = 109 and l_dtbl(i).col_type_name = 'PLJSON_VARRAY' then\n if (include_arrays) then\n dbms_sql.column_value(l_cur, i, read_varray);\n inner_obj.put(l_dtbl(i).col_name, pljson_list(read_varray));\n end if;\n /* E.I.Sarmas (github.com/dsnz) 2018-05-01 handling of pljson_narray in select */\n when l_dtbl(i).col_type = 109 and l_dtbl(i).col_type_name = 'PLJSON_NARRAY' then\n if (include_arrays) then\n dbms_sql.column_value(l_cur, i, read_narray);\n inner_obj.put(l_dtbl(i).col_name, pljson_list(read_narray));\n end if;\n\n else null; --discard other types\n end case;\n end loop;\n inner_obj.check_for_duplicate := 1;\n outer_list.append(inner_obj);\nend loop;\ndbms_sql.close_cursor(l_cur);\nreturn outer_list;\n</code></pre> <p>end executeList;</p> <p>/ object with lists / function executeObject(stmt varchar2, bindvar pljson, cur_num number) return pljson as l_cur number; l_dtbl dbms_sql.desc_tab; l_cnt number; l_status number; l_val varchar2(4000); inner_list_names pljson_list := pljson_list(); inner_list_data pljson_list := pljson_list(); data_list pljson_list; outer_obj pljson := pljson(); conv number; read_date date; read_clob clob; read_blob blob; col_type number; begin if (cur_num is not null) then l_cur := cur_num; else l_cur := dbms_sql.open_cursor; dbms_sql.parse(l_cur, stmt, dbms_sql.native); if (bindvar is not null) then bind_json(l_cur, bindvar); end if; end if; dbms_sql.describe_columns(l_cur, l_cnt, l_dtbl); for i in 1..l_cnt loop col_type := l_dtbl(i).col_type; if (col_type = 12) then dbms_sql.define_column(l_cur, i, read_date); elsif (col_type = 112) then dbms_sql.define_column(l_cur, i, read_clob); elsif (col_type = 113) then dbms_sql.define_column(l_cur, i, read_blob); elsif (col_type in (1, 2, 96)) then dbms_sql.define_column(l_cur, i, l_val, 4000); end if; end loop; if (cur_num is null) then l_status := dbms_sql.execute(l_cur); end if;</p> <pre><code>--build up name_list\nfor i in 1..l_cnt loop\n case l_dtbl(i).col_type\n when 1 then inner_list_names.append(l_dtbl(i).col_name);\n when 96 then inner_list_names.append(l_dtbl(i).col_name);\n when 2 then inner_list_names.append(l_dtbl(i).col_name);\n when 12 then if (include_dates) then inner_list_names.append(l_dtbl(i).col_name); end if;\n when 112 then if (include_clobs) then inner_list_names.append(l_dtbl(i).col_name); end if;\n when 113 then if (include_blobs) then inner_list_names.append(l_dtbl(i).col_name); end if;\n else null;\n end case;\nend loop;\n\n--loop through rows\nwhile ( dbms_sql.fetch_rows(l_cur) &gt; 0 ) loop\n data_list := pljson_list();\n --loop through columns\n for i in 1..l_cnt loop\n case true\n --handling string types\n when l_dtbl(i).col_type in (1, 96) then -- varchar2\n dbms_sql.column_value(l_cur, i, l_val);\n if (l_val is null) then\n if (null_as_empty_string) then\n data_list.append(''); --treat as emptystring?\n else\n data_list.append(pljson_null()); --null\n end if;\n else\n data_list.append(pljson_string(l_val)); --null\n end if;\n --dbms_output.put_line(l_dtbl(i).col_name||' --&gt; '||l_val||'varchar2' ||l_dtbl(i).col_type);\n --handling number types\n when l_dtbl(i).col_type = 2 then -- number\n dbms_sql.column_value(l_cur, i, l_val);\n conv := l_val;\n data_list.append(conv);\n -- dbms_output.put_line(l_dtbl(i).col_name||' --&gt; '||l_val||'number ' ||l_dtbl(i).col_type);\n when l_dtbl(i).col_type = 12 then -- date\n if (include_dates) then\n dbms_sql.column_value(l_cur, i, read_date);\n data_list.append(pljson_ext.to_json_string(read_date));\n end if;\n --dbms_output.put_line(l_dtbl(i).col_name||' --&gt; '||l_val||'date ' ||l_dtbl(i).col_type);\n when l_dtbl(i).col_type = 112 then --clob\n if (include_clobs) then\n dbms_sql.column_value(l_cur, i, read_clob);\n data_list.append(pljson_string(read_clob));\n end if;\n when l_dtbl(i).col_type = 113 then --blob\n if (include_blobs) then\n dbms_sql.column_value(l_cur, i, read_blob);\n if (dbms_lob.getlength(read_blob) &gt; 0) then\n data_list.append(pljson_ext.encode(read_blob));\n else\n data_list.append(pljson_null());\n end if;\n end if;\n else null; --discard other types\n end case;\n end loop;\n inner_list_data.append(data_list);\nend loop;\n\nouter_obj.put('names', inner_list_names);\nouter_obj.put('data', inner_list_data);\ndbms_sql.close_cursor(l_cur);\nreturn outer_obj;\n</code></pre> <p>end executeObject;</p> <p>end pljson_dyn;```</p>"},{"location":"packages/PLJSON_EXT/","title":"PLJSON_EXT","text":""},{"location":"packages/PLJSON_EXT/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_ext as /* Copyright (c) 2009 Jonas Krogsboell</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */</p> <p>/ This package contains extra methods to lookup types and an easy way of adding date values in json - without changing the structure / function parsePath(json_path varchar2, base number default 1) return pljson_list;</p> <p>--JSON pre-parsed path getters function get_json_element(obj pljson, path pljson_list) return pljson_element; function get_string(obj pljson, path pljson_list) return varchar2; function get_number(obj pljson, path pljson_list) return number; function get_double(obj pljson, path pljson_list) return binary_double; function get_json(obj pljson, path pljson_list) return pljson; function get_json_list(obj pljson, path pljson_list) return pljson_list; function get_bool(obj pljson, path pljson_list) return boolean; function get_date(obj pljson, path pljson_list) return date;</p> <p>--saved original code, in case of future bug troubleshooting function get_json_element_original(obj pljson, v_path varchar2, base number default 1) return pljson_element;</p> <p>--JSON Path getters function get_json_element(obj pljson, v_path varchar2, base number default 1) return pljson_element; function get_string(obj pljson, path varchar2, base number default 1) return varchar2; function get_number(obj pljson, path varchar2, base number default 1) return number; function get_double(obj pljson, path varchar2, base number default 1) return binary_double; function get_json(obj pljson, path varchar2, base number default 1) return pljson; function get_json_list(obj pljson, path varchar2, base number default 1) return pljson_list; function get_bool(obj pljson, path varchar2, base number default 1) return boolean;</p> <p>--JSON pre-parsed path putters procedure put(obj in out nocopy pljson, path pljson_list, elem varchar2); procedure put(obj in out nocopy pljson, path pljson_list, elem number); procedure put(obj in out nocopy pljson, path pljson_list, elem binary_double); procedure put(obj in out nocopy pljson, path pljson_list, elem pljson); procedure put(obj in out nocopy pljson, path pljson_list, elem pljson_list); procedure put(obj in out nocopy pljson, path pljson_list, elem boolean); procedure put(obj in out nocopy pljson, path pljson_list, elem pljson_element); procedure put(obj in out nocopy pljson, path pljson_list, elem date);</p> <p>--JSON Path putters procedure put(obj in out nocopy pljson, path varchar2, elem varchar2, base number default 1); procedure put(obj in out nocopy pljson, path varchar2, elem number, base number default 1); procedure put(obj in out nocopy pljson, path varchar2, elem binary_double, base number default 1); procedure put(obj in out nocopy pljson, path varchar2, elem pljson, base number default 1); procedure put(obj in out nocopy pljson, path varchar2, elem pljson_list, base number default 1); procedure put(obj in out nocopy pljson, path varchar2, elem boolean, base number default 1); procedure put(obj in out nocopy pljson, path varchar2, elem pljson_element, base number default 1);</p> <p>procedure remove(obj in out nocopy pljson, path pljson_list); procedure remove(obj in out nocopy pljson, path varchar2, base number default 1);</p> <p>--Pretty print with JSON Path - obsolete in 0.9.4 - obj.path(v_path).(to_char,print,htp) function pp(obj pljson, v_path varchar2) return varchar2; procedure pp(obj pljson, v_path varchar2); --using dbms_output.put_line procedure pp_htp(obj pljson, v_path varchar2); --using htp.print</p> <p>--extra function checks if number has no fraction function is_integer(v pljson_element) return boolean;</p> <p>format_string varchar2(30 char) := 'yyyy-mm-dd hh24:mi:ss'; --extension enables json to store dates without compromising the implementation function to_json_string(d date) return pljson_string; --notice that a date type in json is also a varchar2 function is_date(v pljson_element) return boolean; --conversion is needed to extract dates function to_date(v pljson_element) return date; -- alias so that old code doesn't break function to_date2(v pljson_element) return date; --JSON Path with date function get_date(obj pljson, path varchar2, base number default 1) return date; procedure put(obj in out nocopy pljson, path varchar2, elem date, base number default 1);</p> <p>/ encoding in lines of 64 chars ending with CR+NL / function encodeBase64Blob2Clob(p_blob in blob) return clob; / assumes single base64 string or broken into equal length lines of max 64 or 76 chars (as specified by RFC-1421 or RFC-2045) line ending can be CR+NL or NL / function decodeBase64Clob2Blob(p_clob clob) return blob;</p> <p>function base64(binarydata blob) return pljson_list; function base64(l pljson_list) return blob;</p> <p>function encode(binarydata blob) return pljson_string; function decode(v pljson_string) return blob;</p> <p>/ implemented as a procedure to force you to declare the CLOB so you can free it later / procedure blob2clob(b blob, c out clob, charset varchar2 default 'UTF8'); end pljson_ext;```</p>"},{"location":"packages/PLJSON_EXT/#package-body","title":"Package Body","text":"<p>```sql package body pljson_ext as /* Copyright (c) 2009 Jonas Krogsboell</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */</p> <p>scanner_exception exception; pragma exception_init(scanner_exception, -20100); parser_exception exception; pragma exception_init(parser_exception, -20101); jext_exception exception; pragma exception_init(jext_exception, -20110);</p> <p>--extra function checks if number has no fraction function is_integer(v pljson_element) return boolean as num number; num_double binary_double; int_number number(38); --the oracle way to specify an integer int_double binary_double; --the oracle way to specify an integer begin / if (v.is_number()) then myint := v.get_number(); return (myint = v.get_number()); --no rounding errors? else return false; end if; / if (not v.is_number()) then raise_application_error(-20109, 'not a number-value'); end if; / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / if (v.is_number_repr_number()) then num := v.get_number(); int_number := trunc(num); --dbms_output.put_line('number: ' || num || ' -&gt; ' || int_number); return (int_number = num); --no rounding errors? elsif (v.is_number_repr_double()) then num_double := v.get_double(); int_double := trunc(num_double); --dbms_output.put_line('double: ' || num_double || ' -&gt; ' || int_double); return (int_double = num_double); --no rounding errors? else return false; end if; end;</p> <p>--extension enables json to store dates without compromising the implementation function to_json_string(d date) return pljson_string as begin return pljson_string(to_char(d, format_string)); end;</p> <p>--notice that a date type in json is also a varchar2 function is_date(v pljson_element) return boolean as temp date; begin temp := pljson_ext.to_date(v); return true; exception when others then return false; end;</p> <p>--conversion is needed to extract dates function to_date(v pljson_element) return date as begin if (v.is_string()) then return standard.to_date(v.get_string(), format_string); else raise_application_error(-20110, 'not a date-value'); end if; exception when others then raise_application_error(-20110, 'Anydata did not contain a date on the format: '||format_string); end;</p> <p>-- alias so that old code doesn't break function to_date2(v pljson_element) return date as begin return to_date(v); end;</p> <p>/ assumes single base64 string or broken into equal length lines of max 64 or 76 chars (as specified by RFC-1421 or RFC-2045) line ending can be CR+NL or NL / function decodeBase64Clob2Blob(p_clob clob) return blob is r_blob blob; clob_size number; pos number; c_buf varchar2(32767); r_buf raw(32767); v_read_size number; v_line_size number; begin dbms_lob.createtemporary(r_blob, false, dbms_lob.call); / E.I.Sarmas (github.com/dsnz) 2017-12-07 fix for alignment issues assumes single base64 string or broken into equal length lines of max 64 or 76 followed by CR+NL as specified by RFC-1421 or RFC-2045 which seem to be the supported ones by Oracle utl_encode also support single NL instead of CR+NL ! / clob_size := dbms_lob.getlength(p_clob); v_line_size := 64; if clob_size &gt;= 65 and dbms_lob.substr(p_clob, 1, 65) = chr(10) then v_line_size := 65; elsif clob_size &gt;= 66 and dbms_lob.substr(p_clob, 1, 65) = chr(13) then v_line_size := 66; elsif clob_size &gt;= 77 and dbms_lob.substr(p_clob, 1, 77) = chr(10) then v_line_size := 77; elsif clob_size &gt;= 78 and dbms_lob.substr(p_clob, 1, 77) = chr(13) then v_line_size := 78; end if; --dbms_output.put_line('decoding in multiples of ' || v_line_size); v_read_size := floor(32767/v_line_size)*v_line_size;</p> <pre><code>pos := 1;\nwhile (pos &lt; clob_size) loop\n dbms_lob.read(p_clob, v_read_size, pos, c_buf);\n r_buf := utl_encode.base64_decode(utl_raw.cast_to_raw(c_buf));\n dbms_lob.writeappend(r_blob, utl_raw.length(r_buf), r_buf);\n pos := pos + v_read_size;\nend loop;\nreturn r_blob;\n</code></pre> <p>end decodeBase64Clob2Blob;</p> <p>/ encoding in lines of 64 chars ending with CR+NL / function encodeBase64Blob2Clob(p_blob in blob) return clob is r_clob clob; / E.I.Sarmas (github.com/dsnz) 2017-12-07 NOTE: must be multiple of 48 !!! / c_step pls_integer := 12000; c_buf varchar2(32767); begin if p_blob is not null then dbms_lob.createtemporary(r_clob, false, dbms_lob.call); for i in 0 .. trunc((dbms_lob.getlength(p_blob) - 1)/c_step) loop c_buf := utl_raw.cast_to_varchar2(utl_encode.base64_encode(dbms_lob.substr(p_blob, c_step, i * c_step + 1))); / E.I.Sarmas (github.com/dsnz) 2017-12-07 fix for alignment issues must output CR+NL at end always, so will align with the following block and can be decoded correctly assumes ending in CR+NL / if substr(c_buf, length(c_buf)) != chr(10) then c_buf := c_buf || CHR(13) || CHR(10); end if; / dbms_output.put_line( 'l=' || length(c_buf) || ' e=' || ascii(substr(c_buf, length(c_buf) - 1)) || ' ' || ascii(substr(c_buf, length(c_buf))) ); / dbms_lob.writeappend(lob_loc =&gt; r_clob, amount =&gt; length(c_buf), buffer =&gt; c_buf); end loop; end if; return r_clob; end encodeBase64Blob2Clob;</p> <p>--Json Path parser function parsePath(json_path varchar2, base number default 1) return pljson_list as build_path varchar2(32767) := '['; buf varchar2(4); endstring varchar2(1); indx number := 1; ret pljson_list;</p> <pre><code>procedure next_char as\nbegin\n if (indx &lt;= length(json_path)) then\n buf := substr(json_path, indx, 1);\n indx := indx + 1;\n else\n buf := null;\n end if;\nend;\n--skip ws\nprocedure skipws as begin while (buf in (chr(9), chr(10), chr(13), ' ')) loop next_char; end loop; end;\n</code></pre> <p>begin next_char(); while (buf is not null) loop if (buf = '.') then next_char(); if (buf is null) then raise_application_error(-20110, 'JSON Path parse error: . is not a valid json_path end'); end if; if (not regexp_like(buf, '^[[:alnum:]_ ]+', 'c') ) then raise_application_error(-20110, 'JSON Path parse error: alpha-numeric character or space expected at position '||indx); end if;</p> <pre><code> if (build_path != '[') then build_path := build_path || ','; end if;\n build_path := build_path || '\"';\n while (regexp_like(buf, '^[[:alnum:]\\_ ]+', 'c') ) loop\n build_path := build_path || buf;\n next_char();\n end loop;\n build_path := build_path || '\"';\n elsif (buf = '[') then\n next_char();\n skipws();\n if (buf is null) then raise_application_error(-20110, 'JSON Path parse error: [ is not a valid json_path end'); end if;\n if (buf in ('1','2','3','4','5','6','7','8','9') or (buf = '0' and base = 0)) then\n if (build_path != '[') then build_path := build_path || ','; end if;\n while (buf in ('0','1','2','3','4','5','6','7','8','9')) loop\n build_path := build_path || buf;\n next_char();\n end loop;\n elsif (regexp_like(buf, '^(\\\"|\\'')', 'c')) then\n endstring := buf;\n if (build_path != '[') then build_path := build_path || ','; end if;\n build_path := build_path || '\"';\n next_char();\n if (buf is null) then raise_application_error(-20110, 'JSON Path parse error: premature json_path end'); end if;\n while (buf != endstring) loop\n build_path := build_path || buf;\n next_char();\n if (buf is null) then raise_application_error(-20110, 'JSON Path parse error: premature json_path end'); end if;\n if (buf = '\\') then\n next_char();\n build_path := build_path || '\\' || buf;\n next_char();\n end if;\n end loop;\n build_path := build_path || '\"';\n next_char();\n else\n raise_application_error(-20110, 'JSON Path parse error: expected a string or an positive integer at '||indx);\n end if;\n skipws();\n if (buf is null) then raise_application_error(-20110, 'JSON Path parse error: premature json_path end'); end if;\n if (buf != ']') then raise_application_error(-20110, 'JSON Path parse error: no array ending found. found: '|| buf); end if;\n next_char();\n skipws();\n elsif (build_path = '[') then\n if (not regexp_like(buf, '^[[:alnum:]\\_ ]+', 'c') ) then\n raise_application_error(-20110, 'JSON Path parse error: alpha-numeric character or space expected at position '||indx);\n end if;\n build_path := build_path || '\"';\n while (regexp_like(buf, '^[[:alnum:]\\_ ]+', 'c') ) loop\n build_path := build_path || buf;\n next_char();\n end loop;\n build_path := build_path || '\"';\n else\n raise_application_error(-20110, 'JSON Path parse error: expected . or [ found '|| buf || ' at position '|| indx);\n end if;\n\nend loop;\n\nbuild_path := build_path || ']';\nbuild_path := replace(replace(replace(replace(replace(build_path, chr(9), '\\t'), chr(10), '\\n'), chr(13), '\\f'), chr(8), '\\b'), chr(14), '\\r');\n\nret := pljson_list(build_path);\nif (base != 1) then\n --fix base 0 to base 1\n declare\n elem pljson_element;\n begin\n for i in 1 .. ret.count loop\n elem := ret.get(i);\n if (elem.is_number()) then\n ret.replace(i, elem.get_number()+1);\n end if;\n end loop;\n end;\nend if;\n\nreturn ret;\n</code></pre> <p>end parsePath;</p> <p>--JSON pre-parsed path getters / contributed by @asfernandes / function get_json_element(obj pljson, path pljson_list) return pljson_element as path_segments pljson_path := pljson_path(); ret pljson_element; begin if (path.count = 0) then return obj; end if;</p> <pre><code>for i in 1 .. path.count loop\n path_segments.extend;\n if (path.get(i).is_number()) then\n path_segments(path_segments.count) := pljson_path_segment(path.get(i).get_number(), null);\n else\n path_segments(path_segments.count) := pljson_path_segment(null, path.get(i).get_string());\n end if;\nend loop;\n\nobj.get_internal_path(path_segments, 1, ret);\nreturn ret;\n</code></pre> <p>exception when scanner_exception then raise; when parser_exception then raise; when jext_exception then raise; when others then return null; end get_json_element;</p> <p>function get_string(obj pljson, path pljson_list) return varchar2 as temp pljson_element; begin temp := get_json_element(obj, path); if (temp is null or not temp.is_string()) then return null; else return temp.get_string(); end if; end;</p> <p>function get_number(obj pljson, path pljson_list) return number as temp pljson_element; begin temp := get_json_element(obj, path); if (temp is null or not temp.is_number()) then return null; else return temp.get_number(); end if; end;</p> <p>function get_double(obj pljson, path pljson_list) return binary_double as temp pljson_element; begin temp := get_json_element(obj, path); if (temp is null or not temp.is_number()) then return null; else return temp.get_double(); end if; end;</p> <p>function get_json(obj pljson, path pljson_list) return pljson as temp pljson_element; begin temp := get_json_element(obj, path); if (temp is null or not temp.is_object()) then return null; else return treat(temp as pljson); end if; end;</p> <p>function get_json_list(obj pljson, path pljson_list) return pljson_list as temp pljson_element; begin temp := get_json_element(obj, path); if (temp is null or not temp.is_array()) then return null; else return treat(temp as pljson_list); end if; end;</p> <p>function get_bool(obj pljson, path pljson_list) return boolean as temp pljson_element; begin temp := get_json_element(obj, path); if (temp is null or not temp.is_bool()) then return null; else return temp.get_bool(); end if; end;</p> <p>function get_date(obj pljson, path pljson_list) return date as temp pljson_element; begin temp := get_json_element(obj, path); if (temp is null or not is_date(temp)) then return null; else return pljson_ext.to_date(temp); end if; end;</p> <p>--JSON Path getters --saved original code, in case of future bug troubleshooting function get_json_element_original(obj pljson, v_path varchar2, base number default 1) return pljson_element as path pljson_list; ret pljson_element; o pljson; l pljson_list; begin path := parsePath(v_path, base); ret := obj; if (path.count = 0) then return ret; end if;</p> <pre><code>for i in 1 .. path.count loop\n if (path.get(i).is_string()) then\n --string fetch only on json\n ------o := pljson(ret);\n ------ret := o.get(path.get(i).get_string());\n /* E.I.Sarmas (github.com/dsnz) 2020-04-18 use inheritance and avoid treat() */\n ret := ret.get(path.get(i).get_string());\n --experimental, ignore\n --ret := get_piece(o, path.get(i).get_string());\n else\n --number fetch on json and json_list\n if (ret.is_array()) then\n ------l := pljson_list(ret);\n ------ret := l.get(path.get(i).get_number());\n /* E.I.Sarmas (github.com/dsnz) 2020-04-18 use inheritance and avoid treat() */\n ret := ret.get(path.get(i).get_number());\n --experimental, ignore\n --ret := get_piece(l, path.get(i).get_number());\n else\n ------o := pljson(ret);\n ------l := o.get_values();\n ------ret := l.get(path.get(i).get_number());\n /* E.I.Sarmas (github.com/dsnz) 2020-04-18 use inheritance and avoid treat() */\n ret := ret.get(path.get(i).get_number());\n --experimental, ignore\n --ret := get_piece(l, path.get(i).get_number());\n end if;\n end if;\nend loop;\n\nreturn ret;\n</code></pre> <p>exception when scanner_exception then raise; when parser_exception then raise; when jext_exception then raise; when others then return null; end get_json_element_original;</p> <p>function get_json_element(obj pljson, v_path varchar2, base number default 1) return pljson_element as path pljson_list; begin path := parsePath(v_path, base); return get_json_element(obj, path); end get_json_element;</p> <p>function get_string(obj pljson, path varchar2, base number default 1) return varchar2 as temp pljson_element; begin temp := get_json_element(obj, path, base); if (temp is null or not temp.is_string()) then return null; else return temp.get_string(); end if; end;</p> <p>function get_number(obj pljson, path varchar2, base number default 1) return number as temp pljson_element; begin temp := get_json_element(obj, path, base); if (temp is null or not temp.is_number()) then return null; else return temp.get_number(); end if; end;</p> <p>/ E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / function get_double(obj pljson, path varchar2, base number default 1) return binary_double as temp pljson_element; begin temp := get_json_element(obj, path, base); if (temp is null or not temp.is_number()) then return null; else return temp.get_double(); end if; end;</p> <p>function get_json(obj pljson, path varchar2, base number default 1) return pljson as temp pljson_element; begin temp := get_json_element(obj, path, base); if (temp is null or not temp.is_object()) then return null; else return treat(temp as pljson); end if; end;</p> <p>function get_json_list(obj pljson, path varchar2, base number default 1) return pljson_list as temp pljson_element; begin temp := get_json_element(obj, path, base); if (temp is null or not temp.is_array()) then return null; else return treat(temp as pljson_list); end if; end;</p> <p>function get_bool(obj pljson, path varchar2, base number default 1) return boolean as temp pljson_element; begin temp := get_json_element(obj, path, base); if (temp is null or not temp.is_bool()) then return null; else return temp.get_bool(); end if; end;</p> <p>function get_date(obj pljson, path varchar2, base number default 1) return date as temp pljson_element; begin temp := get_json_element(obj, path, base); if (temp is null or not is_date(temp)) then return null; else return pljson_ext.to_date(temp); end if; end;</p> <p>/ JSON pre-parsed path putter internal function / procedure put_internal_preparsed(obj in out nocopy pljson, path pljson_list, elem pljson_element) as path_segments pljson_path := pljson_path(); dummy boolean; begin if (path.count = 0) then raise_application_error(-20110, 'PLJSON_EXT put error: cannot put with empty string.'); end if;</p> <pre><code>for i in 1 .. path.count loop\n path_segments.extend;\n\n if (path.get(i).is_number()) then\n path_segments(path_segments.count) := pljson_path_segment(path.get(i).get_number(), null);\n else\n path_segments(path_segments.count) := pljson_path_segment(null, path.get(i).get_string());\n end if;\nend loop;\n\ndummy := obj.put_internal_path(path_segments, elem, 1);\n</code></pre> <p>end;</p> <p>/ JSON Path putter internal function / --saved original code, in case of future bug troubleshooting procedure put_internal_original(obj in out nocopy pljson, v_path varchar2, elem pljson_element, base number) as val pljson_element := elem; path pljson_list; backreference pljson_list := pljson_list();</p> <pre><code>keyval pljson_element; keynum number; keystring varchar2(4000);\ntemp pljson_element := obj;\nobj_temp pljson;\nlist_temp pljson_list;\ninserter pljson_element;\n</code></pre> <p>begin path := pljson_ext.parsePath(v_path, base); if (path.count = 0) then raise_application_error(-20110, 'PLJSON_EXT put error: cannot put with empty string.'); end if;</p> <pre><code>--build backreference\nfor i in 1 .. path.count loop\n --backreference.print(false);\n keyval := path.get(i);\n if (keyval.is_number()) then\n --number index\n keynum := keyval.get_number();\n if ((not temp.is_object()) and (not temp.is_array())) then\n if (val is null) then return; end if;\n backreference.remove_last;\n temp := pljson_list();\n backreference.append(temp);\n end if;\n\n if (temp.is_object()) then\n obj_temp := pljson(temp);\n if (obj_temp.count &lt; keynum) then\n if (val is null) then return; end if;\n raise_application_error(-20110, 'PLJSON_EXT put error: access object with too few members.');\n end if;\n temp := obj_temp.get(keynum);\n else\n list_temp := pljson_list(temp);\n if (list_temp.count &lt; keynum) then\n if (val is null) then return; end if;\n --raise error or quit if val is null\n for i in list_temp.count+1 .. keynum loop\n list_temp.append(pljson_null());\n end loop;\n backreference.remove_last;\n backreference.append(list_temp);\n end if;\n\n temp := list_temp.get(keynum);\n end if;\n else\n --string index\n keystring := keyval.get_string();\n if (not temp.is_object()) then\n --backreference.print;\n if (val is null) then return; end if;\n backreference.remove_last;\n temp := pljson();\n backreference.append(temp);\n --raise_application_error(-20110, 'PLJSON_EXT put error: trying to access a non object with a string.');\n end if;\n obj_temp := pljson(temp);\n temp := obj_temp.get(keystring);\n end if;\n\n if (temp is null) then\n if (val is null) then return; end if;\n --what to expect?\n keyval := path.get(i+1);\n if (keyval is not null and keyval.is_number()) then\n temp := pljson_list();\n else\n temp := pljson();\n end if;\n end if;\n backreference.append(temp);\nend loop;\n\n-- backreference.print(false);\n-- path.print(false);\n\n--use backreference and path together\ninserter := val;\nfor i in reverse 1 .. backreference.count loop\n -- inserter.print(false);\n if ( i = 1 ) then\n keyval := path.get(1);\n if (keyval.is_string()) then\n keystring := keyval.get_string();\n else\n keynum := keyval.get_number();\n declare\n t1 pljson_element := obj.get(keynum);\n begin\n keystring := t1.mapname;\n end;\n end if;\n if (inserter is null) then obj.remove(keystring); else obj.put(keystring, inserter); end if;\n else\n temp := backreference.get(i-1);\n if (temp.is_object()) then\n keyval := path.get(i);\n obj_temp := pljson(temp);\n if (keyval.is_string()) then\n keystring := keyval.get_string();\n else\n keynum := keyval.get_number();\n declare\n t1 pljson_element := obj_temp.get(keynum);\n begin\n keystring := t1.mapname;\n end;\n end if;\n if (inserter is null) then\n obj_temp.remove(keystring);\n if (obj_temp.count &gt; 0) then inserter := obj_temp; end if;\n else\n obj_temp.put(keystring, inserter);\n inserter := obj_temp;\n end if;\n else\n --array only number\n keynum := path.get(i).get_number();\n list_temp := pljson_list(temp);\n list_temp.remove(keynum);\n if (not inserter is null) then\n list_temp.append(inserter, keynum);\n inserter := list_temp;\n else\n if (list_temp.count &gt; 0) then inserter := list_temp; end if;\n end if;\n end if;\n end if;\n\nend loop;\n</code></pre> <p>end put_internal_original;</p> <p>procedure put_internal(obj in out nocopy pljson, v_path varchar2, elem pljson_element, base number) as path pljson_list; begin path := pljson_ext.parsePath(v_path, base); put_internal_preparsed(obj, path, elem); end put_internal;</p> <p>/ JSON pre-parsed path putters / procedure put(obj in out nocopy pljson, path pljson_list, elem varchar2) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, pljson_string(elem)); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path pljson_list, elem number) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, pljson_number(elem)); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path pljson_list, elem binary_double) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, pljson_number(elem)); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path pljson_list, elem pljson) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, elem); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path pljson_list, elem pljson_list) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, elem); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path pljson_list, elem boolean) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, pljson_bool(elem)); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path pljson_list, elem pljson_element) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, elem); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path pljson_list, elem date) as begin if elem is null then put_internal_preparsed(obj, path, pljson_null()); else put_internal_preparsed(obj, path, pljson_ext.to_json_string(elem)); end if; end;</p> <p>/ JSON Path putters / procedure put(obj in out nocopy pljson, path varchar2, elem varchar2, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, pljson_string(elem), base); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path varchar2, elem number, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, pljson_number(elem), base); end if; end;</p> <p>/ E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / procedure put(obj in out nocopy pljson, path varchar2, elem binary_double, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, pljson_number(elem), base); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path varchar2, elem pljson, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, elem, base); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path varchar2, elem pljson_list, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, elem, base); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path varchar2, elem boolean, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, pljson_bool(elem), base); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path varchar2, elem pljson_element, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, elem, base); end if; end;</p> <p>procedure put(obj in out nocopy pljson, path varchar2, elem date, base number default 1) as begin if elem is null then put_internal(obj, path, pljson_null(), base); else put_internal(obj, path, pljson_ext.to_json_string(elem), base); end if; end;</p> <p>procedure remove(obj in out nocopy pljson, path pljson_list) as begin pljson_ext.put_internal_preparsed(obj, path, null); end remove;</p> <p>procedure remove(obj in out nocopy pljson, path varchar2, base number default 1) as begin pljson_ext.put_internal(obj, path, null, base); --if (json_ext.get_json_element(obj, path) is not null) then --end if; end remove;</p> <p>--Pretty print with JSON Path function pp(obj pljson, v_path varchar2) return varchar2 as json_part pljson_element; begin json_part := pljson_ext.get_json_element(obj, v_path); if (json_part is null) then return ''; else return pljson_printer.pretty_print_any(json_part); --escapes a possible internal string end if; end pp;</p> <p>procedure pp(obj pljson, v_path varchar2) as --using dbms_output.put_line begin dbms_output.put_line(pp(obj, v_path)); end pp;</p> <p>-- spaces = false! procedure pp_htp(obj pljson, v_path varchar2) as --using htp.print json_part pljson_element; begin json_part := pljson_ext.get_json_element(obj, v_path); if (json_part is null) then htp.print; else htp.print(pljson_printer.pretty_print_any(json_part, false)); end if; end pp_htp;</p> <p>function base64(binarydata blob) return pljson_list as obj pljson_list := pljson_list(); c clob := empty_clob();</p> <pre><code>v_clob_offset NUMBER := 1;\nv_lang_context NUMBER := DBMS_LOB.DEFAULT_LANG_CTX;\nv_amount PLS_INTEGER;\n</code></pre> <p>begin dbms_lob.createtemporary(c, false, dbms_lob.call); c := encodeBase64Blob2Clob(binarydata); v_amount := DBMS_LOB.GETLENGTH(c); v_clob_offset := 1; --dbms_output.put_line('V amount: '||v_amount); while (v_clob_offset &lt; v_amount) loop --dbms_output.put_line(v_offset); --temp := ; --dbms_output.put_line('size: '||length(temp)); obj.append(dbms_lob.SUBSTR(c, 4000, v_clob_offset)); v_clob_offset := v_clob_offset + 4000; end loop; dbms_lob.freetemporary(c); --dbms_output.put_line(obj.count); --dbms_output.put_line(obj.get_last().to_char); return obj;</p> <p>end base64;</p> <p>function base64(l pljson_list) return blob as c clob := empty_clob(); b_ret blob;</p> <pre><code>v_lang_context NUMBER := 0; --DBMS_LOB.DEFAULT_LANG_CTX;\n</code></pre> <p>-- v_amount PLS_INTEGER; begin dbms_lob.createtemporary(c, false, dbms_lob.call); for i in 1 .. l.count loop dbms_lob.append(c, l.get(i).get_string()); end loop; -- v_amount := DBMS_LOB.GETLENGTH(c); -- dbms_output.put_line('L C'||v_amount); b_ret := decodeBase64Clob2Blob(c); dbms_lob.freetemporary(c); return b_ret; end base64;</p> <p>function encode(binarydata blob) return pljson_string as obj pljson_string; c clob; v_lang_context NUMBER := DBMS_LOB.DEFAULT_LANG_CTX; begin dbms_lob.createtemporary(c, false, dbms_lob.call); c := encodeBase64Blob2Clob(binarydata); obj := pljson_string(c);</p> <p>--dbms_output.put_line(obj.count); --dbms_output.put_line(obj.get_last().to_char); /dbms_lob.freetemporary(c);/ return obj; end encode;</p> <p>function decode(v pljson_string) return blob as --c clob := empty_clob(); c clob; b_ret blob;</p> <pre><code>v_lang_context NUMBER := 0; --DBMS_LOB.DEFAULT_LANG_CTX;\n</code></pre> <p>-- v_amount PLS_INTEGER; begin / dbms_lob.createtemporary(c, false, dbms_lob.call); v.get_string(c); / c := v.get_clob(); -- v_amount := DBMS_LOB.GETLENGTH(c); -- dbms_output.put_line('L C'||v_amount); b_ret := decodeBase64Clob2Blob(c); /dbms_lob.freetemporary(c);/ return b_ret;</p> <p>end decode;</p> <p>procedure blob2clob(b blob, c out clob, charset varchar2 default 'UTF8') as v_dest_offset integer := 1; v_src_offset integer := 1; v_lang_context integer := 0; v_warning integer := 0; begin dbms_lob.createtemporary(c, false, dbms_lob.call); dbms_lob.converttoclob( dest_lob =&gt; c, src_blob =&gt; b, amount =&gt; dbms_lob.LOBMAXSIZE, dest_offset =&gt; v_dest_offset, src_offset =&gt; v_src_offset, blob_csid =&gt; nls_charset_id(charset), lang_context =&gt; v_lang_context, warning =&gt; v_warning); end; end pljson_ext;```</p>"},{"location":"packages/PLJSON_HELPER/","title":"PLJSON_HELPER","text":""},{"location":"packages/PLJSON_HELPER/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_helper as / Example: set serveroutput on; declare v_a json; v_b json; begin v_a := json('{a:1, b:{a:null}, e:false}'); v_b := json('{c:3, e:{}, b:{b:2}}'); json_helper.merge(v_a, v_b).print(false); end; -- {\"a\":1,\"b\":{\"a\":null,\"b\":2},\"e\":{},\"c\":3} / -- Recursive merge -- Courtesy of Matt Nolan - edited by Jonas Krogsboell function merge(p_a_json pljson, p_b_json pljson) return pljson;</p> <p>-- Join two lists -- json_helper.join(json_list('[1,2,3]'),json_list('[4,5,6]')) -&gt; [1,2,3,4,5,6] function join(p_a_list pljson_list, p_b_list pljson_list) return pljson_list;</p> <p>-- keep only specific keys in json object -- json_helper.keep(json('{a:1,b:2,c:3,d:4,e:5,f:6}'),json_list('[\"a\",\"f\",\"c\"]')) -&gt; {\"a\":1,\"f\":6,\"c\":3} function keep(p_json pljson, p_keys pljson_list) return pljson;</p> <p>-- remove specific keys in json object -- json_helper.remove(json('{a:1,b:2,c:3,d:4,e:5,f:6}'),json_list('[\"a\",\"f\",\"c\"]')) -&gt; {\"b\":2,\"d\":4,\"e\":5} function remove(p_json pljson, p_keys pljson_list) return pljson;</p> <p>--equals function equals(p_v1 pljson_element, p_v2 pljson_element, exact boolean default true) return boolean; function equals(p_v1 pljson_element, p_v2 pljson, exact boolean default true) return boolean; function equals(p_v1 pljson_element, p_v2 pljson_list, exact boolean default true) return boolean; function equals(p_v1 pljson_element, p_v2 number) return boolean; / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / function equals(p_v1 pljson_element, p_v2 binary_double) return boolean; function equals(p_v1 pljson_element, p_v2 varchar2) return boolean; function equals(p_v1 pljson_element, p_v2 boolean) return boolean; function equals(p_v1 pljson_element, p_v2 clob) return boolean; function equals(p_v1 pljson, p_v2 pljson, exact boolean default true) return boolean; function equals(p_v1 pljson_list, p_v2 pljson_list, exact boolean default true) return boolean;</p> <p>--contains json, json_value --contains json_list, json_value function contains(p_v1 pljson, p_v2 pljson_element, exact boolean default false) return boolean; function contains(p_v1 pljson, p_v2 pljson, exact boolean default false) return boolean; function contains(p_v1 pljson, p_v2 pljson_list, exact boolean default false) return boolean; function contains(p_v1 pljson, p_v2 number, exact boolean default false) return boolean; / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / function contains(p_v1 pljson, p_v2 binary_double, exact boolean default false) return boolean; function contains(p_v1 pljson, p_v2 varchar2, exact boolean default false) return boolean; function contains(p_v1 pljson, p_v2 boolean, exact boolean default false) return boolean; function contains(p_v1 pljson, p_v2 clob, exact boolean default false) return boolean;</p> <p>function contains(p_v1 pljson_list, p_v2 pljson_element, exact boolean default false) return boolean; function contains(p_v1 pljson_list, p_v2 pljson, exact boolean default false) return boolean; function contains(p_v1 pljson_list, p_v2 pljson_list, exact boolean default false) return boolean; function contains(p_v1 pljson_list, p_v2 number, exact boolean default false) return boolean; / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / function contains(p_v1 pljson_list, p_v2 binary_double, exact boolean default false) return boolean; function contains(p_v1 pljson_list, p_v2 varchar2, exact boolean default false) return boolean; function contains(p_v1 pljson_list, p_v2 boolean, exact boolean default false) return boolean; function contains(p_v1 pljson_list, p_v2 clob, exact boolean default false) return boolean;</p> <p>end pljson_helper;```</p>"},{"location":"packages/PLJSON_HELPER/#package-body","title":"Package Body","text":"<p>```sql package body pljson_helper as</p> <p>--recursive merge function merge(p_a_json pljson, p_b_json pljson) return pljson as l_json pljson; l_jv pljson_element; l_indx number; l_recursive pljson_element; begin -- -- Initialize our return object -- l_json := p_a_json;</p> <pre><code>-- loop through p_b_json\nl_indx := p_b_json.json_data.first;\nloop\n exit when l_indx is null;\n l_jv := p_b_json.json_data(l_indx);\n if (l_jv.is_object) then\n --recursive\n l_recursive := l_json.get(l_jv.mapname);\n if (l_recursive is not null and l_recursive.is_object) then\n l_json.put(l_jv.mapname, merge(pljson(l_recursive), pljson(l_jv)));\n else\n l_json.put(l_jv.mapname, l_jv);\n end if;\n else\n l_json.put(l_jv.mapname, l_jv);\n end if;\n\n --increment\n l_indx := p_b_json.json_data.next(l_indx);\nend loop;\n\nreturn l_json;\n</code></pre> <p>end merge;</p> <p>-- join two lists function join(p_a_list pljson_list, p_b_list pljson_list) return pljson_list as l_json_list pljson_list := p_a_list; begin for indx in 1 .. p_b_list.count loop l_json_list.append(p_b_list.get(indx)); end loop;</p> <pre><code>return l_json_list;\n</code></pre> <p>end join;</p> <p>-- keep keys. function keep(p_json pljson, p_keys pljson_list) return pljson as l_json pljson := pljson(); mapname varchar2(4000); begin for i in 1 .. p_keys.count loop mapname := p_keys.get(i).get_string(); if (p_json.exist(mapname)) then l_json.put(mapname, p_json.get(mapname)); end if; end loop;</p> <pre><code>return l_json;\n</code></pre> <p>end keep;</p> <p>-- drop keys. function remove(p_json pljson, p_keys pljson_list) return pljson as l_json pljson := p_json; begin for i in 1 .. p_keys.count loop l_json.remove(p_keys.get(i).get_string()); end loop;</p> <pre><code>return l_json;\n</code></pre> <p>end remove;</p> <p>--equals functions</p> <p>function equals(p_v1 pljson_element, p_v2 number) return boolean as begin if (p_v2 is null) then return p_v1.is_null; end if;</p> <pre><code>if (not p_v1.is_number) then\n return false;\nend if;\n\nreturn p_v2 = p_v1.get_number();\n</code></pre> <p>end;</p> <p>/ E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / function equals(p_v1 pljson_element, p_v2 binary_double) return boolean as begin if (p_v2 is null) then return p_v1.is_null; end if;</p> <pre><code>if (not p_v1.is_number) then\n return false;\nend if;\n\nreturn p_v2 = p_v1.get_double();\n</code></pre> <p>end;</p> <p>function equals(p_v1 pljson_element, p_v2 boolean) return boolean as begin if (p_v2 is null) then return p_v1.is_null; end if;</p> <pre><code>if (not p_v1.is_bool) then\n return false;\nend if;\n\nreturn p_v2 = p_v1.get_bool();\n</code></pre> <p>end;</p> <p>function equals(p_v1 pljson_element, p_v2 varchar2) return boolean as begin if (p_v2 is null) then return (p_v1.is_null or p_v1.get_string() is null); end if;</p> <pre><code>if (not p_v1.is_string) then\n return false;\nend if;\n\nreturn p_v2 = p_v1.get_string();\n</code></pre> <p>end;</p> <p>function equals(p_v1 pljson_element, p_v2 clob) return boolean as my_clob clob; res boolean; begin if (p_v2 is null) then return p_v1.is_null; end if;</p> <pre><code>if (not p_v1.is_string) then\n return false;\nend if;\n\n/*\nmy_clob := empty_clob();\ndbms_lob.createtemporary(my_clob, true);\np_v1.get_string(my_clob);\n*/\nmy_clob := p_v1.get_clob();\nres := dbms_lob.compare(p_v2, my_clob) = 0;\n/*dbms_lob.freetemporary(my_clob);*/\nreturn res;\n</code></pre> <p>end;</p> <p>function equals(p_v1 pljson_element, p_v2 pljson_element, exact boolean) return boolean as begin if (p_v2 is null or p_v2.is_null) then return (p_v1 is null or p_v1.is_null); end if;</p> <pre><code>if (p_v2.is_number) then return equals(p_v1, p_v2.get_number); end if;\nif (p_v2.is_bool) then return equals(p_v1, p_v2.get_bool); end if;\nif (p_v2.is_object) then return equals(p_v1, pljson(p_v2), exact); end if;\nif (p_v2.is_array) then return equals(p_v1, pljson_list(p_v2), exact); end if;\nif (p_v2.is_string) then\n if (treat(p_v2 as pljson_string).extended_str is null) then\n return equals(p_v1, p_v2.get_string);\n else\n declare\n my_clob clob; res boolean;\n begin\n /*\n my_clob := empty_clob();\n dbms_lob.createtemporary(my_clob, true);\n p_v2.get_string(my_clob);\n */\n my_clob := p_v2.get_clob();\n res := equals(p_v1, my_clob);\n /*dbms_lob.freetemporary(my_clob);*/\n return res;\n end;\n end if;\nend if;\n\nreturn false; --should never happen\n</code></pre> <p>end;</p> <p>function equals(p_v1 pljson_element, p_v2 pljson_list, exact boolean) return boolean as cmp pljson_list; res boolean := true; begin -- p_v1.print(false); -- p_v2.print(false); -- dbms_output.put_line('labc1'||case when exact then 'X' else 'U' end);</p> <pre><code>if (p_v2 is null) then\n return p_v1.is_null;\nend if;\n\nif (not p_v1.is_array) then\n return false;\nend if;\n</code></pre> <p>-- dbms_output.put_line('labc2'||case when exact then 'X' else 'U' end);</p> <pre><code>cmp := pljson_list(p_v1);\nif (cmp.count != p_v2.count and exact) then return false; end if;\n</code></pre> <p>-- dbms_output.put_line('labc3'||case when exact then 'X' else 'U' end);</p> <pre><code>if (exact) then\n for i in 1 .. cmp.count loop\n res := equals(cmp.get(i), p_v2.get(i), exact);\n if (not res) then return res; end if;\n end loop;\nelse\n</code></pre> <p>-- dbms_output.put_line('labc4'||case when exact then 'X' else 'U' end); if (p_v2.count &gt; cmp.count) then return false; end if; -- dbms_output.put_line('labc5'||case when exact then 'X' else 'U' end);</p> <pre><code> --match sublist here!\n for x in 0 .. (cmp.count-p_v2.count) loop\n</code></pre> <p>-- dbms_output.put_line('labc7'||x);</p> <pre><code> for i in 1 .. p_v2.count loop\n res := equals(cmp.get(x+i), p_v2.get(i), exact);\n if (not res) then\n goto next_index;\n end if;\n end loop;\n return true;\n\n &lt;&lt;next_index&gt;&gt;\n null;\n end loop;\n</code></pre> <p>-- dbms_output.put_line('labc7'||case when exact then 'X' else 'U' end);</p> <pre><code>return false; --no match\n\nend if;\n\nreturn res;\n</code></pre> <p>end;</p> <p>function equals(p_v1 pljson_element, p_v2 pljson, exact boolean) return boolean as cmp pljson; res boolean := true; begin -- p_v1.print(false); -- p_v2.print(false); -- dbms_output.put_line('abc1');</p> <pre><code>if (p_v2 is null) then\n return p_v1.is_null;\nend if;\n\nif (not p_v1.is_object) then\n return false;\nend if;\n\ncmp := pljson(p_v1);\n</code></pre> <p>-- dbms_output.put_line('abc2');</p> <pre><code>if (cmp.count != p_v2.count and exact) then return false; end if;\n</code></pre> <p>-- dbms_output.put_line('abc3'); declare k1 pljson_list := p_v2.get_keys(); key_index number; begin for i in 1 .. k1.count loop key_index := cmp.index_of(k1.get(i).get_string()); if (key_index = -1) then return false; end if; if (exact) then if (not equals(p_v2.get(i), cmp.get(key_index), true)) then return false; end if; else --non exact declare v1 pljson_element := cmp.get(key_index); v2 pljson_element := p_v2.get(i); begin -- dbms_output.put_line('abc3 1/2'); -- v1.print(false); -- v2.print(false);</p> <pre><code> if (v1.is_object and v2.is_object) then\n if (not equals(v1, v2, false)) then return false; end if;\n elsif (v1.is_array and v2.is_array) then\n if (not equals(v1, v2, false)) then return false; end if;\n else\n if (not equals(v1, v2, true)) then return false; end if;\n end if;\n end;\n\n end if;\n end loop;\nend;\n</code></pre> <p>-- dbms_output.put_line('abc4');</p> <pre><code>return true;\n</code></pre> <p>end;</p> <p>function equals(p_v1 pljson, p_v2 pljson, exact boolean) return boolean as begin return equals(p_v1, p_v2, exact); end;</p> <p>function equals(p_v1 pljson_list, p_v2 pljson_list, exact boolean) return boolean as begin return equals(p_v1, p_v2, exact); end;</p> <p>--contain function contains(p_v1 pljson, p_v2 pljson_element, exact boolean) return boolean as v_values pljson_list; begin if (equals(p_v1, p_v2, exact)) then return true; end if;</p> <pre><code>v_values := p_v1.get_values();\n\nfor i in 1 .. v_values.count loop\n declare\n v_val pljson_element := v_values.get(i);\n begin\n if (v_val.is_object) then\n if (contains(pljson(v_val), p_v2, exact)) then return true; end if;\n end if;\n if (v_val.is_array) then\n if (contains(pljson_list(v_val), p_v2, exact)) then return true; end if;\n end if;\n\n if (equals(v_val, p_v2, exact)) then return true; end if;\n end;\n\nend loop;\n\nreturn false;\n</code></pre> <p>end;</p> <p>function contains(p_v1 pljson_list, p_v2 pljson_element, exact boolean) return boolean as begin if (equals(p_v1, p_v2, exact)) then return true; end if;</p> <pre><code>for i in 1 .. p_v1.count loop\n declare\n v_val pljson_element := p_v1.get(i);\n begin\n if (v_val.is_object) then\n if (contains(pljson(v_val), p_v2, exact)) then return true; end if;\n end if;\n if (v_val.is_array) then\n if (contains(pljson_list(v_val), p_v2, exact)) then return true; end if;\n end if;\n\n if (equals(v_val, p_v2, exact)) then return true; end if;\n end;\n\nend loop;\n\nreturn false;\n</code></pre> <p>end;</p> <p>function contains(p_v1 pljson, p_v2 pljson, exact boolean ) return boolean as begin return contains(p_v1, p_v2, exact); end; function contains(p_v1 pljson, p_v2 pljson_list, exact boolean ) return boolean as begin return contains(p_v1, p_v2, exact); end; function contains(p_v1 pljson, p_v2 number, exact boolean ) return boolean as begin return contains(p_v1, pljson_number(p_v2), exact); end; / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / function contains(p_v1 pljson, p_v2 binary_double, exact boolean ) return boolean as begin return contains(p_v1, pljson_number(p_v2), exact); end; function contains(p_v1 pljson, p_v2 varchar2, exact boolean ) return boolean as begin return contains(p_v1, pljson_string(p_v2), exact); end; function contains(p_v1 pljson, p_v2 boolean, exact boolean ) return boolean as begin return contains(p_v1, pljson_bool(p_v2), exact); end; function contains(p_v1 pljson, p_v2 clob, exact boolean ) return boolean as begin return contains(p_v1, pljson_string(p_v2), exact); end;</p> <p>function contains(p_v1 pljson_list, p_v2 pljson, exact boolean ) return boolean as begin return contains(p_v1, p_v2, exact); end; function contains(p_v1 pljson_list, p_v2 pljson_list, exact boolean ) return boolean as begin return contains(p_v1, p_v2, exact); end; function contains(p_v1 pljson_list, p_v2 number, exact boolean ) return boolean as begin return contains(p_v1, pljson_number(p_v2), exact); end; / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / function contains(p_v1 pljson_list, p_v2 binary_double, exact boolean ) return boolean as begin return contains(p_v1, pljson_number(p_v2), exact); end; function contains(p_v1 pljson_list, p_v2 varchar2, exact boolean ) return boolean as begin return contains(p_v1, pljson_string(p_v2), exact); end; function contains(p_v1 pljson_list, p_v2 boolean, exact boolean ) return boolean as begin return contains(p_v1, pljson_bool(p_v2), exact); end; function contains(p_v1 pljson_list, p_v2 clob, exact boolean ) return boolean as begin return contains(p_v1, pljson_string(p_v2), exact); end;</p> <p>end pljson_helper;```</p>"},{"location":"packages/PLJSON_ML/","title":"PLJSON_ML","text":""},{"location":"packages/PLJSON_ML/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_ml as /* Copyright (c) 2010 Jonas Krogsboell</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */</p> <p>/ This package contains extra methods to lookup types and an easy way of adding date values in json - without changing the structure /</p> <p>jsonml_stylesheet xmltype := null;</p> <p>function xml2json(xml in xmltype) return pljson_list; function xmlstr2json(xmlstr in varchar2) return pljson_list;</p> <p>end pljson_ml;```</p>"},{"location":"packages/PLJSON_ML/#package-body","title":"Package Body","text":"<p>```sql package body pljson_ml as function get_jsonml_stylesheet return xmltype;</p> <p>function xml2json(xml in xmltype) return pljson_list as l_json xmltype; l_returnvalue clob; begin l_json := xml.transform (get_jsonml_stylesheet); l_returnvalue := l_json.getclobval(); l_returnvalue := dbms_xmlgen.convert (l_returnvalue, dbms_xmlgen.entity_decode); --dbms_output.put_line(l_returnvalue); return pljson_list(l_returnvalue); end xml2json;</p> <p>function xmlstr2json(xmlstr in varchar2) return pljson_list as begin return xml2json(xmltype(xmlstr)); end xmlstr2json;</p> <p>function get_jsonml_stylesheet return xmltype as begin if (jsonml_stylesheet is null) then jsonml_stylesheet := xmltype('</p> <p> <pre><code>&lt;xsl:output method=\"text\"\n media-type=\"application/json\"\n encoding=\"UTF-8\"\n indent=\"no\"\n omit-xml-declaration=\"yes\" /&gt;\n\n&lt;!-- constants --&gt;\n&lt;xsl:variable name=\"XHTML\"\n select=\"''http://www.w3.org/1999/xhtml''\" /&gt;\n\n&lt;xsl:variable name=\"START_ELEM\"\n select=\"''[''\" /&gt;\n\n&lt;xsl:variable name=\"END_ELEM\"\n select=\"'']''\" /&gt;\n\n&lt;xsl:variable name=\"VALUE_DELIM\"\n select=\"'',''\" /&gt;\n\n&lt;xsl:variable name=\"START_ATTRIB\"\n select=\"''{''\" /&gt;\n\n&lt;xsl:variable name=\"END_ATTRIB\"\n select=\"''}''\" /&gt;\n\n&lt;xsl:variable name=\"NAME_DELIM\"\n select=\"'':''\" /&gt;\n\n&lt;xsl:variable name=\"STRING_DELIM\"\n select=\"''&amp;#x22;''\" /&gt;\n\n&lt;xsl:variable name=\"START_COMMENT\"\n select=\"''/*''\" /&gt;\n\n&lt;xsl:variable name=\"END_COMMENT\"\n select=\"''*/''\" /&gt;\n\n&lt;!-- root-node --&gt;\n&lt;xsl:template match=\"/\"&gt;\n &lt;xsl:apply-templates select=\"*\" /&gt;\n&lt;/xsl:template&gt;\n\n&lt;!-- comments --&gt;\n&lt;xsl:template match=\"comment()\"&gt;\n&lt;!-- uncomment to support JSON comments --&gt;\n&lt;!--\n &lt;xsl:value-of select=\"$START_COMMENT\" /&gt;\n\n &lt;xsl:value-of select=\".\"\n disable-output-escaping=\"yes\" /&gt;\n\n &lt;xsl:value-of select=\"$END_COMMENT\" /&gt;\n--&gt;\n&lt;/xsl:template&gt;\n\n&lt;!-- elements --&gt;\n&lt;xsl:template match=\"*\"&gt;\n &lt;xsl:value-of select=\"$START_ELEM\" /&gt;\n\n &lt;!-- tag-name string --&gt;\n &lt;xsl:value-of select=\"$STRING_DELIM\" /&gt;\n &lt;xsl:choose&gt;\n &lt;xsl:when test=\"namespace-uri()=$XHTML\"&gt;\n &lt;xsl:value-of select=\"local-name()\" /&gt;\n &lt;/xsl:when&gt;\n &lt;xsl:otherwise&gt;\n &lt;xsl:value-of select=\"name()\" /&gt;\n &lt;/xsl:otherwise&gt;\n &lt;/xsl:choose&gt;\n &lt;xsl:value-of select=\"$STRING_DELIM\" /&gt;\n\n &lt;!-- attribute object --&gt;\n &lt;xsl:if test=\"count(@*)&gt;0\"&gt;\n &lt;xsl:value-of select=\"$VALUE_DELIM\" /&gt;\n &lt;xsl:value-of select=\"$START_ATTRIB\" /&gt;\n &lt;xsl:for-each select=\"@*\"&gt;\n &lt;xsl:if test=\"position()&gt;1\"&gt;\n &lt;xsl:value-of select=\"$VALUE_DELIM\" /&gt;\n &lt;/xsl:if&gt;\n &lt;xsl:apply-templates select=\".\" /&gt;\n &lt;/xsl:for-each&gt;\n &lt;xsl:value-of select=\"$END_ATTRIB\" /&gt;\n &lt;/xsl:if&gt;\n\n &lt;!-- child elements and text-nodes --&gt;\n &lt;xsl:for-each select=\"*|text()\"&gt;\n &lt;xsl:value-of select=\"$VALUE_DELIM\" /&gt;\n &lt;xsl:apply-templates select=\".\" /&gt;\n &lt;/xsl:for-each&gt;\n\n &lt;xsl:value-of select=\"$END_ELEM\" /&gt;\n&lt;/xsl:template&gt;\n\n&lt;!-- text-nodes --&gt;\n&lt;xsl:template match=\"text()\"&gt;\n &lt;xsl:call-template name=\"escape-string\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\".\" /&gt;\n &lt;/xsl:call-template&gt;\n&lt;/xsl:template&gt;\n\n&lt;!-- attributes --&gt;\n&lt;xsl:template match=\"@*\"&gt;\n &lt;xsl:value-of select=\"$STRING_DELIM\" /&gt;\n &lt;xsl:choose&gt;\n &lt;xsl:when test=\"namespace-uri()=$XHTML\"&gt;\n &lt;xsl:value-of select=\"local-name()\" /&gt;\n &lt;/xsl:when&gt;\n &lt;xsl:otherwise&gt;\n &lt;xsl:value-of select=\"name()\" /&gt;\n &lt;/xsl:otherwise&gt;\n &lt;/xsl:choose&gt;\n &lt;xsl:value-of select=\"$STRING_DELIM\" /&gt;\n\n &lt;xsl:value-of select=\"$NAME_DELIM\" /&gt;\n\n &lt;xsl:call-template name=\"escape-string\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\".\" /&gt;\n &lt;/xsl:call-template&gt;\n\n&lt;/xsl:template&gt;\n\n&lt;!-- escape-string: quotes and escapes --&gt;\n&lt;xsl:template name=\"escape-string\"&gt;\n &lt;xsl:param name=\"value\" /&gt;\n\n &lt;xsl:value-of select=\"$STRING_DELIM\" /&gt;\n\n &lt;xsl:if test=\"string-length($value)&gt;0\"&gt;\n &lt;xsl:variable name=\"escaped-whacks\"&gt;\n &lt;!-- escape backslashes --&gt;\n &lt;xsl:call-template name=\"string-replace\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\"$value\" /&gt;\n &lt;xsl:with-param name=\"find\"\n select=\"''\\''\" /&gt;\n &lt;xsl:with-param name=\"replace\"\n select=\"''\\\\''\" /&gt;\n &lt;/xsl:call-template&gt;\n &lt;/xsl:variable&gt;\n\n &lt;xsl:variable name=\"escaped-LF\"&gt;\n &lt;!-- escape line feeds --&gt;\n &lt;xsl:call-template name=\"string-replace\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\"$escaped-whacks\" /&gt;\n &lt;xsl:with-param name=\"find\"\n select=\"''&amp;#x0A;''\" /&gt;\n &lt;xsl:with-param name=\"replace\"\n select=\"''\\n''\" /&gt;\n &lt;/xsl:call-template&gt;\n &lt;/xsl:variable&gt;\n\n &lt;xsl:variable name=\"escaped-CR\"&gt;\n &lt;!-- escape carriage returns --&gt;\n &lt;xsl:call-template name=\"string-replace\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\"$escaped-LF\" /&gt;\n &lt;xsl:with-param name=\"find\"\n select=\"''&amp;#x0D;''\" /&gt;\n &lt;xsl:with-param name=\"replace\"\n select=\"''\\r''\" /&gt;\n &lt;/xsl:call-template&gt;\n &lt;/xsl:variable&gt;\n\n &lt;xsl:variable name=\"escaped-tabs\"&gt;\n &lt;!-- escape tabs --&gt;\n &lt;xsl:call-template name=\"string-replace\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\"$escaped-CR\" /&gt;\n &lt;xsl:with-param name=\"find\"\n select=\"''&amp;#x09;''\" /&gt;\n &lt;xsl:with-param name=\"replace\"\n select=\"''\\t''\" /&gt;\n &lt;/xsl:call-template&gt;\n &lt;/xsl:variable&gt;\n\n &lt;!-- escape quotes --&gt;\n &lt;xsl:call-template name=\"string-replace\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\"$escaped-tabs\" /&gt;\n &lt;xsl:with-param name=\"find\"\n select=\"''&amp;quot;''\" /&gt;\n &lt;xsl:with-param name=\"replace\"\n select=\"''\\&amp;quot;''\" /&gt;\n &lt;/xsl:call-template&gt;\n &lt;/xsl:if&gt;\n\n &lt;xsl:value-of select=\"$STRING_DELIM\" /&gt;\n&lt;/xsl:template&gt;\n\n&lt;!-- string-replace: replaces occurances of one string with another --&gt;\n&lt;xsl:template name=\"string-replace\"&gt;\n &lt;xsl:param name=\"value\" /&gt;\n &lt;xsl:param name=\"find\" /&gt;\n &lt;xsl:param name=\"replace\" /&gt;\n\n &lt;xsl:choose&gt;\n &lt;xsl:when test=\"contains($value,$find)\"&gt;\n &lt;!-- replace and call recursively on next --&gt;\n &lt;xsl:value-of select=\"substring-before($value,$find)\"\n disable-output-escaping=\"yes\" /&gt;\n &lt;xsl:value-of select=\"$replace\"\n disable-output-escaping=\"yes\" /&gt;\n &lt;xsl:call-template name=\"string-replace\"&gt;\n &lt;xsl:with-param name=\"value\"\n select=\"substring-after($value,$find)\" /&gt;\n &lt;xsl:with-param name=\"find\"\n select=\"$find\" /&gt;\n &lt;xsl:with-param name=\"replace\"\n select=\"$replace\" /&gt;\n &lt;/xsl:call-template&gt;\n &lt;/xsl:when&gt;\n &lt;xsl:otherwise&gt;\n &lt;!-- no replacement necessary --&gt;\n &lt;xsl:value-of select=\"$value\"\n disable-output-escaping=\"yes\" /&gt;\n &lt;/xsl:otherwise&gt;\n &lt;/xsl:choose&gt;\n&lt;/xsl:template&gt;\n</code></pre> <p>'); end if; return jsonml_stylesheet; end get_jsonml_stylesheet;</p> <p>end pljson_ml;```</p>"},{"location":"packages/PLJSON_OBJECT_CACHE/","title":"PLJSON_OBJECT_CACHE","text":""},{"location":"packages/PLJSON_OBJECT_CACHE/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_object_cache as</p> <p>/ E.I.Sarmas (github.com/dsnz) 2020-04-18 object cache to speed up internal operations /</p> <p>/ !!! NOTE: this package is used internally by pljson and it's not part of the api !!! /</p> <p>/ index by string of \"id.path\" or \"path\" / type pljson_element_tab is table of pljson_element index by varchar2(250);</p> <p>last_id number := 0; pljson_element_cache pljson_element_tab; cache_reqs number := 0; cache_hits number := 0; cache_invalid_reqs number := 0;</p> <p>type vset is table of varchar2(1) index by varchar2(250); names_set vset;</p> <p>procedure set_names_set(names pljson_varray); function in_names_set(a_name varchar2) return boolean;</p> <p>procedure reset; procedure flush; procedure print_stats; function next_id return number; function object_key(elem pljson_element, piece varchar2) return varchar2; function get(key varchar2) return pljson_element; procedure set(key varchar2, val pljson_element); end;```</p>"},{"location":"packages/PLJSON_OBJECT_CACHE/#package-body","title":"Package Body","text":"<p>```sql package body pljson_object_cache as</p> <p>/ E.I.Sarmas (github.com/dsnz) 2020-04-18 object cache to speed up internal operations /</p> <p>/ !!! NOTE: this package is used internally by pljson and it's not part of the api !!! /</p> <p>procedure set_names_set(names pljson_varray) is begin if names.COUNT = 0 then return; end if; for i in names.FIRST .. names.LAST loop names_set(names(i)) := '1'; end loop; end;</p> <p>function in_names_set(a_name varchar2) return boolean is begin if names_set.exists(a_name) then return true; else return false; end if; end;</p> <p>procedure reset is begin last_id := 0; flush; end;</p> <p>procedure flush is begin pljson_element_cache.delete; cache_reqs := 0; cache_hits := 0; cache_invalid_reqs := 0; end;</p> <p>procedure print_stats is begin dbms_output.put_line('reqs = ' || cache_reqs); dbms_output.put_line('hits = ' || cache_hits); dbms_output.put_line('invalid reqs = ' || cache_invalid_reqs); dbms_output.put_line('cache count = ' || pljson_element_cache.count); dbms_output.put_line('id count = ' || last_id); end;</p> <p>function next_id return number is begin last_id := last_id + 1; return last_id; end;</p> <p>function object_key(elem pljson_element, piece varchar2) return varchar2 is key varchar2(250); begin if elem.object_id is null or elem.object_id = 0 then cache_invalid_reqs := cache_invalid_reqs + 1; return null; end if; key := to_char(elem.object_id)||'.'||piece; return key; end;</p> <p>function get(key varchar2) return pljson_element is cache_key varchar2(32767); begin cache_key := key; if cache_key is null then cache_key := '$'; end if; cache_reqs := cache_reqs + 1; if pljson_element_cache.exists(cache_key) then cache_hits := cache_hits + 1; return pljson_element_cache(cache_key); else return null; end if; end;</p> <p>procedure set(key varchar2, val pljson_element) is cache_key varchar2(32767); begin cache_key := key; if cache_key is null then cache_key := '$'; end if; --dbms_output.put_line('caching: ' || cache_key); pljson_element_cache(cache_key) := val; end;</p> <p>/* -- experimental, ignore -- to use with 'get_json_element'</p> <p>function get_piece(elem pljson, piece varchar2) return pljson_element is key varchar2(250); val pljson_element; begin key := object_cache.object_key(elem, piece); if key is null then return elem.get(piece); end if; val := object_cache.get(key); if val is not null then return val; else val := elem.get(piece); object_cache.set(key, val); return val; end if; end;</p> <p>function get_piece(elem pljson_list, piece varchar2) return pljson_element is key varchar2(250); val pljson_element; begin key := object_cache.object_key(elem, piece); if key is null then return elem.get(piece); end if; val := object_cache.get(key); if val is not null then return val; else val := elem.get(piece); object_cache.set(key, val); return val; end if; end; */ end;```</p>"},{"location":"packages/PLJSON_PARSER/","title":"PLJSON_PARSER","text":""},{"location":"packages/PLJSON_PARSER/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_parser as /* Copyright (c) 2010 Jonas Krogsboell</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */</p> <p>/ Internal type for processing. / / scanner tokens: '{', '}', ',', ':', '[', ']', STRING, NUMBER, TRUE, FALSE, NULL */ type rToken IS RECORD ( type_name VARCHAR2(7), line PLS_INTEGER, col PLS_INTEGER, data VARCHAR2(32767), data_overflow clob); -- max_string_size</p> <p>type lTokens is table of rToken index by pls_integer; type json_src is record (len number, offset number, offset_chars number, src varchar2(32767), s_clob clob);</p> <p>json_strict boolean not null := false;</p> <p>ucs2_exception EXCEPTION; pragma exception_init(ucs2_exception, -22831);</p> <p>function lengthcc(buf clob) return number;</p> <p>function next_char(indx number, s in out nocopy json_src) return varchar2; function next_char2(indx number, s in out nocopy json_src, amount number default 1) return varchar2; function parseObj(tokens lTokens, indx in out nocopy pls_integer) return pljson;</p> <p>function prepareClob(buf in clob) return pljson_parser.json_src; function prepareVarchar2(buf in varchar2) return pljson_parser.json_src; function lexer(jsrc in out nocopy json_src) return lTokens; procedure print_token(t rToken);</p> <p>/* * <p>Primary parsing method. It can parse a JSON object.</p> * * @return An instance of <code>pljson</code>. * @throws PARSER_ERROR -20101 when invalid input found. * @throws SCANNER_ERROR -20100 when lexing fails. / function parser(str varchar2) return pljson; function parse_list(str varchar2) return pljson_list; function parse_any(str varchar2) return pljson_element; function parser(str clob) return pljson; function parse_list(str clob) return pljson_list; function parse_any(str clob) return pljson_element; procedure remove_duplicates(obj in out nocopy pljson); function get_version return varchar2;</p> <p>end pljson_parser;```</p>"},{"location":"packages/PLJSON_PARSER/#package-body","title":"Package Body","text":"<p>```sql package body pljson_parser as /* Copyright (c) 2009 Jonas Krogsboell</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */</p> <p>decimalpoint varchar2(1 char) := '.';</p> <p>/ moved to package spec ucs2_exception EXCEPTION; pragma exception_init(ucs2_exception, -22831); /</p> <p>function lengthcc(buf clob) return number as offset number := 0; len number := 0; src varchar2(32767); src_len number; begin while true loop begin src := dbms_lob.substr(buf, 4000, offset+1); exception when ucs2_exception then src := dbms_lob.substr(buf, 3999, offset+1); end; exit when src is null; len := len + length(src); offset := offset + length2(src); --dbms_output.put_line('offset = ' || offset || ' len = ' || len); end loop; return len; end;</p> <p>procedure update_decimalpoint as begin select substr(value, 1, 1) into decimalpoint from nls_session_parameters where parameter = 'NLS_NUMERIC_CHARACTERS'; end update_decimalpoint;</p> <p>/ type json_src is record (len number, offset number, src varchar2(32767), s_clob clob); / / assertions offset: contains 0-base offset of buffer, so 1-st entry is offset + 1, 4000-th entry = offset + 4000 src: contains offset + 1 .. offset + 4000, ex. 1..4000, 4001..8000, etc. / function next_char(indx number, s in out nocopy json_src) return varchar2 as begin if (indx &gt; s.len) then return null; end if;</p> <pre><code>--right offset?\n/* if (indx &gt; 4000 + s.offset or indx &lt; s.offset) then */\n/* fix for issue #37 */\n/* code before fix for issue #169\nif (indx &gt; 4000 + s.offset or indx &lt;= s.offset) then\n s.offset := indx - (indx mod 4000);\n -- addon fix for issue #37\n if s.offset = indx then\n s.offset := s.offset - 4000;\n end if;\n s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);\nend if;\n--read from s.src\nreturn substr(s.src, indx-s.offset, 1);\n*/\n\n/* use of length, so works correctly for 4-byte unicode characters (issue #169) */\n/* lengthc does not work (issue #190) */\nif (indx &gt; length(s.src) + s.offset_chars) then\n while (indx &gt; length(s.src) + s.offset_chars) loop\n s.offset_chars := s.offset_chars + length(s.src);\n s.offset := s.offset + length2(s.src);\n /* exception check, so works correctly for 4-byte unicode characters (issue #169) */\n begin\n s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);\n exception\n when ucs2_exception then\n s.src := dbms_lob.substr(s.s_clob, 3999, s.offset+1);\n end;\n end loop;\nelsif (indx &lt;= s.offset_chars) then\n s.offset_chars := 0;\n s.offset := 0;\n /* exception check, so works correctly for 4-byte unicode characters (issue #169) */\n begin\n s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);\n exception\n when ucs2_exception then\n s.src := dbms_lob.substr(s.s_clob, 3999, s.offset+1);\n end;\n while (indx &gt; length(s.src) + s.offset_chars) loop\n s.offset_chars := s.offset_chars + length(s.src);\n s.offset := s.offset + length2(s.src);\n /* exception check, so works correctly for 4-byte unicode characters (issue #169) */\n begin\n s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);\n exception\n when ucs2_exception then\n s.src := dbms_lob.substr(s.s_clob, 3999, s.offset+1);\n end;\n end loop;\nend if;\n--dbms_output.put_line('indx: ' || indx || ' offset: ' || s.offset || ' (chars: ' || s.offset_chars || ') src chars: ' || length(s.src));\n--read from s.src\nreturn substr(s.src, indx-s.offset_chars, 1);\n</code></pre> <p>end;</p> <p>function next_char2(indx number, s in out nocopy json_src, amount number default 1) return varchar2 as buf varchar2(32767) := ''; begin for i in 1..amount loop buf := buf || next_char(indx-1+i, s); end loop; return buf; end;</p> <p>function prepareClob(buf clob) return pljson_parser.json_src as temp pljson_parser.json_src; begin temp.s_clob := buf; temp.offset_chars := 0; temp.offset := 0; / exception check, so works correctly for 4-byte unicode characters (issue #169) / begin temp.src := dbms_lob.substr(buf, 4000, temp.offset+1); exception when ucs2_exception then temp.src := dbms_lob.substr(buf, 3999, temp.offset+1); end; / use of lengthcc, so works correctly for 4-byte unicode characters (issue #169) / temp.len := lengthcc(buf); --dbms_lob.getlength(buf); return temp; end;</p> <p>function prepareVarchar2(buf varchar2) return pljson_parser.json_src as temp pljson_parser.json_src; begin temp.s_clob := buf; temp.offset_chars := 0; temp.offset := 0; temp.src := substr(buf, 1, 4000); temp.len := length(buf); return temp; end;</p> <p>procedure debug(text varchar2) as begin dbms_output.put_line(text); end;</p> <p>procedure print_token(t rToken) as begin dbms_output.put_line('Line: '||t.line||' - Column: '||t.col||' - Type: '||t.type_name||' - Content: '||t.data); end print_token;</p> <p>/ SCANNER FUNCTIONS START / procedure s_error(text varchar2, line number, col number) as begin raise_application_error(-20100, 'JSON Scanner exception @ line: '||line||' column: '||col||' - '||text); end;</p> <p>procedure s_error(text varchar2, tok rToken) as begin raise_application_error(-20100, 'JSON Scanner exception @ line: '||tok.line||' column: '||tok.col||' - '||text); end;</p> <p>function mt(t varchar2, l pls_integer, c pls_integer, d varchar2) return rToken as token rToken; begin token.type_name := t; token.line := l; token.col := c; token.data := d; return token; end;</p> <p>function lexNumber(jsrc in out nocopy json_src, tok in out nocopy rToken, indx in out nocopy pls_integer) return pls_integer as numbuf varchar2(4000) := ''; buf varchar2(4); checkLoop boolean; begin buf := next_char(indx, jsrc); if (buf = '-') then numbuf := '-'; indx := indx + 1; end if; buf := next_char(indx, jsrc); --0 or 1-9* if (buf = '0') then numbuf := numbuf || '0'; indx := indx + 1; buf := next_char(indx, jsrc); elsif (buf &gt;= '1' and buf &lt;= '9') then numbuf := numbuf || buf; indx := indx + 1; --read digits buf := next_char(indx, jsrc); while (buf &gt;= '0' and buf &lt;= '9') loop numbuf := numbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); end loop; end if; --fraction if (buf = '.') then numbuf := numbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); checkLoop := FALSE; while (buf &gt;= '0' and buf &lt;= '9') loop checkLoop := TRUE; numbuf := numbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); end loop; if (not checkLoop) then s_error('Expected: digits in fraction', tok); end if; end if; --exp part if (buf in ('e', 'E')) then numbuf := numbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); if (buf = '+' or buf = '-') then numbuf := numbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); end if; checkLoop := FALSE; while (buf &gt;= '0' and buf &lt;= '9') loop checkLoop := TRUE; numbuf := numbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); end loop; if (not checkLoop) then s_error('Expected: digits in exp', tok); end if; end if;</p> <pre><code>tok.data := numbuf;\nreturn indx;\n</code></pre> <p>end lexNumber;</p> <p>-- a-zA-Z* function lexName(jsrc in out nocopy json_src, tok in out nocopy rToken, indx in out nocopy pls_integer) return pls_integer as varbuf varchar2(32767) := ''; buf varchar(4); num number; begin buf := next_char(indx, jsrc); while (REGEXP_LIKE(buf, '^[[:alnum:]_]$', 'i')) loop varbuf := varbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); if (buf is null) then goto retname; --debug('Premature string ending'); end if; end loop; &lt;&gt; --could check for reserved keywords here --debug(varbuf); tok.data := varbuf; return indx-1; end lexName; <p>procedure updateClob(v_extended in out nocopy clob, v_str varchar2) as begin / use of length2, so works correctly for 4-byte unicode characters (issue #169) / dbms_lob.writeappend(v_extended, length2(v_str), v_str); end updateClob;</p> <p>function lexString(jsrc in out nocopy json_src, tok in out nocopy rToken, indx in out nocopy pls_integer, endChar char) return pls_integer as v_extended clob := null; v_count number := 0; varbuf varchar2(32767) := ''; buf varchar(4); wrong boolean; max_string_chars number := 5000; / chunk size, less than this number may be copied / begin indx := indx + 1; buf := next_char(indx, jsrc); while (buf != endChar) loop --clob control if (v_count &gt; 8191) then --crazy oracle error (16383 is the highest working length with unistr - 8192 choosen to be safe) if (v_extended is null) then v_extended := empty_clob(); dbms_lob.createtemporary(v_extended, true); end if; updateClob(v_extended, unistr(varbuf)); varbuf := ''; v_count := 0; end if; if (buf = Chr(13) or buf = CHR(9) or buf = CHR(10)) then s_error('Control characters not allowed (CHR(9),CHR(10),CHR(13))', tok); end if; if (buf = '\\') then --varbuf := varbuf || buf; indx := indx + 1; buf := next_char(indx, jsrc); case when buf in ('\\') then varbuf := varbuf || buf || buf; v_count := v_count + 2; indx := indx + 1; buf := next_char(indx, jsrc); when buf in ('\"', '/') then varbuf := varbuf || buf; v_count := v_count + 1; indx := indx + 1; buf := next_char(indx, jsrc); when buf = '''' then if (json_strict = false) then varbuf := varbuf || buf; v_count := v_count + 1; indx := indx + 1; buf := next_char(indx, jsrc); else s_error('strictmode - expected: \" \\ / b f n r t u ', tok); end if; when buf in ('b', 'f', 'n', 'r', 't') then --backspace b = U+0008 --formfeed f = U+000C --newline n = U+000A --carret r = U+000D --tabulator t = U+0009 case buf when 'b' then varbuf := varbuf || chr(8); when 'f' then varbuf := varbuf || chr(12); when 'n' then varbuf := varbuf || chr(10); when 'r' then varbuf := varbuf || chr(13); when 't' then varbuf := varbuf || chr(9); end case; --varbuf := varbuf || buf; v_count := v_count + 1; indx := indx + 1; buf := next_char(indx, jsrc); when buf = 'u' then --four hexadecimal chars declare four varchar2(4); begin four := next_char2(indx+1, jsrc, 4); wrong := FALSE; if (upper(substr(four, 1, 1)) not in ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f')) then wrong := TRUE; end if; if (upper(substr(four, 2, 1)) not in ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f')) then wrong := TRUE; end if; if (upper(substr(four, 3, 1)) not in ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f')) then wrong := TRUE; end if; if (upper(substr(four, 4, 1)) not in ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','a','b','c','d','e','f')) then wrong := TRUE; end if; if (wrong) then s_error('expected: \" \\u([0-9][A-F]){4}', tok); end if; -- varbuf := varbuf || buf || four; varbuf := varbuf || '\\'||four;--chr(to_number(four,'XXXX')); v_count := v_count + 5; indx := indx + 5; buf := next_char(indx, jsrc); end; else s_error('expected: \" \\ / b f n r t u ', tok); end case; else varbuf := varbuf || buf; v_count := v_count + 1; indx := indx + 1; buf := next_char(indx, jsrc); end if; end loop;</p> <pre><code>if (buf is null) then\n s_error('string ending not found', tok);\n --debug('Premature string ending');\nend if;\n\n--debug(varbuf);\n--dbms_output.put_line(varbuf);\nif (v_extended is not null) then\n updateClob(v_extended, unistr(varbuf));\n tok.data_overflow := v_extended;\n -- tok.data := dbms_lob.substr(v_extended, 1, 32767);\n /* may read less than \"max_string_chars\" characters but it's a sample so doesn't matter */\n dbms_lob.read(v_extended, max_string_chars, 1, tok.data);\nelse\n tok.data := unistr(varbuf);\nend if;\nreturn indx;\n</code></pre> <p>end lexString;</p> <p>/ scanner tokens: '{', '}', ',', ':', '[', ']', STRING, NUMBER, TRUE, FALSE, NULL / function lexer(jsrc in out nocopy json_src) return lTokens as tokens lTokens; indx pls_integer := 1; tok_indx pls_integer := 1; buf varchar2(4); lin_no number := 1; col_no number := 0; begin while (indx &lt;= jsrc.len) loop --read into buf buf := next_char(indx, jsrc); col_no := col_no + 1; --convert to switch case case when buf = '{' then tokens(tok_indx) := mt('{', lin_no, col_no, null); tok_indx := tok_indx + 1; when buf = '}' then tokens(tok_indx) := mt('}', lin_no, col_no, null); tok_indx := tok_indx + 1; when buf = ',' then tokens(tok_indx) := mt(',', lin_no, col_no, null); tok_indx := tok_indx + 1; when buf = ':' then tokens(tok_indx) := mt(':', lin_no, col_no, null); tok_indx := tok_indx + 1; when buf = '[' then tokens(tok_indx) := mt('[', lin_no, col_no, null); tok_indx := tok_indx + 1; when buf = ']' then tokens(tok_indx) := mt(']', lin_no, col_no, null); tok_indx := tok_indx + 1; when buf = 't' then if (next_char2(indx, jsrc, 4) != 'true') then if (json_strict = false and REGEXP_LIKE(buf, '^[[:alpha:]]$', 'i')) then tokens(tok_indx) := mt('STRING', lin_no, col_no, null); indx := lexName(jsrc, tokens(tok_indx), indx); col_no := col_no + length(tokens(tok_indx).data) + 1; tok_indx := tok_indx + 1; else s_error('Expected: ''true''', lin_no, col_no); end if; else tokens(tok_indx) := mt('TRUE', lin_no, col_no, null); tok_indx := tok_indx + 1; indx := indx + 3; col_no := col_no + 3; end if; when buf = 'n' then if (next_char2(indx, jsrc, 4) != 'null') then if (json_strict = false and REGEXP_LIKE(buf, '^[[:alpha:]]$', 'i')) then tokens(tok_indx) := mt('STRING', lin_no, col_no, null); indx := lexName(jsrc, tokens(tok_indx), indx); col_no := col_no + length(tokens(tok_indx).data) + 1; tok_indx := tok_indx + 1; else s_error('Expected: ''null''', lin_no, col_no); end if; else tokens(tok_indx) := mt('NULL', lin_no, col_no, null); tok_indx := tok_indx + 1; indx := indx + 3; col_no := col_no + 3; end if; when buf = 'f' then if (next_char2(indx, jsrc, 5) != 'false') then if (json_strict = false and REGEXP_LIKE(buf, '^[[:alpha:]]$', 'i')) then tokens(tok_indx) := mt('STRING', lin_no, col_no, null); indx := lexName(jsrc, tokens(tok_indx), indx); col_no := col_no + length(tokens(tok_indx).data) + 1; tok_indx := tok_indx + 1; else s_error('Expected: ''false''', lin_no, col_no); end if; else tokens(tok_indx) := mt('FALSE', lin_no, col_no, null); tok_indx := tok_indx + 1; indx := indx + 4; col_no := col_no + 4; end if; / -- 9 = TAB, 10 = \\n, 13 = \\r (Linux = \\n, Windows = \\r\\n, Mac = \\r / when (buf = Chr(10)) then --linux newlines lin_no := lin_no + 1; col_no := 0;</p> <pre><code> when (buf = Chr(13)) then --Windows or Mac way\n lin_no := lin_no + 1;\n col_no := 0;\n if (jsrc.len &gt;= indx+1) then -- better safe than sorry\n buf := next_char(indx+1, jsrc);\n if (buf = Chr(10)) then --\\r\\n\n indx := indx + 1;\n end if;\n end if;\n\n when (buf = CHR(9)) then null; --tabbing\n when (buf in ('-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) then --number\n tokens(tok_indx) := mt('NUMBER', lin_no, col_no, null);\n indx := lexNumber(jsrc, tokens(tok_indx), indx)-1;\n col_no := col_no + length(tokens(tok_indx).data);\n tok_indx := tok_indx + 1;\n when buf = '\"' then --string\n tokens(tok_indx) := mt('STRING', lin_no, col_no, null);\n indx := lexString(jsrc, tokens(tok_indx), indx, '\"');\n col_no := col_no + length(tokens(tok_indx).data) + 1;\n tok_indx := tok_indx + 1;\n when buf = '''' and json_strict = false then --string\n tokens(tok_indx) := mt('STRING', lin_no, col_no, null);\n indx := lexString(jsrc, tokens(tok_indx), indx, '''');\n col_no := col_no + length(tokens(tok_indx).data) + 1; --hovsa her\n tok_indx := tok_indx + 1;\n when json_strict = false and REGEXP_LIKE(buf, '^[[:alpha:]]$', 'i') then\n tokens(tok_indx) := mt('STRING', lin_no, col_no, null);\n indx := lexName(jsrc, tokens(tok_indx), indx);\n if (tokens(tok_indx).data_overflow is not null) then\n /* use of lengthcc, so works correctly for 4-byte unicode characters (issue #169) */\n col_no := col_no + lengthcc(tokens(tok_indx).data_overflow) + 1; --dbms_lob.getlength(tokens(tok_indx).data_overflow) + 1;\n else\n col_no := col_no + length(tokens(tok_indx).data) + 1;\n end if;\n tok_indx := tok_indx + 1;\n when json_strict = false and buf||next_char(indx+1, jsrc) = '/*' then --strip comments\n declare\n saveindx number := indx;\n un_esc clob;\n begin\n indx := indx + 1;\n loop\n indx := indx + 1;\n buf := next_char(indx, jsrc)||next_char(indx+1, jsrc);\n exit when buf = '*/';\n exit when buf is null;\n end loop;\n\n if (indx = saveindx+2) then\n --enter unescaped mode\n --dbms_output.put_line('Entering unescaped mode');\n un_esc := empty_clob();\n dbms_lob.createtemporary(un_esc, true);\n indx := indx + 1;\n loop\n indx := indx + 1;\n buf := next_char(indx, jsrc)||next_char(indx+1, jsrc)||next_char(indx+2, jsrc)||next_char(indx+3, jsrc);\n exit when buf = '/**/';\n if buf is null then\n s_error('Unexpected sequence /**/ to end unescaped data: '||buf, lin_no, col_no);\n end if;\n buf := next_char(indx, jsrc);\n /* use of length2, so works correctly for 4-byte unicode characters (issue #169) */\n dbms_lob.writeappend(un_esc, length2(buf), buf);\n end loop;\n tokens(tok_indx) := mt('ESTRING', lin_no, col_no, null);\n tokens(tok_indx).data_overflow := un_esc;\n /* use of lengthcc, so works correctly for 4-byte unicode characters (issue #169) */\n col_no := col_no + lengthcc(un_esc) + 1; --dbms_lob.getlength(un_esc) + 1; --note: line count won't work properly\n tok_indx := tok_indx + 1;\n indx := indx + 2;\n end if;\n\n indx := indx + 1;\n end;\n when buf = ' ' then null; --space\n else\n s_error('Unexpected char: '||buf, lin_no, col_no);\n end case;\n\n indx := indx + 1;\nend loop;\n\nreturn tokens;\n</code></pre> <p>end lexer;</p> <p>/ SCANNER END /</p> <p>/ PARSER FUNCTIONS START / procedure p_error(text varchar2, tok rToken) as begin raise_application_error(-20101, 'JSON Parser exception @ line: '||tok.line||' column: '||tok.col||' - '||text); end;</p> <p>function parseArr(tokens lTokens, indx in out nocopy pls_integer) return pljson_list as e_arr pljson_element_array := pljson_element_array(); ret_list pljson_list := pljson_list(); v_count number := 0; tok rToken; pv pljson_number; begin --value, value, value ] if (indx &gt; tokens.count) then p_error('more elements in array was excepted', tok); end if; tok := tokens(indx); while (tok.type_name != ']') loop e_arr.extend; v_count := v_count + 1; case tok.type_name when 'TRUE' then e_arr(v_count) := pljson_bool(true); when 'FALSE' then e_arr(v_count) := pljson_bool(false); when 'NULL' then e_arr(v_count) := pljson_null(); when 'STRING' then e_arr(v_count) := case when tok.data_overflow is not null then pljson_string(tok.data_overflow) else pljson_string(tok.data) end; when 'ESTRING' then e_arr(v_count) := pljson_string(tok.data_overflow, false); / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / --when 'NUMBER' then e_arr(v_count) := pljson_number(to_number(replace(tok.data, '.', decimalpoint))); when 'NUMBER' then pv := pljson_number(0); pv.parse_number(replace(tok.data, '.', decimalpoint)); e_arr(v_count) := pv; when '[' then declare e_list pljson_list; begin indx := indx + 1; e_list := parseArr(tokens, indx); e_arr(v_count) := e_list; end; when '{' then indx := indx + 1; e_arr(v_count) := parseObj(tokens, indx); else p_error('Expected a value', tok); end case; indx := indx + 1; if (indx &gt; tokens.count) then p_error('] not found', tok); end if; tok := tokens(indx); if (tok.type_name = ',') then --advance indx := indx + 1; if (indx &gt; tokens.count) then p_error('more elements in array was excepted', tok); end if; tok := tokens(indx); if (tok.type_name = ']') then --premature exit p_error('Premature exit in array', tok); end if; elsif (tok.type_name != ']') then --error p_error('Expected , or ]', tok); end if;</p> <pre><code>end loop;\nret_list.list_data := e_arr;\nreturn ret_list;\n</code></pre> <p>end parseArr;</p> <p>function parseMem(tokens lTokens, indx in out pls_integer, mem_name varchar2, mem_indx number) return pljson_element as mem pljson_element; tok rToken; pv pljson_number; begin tok := tokens(indx); case tok.type_name when 'TRUE' then mem := pljson_bool(true); when 'FALSE' then mem := pljson_bool(false); when 'NULL' then mem := pljson_null(); when 'STRING' then mem := case when tok.data_overflow is not null then pljson_string(tok.data_overflow) else pljson_string(tok.data) end; when 'ESTRING' then mem := pljson_string(tok.data_overflow, false); / E.I.Sarmas (github.com/dsnz) 2016-12-01 support for binary_double numbers / --when 'NUMBER' then mem := pljson_number(to_number(replace(tok.data, '.', decimalpoint))); when 'NUMBER' then pv := pljson_number(0); pv.parse_number(replace(tok.data, '.', decimalpoint)); mem := pv; when '[' then declare e_list pljson_list; begin indx := indx + 1; e_list := parseArr(tokens, indx); mem := e_list; end; when '{' then indx := indx + 1; mem := parseObj(tokens, indx); else p_error('Found '||tok.type_name, tok); end case; mem.mapname := mem_name; mem.mapindx := mem_indx;</p> <pre><code>indx := indx + 1;\nreturn mem;\n</code></pre> <p>end parseMem;</p> <p>/procedure test_duplicate_members(arr in json_member_array, mem_name in varchar2, wheretok rToken) as begin for i in 1 .. arr.count loop if (arr(i).member_name = mem_name) then p_error('Duplicate member name', wheretok); end if; end loop; end test_duplicate_members;/</p> <p>function parseObj(tokens lTokens, indx in out nocopy pls_integer) return pljson as type memmap is table of number index by varchar2(4000); -- i've read somewhere that this is not possible - but it is! mymap memmap; nullelemfound boolean := false;</p> <pre><code>obj pljson;\ntok rToken;\nmem_name varchar(4000);\narr pljson_element_array := pljson_element_array();\n</code></pre> <p>begin --what to expect? while (indx &lt;= tokens.count) loop tok := tokens(indx); --debug('E: '||tok.type_name); case tok.type_name when 'STRING' then --member mem_name := substr(tok.data, 1, 4000); begin if (mem_name is null) then if (nullelemfound) then p_error('Duplicate empty member: ', tok); else nullelemfound := true; end if; elsif (mymap(mem_name) is not null) then p_error('Duplicate member name: '||mem_name, tok); end if; exception when no_data_found then mymap(mem_name) := 1; end;</p> <pre><code> indx := indx + 1;\n if (indx &gt; tokens.count) then p_error('Unexpected end of input', tok); end if;\n tok := tokens(indx);\n indx := indx + 1;\n if (indx &gt; tokens.count) then p_error('Unexpected end of input', tok); end if;\n if (tok.type_name = ':') then\n --parse\n declare\n jmb pljson_element;\n x number;\n begin\n x := arr.count + 1;\n jmb := parseMem(tokens, indx, mem_name, x);\n arr.extend;\n arr(x) := jmb;\n end;\n else\n p_error('Expected '':''', tok);\n end if;\n --move indx forward if ',' is found\n if (indx &gt; tokens.count) then p_error('Unexpected end of input', tok); end if;\n\n tok := tokens(indx);\n if (tok.type_name = ',') then\n --debug('found ,');\n indx := indx + 1;\n tok := tokens(indx);\n if (tok.type_name = '}') then --premature exit\n p_error('Premature exit in json object', tok);\n end if;\n elsif (tok.type_name != '}') then\n p_error('A comma seperator is probably missing', tok);\n end if;\n when '}' then\n obj := pljson();\n obj.json_data := arr;\n return obj;\n else\n p_error('Expected string or }', tok);\n end case;\nend loop;\n\np_error('} not found', tokens(indx-1));\n\nreturn obj;\n</code></pre> <p>end;</p> <p>function parser(str varchar2) return pljson as tokens lTokens; obj pljson; indx pls_integer := 1; jsrc json_src; begin update_decimalpoint(); jsrc := prepareVarchar2(str); tokens := lexer(jsrc); if (tokens(indx).type_name = '{') then indx := indx + 1; obj := parseObj(tokens, indx); else raise_application_error(-20101, 'JSON Parser exception - no { start found'); end if; if (tokens.count != indx) then p_error('} should end the JSON object', tokens(indx)); end if;</p> <pre><code>return obj;\n</code></pre> <p>end parser;</p> <p>function parse_list(str varchar2) return pljson_list as tokens lTokens; obj pljson_list; indx pls_integer := 1; jsrc json_src; begin update_decimalpoint(); jsrc := prepareVarchar2(str); tokens := lexer(jsrc); if (tokens(indx).type_name = '[') then indx := indx + 1; obj := parseArr(tokens, indx); else raise_application_error(-20101, 'JSON List Parser exception - no [ start found'); end if; if (tokens.count != indx) then p_error('] should end the JSON List object', tokens(indx)); end if;</p> <pre><code>return obj;\n</code></pre> <p>end parse_list;</p> <p>function parse_list(str clob) return pljson_list as tokens lTokens; obj pljson_list; indx pls_integer := 1; jsrc json_src; begin update_decimalpoint(); jsrc := prepareClob(str); tokens := lexer(jsrc); if (tokens(indx).type_name = '[') then indx := indx + 1; obj := parseArr(tokens, indx); else raise_application_error(-20101, 'JSON List Parser exception - no [ start found'); end if; if (tokens.count != indx) then p_error('] should end the JSON List object', tokens(indx)); end if;</p> <pre><code>return obj;\n</code></pre> <p>end parse_list;</p> <p>function parser(str clob) return pljson as tokens lTokens; obj pljson; indx pls_integer := 1; jsrc json_src; begin update_decimalpoint(); --dbms_output.put_line('Using clob'); jsrc := prepareClob(str); tokens := lexer(jsrc); if (tokens(indx).type_name = '{') then indx := indx + 1; obj := parseObj(tokens, indx); else raise_application_error(-20101, 'JSON Parser exception - no { start found'); end if; if (tokens.count != indx) then p_error('} should end the JSON object', tokens(indx)); end if;</p> <pre><code>return obj;\n</code></pre> <p>end parser;</p> <p>function parse_any(str varchar2) return pljson_element as tokens lTokens; obj pljson_list; ret pljson_element; indx pls_integer := 1; jsrc json_src; begin update_decimalpoint(); jsrc := prepareVarchar2(str); tokens := lexer(jsrc); tokens(tokens.count+1).type_name := ']'; obj := parseArr(tokens, indx); if (tokens.count != indx) then p_error('] should end the JSON List object', tokens(indx)); end if;</p> <pre><code>return obj.head();\n</code></pre> <p>end parse_any;</p> <p>function parse_any(str clob) return pljson_element as tokens lTokens; obj pljson_list; indx pls_integer := 1; jsrc json_src; begin update_decimalpoint(); jsrc := prepareClob(str); tokens := lexer(jsrc); tokens(tokens.count+1).type_name := ']'; obj := parseArr(tokens, indx); if (tokens.count != indx) then p_error('] should end the JSON List object', tokens(indx)); end if;</p> <pre><code>return obj.head();\n</code></pre> <p>end parse_any;</p> <p>/ last entry is the one to keep / procedure remove_duplicates(obj in out nocopy pljson) as type memberlist is table of pljson_element index by varchar2(4000); members memberlist; nulljsonvalue pljson_element := null; validated pljson := pljson(); indx varchar2(4000); begin for i in 1 .. obj.count loop if (obj.get(i).mapname is null) then nulljsonvalue := obj.get(i); else members(obj.get(i).mapname) := obj.get(i); end if; end loop;</p> <pre><code>validated.check_duplicate(false);\nindx := members.first;\nloop\n exit when indx is null;\n validated.put(indx, members(indx));\n indx := members.next(indx);\nend loop;\nif (nulljsonvalue is not null) then\n validated.put('', nulljsonvalue);\nend if;\n\nvalidated.check_for_duplicate := obj.check_for_duplicate;\n\nobj := validated;\n</code></pre> <p>end;</p> <p>function get_version return varchar2 as begin return 'PL/JSON 3.5.2'; end get_version;</p> <p>end pljson_parser;```</p>"},{"location":"packages/PLJSON_PRINTER/","title":"PLJSON_PRINTER","text":""},{"location":"packages/PLJSON_PRINTER/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_printer as / Copyright (c) 2010 Jonas Krogsboell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. / indent_string varchar2(10 char) := ' '; --chr(9); for tab newline_char varchar2(2 char) := chr(13)||chr(10); -- Windows style --newline_char varchar2(2) := chr(10); -- Mac style --newline_char varchar2(2) := chr(13); -- Linux style ascii_output boolean not null := true; empty_string_as_null boolean not null := false; escape_solidus boolean not null := false;</p> <p>function pretty_print(obj pljson, spaces boolean default true, line_length number default 0) return varchar2; function pretty_print_list(obj pljson_list, spaces boolean default true, line_length number default 0) return varchar2; function pretty_print_any(json_part pljson_element, spaces boolean default true, line_length number default 0) return varchar2; procedure pretty_print(obj pljson, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true); procedure pretty_print_list(obj pljson_list, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true); procedure pretty_print_any(json_part pljson_element, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true);</p> <p>procedure dbms_output_clob(my_clob clob, delim varchar2, jsonp varchar2 default null); procedure htp_output_clob(my_clob clob, jsonp varchar2 default null); -- made public just for testing/profiling... function escapeString(str varchar2) return varchar2;</p> <p>end pljson_printer;```</p>"},{"location":"packages/PLJSON_PRINTER/#package-body","title":"Package Body","text":"<p>```sql package body pljson_printer as max_line_len number := 0; cur_line_len number := 0;</p> <p>-- associative array used inside escapeString to cache the escaped version of every character -- escaped so far (example: char_map('\"') contains the '\\\"' string) -- (if the character does not need to be escaped, the character is stored unchanged in the array itself) -- type Rmap_char is record(buf varchar2(40), len integer); type Tmap_char_string is table of varchar2(40) index by varchar2(1 char); / index by unicode char / char_map Tmap_char_string; -- since char_map the associative array is a global variable reused across multiple calls to escapeString, -- i need to be able to detect that the escape_solidus or ascii_output global parameters have been changed, -- in order to clear it and avoid using escape sequences that have been cached using the previous values char_map_escape_solidus boolean := escape_solidus; char_map_ascii_output boolean := ascii_output;</p> <p>function llcheck(str in varchar2) return varchar2 as begin --dbms_output.put_line(cur_line_len || ' : ' || str); if (max_line_len &gt; 0 and length(str)+cur_line_len &gt; max_line_len) then cur_line_len := length(str); return newline_char || str; else cur_line_len := cur_line_len + length(str); return str; end if; end llcheck;</p> <p>-- escapes a single character. function escapeChar(ch char) return varchar2 deterministic is result varchar2(20); begin --backspace b = U+0008 --formfeed f = U+000C --newline n = U+000A --carret r = U+000D --tabulator t = U+0009 result := ch;</p> <pre><code> case ch\n when chr( 8) then result := '\\b';\n when chr( 9) then result := '\\t';\n when chr(10) then result := '\\n';\n when chr(12) then result := '\\f';\n when chr(13) then result := '\\r';\n when chr(34) then result := '\\\"';\n when chr(47) then if (escape_solidus) then result := '\\/'; end if;\n when chr(92) then result := '\\\\';\n /* WARNING: ascii() returns PLS_INTEGER and large unicode code points can be negative */\n else if (ascii(ch) &gt;= 0 and ascii(ch) &lt; 32) then\n result := '\\u' || replace(substr(to_char(ascii(ch), 'XXXX'), 2, 4), ' ', '0');\n elsif (ascii_output) then\n result := replace(asciistr(ch), '\\', '\\u');\n end if;\n end case;\n return result;\n</code></pre> <p>end;</p> <p>function escapeString(str varchar2) return varchar2 as sb varchar2(32767 byte) := ''; buf varchar2(40); ch varchar2(1 char); / unicode char / begin if (str is null) then return ''; end if;</p> <pre><code>-- clear the cache if global parameters have been changed\nif char_map_escape_solidus &lt;&gt; escape_solidus or\n char_map_ascii_output &lt;&gt; ascii_output\nthen\n char_map.delete;\n char_map_escape_solidus := escape_solidus;\n char_map_ascii_output := ascii_output;\nend if;\n\nfor i in 1 .. length(str) loop\n ch := substr(str, i, 1 ) ;\n\n begin\n -- it this char has already been processed, I have cached its escaped value\n buf:=char_map(ch);\n exception when no_Data_found then\n -- otherwise, i convert the value and add it to the cache\n buf := escapeChar(ch);\n char_map(ch) := buf;\n end;\n\n sb := sb || buf;\nend loop;\nreturn sb;\n</code></pre> <p>end escapeString;</p> <p>function newline(spaces boolean) return varchar2 as begin cur_line_len := 0; if (spaces) then return newline_char; else return ''; end if; end;</p> <p>/ function get_schema return varchar2 as begin return sys_context('userenv', 'current_schema'); end; / function tab(indent number, spaces boolean) return varchar2 as i varchar(200) := ''; begin if (not spaces) then return ''; end if; for x in 1 .. indent loop i := i || indent_string; end loop; return i; end;</p> <p>function getCommaSep(spaces boolean) return varchar2 as begin if (spaces) then return ', '; else return ','; end if; end;</p> <p>function getMemName(mem pljson_element, spaces boolean) return varchar2 as begin if (spaces) then return llcheck('\"'||escapeString(mem.mapname)||'\"') || llcheck(' : '); else return llcheck('\"'||escapeString(mem.mapname)||'\"') || llcheck(':'); end if; end;</p> <p>/ Clob method start here / procedure add_to_clob(buf_lob in out nocopy clob, buf_str in out nocopy varchar2, str varchar2) as begin -- if (length(str) &gt; 5000 - length(buf_str)) then if (lengthb(str) &gt; 32767 - lengthb(buf_str)) then -- dbms_lob.writeappend(buf_lob, length2(buf_str), buf_str); dbms_lob.append(buf_lob, buf_str); buf_str := str; else buf_str := buf_str || str; end if; end add_to_clob;</p> <p>procedure flush_clob(buf_lob in out nocopy clob, buf_str in out nocopy varchar2) as begin -- dbms_lob.writeappend(buf_lob, length2(buf_str), buf_str); dbms_lob.append(buf_lob, buf_str); end flush_clob;</p> <p>procedure ppObj(obj pljson, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2);</p> <p>procedure ppString(elem pljson_string, buf in out nocopy clob, buf_str in out nocopy varchar2) is offset number := 1; / E.I.Sarmas (github.com/dsnz) 2016-01-21 limit to 5000 chars / v_str varchar(5000 char); amount number := 5000; / chunk size for use in escapeString, less than this number may be copied / begin if empty_string_as_null and elem.extended_str is null and elem.str is null then add_to_clob(buf, buf_str, 'null'); else add_to_clob(buf, buf_str, case when elem.num = 1 then '\"' else '//' end); if (elem.extended_str is not null) then --clob implementation while (offset &lt;= dbms_lob.getlength(elem.extended_str)) loop dbms_lob.read(elem.extended_str, amount, offset, v_str); if (elem.num = 1) then add_to_clob(buf, buf_str, escapeString(v_str)); else add_to_clob(buf, buf_str, v_str); end if; offset := offset + amount; end loop; else if (elem.num = 1) then while (offset &lt;= length(elem.str)) loop v_str:=substr(elem.str, offset, amount); add_to_clob(buf, buf_str, escapeString(v_str)); offset := offset + amount; end loop; else add_to_clob(buf, buf_str, elem.str); end if; end if; add_to_clob(buf, buf_str, case when elem.num = 1 then '\"' else '//' end); end if; end;</p> <p>procedure ppEA(input pljson_list, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2) as elem pljson_element; arr pljson_element_array := input.list_data; numbuf varchar2(4000); begin for y in 1 .. arr.count loop elem := arr(y); if (elem is not null) then case elem.typeval / number / when 4 then numbuf := treat(elem as pljson_number).number_toString(); add_to_clob(buf, buf_str, llcheck(numbuf)); / string / when 3 then ppString(treat(elem as pljson_string), buf, buf_str); / bool / when 5 then if (elem.get_bool()) then add_to_clob(buf, buf_str, llcheck('true')); else add_to_clob(buf, buf_str, llcheck('false')); end if; / null / when 6 then add_to_clob(buf, buf_str, llcheck('null')); / array / when 2 then add_to_clob(buf, buf_str, llcheck('[')); ppEA(treat(elem as pljson_list), indent, buf, spaces, buf_str); add_to_clob(buf, buf_str, llcheck(']')); / object / when 1 then ppObj(treat(elem as pljson), indent, buf, spaces, buf_str); else add_to_clob(buf, buf_str, llcheck(elem.get_type)); end case; end if; if (y != arr.count) then add_to_clob(buf, buf_str, llcheck(getCommaSep(spaces))); end if; end loop; end ppEA;</p> <p>procedure ppMem(mem pljson_element, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2) as numbuf varchar2(4000); begin add_to_clob(buf, buf_str, llcheck(tab(indent, spaces)) || llcheck(getMemName(mem, spaces))); case mem.typeval / number / when 4 then numbuf := treat(mem as pljson_number).number_toString(); add_to_clob(buf, buf_str, llcheck(numbuf)); / string / when 3 then ppString(treat(mem as pljson_string), buf, buf_str); / bool / when 5 then if (mem.get_bool()) then add_to_clob(buf, buf_str, llcheck('true')); else add_to_clob(buf, buf_str, llcheck('false')); end if; / null / when 6 then add_to_clob(buf, buf_str, llcheck('null')); / array / when 2 then add_to_clob(buf, buf_str, llcheck('[')); ppEA(treat(mem as pljson_list), indent, buf, spaces, buf_str); add_to_clob(buf, buf_str, llcheck(']')); / object / when 1 then ppObj(treat(mem as pljson), indent, buf, spaces, buf_str); else add_to_clob(buf, buf_str, llcheck(mem.get_type)); end case; end ppMem;</p> <p>procedure ppObj(obj pljson, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2) as begin add_to_clob(buf, buf_str, llcheck('{') || newline(spaces)); for m in 1 .. obj.json_data.count loop ppMem(obj.json_data(m), indent+1, buf, spaces, buf_str); if (m != obj.json_data.count) then add_to_clob(buf, buf_str, llcheck(',') || newline(spaces)); else add_to_clob(buf, buf_str, newline(spaces)); end if; end loop; add_to_clob(buf, buf_str, llcheck(tab(indent, spaces)) || llcheck('}')); -- || chr(13); end ppObj;</p> <p>procedure pretty_print(obj pljson, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true) as buf_str varchar2(32767); amount number := dbms_lob.getlength(buf); begin if (erase_clob and amount &gt; 0) then dbms_lob.trim(buf, 0); -- dbms_lob.erase(buf, amount); end if;</p> <pre><code>max_line_len := line_length;\ncur_line_len := 0;\nppObj(obj, 0, buf, spaces, buf_str);\nflush_clob(buf, buf_str);\n</code></pre> <p>end;</p> <p>procedure pretty_print_list(obj pljson_list, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true) as buf_str varchar2(32767); amount number := dbms_lob.getlength(buf); begin if (erase_clob and amount &gt; 0) then dbms_lob.trim(buf, 0); -- dbms_lob.erase(buf, amount); end if;</p> <pre><code>max_line_len := line_length;\ncur_line_len := 0;\nadd_to_clob(buf, buf_str, llcheck('['));\nppEA(obj, 0, buf, spaces, buf_str);\nadd_to_clob(buf, buf_str, llcheck(']'));\nflush_clob(buf, buf_str);\n</code></pre> <p>end;</p> <p>procedure pretty_print_any(json_part pljson_element, spaces boolean default true, buf in out nocopy clob, line_length number default 0, erase_clob boolean default true) as buf_str varchar2(32767) := ''; numbuf varchar2(4000); amount number := dbms_lob.getlength(buf); begin if (erase_clob and amount &gt; 0) then dbms_lob.trim(buf, 0); -- dbms_lob.erase(buf, amount); end if;</p> <pre><code>case json_part.typeval\n /* number */\n when 4 then\n numbuf := treat(json_part as pljson_number).number_toString();\n add_to_clob(buf, buf_str, numbuf);\n /* string */\n when 3 then\n ppString(treat(json_part as pljson_string), buf, buf_str);\n /* bool */\n when 5 then\n if (json_part.get_bool()) then\n add_to_clob(buf, buf_str, 'true');\n else\n add_to_clob(buf, buf_str, 'false');\n end if;\n /* null */\n when 6 then\n add_to_clob(buf, buf_str, 'null');\n /* array */\n when 2 then\n pretty_print_list(pljson_list(json_part), spaces, buf, line_length);\n return;\n /* object */\n when 1 then\n pretty_print(pljson(json_part), spaces, buf, line_length);\n return;\n else\n add_to_clob(buf, buf_str, 'unknown type:' || json_part.get_type);\nend case;\nflush_clob(buf, buf_str);\n</code></pre> <p>end;</p> <p>/ Clob method end here /</p> <p>/ Varchar2 method start here / procedure add_buf (buf in out nocopy varchar2, str in varchar2) as begin if (lengthb(str)&gt;32767-lengthb(buf)) then raise_application_error(-20001,'Length of result JSON more than 32767 bytes. Use to_clob() procedures'); end if; buf := buf || str; end;</p> <p>procedure ppString(elem pljson_string, buf in out nocopy varchar2) is offset number := 1; / E.I.Sarmas (github.com/dsnz) 2016-01-21 limit to 5000 chars / v_str varchar(5000 char); amount number := 5000; / chunk size for use in escapeString, less than this number may be copied / begin if empty_string_as_null and elem.extended_str is null and elem.str is null then add_buf(buf, 'null'); else add_buf(buf, case when elem.num = 1 then '\"' else '//' end); if (elem.extended_str is not null) then --clob implementation while (offset &lt;= dbms_lob.getlength(elem.extended_str)) loop dbms_lob.read(elem.extended_str, amount, offset, v_str); if (elem.num = 1) then add_buf(buf, escapeString(v_str)); else add_buf(buf, v_str); end if; offset := offset + amount; end loop; else if (elem.num = 1) then while (offset &lt;= length(elem.str)) loop v_str:=substr(elem.str, offset, amount); add_buf(buf, escapeString(v_str)); offset := offset + amount; end loop; else add_buf(buf, elem.str); end if; end if; add_buf(buf, case when elem.num = 1 then '\"' else '//' end); end if; end;</p> <p>procedure ppObj(obj pljson, indent number, buf in out nocopy varchar2, spaces boolean);</p> <p>procedure ppEA(input pljson_list, indent number, buf in out varchar2, spaces boolean) as elem pljson_element; arr pljson_element_array := input.list_data; str varchar2(400); begin for y in 1 .. arr.count loop elem := arr(y); if (elem is not null) then case elem.typeval / number / when 4 then str := treat(elem as pljson_number).number_toString(); add_buf(buf, llcheck(str)); / string / when 3 then ppString(treat(elem as pljson_string), buf); / bool / when 5 then if (elem.get_bool()) then add_buf (buf, llcheck('true')); else add_buf (buf, llcheck('false')); end if; / null / when 6 then add_buf (buf, llcheck('null')); / array / when 2 then add_buf( buf, llcheck('[')); ppEA(treat(elem as pljson_list), indent, buf, spaces); add_buf( buf, llcheck(']')); / object / when 1 then ppObj(treat(elem as pljson), indent, buf, spaces); else add_buf (buf, llcheck(elem.get_type)); / should never happen / end case; end if; if (y != arr.count) then add_buf(buf, llcheck(getCommaSep(spaces))); end if; end loop; end ppEA;</p> <p>procedure ppMem(mem pljson_element, indent number, buf in out nocopy varchar2, spaces boolean) as str varchar2(400) := ''; begin add_buf(buf, llcheck(tab(indent, spaces)) || getMemName(mem, spaces)); case mem.typeval / number / when 4 then str := treat(mem as pljson_number).number_toString(); add_buf(buf, llcheck(str)); / string / when 3 then ppString(treat(mem as pljson_string), buf); / bool / when 5 then if (mem.get_bool()) then add_buf(buf, llcheck('true')); else add_buf(buf, llcheck('false')); end if; / null / when 6 then add_buf(buf, llcheck('null')); / array / when 2 then add_buf(buf, llcheck('[')); ppEA(treat(mem as pljson_list), indent, buf, spaces); add_buf(buf, llcheck(']')); / object / when 1 then ppObj(treat(mem as pljson), indent, buf, spaces); else add_buf(buf, llcheck(mem.get_type)); / should never happen / end case; end ppMem;</p> <p>procedure ppObj(obj pljson, indent number, buf in out nocopy varchar2, spaces boolean) as begin add_buf (buf, llcheck('{') || newline(spaces)); for m in 1 .. obj.json_data.count loop ppMem(obj.json_data(m), indent+1, buf, spaces); if (m != obj.json_data.count) then add_buf(buf, llcheck(',') || newline(spaces)); else add_buf(buf, newline(spaces)); end if; end loop; add_buf(buf, llcheck(tab(indent, spaces)) || llcheck('}')); -- || chr(13); end ppObj;</p> <p>function pretty_print(obj pljson, spaces boolean default true, line_length number default 0) return varchar2 as buf varchar2(32767 byte) := ''; begin max_line_len := line_length; cur_line_len := 0; ppObj(obj, 0, buf, spaces); return buf; end pretty_print;</p> <p>function pretty_print_list(obj pljson_list, spaces boolean default true, line_length number default 0) return varchar2 as buf varchar2(32767 byte) :=''; begin max_line_len := line_length; cur_line_len := 0; add_buf(buf, llcheck('[')); ppEA(obj, 0, buf, spaces); add_buf(buf, llcheck(']')); return buf; end;</p> <p>function pretty_print_any(json_part pljson_element, spaces boolean default true, line_length number default 0) return varchar2 as buf varchar2(32767) := ''; begin case json_part.typeval / number / when 4 then buf := treat(json_part as pljson_number).number_toString(); / string / when 3 then ppString(treat(json_part as pljson_string), buf); / bool / when 5 then if (json_part.get_bool()) then buf := 'true'; else buf := 'false'; end if; / null / when 6 then buf := 'null'; / array / when 2 then buf := pretty_print_list(pljson_list(json_part), spaces, line_length); / object / when 1 then buf := pretty_print(pljson(json_part), spaces, line_length); else buf := 'weird error: ' || json_part.get_type; end case; return buf; end;</p> <p>procedure dbms_output_clob(my_clob clob, delim varchar2, jsonp varchar2 default null) as prev number := 1; indx number := 1; size_of_nl number := length2(delim); v_str varchar2(32767); amount number; max_string_chars number := 5000; / chunk size, less than this number may be copied / begin if (jsonp is not null) then dbms_output.put_line(jsonp||'('); end if; while (indx != 0) loop --read every line indx := dbms_lob.instr(my_clob, delim, prev+1); --dbms_output.put_line(prev || ' to ' || indx);</p> <pre><code> if (indx = 0) then\n --emit from prev to end;\n amount := max_string_chars;\n --dbms_output.put_line(' mycloblen ' || dbms_lob.getlength(my_clob));\n loop\n dbms_lob.read(my_clob, amount, prev, v_str);\n dbms_output.put_line(v_str);\n prev := prev+amount;\n exit when prev &gt;= dbms_lob.getlength(my_clob);\n end loop;\n else\n amount := indx - prev;\n if (amount &gt; max_string_chars) then\n amount := max_string_chars;\n --dbms_output.put_line(' mycloblen ' || dbms_lob.getlength(my_clob));\n loop\n dbms_lob.read(my_clob, amount, prev, v_str);\n dbms_output.put_line(v_str);\n prev := prev+amount;\n amount := indx - prev;\n exit when prev &gt;= indx - 1;\n if (amount &gt; max_string_chars) then\n amount := max_string_chars;\n end if;\n end loop;\n prev := indx + size_of_nl;\n else\n dbms_lob.read(my_clob, amount, prev, v_str);\n dbms_output.put_line(v_str);\n prev := indx + size_of_nl;\n end if;\n end if;\n\nend loop;\nif (jsonp is not null) then dbms_output.put_line(')'); end if;\n</code></pre> <p>/* while (amount != 0) loop indx := dbms_lob.instr(my_clob, delim, prev+1);</p> <p>-- dbms_output.put_line(prev || ' to ' || indx); if (indx = 0) then indx := dbms_lob.getlength(my_clob)+1; end if; if (indx-prev &gt; 32767) then indx := prev+32767; end if; -- dbms_output.put_line(prev || ' to ' || indx); --substr doesnt work properly on all platforms! (come on oracle - error on Oracle VM for virtualbox) -- dbms_output.put_line(dbms_lob.substr(my_clob, indx-prev, prev)); amount := indx-prev; -- dbms_output.put_line('amount'||amount); dbms_lob.read(my_clob, amount, prev, v_str); dbms_output.put_line(v_str); prev := indx+size_of_nl; if (amount = 32767) then prev := prev-size_of_nl-1; end if; end loop; if (jsonp is not null) then dbms_output.put_line(')'); end if;*/ end;</p> <p>/* procedure dbms_output_clob(my_clob clob, delim varchar2, jsonp varchar2 default null) as prev number := 1; indx number := 1; size_of_nl number := length2(delim); v_str varchar2(32767); amount number; begin if (jsonp is not null) then dbms_output.put_line(jsonp||'('); end if; while (indx != 0) loop indx := dbms_lob.instr(my_clob, delim, prev+1);</p> <pre><code> --dbms_output.put_line(prev || ' to ' || indx);\n if (indx-prev &gt; 32767) then\n indx := prev+32767;\n end if;\n --dbms_output.put_line(prev || ' to ' || indx);\n --substr doesnt work properly on all platforms! (come on oracle - error on Oracle VM for virtualbox)\n if (indx = 0) then\n --dbms_output.put_line(dbms_lob.substr(my_clob, dbms_lob.getlength(my_clob)-prev+size_of_nl, prev));\n amount := dbms_lob.getlength(my_clob)-prev+size_of_nl;\n dbms_lob.read(my_clob, amount, prev, v_str);\n else\n --dbms_output.put_line(dbms_lob.substr(my_clob, indx-prev, prev));\n amount := indx-prev;\n --dbms_output.put_line('amount'||amount);\n dbms_lob.read(my_clob, amount, prev, v_str);\n end if;\n dbms_output.put_line(v_str);\n prev := indx+size_of_nl;\n if (amount = 32767) then prev := prev-size_of_nl-1; end if;\nend loop;\nif (jsonp is not null) then dbms_output.put_line(')'); end if;\n</code></pre> <p>end; */</p> <p>procedure htp_output_clob(my_clob clob, jsonp varchar2 default null) as /amount number := 4096; pos number := 1; len number; / l_amt number default 4096; l_off number default 1; l_str varchar2(32000); begin if (jsonp is not null) then htp.prn(jsonp||'('); end if;</p> <pre><code>begin\n loop\n dbms_lob.read( my_clob, l_amt, l_off, l_str );\n\n -- it is vital to use htp.PRN to avoid\n -- spurious line feeds getting added to your\n -- document\n htp.prn( l_str );\n l_off := l_off+l_amt;\n end loop;\nexception\n when no_data_found then NULL;\nend;\n\n/*\nlen := dbms_lob.getlength(my_clob);\n\nwhile (pos &lt; len) loop\n htp.prn(dbms_lob.substr(my_clob, amount, pos)); -- should I replace substr with dbms_lob.read?\n --dbms_output.put_line(dbms_lob.substr(my_clob, amount, pos));\n pos := pos + amount;\nend loop;\n*/\nif (jsonp is not null) then htp.prn(')'); end if;\n</code></pre> <p>end;</p> <p>end pljson_printer;```</p>"},{"location":"packages/PLJSON_UT/","title":"PLJSON_UT","text":""},{"location":"packages/PLJSON_UT/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_ut as</p> <p>/ * * E.I.Sarmas (github.com/dsnz) 2017-07-22 * * Simple unit test framework for pljson * /</p> <p>suite_id number; suite_name varchar2(100); file_name varchar2(100); pass_count number; fail_count number; total_count number;</p> <p>case_name varchar2(100); case_pass number; case_fail number; case_total number;</p> <p>INDENT_1 varchar2(10) := ' '; INDENT_2 varchar2(10) := ' ';</p> <p>procedure testsuite(suite_name_ varchar2, file_name_ varchar2); procedure testcase(case_name_ varchar2);</p> <p>procedure pass(test_name varchar2 := null); procedure fail(test_name varchar2 := null);</p> <p>procedure assertTrue(b boolean, test_name varchar2 := null); procedure assertFalse(b boolean, test_name varchar2 := null);</p> <p>procedure testsuite_report;</p> <p>procedure startup; procedure shutdown;</p> <p>end pljson_ut;```</p>"},{"location":"packages/PLJSON_UT/#package-body","title":"Package Body","text":"<p>```sql package body pljson_ut as</p> <p>/ * * E.I.Sarmas (github.com/dsnz) 2017-07-22 * * Simple unit test framework for pljson * /</p> <p>procedure testsuite(suite_name_ varchar2, file_name_ varchar2) is begin suite_id := suite_id + 1; suite_name := suite_name_; file_name := file_name_; pass_count := 0; fail_count := 0; total_count := 0; dbms_output.put_line(suite_name_); end;</p> <p>procedure testcase(case_name_ varchar2) is begin case_name := case_name_; case_pass := 0; case_fail := 0; case_total := 0; dbms_output.put_line(INDENT_1 || case_name_); end;</p> <p>procedure pass(test_name varchar2 := null) is begin if (case_total = 0) then pass_count := pass_count + 1; total_count := total_count + 1; end if; case_pass := case_pass + 1; case_total := case_total + 1; if (test_name is not null) then dbms_output.put_line(INDENT_2 || 'OK: '|| test_name); end if; end;</p> <p>procedure fail(test_name varchar2 := null) is begin if (case_fail = 0) then fail_count := fail_count + 1; if (case_total = 0) then total_count := total_count + 1; else pass_count := pass_count - 1; end if; end if; case_fail := case_fail + 1; case_total := case_total + 1; if (test_name is not null) then dbms_output.put_line(INDENT_2 || 'FAILED: '|| test_name); end if; end;</p> <p>procedure assertTrue(b boolean, test_name varchar2 := null) is begin if (b) then pass(test_name); else fail(test_name); end if; end;</p> <p>procedure assertFalse(b boolean, test_name varchar2 := null) is begin if (not b) then pass(test_name); else fail(test_name); end if; end;</p> <p>procedure testsuite_report is begin dbms_output.put_line(''); dbms_output.put_line( total_count || ' tests, ' || pass_count || ' passed, ' || fail_count || ' failed' );</p> <pre><code>execute immediate 'insert into pljson_testsuite values (:1, :2, :3, :4, :5, :6)'\n using suite_id, suite_name, file_name, pass_count, fail_count, total_count;\n</code></pre> <p>end;</p> <p>procedure startup is begin suite_id := 0; execute immediate 'truncate table pljson_testsuite'; end;</p> <p>procedure shutdown is begin commit;</p> <pre><code>dbms_output.put_line('');\nfor rec in (\n select suite_id, suite_name, passed, failed, total, file_name\n from (\n select 3 s, suite_id,\n lpad(suite_name, 30) suite_name,\n to_char(passed, '999999') passed,\n to_char(failed, '999999') failed,\n to_char(total, '999999') total,\n lpad(file_name, 30) file_name\n from pljson_testsuite\n union\n select 1 s, 0 suite_id,\n lpad('SUITE_NAME', 30) suite_name,\n lpad('PASSED', 7) passed,\n lpad('FAILED', 7) failed,\n lpad('TOTAL', 7) total,\n lpad('FILE_NAME', 30) file_name\n from dual\n union\n select 5 s, 0,\n lpad('ALL TESTS', 30) suite_name,\n to_char(sum(passed), '999999') passed,\n to_char(sum(failed), '999999') failed,\n to_char(sum(total), '999999') total,\n lpad(' ', 30) file_name\n from pljson_testsuite\n union\n select 2 s, 0 suite_id,\n lpad('-', 30, '-') suite_name,\n lpad('-', 7, '-') passed,\n lpad('-', 7, '-') failed,\n lpad('-', 7, '-') total,\n lpad('-', 30, '-') file_name\n from dual\n union\n select 4 s, 0 suite_id,\n lpad('-', 30, '-') suite_name,\n lpad('-', 7, '-') passed,\n lpad('-', 7, '-') failed,\n lpad('-', 7, '-') total,\n lpad('-', 30, '-') file_name\n from dual\n order by s, suite_id\n )\n)\nloop\n dbms_output.put_line(\n rec.suite_name||' '||rec.passed||' '||rec.failed||' '||rec.total||' '||rec.file_name\n );\nend loop;\n</code></pre> <p>end;</p> <p>end pljson_ut;```</p>"},{"location":"packages/PLJSON_UTIL_PKG/","title":"PLJSON_UTIL_PKG","text":""},{"location":"packages/PLJSON_UTIL_PKG/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_util_pkg authid current_user as</p> <p>/*</p> <p>Purpose: JSON utilities for PL/SQL see http://ora-00001.blogspot.com/</p> <p>Remarks:</p> <p>Who Date Description</p> <p>MBR 30.01.2010 Created JKR 01.05.2010 Edited to fit in PL/JSON JKR 19.01.2011 Newest stylesheet + bugfix handling</p> <p>*/</p> <p>-- generate JSON from REF Cursor function ref_cursor_to_json (p_ref_cursor in sys_refcursor, p_max_rows in number := null, p_skip_rows in number := null) return pljson_list;</p> <p>-- generate JSON from SQL statement function sql_to_json (p_sql in varchar2, p_max_rows in number := null, p_skip_rows in number := null) return pljson_list;</p> <p>end pljson_util_pkg;```</p>"},{"location":"packages/PLJSON_UTIL_PKG/#package-body","title":"Package Body","text":"<p>```sql package body pljson_util_pkg as scanner_exception exception; pragma exception_init(scanner_exception, -20100); parser_exception exception; pragma exception_init(parser_exception, -20101);</p> <p>/*</p> <p>Purpose: JSON utilities for PL/SQL</p> <p>Remarks:</p> <p>Who Date Description</p> <p>MBR 30.01.2010 Created</p> <p>*/</p> <p>function get_xml_to_json_stylesheet return varchar2 as stylesheet varchar2(32767); nls_numeric_characters varchar2(2); begin</p> <p>/*</p> <p>Purpose: return XSLT stylesheet for XML to JSON transformation</p> <p>Remarks: see http://code.google.com/p/xml2json-xslt/</p> <p>Who Date Description</p> <p>MBR 30.01.2010 Created MBR 30.01.2010 Added fix for nulls</p> <p>*/</p> <p>stylesheet := q'^ <p> </p> <p>0123456789</p> <p></p> <p> </p> <p> \" \" </p> <p> </p> <p> </p> <p> </p> <p> <pre><code>&lt;xsl:variable name=\"num_string\" select=\"translate(., '{{nls_numeric_characters}}', '.,')\"/&gt;\n\n&lt;xsl:choose&gt;\n &lt;xsl:when test=\"starts-with($num_string, '.')\"&gt;\n &lt;xsl:value-of select=\"concat('0', $num_string)\"/&gt;\n &lt;/xsl:when&gt;\n &lt;xsl:otherwise&gt;\n &lt;xsl:value-of select=\"$num_string\"/&gt;\n &lt;/xsl:otherwise&gt;\n&lt;/xsl:choose&gt;\n</code></pre> <p></p> <p>true false</p> <p> { : null , } </p> <p> [ null , ] </p> <p> </p> <p>^';</p> <p>select value into nls_numeric_characters from nls_session_parameters where parameter = 'NLS_NUMERIC_CHARACTERS';</p> <p>return replace(stylesheet, '{{nls_numeric_characters}}', nls_numeric_characters);</p> <p>end get_xml_to_json_stylesheet;</p> <p>function ref_cursor_to_json (p_ref_cursor in sys_refcursor, p_max_rows in number := null, p_skip_rows in number := null) return pljson_list as l_ctx dbms_xmlgen.ctxhandle; l_num_rows pls_integer; l_xml xmltype; l_xsl xmltype := xmltype(get_xml_to_json_stylesheet); l_returnvalue clob; begin</p> <p>/*</p> <p>Purpose: generate JSON from REF Cursor</p> <p>Remarks:</p> <p>Who Date Description</p> <p>MBR 30.01.2010 Created JKR 01.05.2010 Edited to fit in PL/JSON</p> <p>*/</p> <p>l_ctx := dbms_xmlgen.newcontext (p_ref_cursor);</p> <p>dbms_xmlgen.setnullhandling (l_ctx, dbms_xmlgen.empty_tag);</p> <p>-- for pagination</p> <p>if p_max_rows is not null then dbms_xmlgen.setmaxrows (l_ctx, p_max_rows); end if;</p> <p>if p_skip_rows is not null then dbms_xmlgen.setskiprows (l_ctx, p_skip_rows); end if;</p> <p>-- get the XML content l_xml := dbms_xmlgen.getxmltype (l_ctx, dbms_xmlgen.none);</p> <p>l_num_rows := dbms_xmlgen.getnumrowsprocessed (l_ctx);</p> <p>dbms_xmlgen.closecontext (l_ctx);</p> <p>close p_ref_cursor;</p> <p>if(l_num_rows = 0) then return pljson_list(); end if;</p> <p>--dbms_output.put_line(l_xml.getstringval); -- perform the XSL transformation SELECT l_xml.transform(l_xsl).getclobval() INTO l_returnvalue FROM DUAL;</p> <p>--dbms_output.put_line(l_returnvalue);</p> <p>if(l_num_rows &gt; 1) then return pljson_list(pljson(l_returnvalue).get('ROWSET')); end if;</p> <p>declare ret pljson_list := pljson_list(); begin ret.append( pljson( pljson(l_returnvalue).get('ROWSET') ).get('ROW') ); return ret; end;</p> <p>exception when scanner_exception then dbms_output.put('Scanner problem with the following input: '); dbms_output.put_line(l_returnvalue); raise; when parser_exception then dbms_output.put('Parser problem with the following input: '); dbms_output.put_line(l_returnvalue); raise; when others then raise; end ref_cursor_to_json;</p> <p>function sql_to_json (p_sql in varchar2, p_max_rows in number := null, p_skip_rows in number := null) return pljson_list as v_cur sys_refcursor; begin open v_cur for p_sql; return ref_cursor_to_json(v_cur, p_max_rows, p_skip_rows);</p> <p>end sql_to_json;</p> <p>end pljson_util_pkg;```</p>"},{"location":"packages/PLJSON_XML/","title":"PLJSON_XML","text":""},{"location":"packages/PLJSON_XML/#package-specification","title":"Package Specification","text":"<p>```sql package pljson_xml as /* Copyright (c) 2010 Jonas Krogsboell</p> <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p> <p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p> <p>THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */</p> <p>/ declare obj json := json('{a:1, b:[2, 3, 4], c:true}'); x xmltype; begin obj.print; x := json_xml.json_to_xml(obj); dbms_output.put_line(x.getclobval()); end; /</p> <p>function json_to_xml(obj pljson, tagname varchar2 default 'root') return xmltype;</p> <p>end pljson_xml;```</p>"},{"location":"packages/PLJSON_XML/#package-body","title":"Package Body","text":"<p>```sql package body pljson_xml as</p> <p>function escapeStr(str varchar2) return varchar2 as buf varchar2(32767) := ''; ch varchar2(4); begin for i in 1 .. length(str) loop ch := substr(str, i, 1); case ch when '&amp;' then buf := buf || '&amp;'; when '&lt;' then buf := buf || '&lt;'; when '&gt;' then buf := buf || '&gt;'; when '\"' then buf := buf || '\"'; else buf := buf || ch; end case; end loop; return buf; end escapeStr;</p> <p>/ Clob methods from printer / procedure add_to_clob(buf_lob in out nocopy clob, buf_str in out nocopy varchar2, str varchar2) as begin -- if (length(str) &gt; 5000 - length(buf_str)) then if (lengthb(str) &gt; 32767 - lengthb(buf_str)) then dbms_lob.append(buf_lob, buf_str); buf_str := str; else buf_str := buf_str || str; end if; end add_to_clob;</p> <p>procedure flush_clob(buf_lob in out nocopy clob, buf_str in out nocopy varchar2) as begin dbms_lob.append(buf_lob, buf_str); end flush_clob;</p> <p>procedure toString(obj pljson_element, tagname in varchar2, xmlstr in out nocopy clob, xmlbuf in out nocopy varchar2) as v_obj pljson; v_list pljson_list;</p> <pre><code>v_keys pljson_list;\nv_value pljson_element;\nkey_str varchar2(4000);\n</code></pre> <p>begin if (obj.is_object()) then add_to_clob(xmlstr, xmlbuf, '&lt;' || tagname || '&gt;'); v_obj := pljson(obj);</p> <pre><code> v_keys := v_obj.get_keys();\n for i in 1 .. v_keys.count loop\n v_value := v_obj.get(i);\n key_str := v_keys.get(i).get_string();\n\n if (key_str = 'content') then\n if (v_value.is_array()) then\n declare\n v_l pljson_list := pljson_list(v_value);\n begin\n for j in 1 .. v_l.count loop\n if (j &gt; 1) then add_to_clob(xmlstr, xmlbuf, chr(13)||chr(10)); end if;\n add_to_clob(xmlstr, xmlbuf, escapeStr(v_l.get(j).to_char()));\n end loop;\n end;\n else\n add_to_clob(xmlstr, xmlbuf, escapeStr(v_value.to_char()));\n end if;\n elsif (v_value.is_array()) then\n declare\n v_l pljson_list := pljson_list(v_value);\n begin\n for j in 1 .. v_l.count loop\n v_value := v_l.get(j);\n if (v_value.is_array()) then\n add_to_clob(xmlstr, xmlbuf, '&lt;' || key_str || '&gt;');\n add_to_clob(xmlstr, xmlbuf, escapeStr(v_value.to_char()));\n add_to_clob(xmlstr, xmlbuf, '&lt;/' || key_str || '&gt;');\n else\n toString(v_value, key_str, xmlstr, xmlbuf);\n end if;\n end loop;\n end;\n elsif (v_value.is_null() or (v_value.is_string() and v_value.get_string() = '')) then\n add_to_clob(xmlstr, xmlbuf, '&lt;' || key_str || '/&gt;');\n else\n toString(v_value, key_str, xmlstr, xmlbuf);\n end if;\n end loop;\n\n add_to_clob(xmlstr, xmlbuf, '&lt;/' || tagname || '&gt;');\nelsif (obj.is_array()) then\n v_list := pljson_list(obj);\n for i in 1 .. v_list.count loop\n v_value := v_list.get(i);\n toString(v_value, nvl(tagname, 'array'), xmlstr, xmlbuf);\n end loop;\nelse\n add_to_clob(xmlstr, xmlbuf, '&lt;' || tagname || '&gt;'||case when obj.value_of() is not null then escapeStr(obj.value_of()) end ||'&lt;/' || tagname || '&gt;');\nend if;\n</code></pre> <p>end toString;</p> <p>function json_to_xml(obj pljson, tagname varchar2 default 'root') return xmltype as xmlstr clob := empty_clob(); xmlbuf varchar2(32767) := ''; returnValue xmltype; begin dbms_lob.createtemporary(xmlstr, true);</p> <pre><code>toString(obj, tagname, xmlstr, xmlbuf);\n\nflush_clob(xmlstr, xmlbuf);\nreturnValue := xmltype('&lt;?xml version=\"1.0\"?&gt;'||xmlstr);\ndbms_lob.freetemporary(xmlstr);\nreturn returnValue;\n</code></pre> <p>end;</p> <p>end pljson_xml;```</p>"},{"location":"packages/UTL_BASE64/","title":"UTL_BASE64","text":""},{"location":"packages/UTL_BASE64/#package-specification","title":"Package Specification","text":"<pre><code>PACKAGE \"UTL_BASE64\" is\n function decode_base64(p_clob_in in clob) return blob;\n\n function encode_base64(p_blob_in in blob) return clob;\n\n FUNCTION encodeBlob2Base64(pBlobIn IN BLOB) RETURN BLOB;\n\n FUNCTION decodeBase642Blob(pBlobIn IN BLOB) RETURN BLOB;\n\n function base64encode(p_blob in blob) return clob;\nend;\n</code></pre>"},{"location":"packages/UTL_BASE64/#package-body","title":"Package Body","text":"<pre><code>PACKAGE BODY \"UTL_BASE64\" is\n function decode_base64(p_clob_in in clob) return blob is\n v_blob blob;\n v_result blob;\n v_offset integer;\n v_buffer_size binary_integer := 48;\n v_buffer_varchar varchar2(48);\n v_buffer_raw raw(48);\n begin\n if p_clob_in is null then\n return null;\n end if;\n dbms_lob.createtemporary(v_blob, true);\n v_offset := 1;\n for i in 1 .. ceil(dbms_lob.getlength(p_clob_in) / v_buffer_size) loop\n dbms_lob.read(p_clob_in, v_buffer_size, v_offset, v_buffer_varchar);\n v_buffer_raw := utl_raw.cast_to_raw(v_buffer_varchar);\n v_buffer_raw := utl_encode.base64_decode(v_buffer_raw);\n dbms_lob.writeappend(v_blob, utl_raw.length(v_buffer_raw), v_buffer_raw);\n v_offset := v_offset + v_buffer_size;\n end loop;\n v_result := v_blob;\n dbms_lob.freetemporary(v_blob);\n return v_result;\n end decode_base64;\n\n function encode_base64(p_blob_in in blob) return clob is\n v_clob clob;\n v_result clob;\n v_offset integer;\n v_chunk_size binary_integer := (48 / 4) * 3;\n v_buffer_varchar varchar2(48);\n v_buffer_raw raw(48);\n begin\n if p_blob_in is null then\n return null;\n end if;\n dbms_lob.createtemporary(v_clob, true);\n v_offset := 1;\n for i in 1 .. ceil(dbms_lob.getlength(p_blob_in) / v_chunk_size) loop\n dbms_lob.read(p_blob_in, v_chunk_size, v_offset, v_buffer_raw);\n v_buffer_raw := utl_encode.base64_encode(v_buffer_raw);\n v_buffer_varchar := utl_raw.cast_to_varchar2(v_buffer_raw);\n dbms_lob.writeappend(v_clob, length(v_buffer_varchar), v_buffer_varchar);\n v_offset := v_offset + v_chunk_size;\n end loop;\n v_result := v_clob;\n dbms_lob.freetemporary(v_clob);\n return v_result;\n end encode_base64;\n\n FUNCTION encodeBlob2Base64(pBlobIn IN BLOB) RETURN BLOB IS\n vAmount NUMBER := 45;\n vBlobEnc BLOB := empty_blob();\n vBlobEncLen NUMBER := 0;\n vBlobInLen NUMBER := 0;\n vBuffer RAW(45);\n vOffset NUMBER := 1;\n BEGIN\n-- dbms_output.put_line('Start base64 encoding.');\n vBlobInLen := dbms_lob.getlength(pBlobIn);\n-- dbms_output.put_line('&lt;BlobInLength&gt;' || vBlobInLen);\n dbms_lob.createtemporary(vBlobEnc, TRUE);\n LOOP\n IF vOffset &gt;= vBlobInLen THEN\n EXIT;\n END IF;\n dbms_lob.read(pBlobIn, vAmount, vOffset, vBuffer);\n BEGIN\n dbms_lob.append(vBlobEnc, utl_encode.base64_encode(vBuffer));\n EXCEPTION\n WHEN OTHERS THEN\n dbms_output.put_line('&lt;vAmount&gt;' || vAmount || '&lt;vOffset&gt;' || vOffset || '&lt;vBuffer&gt;' || vBuffer);\n dbms_output.put_line('ERROR IN append: ' || SQLERRM);\n RAISE;\n END;\n vOffset := vOffset + vAmount;\n END LOOP;\n vBlobEncLen := dbms_lob.getlength(vBlobEnc);\n-- dbms_output.put_line('&lt;BlobEncLength&gt;' || vBlobEncLen);\n-- dbms_output.put_line('Finshed base64 encoding.');\n RETURN vBlobEnc;\n END encodeBlob2Base64;\n\n FUNCTION decodeBase642Blob(pBlobIn IN BLOB) RETURN BLOB IS\n vAmount NUMBER := 256;--32;\n vBlobDec BLOB := empty_blob();\n vBlobDecLen NUMBER := 0;\n vBlobInLen NUMBER := 0;\n vBuffer RAW(256);--32);\n vOffset NUMBER := 1;\n BEGIN\n-- dbms_output.put_line('Start base64 decoding.');\n vBlobInLen := dbms_lob.getlength(pBlobIn);\n-- dbms_output.put_line('&lt;BlobInLength&gt;' || vBlobInLen);\n dbms_lob.createtemporary(vBlobDec, TRUE);\n LOOP\n IF vOffset &gt;= vBlobInLen THEN\n EXIT;\n END IF;\n dbms_lob.read(pBlobIn, vAmount, vOffset, vBuffer);\n BEGIN\n dbms_lob.append(vBlobDec, utl_encode.base64_decode(vBuffer));\n EXCEPTION\n WHEN OTHERS THEN\n dbms_output.put_line('&lt;vAmount&gt;' || vAmount || '&lt;vOffset&gt;' || vOffset || '&lt;vBuffer&gt;' || vBuffer);\n dbms_output.put_line('ERROR IN append: ' || SQLERRM);\n RAISE;\n END;\n vOffset := vOffset + vAmount;\n END LOOP;\n vBlobDecLen := dbms_lob.getlength(vBlobDec);\n-- dbms_output.put_line('&lt;BlobDecLength&gt;' || vBlobDecLen);\n-- dbms_output.put_line('Finshed base64 decoding.');\n RETURN vBlobDec;\n END decodeBase642Blob;\n\n function base64encode(p_blob in blob) \n return clob \n is \n CRLF constant varchar2(2) := chr(13)||chr(10); \n l_clob clob; \n l_amount integer := 23826; \n l_offset integer := 1; \n l_raw raw(32767); \n l_buf varchar2(32767); \n l_len integer := dbms_lob.getlength(p_blob); \n begin \n\n dbms_lob.createtemporary(l_clob, true, dbms_lob.call); \n\n while l_offset &lt;= l_len loop \n dbms_lob.read(p_blob, l_amount, l_offset, l_raw); \n l_offset := l_offset + l_amount; \n l_buf := utl_raw.cast_to_varchar2(utl_encode.base64_encode(l_raw)); \n l_buf := replace(l_buf, CRLF); \n dbms_lob.writeappend(l_clob, length(l_buf), l_buf); \n end loop; \n\n return l_clob; \n\n end base64encode; \n\nend;\n</code></pre>"},{"location":"packages/XLIB_COMPONENT/","title":"XLIB_COMPONENT","text":""},{"location":"packages/XLIB_COMPONENT/#package-specification","title":"Package Specification","text":"<p>```sql PACKAGE \"XLIB_COMPONENT\" AS /*========================================================================= $Id: xlib_component.pks 57 2013-05-13 07:09:51Z dietmar.aust $</p> <p>Purpose :</p> <p>License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de) Licensed under a BSD style license (license.txt) http://www.opal-consulting.de/pls/apex/f?p=20090928:14</p> <p>$LastChangedDate: 2013-05-13 09:09:51 +0200 (Mon, 13 May 2013) $ $LastChangedBy: dietmar.aust $</p> <p>Date Author Comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 06.01.2010 D. Aust Initial creation</p> <p>=========================================================================*/</p> <p>-- how many digits does the version key have? -- 3 =&gt; e.g. 1.0.0 -- 4 =&gt; e.g. 1.0.0.0 c_num_version_components CONSTANT NUMBER := 6;</p> <p>PROCEDURE create_component ( p_name xlib_components.comp_name%TYPE, p_version xlib_components.comp_version%TYPE, p_version_label xlib_components.comp_version_label%TYPE DEFAULT NULL, p_depends_on xlib_components.comp_depends_on%TYPE DEFAULT NULL );</p> <p>PROCEDURE set_component ( p_name xlib_components.comp_name%TYPE, p_version xlib_components.comp_version%TYPE, p_version_label xlib_components.comp_version_label%TYPE DEFAULT NULL, p_depends_on xlib_components.comp_depends_on%TYPE DEFAULT NULL );</p> <p>PROCEDURE delete_component (p_name IN xlib_components.comp_name%TYPE);</p> <p>/* utility functions **/ FUNCTION get_version (p_name IN xlib_components.comp_name%TYPE) RETURN xlib_components.comp_version%TYPE;</p> <p>FUNCTION make_version_string (p_version IN VARCHAR2) RETURN VARCHAR2;</p> <p>PROCEDURE verify_required_component ( p_comp_name IN VARCHAR2, p_comp_version_min IN VARCHAR2 ); END xlib_component;```</p>"},{"location":"packages/XLIB_COMPONENT/#package-body","title":"Package Body","text":"<p>```sql PACKAGE BODY \"XLIB_COMPONENT\" AS /========================================================================= FILE : $Id: xlib_component.pkb 57 2013-05-13 07:09:51Z dietmar.aust $ =========================================================================/ TYPE vc2_arr_t IS TABLE OF VARCHAR2 (32767 CHAR) INDEX BY BINARY_INTEGER;</p> <p>PROCEDURE create_component ( p_name xlib_components.comp_name%TYPE, p_version xlib_components.comp_version%TYPE, p_version_label xlib_components.comp_version_label%TYPE DEFAULT NULL, p_depends_on xlib_components.comp_depends_on%TYPE DEFAULT NULL</p> <p>) IS BEGIN INSERT INTO xlib_components (comp_id, comp_name, comp_version, comp_version_label, comp_depends_on ) VALUES (xlib_seq.NEXTVAL, p_name, p_version, p_version_label, p_depends_on ); END;</p> <p>PROCEDURE set_component ( p_name xlib_components.comp_name%TYPE, p_version xlib_components.comp_version%TYPE, p_version_label xlib_components.comp_version_label%TYPE DEFAULT NULL, p_depends_on xlib_components.comp_depends_on%TYPE DEFAULT NULL ) IS BEGIN INSERT INTO xlib_components (comp_id, comp_name, comp_version, comp_version_label, comp_depends_on ) VALUES (xlib_seq.NEXTVAL, p_name, p_version, p_version_label, p_depends_on ); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN UPDATE xlib_components SET comp_version = p_version, comp_version_label = p_version_label, comp_depends_on = p_depends_on WHERE comp_name = p_name;</p> <pre><code> IF SQL%ROWCOUNT = 0\n THEN\n raise_application_error (-20006,\n 'component ' || p_name || ' not found'\n );\n END IF;\n</code></pre> <p>END;</p> <p>PROCEDURE delete_component (p_name IN xlib_components.comp_name%TYPE) IS BEGIN -- delete component DELETE FROM xlib_components WHERE comp_name = p_name;</p> <pre><code> IF SQL%ROWCOUNT = 0\n THEN\n raise_application_error (-20001,\n 'Component ' || p_name || ' not found'\n );\n END IF;\n</code></pre> <p>END;</p> <p>FUNCTION split_string (p_str IN VARCHAR2, p_sep IN VARCHAR2 DEFAULT ',') RETURN vc2_arr_t AS l_string VARCHAR2 (32767) := p_str || p_sep; l_sep_index PLS_INTEGER; l_index PLS_INTEGER := 1; l_tab vc2_arr_t; BEGIN -- assertions IF LENGTH (p_sep) != 1 THEN raise_application_error (-20004, 'wrong separator format, must be only one character' ); END IF;</p> <pre><code> LOOP\n l_sep_index := INSTR (l_string, p_sep, l_index);\n EXIT WHEN l_sep_index = 0;\n l_tab (l_tab.COUNT) :=\n SUBSTR (l_string, l_index, l_sep_index - l_index);\n l_index := l_sep_index + 1;\n END LOOP;\n\n RETURN l_tab;\n</code></pre> <p>END;</p> <p>FUNCTION get_version (p_name IN xlib_components.comp_name%TYPE) RETURN xlib_components.comp_version%TYPE IS l_version xlib_components.comp_version%TYPE; BEGIN SELECT comp_version INTO l_version FROM xlib_components WHERE comp_name = p_name;</p> <pre><code> RETURN l_version;\n</code></pre> <p>END;</p> <p>PROCEDURE assert_version_format (p_version IN VARCHAR2) IS l_tab vc2_arr_t; l_num NUMBER; BEGIN -- '.' at the beginning or end of the version? IF SUBSTR (p_version, 1, 1) = '.' OR SUBSTR (p_version, LENGTH (p_version), 1) = '.' OR INSTR (p_version, ' ') &gt; 0 THEN raise_application_error (-20002, 'wrong version format'); END IF;</p> <pre><code> l_tab := split_string (p_version, '.');\n\n FOR i IN 0 .. l_tab.COUNT - 1\n LOOP\n l_num := TO_NUMBER (l_tab (i));\n END LOOP;\n</code></pre> <p>EXCEPTION WHEN OTHERS THEN IF SQLCODE = -6502 / numeric or value error / THEN raise_application_error (-20005, 'wrong version format, no numbers.' ); ELSE RAISE; END IF; END;</p> <p>FUNCTION make_version_string (p_version IN VARCHAR2) RETURN VARCHAR2 IS l_num_dots NUMBER; l_tab vc2_arr_t; l_str VARCHAR2 (32767 CHAR); l_comp VARCHAR2 (50 CHAR); BEGIN -- assertions assert_version_format (p_version =&gt; p_version); l_tab := split_string (p_version, '.');</p> <pre><code> FOR i IN 1 .. c_num_version_components\n LOOP\n IF l_tab.EXISTS (i - 1)\n THEN\n l_comp :=\n TO_CHAR (TO_NUMBER (NVL (l_tab (i - 1), '0')), 'FM0000');\n ELSE\n l_comp := '0000';\n END IF;\n\n IF l_str IS NULL\n THEN\n l_str := l_comp;\n ELSE\n l_str := l_str || '.' || l_comp;\n END IF;\n END LOOP;\n\n RETURN l_str;\n</code></pre> <p>END;</p> <p>PROCEDURE verify_required_component ( p_comp_name IN VARCHAR2, p_comp_version_min IN VARCHAR2 ) IS l_current_version VARCHAR2 (50); BEGIN l_current_version := xlib_component.get_version (p_name =&gt; p_comp_name);</p> <pre><code> IF make_version_string (l_current_version)\n &gt;= make_version_string (p_comp_version_min)\n THEN\n NULL; -- ok\n ELSE\n raise_application_error\n (-20020,\n 'this upgrade requires '||p_comp_name||' in version '\n || p_comp_version_min\n || ' or higher, not version '\n || l_current_version\n );\n END IF;\n</code></pre> <p>END; END xlib_component;```</p>"},{"location":"packages/XLIB_HTTP/","title":"XLIB_HTTP","text":""},{"location":"packages/XLIB_HTTP/#package-specification","title":"Package Specification","text":"<p>```sql PACKAGE \"XLIB_HTTP\" AS /*=========================================================================</p> <p>Purpose : Make http callouts</p> <p>License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de) Licensed under a BSD style license (license.txt) http://www.opal-consulting.de/pls/apex/f?p=20090928:14</p> <p>Version Date Author Comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19.02.2007 D. Aust initial creation 07.08.2008 D. Aust - added check_get_request - display_url_raw: pass all request headers to the client 05.08.2012 D. Aust suppress mime header TRANSFER-ENCODING, causes lots of problems with XMLDB listener and others choking. 2.3.0.0 19.05.2014 D. Aust - #294 - Fix chunked encoding problem in xlib_http.get_report - added version information to this package 2.3.0.0 09.05.2015 D. Aust pass JSESSIONID from backend J2EE server to client for image rendering in html reports 2.6.1 28.09.2020 D. Aust - #40 - APEX 20.1 security bundle (PSE 30990551) rejects response header \"Cache-Control: private\" 2.6.2 13.10.2020 D. Aust - added function check_acl()</p> <p>=========================================================================*/</p> <p>c_success CONSTANT CHAR (1) := '1'; c_fail CONSTANT CHAR (1) := '0';</p> <p>-- version of this package version_c constant varchar2(20 char) := '2.6.2';</p> <p>TYPE vc_arr_t IS TABLE OF VARCHAR2 (32767) INDEX BY BINARY_INTEGER; g_empty_vc_arr vc_arr_t;</p> <p>/ Function: MyFunction * * Parameters: * * x - Description of x. * y - Description of y. * z - Description of z. / PROCEDURE display_url_raw ( p_url VARCHAR2, p_mime_type_override IN VARCHAR2 DEFAULT NULL, p_charset IN VARCHAR2 DEFAULT NULL, p_header_name_arr IN vc_arr_t default g_empty_vc_arr, p_header_value_arr IN vc_arr_t default g_empty_vc_arr );</p> <p>/* Procedure: retrieve_blob_from_url</p> <p>Multiplies two integers.</p> <p>Parameters:</p> <pre><code> p_url - url to be called\n\n o_blob - output: the resulting out blob\n o_mime_type - output: the resulting out mime type from the call\n</code></pre> <p>Returns:</p> <pre><code> The two integers multiplied together.\n o_blob - the resulting out blob\n</code></pre> <p>See Also:</p> <pre><code> &lt;escape_form_data&gt;\n</code></pre> <p>*/ PROCEDURE retrieve_blob_from_url ( p_url VARCHAR2, o_blob OUT BLOB, o_mime_type OUT VARCHAR2 );</p> <p>/* Function: escape_form_data Here is some describing text ...</p> <p>--- SQL declare l_i number; begin null;</p> <p>Select count(*) into l_count from dual; end;</p> <p>Parameters: s - string to be escaped</p> <p>Returns: the escaped data */ FUNCTION escape_form_data (s VARCHAR2) RETURN VARCHAR2;</p> <p>/* Function: check_get_request</p> <p>Parameters: p_url the url to be called</p> <p>Returns: Returns c_fail or c_success</p> <p>*/ FUNCTION check_get_request (p_url VARCHAR2) RETURN CHAR;</p> <p>/* Function: check_acl</p> <p>Parameters: p_url the url to be called</p> <p>Returns: Returns c_fail or c_success */ FUNCTION check_acl (p_url VARCHAR2) RETURN CHAR; END;```</p>"},{"location":"packages/XLIB_HTTP/#package-body","title":"Package Body","text":"<p>```sql PACKAGE BODY \"XLIB_HTTP\" AS /*=========================================================================</p> <p>Purpose : Make http callouts</p> <p>License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de) Licensed under a BSD style license (license.txt) https://github.com/daust/JasperReportsIntegration</p> <p>Version Date Author Comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19.02.2007 D. Aust initial creation 07.08.2008 D. Aust - added check_get_request - display_url_raw: pass all request headers to the client 05.08.2012 D. Aust suppress mime header TRANSFER-ENCODING, causes lots of problems with XMLDB listener and others choking. 2.3.0.0 19.05.2014 D. Aust - #294 - Fix chunked encoding problem in xlib_http.get_report - added version information to this package 2.3.0.0 09.05.2015 D. Aust pass JSESSIONID from backend J2EE server to client for image rendering in html reports 2.6.1 28.09.2020 D. Aust - #40 - APEX 20.1 security bundle (PSE 30990551) rejects response header \"Cache-Control: private\" 2.6.2 13.10.2020 D. Aust - added function check_acl()</p> <p>=========================================================================*/</p> <p>m_module VARCHAR2 (50) := 'XLIB_HTTP';</p> <p>PROCEDURE display_url_raw ( p_url VARCHAR2, p_mime_type_override IN VARCHAR2 DEFAULT NULL, p_charset IN VARCHAR2 DEFAULT NULL, p_header_name_arr IN vc_arr_t default g_empty_vc_arr, p_header_value_arr IN vc_arr_t default g_empty_vc_arr ) IS l_http_request UTL_HTTP.req; l_http_response UTL_HTTP.resp; l_blob BLOB; l_raw RAW (32767); l_buffer_size NUMBER := 32767; -- l_proc VARCHAR2 (100) := m_module || '.DISPLAY_URL_RAW'; -- l_mime_type VARCHAR2 (100); l_header_name VARCHAR2 (256); l_header_value VARCHAR2 (1024); l_jsession VARCHAR2 (256); l_path VARCHAR2 (1024); -- l_header_name_arr vc_arr_t; l_header_value_arr vc_arr_t; -- l_msg varchar2(32767); BEGIN xlog (l_proc, 'show url: ' || p_url); --htp.flush(); --htp.init();</p> <pre><code> -- Initialize the BLOB.\n DBMS_LOB.createtemporary (l_blob, FALSE);\n\n l_http_request := UTL_HTTP.begin_request (url =&gt; p_url,\n method =&gt; 'GET',\n http_version =&gt; utl_http.http_version_1_0);\n\n utl_http.set_header (l_http_request, 'Connection', 'Keep-Alive');\n\n -- pass additional headers to the target service\n for i in 1..p_header_name_arr.count loop\n xlog(l_proc, 'pass additional headers to target service: '|| p_header_name_arr(i) ||': '||p_header_value_arr(i));\n utl_http.set_header(l_http_request, p_header_name_arr(i), p_header_value_arr(i));\n end loop;\n\n -- get response from target service\n l_http_response := UTL_HTTP.get_response (l_http_request);\n\n FOR i IN 1 .. UTL_HTTP.get_header_count (l_http_response)\n LOOP\n UTL_HTTP.get_header (l_http_response,\n i,\n l_header_name,\n l_header_value\n );\n -- store header value in arr\n l_header_name_arr (i) := l_header_name;\n l_header_value_arr (i) := l_header_value;\n\n IF LOWER (l_header_name) = 'content-type'\n THEN\n l_mime_type := l_header_value;\n xlog(l_proc, 'content-type from server: ' || l_mime_type);\n END IF;\n END LOOP;\n\n -- override mime type\n IF p_mime_type_override IS NOT NULL\n THEN\n l_mime_type := p_mime_type_override;\n END IF;\n\n -- Copy the response into the BLOB.\n BEGIN\n LOOP\n UTL_HTTP.read_raw (l_http_response, l_raw, l_buffer_size);\n DBMS_LOB.writeappend (l_blob, UTL_RAW.LENGTH (l_raw), l_raw);\n END LOOP;\n EXCEPTION\n WHEN UTL_HTTP.end_of_body\n THEN\n UTL_HTTP.end_response (l_http_response);\n END;\n\n xlog(l_proc, 'set content-type: ' || l_mime_type);\n OWA_UTIL.mime_header (ccontent_type =&gt; l_mime_type,\n bclose_header =&gt; FALSE,\n ccharset =&gt; p_charset\n );\n\n FOR i IN 1 .. l_header_name_arr.COUNT\n LOOP\n IF UPPER (l_header_name_arr (i)) IN\n ('CONTENT-LENGTH', 'CONTENT-TYPE', 'MIME-TYPE', 'TRANSFER-ENCODING',\n 'STRICT-TRANSPORT-SECURITY', 'CACHE-CONTROL', 'PRAGMA', 'EXPIRES')\n THEN\n --xlog (l_proc, 'skip header ' || l_header_name_arr (i));\n null;\n ELSE\n if upper(l_header_name_arr(i)) = 'SET-COOKIE' and l_header_value_arr (i) like 'JSESSIONID%' then\n xlog(l_proc , 'JSESSION_ID found !!!:'||l_header_value_arr (i));\n --extract path\n l_jsession := regexp_substr(l_header_value_arr (i), 'JSESSIONID=(.*);[ ]*Path',1, 1,'i',1);\n l_path := regexp_substr(l_header_value_arr (i), ';[ ]*Path=(.*)',1, 1,'i',1);\n\n xlog(l_proc, 'xx:full:'||l_header_value_arr (i)|| '; xx:session:'||l_jsession || '; xx:path:'||l_path);\n else\n l_header_value := l_header_value_arr (i);\n end if;\n xlog (l_proc,\n 'set header:'\n || l_header_name_arr (i)\n || ': '\n || l_header_value\n );\n HTP.p (l_header_name_arr (i) || ': ' || l_header_value);\n END IF;\n END LOOP;\n\n -- JSESSION Cookies ausgeben\n -- if using tunnel, then the cookie is JRI_JSESSIONID\n -- if not using tunnel, then cookie is JSESSIONID directly\n --\n if xlib_jasperreports.get_use_images_no_tunnel=false then\n l_msg := 'Set-Cookie: ' || xlib_jasperreports.m_jri_cookie_name_c || '=' || l_jsession;\n xlog (l_proc, 'set header:' || l_msg );\n HTP.p (l_msg);\n l_msg := 'Set-Cookie: ' || xlib_jasperreports.m_jri_path_cookie_name_c || '=' || l_path;\n xlog (l_proc, 'set header:' || l_msg );\n HTP.p (l_msg);\n else\n l_msg := 'Set-Cookie: JSESSIONID=' || l_jsession;\n if xlib_jasperreports.get_cookie_path_no_tunnel is not null then\n l_msg := l_msg || '; Path=' || xlib_jasperreports.get_cookie_path_no_tunnel;\n end if;\n xlog (l_proc, 'set header:' || l_msg );\n HTP.p (l_msg);\n end if;\n\n -- set content length\n HTP.p ('Content-length: ' || DBMS_LOB.getlength (l_blob));\n OWA_UTIL.http_header_close;\n WPG_DOCLOAD.download_file (l_blob);\n -- Relase the resources associated with the temporary LOB.\n DBMS_LOB.freetemporary (l_blob);\n</code></pre> <p>EXCEPTION WHEN UTL_HTTP.end_of_body THEN UTL_HTTP.end_response (l_http_response); DBMS_LOB.freetemporary (l_blob); RAISE; WHEN OTHERS THEN xlog (l_proc, 'Error: ' || SQLERRM, 'ERROR'); RAISE; END;</p> <p>PROCEDURE retrieve_blob_from_url ( p_url VARCHAR2, o_blob OUT BLOB, o_mime_type OUT VARCHAR2 ) IS l_http_request UTL_HTTP.req; l_http_response UTL_HTTP.resp; l_raw RAW (32767); -- l_proc VARCHAR2 (100) := m_module || '.RETRIEVE_BLOB_FROM_URL'; -- l_header_name VARCHAR2 (256); l_header_value VARCHAR2 (1024); BEGIN -- Initialize the BLOB. dbms_lob.createtemporary (o_blob, false); l_http_request := utl_http.begin_request (url =&gt; p_url, method =&gt; 'GET', http_version =&gt; utl_http.http_version_1_0);</p> <pre><code> l_http_response := UTL_HTTP.get_response (l_http_request);\n\n FOR i IN 1 .. UTL_HTTP.get_header_count (l_http_response)\n LOOP\n UTL_HTTP.get_header (l_http_response,\n i,\n l_header_name,\n l_header_value\n );\n\n IF LOWER (l_header_name) = 'content-type'\n THEN\n o_mime_type := l_header_value;\n END IF;\n END LOOP;\n\n -- Copy the response into the BLOB.\n BEGIN\n LOOP\n UTL_HTTP.read_raw (l_http_response, l_raw, 32767);\n DBMS_LOB.writeappend (o_blob, UTL_RAW.LENGTH (l_raw), l_raw);\n END LOOP;\n EXCEPTION\n WHEN UTL_HTTP.end_of_body\n THEN\n UTL_HTTP.end_response (l_http_response);\n END;\n</code></pre> <p>-- Relase the resources associated with the temporary LOB. --DBMS_LOB.freetemporary (l_blob); EXCEPTION WHEN OTHERS THEN UTL_HTTP.end_response (l_http_response); DBMS_LOB.freetemporary (o_blob); xlog (l_proc, 'Error: ' || SQLERRM, 'ERROR'); RAISE; END;</p> <p>FUNCTION escape_form_data (s VARCHAR2) RETURN VARCHAR2 IS l_s VARCHAR2 (500 CHAR);</p> <pre><code> FUNCTION r (s VARCHAR2, c VARCHAR2)\n RETURN VARCHAR2\n IS\n BEGIN\n RETURN REPLACE (s, c, '%' || TRIM (TO_CHAR (ASCII (c), 'XX')));\n END;\n</code></pre> <p>BEGIN l_s := s; l_s := REPLACE (l_s, ' ', '+'); l_s := r (l_s, chr(37)); -- % l_s := r (l_s, chr(37)); -- / l_s := r (l_s, chr(63)); -- ? l_s := r (l_s, chr(38)); -- &amp; l_s := r (l_s, chr(228)); -- \ufffd\ufffd\ufffd l_s := r (l_s, chr(196)); -- \ufffd\ufffd l_s := r (l_s, chr(246)); -- \ufffd\ufffd l_s := r (l_s, chr(214)); -- \ufffd\ufffd l_s := r (l_s, chr(252)); -- \ufffd\ufffd l_s := r (l_s, chr(220)); -- \ufffd\ufffd\ufffd l_s := r (l_s, chr(223)); -- \ufffd\ufffd\ufffd RETURN l_s; END;</p> <p>FUNCTION check_get_request (p_url VARCHAR2) RETURN CHAR IS l_clob CLOB; BEGIN IF p_url IS NULL THEN RETURN c_fail; END IF;</p> <pre><code> SELECT HTTPURITYPE (p_url).getclob ()\n INTO l_clob\n FROM DUAL;\n\n /*SELECT c_success\n INTO l_ret\n FROM DUAL\n WHERE EXISTS (SELECT HTTPURITYPE (p_url).getclob ()\n FROM DUAL);\n */\n RETURN c_success;\n</code></pre> <p>EXCEPTION WHEN OTHERS THEN RETURN c_fail; END;</p> <p>FUNCTION check_acl (p_url VARCHAR2) RETURN CHAR IS l_clob CLOB; BEGIN IF p_url IS NULL THEN RETURN c_fail; END IF;</p> <pre><code> SELECT HTTPURITYPE (p_url).getclob ()\n INTO l_clob\n FROM DUAL;\n\n /*SELECT c_success\n INTO l_ret\n FROM DUAL\n WHERE EXISTS (SELECT HTTPURITYPE (p_url).getclob ()\n FROM DUAL);\n */\n RETURN c_success;\n</code></pre> <p>EXCEPTION WHEN OTHERS THEN -- acl problem if sqlcode=24247 then RETURN c_fail; else -- no acl problem return c_success; end if; END; END;```</p>"},{"location":"packages/XLIB_JASPERREPORTS/","title":"XLIB_JASPERREPORTS","text":""},{"location":"packages/XLIB_JASPERREPORTS/#package-specification","title":"Package Specification","text":"<p>```sql PACKAGE \"XLIB_JASPERREPORTS\" AS /*========================================================================= Purpose :</p> <p>License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de) Licensed under a BSD style license (license.txt) http://www.opal-consulting.de/pls/apex/f?p=20090928:14</p> <p>$LastChangedDate: 2018-09-30 09:00:44 +0200 (So, 30 Sep 2018) $ $LastChangedBy: dietmar.aust $</p> <p>Version Date Author Comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 06.01.2010 D. Aust Initial creation 06.05.2011 D. Aust added constants for xlsx and docx 05.08.2012 D. Aust added version 2.0.0 features: - direct printing - save file on server 11.05.2013 D. Aust added support for tunneling images for html exports only 2.3.0.0 19.05.2014 D. Aust - #294 - Fix chunked encoding problem in xlib_http.get_report - added version information to this package 2.4.0.0 15.10.2017 D. Aust FEATURE: #3941 - Support for timeZones (report parameter REPORT_TIME_ZONE) 2.5.0.0 29.09.2018 D. Aust FEATURE: #9 - Ability to set Printjob name (programmatically) 2.5.0.1 30.09.2018 D. Aust fix bool2string issue 2.6.1 01.10.2020 D. Aust add get_default_configuration() and set_default_configuration() 2.6.2 13.10.2020 D. Aust #54 - Timeout value from default table not working</p> <p>=========================================================================*/</p> <p>-- version of this package version_c constant varchar2(20 char) := '2.6.2';</p> <p>-- constants -- supported formats c_rep_format_pdf CONSTANT VARCHAR2 (20) := 'pdf'; c_rep_format_rtf CONSTANT VARCHAR2 (20) := 'rtf'; c_rep_format_xls CONSTANT VARCHAR2 (20) := 'xls'; c_rep_format_html constant varchar2 (20) := 'html'; c_rep_format_html2 CONSTANT VARCHAR2 (20) := 'html2'; c_rep_format_csv CONSTANT VARCHAR2 (20) := 'csv'; c_rep_format_docx CONSTANT VARCHAR2 (20) := 'docx'; c_rep_format_pptx CONSTANT VARCHAR2 (20) := 'pptx'; c_rep_format_xlsx CONSTANT VARCHAR2 (20) := 'xlsx';</p> <p>-- images uri --c_images_uri_tunnel constant varchar2(100 char) -- := 'xlib_jasperreports_img.get_image?p_url=#REPORT_URL#&amp;p_image='; -- #IMAGE_NAME# and #J2EE_CONTEXT# will be substituted on the J2EE server side m_jri_cookie_name_c CONSTANT VARCHAR2 (50) := 'JRI_SESSIONID'; m_jri_path_cookie_name_c CONSTANT VARCHAR2 (50) := 'JRI_PATH'; c_images_uri_tunnel constant varchar2(500 char) := 'wwv_flow.show?p_request=APPLICATION_PROCESS%3DJRI_SHOW_IMAGE&amp;p_flow_id=#APP_ID#&amp;p_flow_step_id=0&amp;p_instance=#APP_SESSION#&amp;x01=#IMAGE_NAME#'; c_images_uri_no_tunnel constant varchar2(500 char) := '#J2EE_CONTEXT_PATH#/report_image?image=#IMAGE_NAME#';</p> <p>-- exceptions report_url_not_defined EXCEPTION;</p> <p>-- sets the url for the report server for all requests in the -- current session</p> <p>PROCEDURE set_report_url (p_report_url IN VARCHAR2);</p> <p>FUNCTION get_report_url RETURN VARCHAR2;</p>"},{"location":"packages/XLIB_JASPERREPORTS/#-set-the-image-uri-for-html-reports-only","title":"-- set the image uri for html reports only!","text":"<p>PROCEDURE set_images_uri (p_images_uri IN VARCHAR2 default null); procedure use_images_no_tunnel (p_server_uri in varchar2 default null, p_cookie_path varchar2 default null); function get_use_images_no_tunnel return boolean;</p> <p>FUNCTION get_images_uri return varchar2; FUNCTION get_cookie_path_no_tunnel RETURN VARCHAR2;</p> <p>/* make a callout with utl_http to the j2ee container running the * JasperReportsIntegration web application * =&gt; return the results * * @param p_rep_name name of the report (needs a name.jasper file deployed on the server) * @param p_rep_format report format, e.g. pdf, rtf, etc, see constants * @param p_data_source data source name, needs to be configured in J2EE application * @param p_out_filename filename if the file should be downloaded * @param p_rep_locale report locale setting, e.g. de_DE or en_US * @param p_rep_encoding encoding, e.g. UTF-8 * @param p_additional_params additional parameters, e.g.: p1=1&amp;p2=2 * @param p_print_is_enabled shall the report be sent to the printer directly? * @param p_print_printer_name name or substring of printer name * @param p_print_media media used, either the paper size or the tray * @param p_print_copies number of copies to be printed * @param p_print_duplex duplex printing? * @param p_print_collate sorting the print output? * @param p_save_is_enabled shall the generated file be saved on the server? * @param p_rep_time_zone \"time zone\" parameter for the execution of the report, a list of valid entries can be found here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones E.g.: Europe/Berlin, UCT, US/Central, US/Pacific, Etc/Greenwich, Europe/London * @param p_save_filename filename for the file to be saved on the server * @param p_print_job_name name of the print job name, by default it uses: JasperReports - * / PROCEDURE show_report ( p_rep_name IN VARCHAR2 DEFAULT 'test', p_rep_format IN VARCHAR2 DEFAULT c_rep_format_pdf, p_data_source IN VARCHAR2 DEFAULT 'default', p_out_filename IN VARCHAR2 DEFAULT NULL, p_rep_locale in varchar2 default 'de_DE', p_rep_encoding in varchar2 default 'UTF-8', p_additional_params in varchar2 default null, p_print_is_enabled in boolean default false, p_print_printer_name in varchar2 default null, p_print_media in varchar2 default null, p_print_copies in number default 1, p_print_duplex in boolean default false, p_print_collate in boolean default false, p_save_is_enabled in boolean default false, p_save_filename in varchar2 default null, p_rep_time_zone in varchar2 default null, p_print_job_name in varchar2 default null ); <p>/ tunnels images for html reports / procedure show_image(p_image_name IN VARCHAR2);</p> <p>/* run the report and return the result as a blob * * @param p_rep_name name of the report (needs a name.jasper file deployed on the server) * @param p_rep_format report format, e.g. pdf, rtf, etc, see constants * @param p_data_source data source name, needs to be configured in J2EE application * @param p_out_filename filename if the file should be downloaded * @param p_rep_locale report locale setting, e.g. de_DE or en_US * @param p_rep_encoding encoding, e.g. UTF-8 * @param p_additional_params additional parameters, e.g.: p1=1&amp;p2=2 * @param p_print_is_enabled shall the report be sent to the printer directly? * @param p_print_printer_name name or substring of printer name * @param p_print_media media used, either the paper size or the tray * @param p_print_copies number of copies to be printed * @param p_print_duplex duplex printing? * @param p_print_collate sorting the print output? * @param p_save_is_enabled shall the generated file be saved on the server? * @param p_save_filename filename for the file to be saved on the server * @param p_rep_time_zone \"time zone\" parameter for the execution of the report, a list of valid entries can be found here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones E.g.: Europe/Berlin, UCT, US/Central, US/Pacific, Etc/Greenwich, Europe/London * @param p_out_blob the blob will be returned here * @param p_out_mime_type the proper mime type of the generated file * @param p_print_job_name name of the print job name, by default it uses: JasperReports - * / PROCEDURE get_report ( p_rep_name IN VARCHAR2 DEFAULT 'test', p_rep_format in varchar2 default c_rep_format_pdf, p_data_source IN VARCHAR2 DEFAULT 'default', p_rep_locale in varchar2 default 'de_DE', p_rep_encoding IN VARCHAR2 DEFAULT 'UTF-8', p_additional_params in varchar2 default null, p_print_is_enabled in boolean default false, p_print_printer_name in varchar2 default null, p_print_media in varchar2 default null, p_print_copies in number default 1, p_print_duplex in boolean default false, p_print_collate in boolean default false, p_save_is_enabled in boolean default false, p_save_filename in varchar2 default null, p_rep_time_zone in varchar2 default null, p_out_blob IN OUT BLOB, p_out_mime_type IN OUT VARCHAR2, p_print_job_name in varchar2 default null );"},{"location":"packages/XLIB_JASPERREPORTS/#-get-default-configuration","title":"-- get default configuration","text":"<p>FUNCTION get_default_configuration return xlib_jasperreports_conf%rowtype;</p>"},{"location":"packages/XLIB_JASPERREPORTS/#-set-default-configuration","title":"-- set default configuration","text":"<pre><code>PROCEDURE set_default_configuration(p_conf in out xlib_jasperreports_conf%rowtype);\n\nPROCEDURE set_default_configuration (\np_protocol IN xlib_jasperreports_conf.conf_protocol%TYPE default 'http',\np_server IN xlib_jasperreports_conf.conf_server%TYPE default 'localhost',\np_port IN xlib_jasperreports_conf.conf_port%TYPE default '80',\np_context_path IN xlib_jasperreports_conf.conf_context_path%TYPE default 'jri',\np_wallet_path IN xlib_jasperreports_conf.conf_wallet_path%TYPE default null,\np_wallet_pwd IN xlib_jasperreports_conf.conf_wallet_pwd%TYPE default null,\np_http_transfer_timeout IN xlib_jasperreports_conf.conf_http_transfer_timeout%TYPE default 60);\n</code></pre> <p>END;```</p>"},{"location":"packages/XLIB_JASPERREPORTS/#package-body","title":"Package Body","text":"<p>```sql PACKAGE BODY \"XLIB_JASPERREPORTS\" AS /*========================================================================= Purpose :</p> <p>License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de) Licensed under a BSD style license (license.txt) http://www.opal-consulting.de/pls/apex/f?p=20090928:14</p> <p>$LastChangedDate: 2018-09-30 09:00:44 +0200 (So, 30 Sep 2018) $ $LastChangedBy: dietmar.aust $</p> <p>Version Date Author Comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 06.01.2010 D. Aust Initial creation 06.05.2011 D. Aust added constants for xlsx and docx 05.08.2012 D. Aust added version 2.0.0 features: - direct printing - save file on server 11.05.2013 D. Aust added support for tunneling images for html exports only 2.3.0.0 19.05.2014 D. Aust - #294 - Fix chunked encoding problem in xlib_http.get_report - added version information to this package 2.4.0.0 15.10.2017 D. Aust FEATURE: #3941 - Support for timeZones (report parameter REPORT_TIME_ZONE) 2.5.0.0 29.09.2018 D. Aust FEATURE: #9 - Ability to set Printjob name (programmatically) 2.5.0.1 30.09.2018 D. Aust fix bool2string issue 2.6.1 01.10.2020 D. Aust add get_default_configuration() and set_default_configuration() 2.6.2 13.10.2020 D. Aust #54 - Timeout value from default table not working</p> <p>=========================================================================*/</p> <p>m_module constant varchar2 (100) := $$plsql_unit; m_report_url VARCHAR2 (32767) := NULL; m_images_uri VARCHAR2 (32767) := NULL; m_use_images_no_tunnel boolean := false; m_cookie_path_no_tunnel varchar2(200 char) := null;</p> <p>-- convert boolean to 'true' or 'false' FUNCTION bool2string (b IN BOOLEAN) RETURN VARCHAR2 IS BEGIN IF b THEN RETURN 'true'; ELSE RETURN 'false'; END IF; END;</p> <pre><code>procedure setup_configuration_defaults\nis\n l_conf xlib_jasperreports_conf%rowtype;\n l_timeout PLS_INTEGER;\nbegin\n l_conf := get_default_configuration();\n\n -- override report url if not defined\n if m_report_url is null then\n m_report_url := l_conf.conf_protocol || '://'||l_conf.conf_server||':'||l_conf.conf_port||'/'||l_conf.conf_context_path||'/report';\n xlog(p_module =&gt; m_module, p_msg =&gt; 'Override report url from defaults: '|| m_report_url, p_type=&gt; 'DEBUG');\n end if;\n\n -- set wallet path and pwd\n -- will ALWAYS override the settings, will ignore previous calls to set_wallet\n -- at least we check whether the config table has an entry for the wallet or not.\n -- thus it could work relying on the wallet set by APEX through the internal workspace! :)\n if lower(m_report_url) like 'https%' and l_conf.conf_wallet_path is not null then\n utl_http.set_wallet(l_conf.conf_wallet_path, l_conf.conf_wallet_pwd);\n xlog(p_module =&gt; m_module, p_msg =&gt; 'Override wallet location/pwd from defaults', p_type=&gt; 'DEBUG');\n end if;\n\n -- override http transfer timeout it not defined\n utl_http.get_transfer_timeout( timeout =&gt; l_timeout );\n --xlog(p_module =&gt; m_module, p_msg =&gt; 'Current setting of transfer_timeout: '||l_timeout, p_type=&gt; 'DEBUG');\n if (l_timeout is null or l_timeout=60 /*60 is the default*/) then\n utl_http.set_transfer_timeout(l_conf.conf_http_transfer_timeout);\n xlog(p_module =&gt; m_module, p_msg =&gt; 'Override http transfer timeout ('||l_timeout||'s) from defaults: '|| l_conf.conf_http_transfer_timeout ||'s', p_type=&gt; 'DEBUG');\n end if;\n\nend;\n</code></pre> <p>PROCEDURE dump_all_cookies IS l_proc VARCHAR2 (100) := m_module || '.dump_all_cookies'; l_name_arr OWA_COOKIE.vc_arr; l_vals_arr OWA_COOKIE.vc_arr; l_vals_ret INTEGER; BEGIN xlog (l_proc, 'start'); OWA_COOKIE.get_all (names =&gt; l_name_arr, vals =&gt; l_vals_arr, num_vals =&gt; l_vals_ret);</p> <pre><code> xlog (l_proc, '#num of cookies: ' || l_vals_ret);\n\n FOR i IN 1 .. l_name_arr.COUNT\n LOOP\n xlog (l_proc, i || ':' || l_name_arr (i) || '=' || l_vals_arr (i));\n END LOOP;\n\n xlog (l_proc, 'end');\n</code></pre> <p>END;</p> <p>-- sets the url for the report server for all requests in the -- current session</p> <p>PROCEDURE set_report_url (p_report_url IN VARCHAR2) IS BEGIN xlog ('set_report_url:', p_report_url); m_report_url := p_report_url; END;</p> <p>FUNCTION get_report_url RETURN VARCHAR2 IS BEGIN RETURN m_report_url; END;</p> <p>-- sets the images_uri only for http reports!</p> <p>PROCEDURE set_images_uri (p_images_uri IN VARCHAR2) IS BEGIN m_images_uri := p_images_uri; END;</p> <p>/* use the images from the application server when both /ords and /jri are installed on the same application server</p> <pre><code> the p_server_uri parameter is rarely used, only when they are not run on the same application server\n and the uri differs. But that comes with a lot of CORS and other cookie issues.\n*/\n</code></pre> <p>procedure use_images_no_tunnel (p_server_uri in varchar2 default null, p_cookie_path varchar2 default null) is begin m_use_images_no_tunnel := true; m_cookie_path_no_tunnel := p_cookie_path;</p> <pre><code> -- the placeholders #J2EE_CONTEXT_PATH# and #IMAGE_NAME# will be replaced\n -- inside the J2EE application with the current values of the deployment\n set_images_uri( p_images_uri =&gt; p_server_uri || '#J2EE_CONTEXT_PATH#/report_image?image=#IMAGE_NAME#');\n</code></pre> <p>end;</p> <p>function get_use_images_no_tunnel return boolean is begin return m_use_images_no_tunnel; end;</p> <pre><code>FUNCTION get_cookie_path_no_tunnel\n RETURN VARCHAR2\n</code></pre> <p>IS BEGIN RETURN m_cookie_path_no_tunnel; END;</p> <p>FUNCTION get_images_uri RETURN VARCHAR2 IS BEGIN RETURN m_images_uri; END;</p> <p>FUNCTION compute_images_uri_tunnel RETURN VARCHAR2 IS l_uri VARCHAR2 (32767 CHAR); BEGIN --l_uri := sys_context( 'userenv', 'current_schema' ) -- || '.' || c_images_uri_tunnel;</p> <pre><code> /*\n c_images_uri_tunnel\n :='xlib_jasperreports_img.get_image?p_url=#REPORT_URL#&amp;p_image=';\n */\n\n --l_uri := replace(l_uri, '#REPORT_URL#', APEX_UTIL.URL_ENCODE(m_report_url));\n --l_uri := replace(l_uri, '#REPORT_URL#', m_report_url);\n\n -- c_images_uri_tunnel constant varchar2(100 char) := 'wwv_flow.show?p_request=APPLICATION_PROCESS%3DJRI_SHOW_IMAGE&amp;p_flow_id=#APP_ID#&amp;p_flow_step_id=0&amp;p_instance=#APP_SESSION#&amp;x01=#IMG_NAME#';\n l_uri := c_images_uri_tunnel;\n l_uri := REPLACE (l_uri, '#APP_ID#', v ('APP_ID'));\n l_uri := REPLACE (l_uri, '#APP_SESSION#', v ('APP_SESSION'));\n\n xlog ('compute tunnel', l_uri);\n\n RETURN l_uri;\n</code></pre> <p>END;</p> <p>-- displays an image for html reports</p> <p>PROCEDURE show_image (p_image_name IN VARCHAR2) IS l_proc VARCHAR2 (100) := m_module || '.show_image'; l_url VARCHAR2 (32767);</p> <pre><code> l_header_name_arr xlib_http.vc_arr_t;\n l_header_value_arr xlib_http.vc_arr_t;\n\n PROCEDURE get_headers_to_pass2j2ee (p_header_name_arr OUT xlib_http.vc_arr_t,\n p_header_value_arr OUT xlib_http.vc_arr_t)\n IS\n l_proc VARCHAR2 (100) := m_module || '.get_headers_to_pass2j2ee';\n jsession_cookie OWA_COOKIE.cookie;\n jsession_path_cookie OWA_COOKIE.cookie;\n BEGIN\n jsession_cookie := OWA_COOKIE.get (name =&gt; m_jri_cookie_name_c);\n jsession_path_cookie := OWA_COOKIE.get (name =&gt; m_jri_path_cookie_name_c);\n\n xlog (l_proc, 'show jsession_id and path: ');\n xlog (l_proc, jsession_cookie.vals (1));\n xlog (l_proc, jsession_path_cookie.vals (1));\n\n\n p_header_name_arr (p_header_name_arr.COUNT + 1) := 'Cookie';\n p_header_value_arr (p_header_value_arr.COUNT + 1) :=\n 'JSESSIONID=' || jsession_cookie.vals (1) || ';Path=' || jsession_path_cookie.vals (1);\n --xlog(l_proc, 'end');\n EXCEPTION\n WHEN OTHERS\n THEN\n xlog (l_proc, DBMS_UTILITY.format_error_backtrace, 'ERROR');\n END;\n</code></pre> <p>BEGIN xlog (l_proc, 'start: ### SHOW IMAGE: ' || p_image_name); dump_all_cookies;</p> <pre><code> -- pick up defaults from table xlib_jasperreports_conf\n setup_configuration_defaults();\n\n -------------------------------------------------------\n -- assert valid values for the input variables\n -------------------------------------------------------\n IF m_report_url IS NULL\n THEN\n RAISE report_url_not_defined;\n END IF;\n\n -------------------------------------------------------\n -- construct URL\n -------------------------------------------------------\n -- _image?image=img_0_0_15&amp;uuid=b41eb881-7ca5-4919-bd8f-5afa8d10b398\n l_url := m_report_url || '_image';\n l_url := l_url || '?image=' || p_image_name;\n l_url := l_url || '&amp;JSESSIONID=' || OWA_COOKIE.get (name =&gt; m_jri_cookie_name_c).vals (1);\n\n -------------------------------------------------------\n -- determine cookies for calling the j2ee server\n -- JSESSIONID needs to be passed, the path needs to\n -- be modified for the j2ee server context\n -------------------------------------------------------\n get_headers_to_pass2j2ee (p_header_name_arr =&gt; l_header_name_arr, p_header_value_arr =&gt; l_header_value_arr);\n\n -------------------------------------------------------\n -- call J2EE server\n -------------------------------------------------------\n xlib_http.\n display_url_raw (p_url =&gt; l_url, p_header_name_arr =&gt; l_header_name_arr, p_header_value_arr =&gt; l_header_value_arr);\n</code></pre> <p>END;</p> <p>-- make a callout with utl_http to the j2ee container running the -- JasperReportsIntegration webapp -- =&gt; return the results</p> <p>PROCEDURE show_report (p_rep_name IN VARCHAR2 DEFAULT 'test', p_rep_format IN VARCHAR2 DEFAULT c_rep_format_pdf, p_data_source IN VARCHAR2 DEFAULT 'default', p_out_filename IN VARCHAR2 DEFAULT NULL, p_rep_locale IN VARCHAR2 DEFAULT 'de_DE', p_rep_encoding IN VARCHAR2 DEFAULT 'UTF-8', p_additional_params IN VARCHAR2 DEFAULT NULL, p_print_is_enabled IN BOOLEAN DEFAULT FALSE, p_print_printer_name IN VARCHAR2 DEFAULT NULL, p_print_media IN VARCHAR2 DEFAULT NULL, p_print_copies IN NUMBER DEFAULT 1, p_print_duplex IN BOOLEAN DEFAULT FALSE, p_print_collate IN BOOLEAN DEFAULT FALSE, p_save_is_enabled IN BOOLEAN DEFAULT FALSE, p_save_filename IN VARCHAR2 DEFAULT NULL, p_rep_time_zone IN VARCHAR2 DEFAULT NULL, p_print_job_name IN VARCHAR2 DEFAULT NULL) IS l_proc VARCHAR2 (100) := m_module || '.SHOW_REPORT'; l_url VARCHAR2 (32767); BEGIN -- pick up defaults from table xlib_jasperreports_conf setup_configuration_defaults();</p> <pre><code> -------------------------------------------------------\n -- assert valid values for the input variables\n -------------------------------------------------------\n IF m_report_url IS NULL\n THEN\n xlog(p_module =&gt; m_module, p_msg =&gt; 'The report url is empty', p_type=&gt; 'ERROR');\n\n RAISE report_url_not_defined;\n END IF;\n\n -------------------------------------------------------\n -- construct URL\n -------------------------------------------------------\n l_url := m_report_url;\n l_url := l_url || '?_repName=' || p_rep_name;\n l_url := l_url || '&amp;_repFormat=' || p_rep_format;\n l_url := l_url || '&amp;_dataSource=' || p_data_source;\n l_url := l_url || '&amp;_outFilename=' || p_out_filename;\n l_url := l_url || '&amp;_repLocale=' || p_rep_locale;\n l_url := l_url || '&amp;_repEncoding=' || p_rep_encoding;\n l_url := l_url || '&amp;_repTimeZone=' || APEX_UTIL.URL_ENCODE (p_rep_time_zone);\n\n -- per default use the tunnel through the database\n IF m_images_uri IS NULL OR m_images_uri = c_images_uri_tunnel\n THEN\n -- tunnel through database\n l_url := l_url || '&amp;_imagesURI=' || APEX_UTIL.URL_ENCODE (compute_images_uri_tunnel);\n ELSE\n -- use parameter, mostly for direct access to servlet\n l_url := l_url || '&amp;_imagesURI=' || APEX_UTIL.URL_ENCODE (m_images_uri);\n END IF;\n\n -- direct printing\n l_url := l_url || '&amp;_printIsEnabled=' || bool2string (p_print_is_enabled);\n l_url := l_url || '&amp;_printPrinterName=' || p_print_printer_name;\n l_url := l_url || '&amp;_printPrinterTray=' || p_print_media;\n l_url := l_url || '&amp;_printCopies=' || p_print_copies;\n l_url := l_url || '&amp;_printDuplex=' || bool2string (p_print_duplex);\n l_url := l_url || '&amp;_printCollate=' || bool2string (p_print_collate);\n l_url := l_url || '&amp;_printJobName=' || p_print_job_name;\n\n -- save file on server\n l_url := l_url || '&amp;_saveIsEnabled=' || bool2string (p_save_is_enabled);\n l_url := l_url || '&amp;_saveFileName=' || p_save_filename;\n</code></pre> <p>/ Each additional parameter needs to be escaped using utl_url.escape() utl_url.escape( url =&gt; p_additional_params, escape_reserved_chars =&gt; true, url_charset =&gt; 'UTF-8' ); /</p> <pre><code> -- additional report parameter passed?\n IF (p_additional_params IS NOT NULL)\n THEN\n</code></pre> <p>-- l_url := l_url || '&amp;' || p_additional_params; l_url := l_url || '&amp;' || utl_url.escape( url =&gt; p_additional_params, escape_reserved_chars =&gt; false, url_charset =&gt; 'UTF-8' ); END IF;</p> <pre><code> -------------------------------------------------------\n -- call J2EE server\n -------------------------------------------------------\n xlib_http.display_url_raw (p_url =&gt; l_url);\n</code></pre> <p>END;</p> <p>-- run the report and return the result as a blob</p> <p>PROCEDURE get_report (p_rep_name IN VARCHAR2 DEFAULT 'test', p_rep_format IN VARCHAR2 DEFAULT c_rep_format_pdf, p_data_source IN VARCHAR2 DEFAULT 'default', p_rep_locale IN VARCHAR2 DEFAULT 'de_DE', p_rep_encoding IN VARCHAR2 DEFAULT 'UTF-8', p_additional_params IN VARCHAR2 DEFAULT NULL, p_print_is_enabled IN BOOLEAN DEFAULT FALSE, p_print_printer_name IN VARCHAR2 DEFAULT NULL, p_print_media IN VARCHAR2 DEFAULT NULL, p_print_copies IN NUMBER DEFAULT 1, p_print_duplex IN BOOLEAN DEFAULT FALSE, p_print_collate IN BOOLEAN DEFAULT FALSE, p_save_is_enabled IN BOOLEAN DEFAULT FALSE, p_save_filename IN VARCHAR2 DEFAULT NULL, p_rep_time_zone IN VARCHAR2 DEFAULT NULL, p_out_blob IN OUT BLOB, p_out_mime_type IN OUT VARCHAR2, p_print_job_name IN VARCHAR2 DEFAULT NULL) IS l_proc VARCHAR2 (100) := m_module || '.GET_REPORT'; l_url VARCHAR2 (32767); BEGIN -- pick up defaults from table xlib_jasperreports_conf setup_configuration_defaults();</p> <pre><code> -------------------------------------------------------\n -- assert valid values for the input variables\n -------------------------------------------------------\n IF m_report_url IS NULL\n THEN\n RAISE report_url_not_defined;\n END IF;\n\n -------------------------------------------------------\n -- construct URL\n -------------------------------------------------------\n l_url := m_report_url;\n l_url := l_url || '?_repName=' || p_rep_name;\n l_url := l_url || '&amp;_repFormat=' || p_rep_format;\n l_url := l_url || '&amp;_dataSource=' || p_data_source;\n l_url := l_url || '&amp;_repLocale=' || p_rep_locale;\n l_url := l_url || '&amp;_repEncoding=' || p_rep_encoding;\n l_url := l_url || '&amp;_repTimeZone=' || APEX_UTIL.URL_ENCODE (p_rep_time_zone);\n\n -- per default use the tunnel through the database\n IF m_images_uri IS NULL OR m_images_uri = c_images_uri_tunnel\n THEN\n -- tunnel through database\n l_url := l_url || '&amp;_imagesURI=' || APEX_UTIL.URL_ENCODE (compute_images_uri_tunnel);\n ELSE\n -- use parameter, mostly for direct access to servlet\n l_url := l_url || '&amp;_imagesURI=' || APEX_UTIL.URL_ENCODE (m_images_uri);\n END IF;\n\n -- direct printing\n l_url := l_url || '&amp;_printIsEnabled=' || bool2string (p_print_is_enabled);\n l_url := l_url || '&amp;_printPrinterName=' || p_print_printer_name;\n l_url := l_url || '&amp;_printPrinterTray=' || p_print_media;\n l_url := l_url || '&amp;_printCopies=' || p_print_copies;\n l_url := l_url || '&amp;_printDuplex=' || bool2string (p_print_duplex);\n l_url := l_url || '&amp;_printCollate=' || bool2string (p_print_collate);\n l_url := l_url || '&amp;_printJobName=' || p_print_job_name;\n\n -- save file on server\n l_url := l_url || '&amp;_saveIsEnabled=' || bool2string (p_save_is_enabled);\n l_url := l_url || '&amp;_saveFileName=' || p_save_filename;\n\n -- additional report parameter passed?\n IF (p_additional_params IS NOT NULL)\n THEN\n</code></pre> <p>-- l_url := l_url || '&amp;' || p_additional_params; l_url := l_url || '&amp;' || utl_url.escape( url =&gt; p_additional_params, escape_reserved_chars =&gt; false, url_charset =&gt; 'UTF-8' ); END IF;</p> <pre><code> -------------------------------------------------------\n -- call Tomcat\n -------------------------------------------------------\n xlib_http.retrieve_blob_from_url (p_url =&gt; l_url, o_blob =&gt; p_out_blob, o_mime_type =&gt; p_out_mime_type);\n</code></pre> <p>END;</p> <p>-- get default configuration</p> <p>FUNCTION get_default_configuration RETURN xlib_jasperreports_conf%ROWTYPE IS l_conf xlib_jasperreports_conf%ROWTYPE; BEGIN SELECT * INTO l_conf FROM xlib_jasperreports_conf WHERE conf_id = 'MAIN';</p> <pre><code> RETURN l_conf;\n</code></pre> <p>END;</p> <p>-- set default configuration</p> <p>PROCEDURE set_default_configuration (p_conf IN OUT xlib_jasperreports_conf%ROWTYPE) IS BEGIN p_conf.conf_id := 'MAIN';</p> <pre><code> UPDATE xlib_jasperreports_conf\n SET row = p_conf\n WHERE conf_id = p_conf.conf_id;\n</code></pre> <p>END;</p> <p>PROCEDURE set_default_configuration ( p_protocol IN xlib_jasperreports_conf.conf_protocol%TYPE default 'http', p_server IN xlib_jasperreports_conf.conf_server%TYPE default 'localhost', p_port IN xlib_jasperreports_conf.conf_port%TYPE default '80', p_context_path IN xlib_jasperreports_conf.conf_context_path%TYPE default 'jri', p_wallet_path IN xlib_jasperreports_conf.conf_wallet_path%TYPE default null, p_wallet_pwd IN xlib_jasperreports_conf.conf_wallet_pwd%TYPE default null, p_http_transfer_timeout IN xlib_jasperreports_conf.conf_http_transfer_timeout%TYPE default 60) IS BEGIN UPDATE xlib_jasperreports_conf SET conf_protocol = p_protocol, conf_server = p_server, conf_port = p_port, conf_context_path = p_context_path, conf_wallet_path = p_wallet_path, conf_wallet_pwd = p_wallet_pwd, conf_http_transfer_timeout = p_http_transfer_timeout WHERE conf_id = 'MAIN'; END; END;```</p>"},{"location":"packages/XLIB_JASPERREPORTS_IMG/","title":"XLIB_JASPERREPORTS_IMG","text":""},{"location":"packages/XLIB_JASPERREPORTS_IMG/#package-specification","title":"Package Specification","text":"<p>```sql PACKAGE XLIB_JASPERREPORTS_IMG AS / $Id: xlib_jasperreports_img.pks 71 2017-10-15 16:25:51Z dietmar.aust $ /</p>"},{"location":"packages/XLIB_JASPERREPORTS_IMG/#-get_image-retrieves-a-report-image-from-the-server","title":"-- get_image: retrieves a report image from the server","text":"<p>PROCEDURE get_image (p_url in varchar2, p_image IN VARCHAR2);</p> <p>procedure test;</p> <p>END XLIB_JASPERREPORTS_IMG;```</p>"},{"location":"packages/XLIB_JASPERREPORTS_IMG/#package-body","title":"Package Body","text":"<p>```sql package body xlib_jasperreports_img as / $Id: xlib_jasperreports_img.pkb 71 2017-10-15 16:25:51Z dietmar.aust $ / m_module constant varchar2 (100) := $$plsql_unit;</p>"},{"location":"packages/XLIB_JASPERREPORTS_IMG/#-get_image-retrieves-a-report-image-from-the-server_1","title":"-- get_image: retrieves a report image from the server","text":"<p>procedure get_image (p_url in varchar2, p_image in varchar2) is l_url varchar2 (32767); l_proc VARCHAR2 (100) := m_module || '.GET_IMAGE'; begin</p> <pre><code> -------------------------------------------------------\n -- construct URL\n -------------------------------------------------------\n l_url := p_url;\n -- use image servlet\n l_url := l_url || '_image?image=' || p_image;\n -- use images directory /report_tmp/\n --l_url := l_url || '_tmp/' || p_image;\n\n -------------------------------------------------------\n -- call J2EE server\n -------------------------------------------------------\n xlog(l_proc, l_url);\n xlib_http.display_url_raw (p_url =&gt; l_url);\n</code></pre> <p>end;</p> <p>procedure test is begin htp.p('test'); end;</p> <p>END XLIB_JASPERREPORTS_IMG;```</p>"},{"location":"packages/XLIB_LOG/","title":"XLIB_LOG","text":""},{"location":"packages/XLIB_LOG/#package-specification","title":"Package Specification","text":"<p>```sql PACKAGE \"XLIB_LOG\" IS /*=========================================================================</p> <p>Purpose : Application Logging</p> <p>License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de) Licensed under a BSD style license (license.txt) https://github.com/daust/JasperReportsIntegration</p> <p>Date Author Comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 06.01.2010 D. Aust Initial creation 13.05.2012 D. Aust insert fails when created_by user value too large</p> <p>=========================================================================*/</p> <p>PROCEDURE m ( p_module IN VARCHAR2, p_msg IN VARCHAR2, p_type IN VARCHAR2 DEFAULT 'DEBUG', p_level PLS_INTEGER DEFAULT 15 ); END;```</p>"},{"location":"packages/XLIB_LOG/#package-body","title":"Package Body","text":"<p>```sql PACKAGE BODY \"XLIB_LOG\" IS</p> <p>PROCEDURE m ( p_module IN VARCHAR2, p_msg IN VARCHAR2, p_type IN VARCHAR2 DEFAULT 'DEBUG', p_level IN PLS_INTEGER DEFAULT 15 ) IS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN INSERT INTO xlib_logs (log_module, log_msg, log_type, log_level, log_created_on, log_created_by ) values ( substr(p_module,1,100) , substr(p_msg,1,4000) , substr(p_type,1,20) , p_level , sysdate , substr(nvl(v('APP_USER'), user),1,100) ); COMMIT; END; END;```</p>"},{"location":"procedures/","title":"Stored Procedures","text":"<p>Questa cartella contiene la documentazione di tutte le 11 stored procedures del database.</p>"},{"location":"procedures/#procedures-business-logic","title":"Procedures Business Logic","text":"Procedura Descrizione EVENTI_AGGIORNA_QTA_LISTA Ricalcola tutte le quantit\u00e0 della lista prelievo EVENTI_AGGIORNA_TOT_OSPITI Aggiorna il totale ospiti in testata evento EVENTI_COPIA Duplica un evento con tutti i dettagli EVENTI_RICALCOLA_ACCONTI Ricalcola gli importi degli acconti EVENTO_ELIMINA_PRELIEVI Elimina i prelievi di un evento LISTE_COPIA Copia selettiva di liste tra due eventi P_CANCEL_SAME_LOCATION_EVENTS Annulla eventi nella stessa location/data"},{"location":"procedures/#procedures-utility","title":"Procedures Utility","text":"Procedura Descrizione ROWSORT_TIPI Riordina i tipi materiale HTPPRN Output HTTP per APEX SEND_DATA_TO_DROPBOX Export dati verso Dropbox XLOG Procedura di logging"},{"location":"procedures/#dettaglio-procedures-critiche","title":"Dettaglio Procedures Critiche","text":""},{"location":"procedures/#eventi_aggiorna_qta_lista","title":"EVENTI_AGGIORNA_QTA_LISTA","text":"<p>Parametri: - <code>p_id_evento NUMBER</code> - ID dell'evento</p> <p>Logica: 1. Cicla su tutti gli articoli nella lista prelievo 2. Per ogni articolo determina il metodo di calcolo: - Quantit\u00e0 Standard: Se <code>QTA_STD_A/S/B</code> sono valorizzate - Tovagliato/Caraffe: Moltiplica per quantit\u00e0 tavoli/angoli - Codice Relativo: Moltiplica per quantit\u00e0 articolo di riferimento - Standard: Moltiplica coefficienti per totale ospiti 3. Verifica disponibilit\u00e0 rispetto alla giacenza 4. Aggiorna note con warning se quantit\u00e0 insufficiente</p>"},{"location":"procedures/#eventi_copia","title":"EVENTI_COPIA","text":"<p>Parametri: - <code>id_evento_old NUMBER</code> - ID evento da copiare - <code>nuova_versione NUMBER DEFAULT 0</code> - 1 per creare nuova versione - <code>id_evento_new OUT NUMBER</code> - ID nuovo evento creato</p> <p>Logica: 1. Copia testata evento 2. Se nuova versione: imposta <code>ID_EVT_PADRE</code>, incrementa <code>VERS_NUMBER</code> 3. Aggiorna evento vecchio con <code>ID_EVT_FIGLIO</code> 4. Copia tutte le tabelle dettaglio: - <code>EVENTI_DET_DEGUST</code> - <code>EVENTI_DET_OSPITI</code> (via UPDATE, non INSERT) - <code>EVENTI_DET_PREL</code> - <code>EVENTI_DET_RIS</code> - <code>EVENTI_ACCONTI</code> - <code>EVENTI_ALTRICOSTI</code> 5. In caso di errore: elimina evento creato e solleva eccezione</p>"},{"location":"procedures/#eventi_ricalcola_acconti","title":"EVENTI_RICALCOLA_ACCONTI","text":"<p>Parametri: - <code>p_event_id NUMBER</code> - ID evento</p> <p>Logica: 1. Calcola totale evento dalle viste costo 2. Se nessun acconto pagato: - Elimina acconti esistenti - Inserisce nuovi acconti con percentuali 30%-50%-20% 3. Se acconti parzialmente pagati: - Mantiene importi pagati - Ricalcola solo acconti non pagati - Verifica che totale acconti \u2264 totale evento</p>"},{"location":"procedures/#liste_copia","title":"LISTE_COPIA","text":"<p>Parametri: - <code>id_evento_from NUMBER</code> - Evento sorgente - <code>id_evento_to NUMBER</code> - Evento destinazione - <code>copia_degustazioni NUMBER DEFAULT 0</code> - <code>copia_prelievi NUMBER DEFAULT 0</code> - <code>copia_risorse NUMBER DEFAULT 0</code> - <code>copia_acconti NUMBER DEFAULT 0</code> - <code>copia_altricosti NUMBER DEFAULT 0</code></p> <p>Logica: Per ogni flag &gt; 0 esegue un MERGE (UPDATE se esiste, INSERT altrimenti).</p>"},{"location":"procedures/EVENTI_AGGIORNA_QTA_LISTA/","title":"EVENTI_AGGIORNA_QTA_LISTA","text":""},{"location":"procedures/EVENTI_AGGIORNA_QTA_LISTA/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql PROCEDURE \"EVENTI_AGGIORNA_QTA_LISTA\" ( p_id_evento NUMBER ) AS -- ricalcola tutte le qta della lista</p> <pre><code>v_cod_art VARCHAR2(10);\nv_coeff_a NUMBER;\nv_coeff_s NUMBER;\nv_coeff_b NUMBER;\nv_ospiti NUMBER;\nv_qta_a NUMBER;\nv_qta_s NUMBER;\nv_qta_b NUMBER;\nv_qta_std_a NUMBER;\nv_qta_std_s NUMBER;\nv_qta_std_b NUMBER;\nv_count_tov NUMBER;\nv_count_tov_buf NUMBER;\nv_qta_giac NUMBER;\nv_qta_imp NUMBER;\nv_data_evt DATE;\nv_qta_man VARCHAR2(100);\n</code></pre> <p>BEGIN</p> <p>-- Daniele Viti -- Scorre tutti gli articoli dell'evento</p> <pre><code>FOR c IN (\n SELECT DISTINCT\n cod_articolo\n FROM\n eventi_det_prel\n WHERE\n id_evento = p_id_evento\n) LOOP\n BEGIN\n\n --default su qta:\n\n --verifica qta standard\n SELECT\n nvl(qta_std_a, 0),\n nvl(qta_std_s, 0),\n nvl(qta_std_b, 0)\n INTO\n v_qta_std_a,\n v_qta_std_s,\n v_qta_std_b\n FROM\n articoli\n WHERE\n cod_articolo = c.cod_articolo;\n\n IF v_qta_std_a &gt; 0 OR v_qta_std_s &gt; 0 OR v_qta_std_b &gt; 0 THEN\n UPDATE eventi_det_prel\n SET\n qta_ape = v_qta_std_a,\n qta_sedu = v_qta_std_s,\n qta_bufdol = v_qta_std_b,\n qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol\n WHERE\n id_evento = p_id_evento\n AND cod_articolo = c.cod_articolo;\n\n COMMIT;\n CONTINUE; -- se esistono le qta standard aggiorna e passa il giro successivo!\n\n END IF;\n\n SELECT\n cod_relativo\n INTO v_cod_art\n FROM\n articoli\n WHERE\n cod_articolo = c.cod_articolo;\n\n IF v_cod_art IS NULL THEN\n --Articolo Relativo assente\n\n --verifica se cod_articolo \u00e8 di tipo TOVAGLE O CARAFFE etc... \n SELECT\n COUNT(*)\n INTO v_count_tov\n FROM\n articoli a\n JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ\n JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo\n WHERE\n ( c.cod_tipo IN ( 'CA-CARAFFE' )\n -- or c.COD_CATEG in ('TOV-BUFF','TOV-SED')\n OR c.cod_categ IN ( 'TOV-SED' ) )\n AND a.cod_articolo = c.cod_articolo;\n\n --verifica se cod_articolo \u00e8 di tipo TOVAGLE BUFFET \n SELECT\n COUNT(*)\n INTO v_count_tov_buf\n FROM\n articoli a\n JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ\n JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo\n WHERE\n c.cod_categ IN ( 'TOV-BUFF' )\n AND a.cod_articolo = c.cod_articolo; -- 'CM-DANI'\n\n IF v_count_tov &gt; 0 THEN\n --c.COD_ARTICOLO \u00e8 di tipo TOVAGLE O CARAFFE etc...\n\n -- reperisco le qta tot inserita per i tavoli\n SELECT\n nvl(SUM(qta_ape),\n 0),\n nvl(SUM(qta_sedu),\n 0),\n nvl(SUM(qta_bufdol),\n 0)\n INTO\n v_qta_a,\n v_qta_s,\n v_qta_b\n FROM\n eventi_det_prel e\n JOIN articoli a ON e.cod_articolo = a.cod_articolo\n JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ\n JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo\n WHERE\n id_evento = p_id_evento\n AND c.cod_tipo IN ( 'TA' );\n\n --recupero il coefficente dell'atricolo (tovagliato o caraffe) e lo moltiplico x la qta tavoli\n SELECT\n nvl(coeff_a, 0),\n nvl(coeff_s, 0),\n nvl(coeff_b, 0)\n INTO\n v_coeff_a,\n v_coeff_s,\n v_coeff_b\n FROM\n articoli\n WHERE\n cod_articolo = c.cod_articolo;\n\n UPDATE eventi_det_prel\n SET\n qta_ape = v_qta_a * v_coeff_a,\n qta_sedu = v_qta_s * v_coeff_s,\n qta_bufdol = v_qta_b * v_coeff_b,\n qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol\n WHERE\n id_evento = p_id_evento\n AND cod_articolo = c.cod_articolo;\n\n COMMIT;\n ELSIF v_count_tov_buf &gt; 0 THEN\n --c.COD_ARTICOLO \u00e8 di tipo TOVAGLE BUFFET\n\n -- reperisco le qta tot inserita per gli angoli buffet\n SELECT\n nvl(SUM(qta_ape),\n 0),\n nvl(SUM(qta_sedu),\n 0),\n nvl(SUM(qta_bufdol),\n 0)\n INTO\n v_qta_a,\n v_qta_s,\n v_qta_b\n FROM\n eventi_det_prel e\n JOIN articoli a ON e.cod_articolo = a.cod_articolo\n JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ\n JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo\n WHERE\n id_evento = p_id_evento\n AND c.cod_tipo IN ( 'AN' );\n\n --recupero il coefficente dell'atricolo (tovagliato buffet) e lo moltiplico x la qta angoli\n SELECT\n nvl(coeff_a, 0),\n nvl(coeff_s, 0),\n nvl(coeff_b, 0)\n INTO\n v_coeff_a,\n v_coeff_s,\n v_coeff_b\n FROM\n articoli\n WHERE\n cod_articolo = c.cod_articolo;\n\n UPDATE eventi_det_prel\n SET\n qta_ape = v_qta_a * v_coeff_a,\n qta_sedu = v_qta_s * v_coeff_s,\n qta_bufdol = v_qta_b * v_coeff_b,\n qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol\n WHERE\n id_evento = p_id_evento\n AND cod_articolo = c.cod_articolo;\n\n COMMIT;\n ELSE\n BEGIN\n v_cod_art := c.cod_articolo;\n SELECT\n nvl(coeff_a, 0),\n nvl(coeff_s, 0),\n nvl(coeff_b, 0)\n INTO\n v_coeff_a,\n v_coeff_s,\n v_coeff_b\n FROM\n articoli\n WHERE\n cod_articolo = v_cod_art;\n\n SELECT\n nvl(tot_ospiti, 0)\n INTO v_ospiti\n FROM\n eventi\n WHERE\n id = p_id_evento;\n\n EXCEPTION\n WHEN no_data_found THEN\n raise_application_error(-20001, 'Errore: Coefficenti/Num Ospiti NON TROVATI - '\n || sqlcode\n || ' - '\n || substr(sqlerrm, 1, 64));\n END;\n\n UPDATE eventi_det_prel\n SET\n qta_ape = trunc(v_coeff_a * v_ospiti),\n qta_sedu = trunc(v_coeff_s * v_ospiti),\n qta_bufdol = trunc(v_coeff_b * v_ospiti),\n qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol\n WHERE\n id_evento = p_id_evento\n AND cod_articolo = c.cod_articolo;\n\n COMMIT;\n END IF;\n\n ELSE\n -- cod relativo valorizzato\n BEGIN\n -- reperisco le qta inserite per il cod_relativo nella lista \n SELECT\n nvl(qta_ape, 0),\n nvl(qta_sedu, 0),\n nvl(qta_bufdol, 0)\n INTO\n v_qta_a,\n v_qta_s,\n v_qta_b\n FROM\n eventi_det_prel\n WHERE\n cod_articolo = v_cod_art\n AND id_evento = p_id_evento;\n\n EXCEPTION\n WHEN no_data_found THEN\n CONTINUE;\n -- Disattivato temporaneamente per evitare spam\n --RAISE_APPLICATION_ERROR(-20000, 'Errore: Qta NON TROVATA !!! - v_cod_art: ' || v_cod_art || ' - ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64)); \n END;\n\n BEGIN\n -- reperisco i coefficenti\n SELECT\n nvl(coeff_a, 0),\n nvl(coeff_s, 0),\n nvl(coeff_b, 0)\n INTO\n v_coeff_a,\n v_coeff_s,\n v_coeff_b\n FROM\n articoli\n WHERE\n cod_articolo = c.cod_articolo;\n\n EXCEPTION\n WHEN no_data_found THEN\n raise_application_error(-20001, 'Errore: Qta/Coefficenti del codice relativo NON TROVATI - '\n || sqlcode\n || ' - '\n || substr(sqlerrm, 1, 64));\n END;\n\n UPDATE eventi_det_prel\n SET\n qta_ape = trunc(v_coeff_a * v_qta_a),\n qta_sedu = trunc(v_coeff_s * v_qta_s),\n qta_bufdol = trunc(v_coeff_b * v_qta_b),\n qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol\n WHERE\n id_evento = p_id_evento\n AND cod_articolo = c.cod_articolo;\n\n COMMIT;\n END IF;\n\n -- NOTE SE SUPERO LA QTA DISPONBILE !!!\n BEGIN\n SELECT\n data\n INTO v_data_evt\n FROM\n eventi\n WHERE\n id = p_id_evento;\n\n EXCEPTION\n WHEN no_data_found THEN\n raise_application_error(-20001, 'v_data_evento - '\n || v_data_evt\n || ' - '\n || sqlcode\n || ' - '\n || substr(sqlerrm, 1, 64));\n END;\n\n BEGIN\n SELECT\n qta_giac\n INTO v_qta_giac\n FROM\n articoli\n WHERE\n cod_articolo = c.cod_articolo;\n\n EXCEPTION\n WHEN no_data_found THEN\n raise_application_error(-20001, 'v_qta_giac - '\n || v_qta_giac\n || ' - '\n || sqlcode\n || ' - '\n || substr(sqlerrm, 1, 64));\n END;\n\n BEGIN\n SELECT\n nvl(f_get_qta_impegnata(c.cod_articolo, v_data_evt),\n 0)\n INTO v_qta_imp\n FROM\n dual;\n\n EXCEPTION\n WHEN no_data_found THEN\n raise_application_error(-20001, 'v_qta_imp - '\n || v_qta_imp\n || ' - '\n || v_cod_art\n || ', '\n || v_data_evt\n || ' - '\n || sqlcode\n || ' - '\n || substr(sqlerrm, 1, 64));\n END;\n\n --RAISE_APPLICATION_ERROR(-20000, 'v_qta_giac - ' || v_qta_giac || ' - ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64)); \n dbms_output.put_line('CodArt: '\n || c.cod_articolo\n || '; Qta Imp: '\n || v_qta_imp\n || '; Qta Giac: '\n || v_qta_giac);\n --NOTA: a differenza del trigger \"BEFORE INSERT ON EVENTI_DET_PREL\", \n -- in questo caso la qta_imp \u00e8 gi\u00e0 comprensiva della qta ricalcolata \n IF v_qta_imp &gt; v_qta_giac THEN\n v_qta_man := v_qta_imp - v_qta_giac;\n --:NEW.NOTE := 'QTA TOT NON Disponibile, mancano: ' || to_char(v_qta_man);\n UPDATE eventi_det_prel\n SET\n note = 'QTA TOT NON Disponibile, mancano: ' || to_char(v_qta_man)\n WHERE\n id_evento = p_id_evento\n AND cod_articolo = c.cod_articolo;\n\n COMMIT;\n ELSE\n UPDATE eventi_det_prel\n SET\n note = NULL\n WHERE\n id_evento = p_id_evento\n AND cod_articolo = c.cod_articolo\n AND note LIKE '%QTA TOT NON Disponibile%';\n\n COMMIT;\n END IF;\n\n EXCEPTION\n WHEN OTHERS THEN\n raise_application_error(-20001, 'Errore: '\n || sqlcode\n || ' - '\n || substr(sqlerrm, 1, 64));\n END;\nEND LOOP;\n\nRETURN;\n</code></pre> <p>END eventi_aggiorna_qta_lista;```</p>"},{"location":"procedures/EVENTI_AGGIORNA_TOT_OSPITI/","title":"EVENTI_AGGIORNA_TOT_OSPITI","text":""},{"location":"procedures/EVENTI_AGGIORNA_TOT_OSPITI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql PROCEDURE \"EVENTI_AGGIORNA_TOT_OSPITI\" ( p_id_evento IN NUMBER DEFAULT 0 ) AS --aggiorna la qta toto ospiti --job aggiorna_tot_ospiti</p> <pre><code>CURSOR c_eventi IS\nSELECT\n id\nFROM\n eventi\nWHERE\n id = p_id_evento;\n\nv_tot_ospiti NUMBER;\n</code></pre> <p>BEGIN / for c in c_eventi loop / BEGIN v_tot_ospiti := f_get_tot_ospiti(p_id_evento); UPDATE eventi SET tot_ospiti = v_tot_ospiti WHERE id = p_id_evento;</p> <pre><code> COMMIT;\nEXCEPTION\n WHEN OTHERS THEN\n raise_application_error(-20000, 'Errore nel calcolo del totale ospiti: '\n || sqlcode\n || ' - '\n || sqlerrm);\nEND;\n</code></pre> <p>-- end loop; </p> <p>END eventi_aggiorna_tot_ospiti;```</p>"},{"location":"procedures/EVENTI_COPIA/","title":"EVENTI_COPIA","text":""},{"location":"procedures/EVENTI_COPIA/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql PROCEDURE eventi_copia ( id_evento_old IN NUMBER, nuova_versione IN NUMBER DEFAULT 0, id_evento_new OUT NUMBER ) AS r_evento eventi%rowtype; v_new_evt_id eventi.id%TYPE; BEGIN SELECT * INTO r_evento FROM eventi WHERE id = id_evento_old;</p> <pre><code>r_evento.id := NULL;\nr_evento.is_template := 0;\nIF nuova_versione = 1 THEN\n r_evento.id_evt_padre := id_evento_old;\n r_evento.vers_number := nvl(r_evento.vers_number, 0) + 1; -- aggiorno il numero versione\nELSE\n r_evento.id_evt_padre := NULL;\n r_evento.vers_number := 0;\nEND IF;\n\n-- Copio l'evento facendo creare il nuovo id dal trigger\nINSERT INTO eventi VALUES r_evento RETURNING id INTO v_new_evt_id;\n\nIF nuova_versione = 1 THEN\n -- Aggiorno il vecchio evento col nuovo id\n UPDATE eventi\n SET\n id_evt_figlio = v_new_evt_id\n WHERE\n id = id_evento_old;\n\nEND IF;\n\nCOMMIT;\n\n-- Aggiungo i figli alla nuova versione\n-- Degustazioni\nINSERT INTO eventi_det_degust (\n id_evento,\n data,\n ora,\n nome,\n telefono,\n email,\n location,\n n_persone,\n menu,\n n_paganti,\n note,\n n_degustazione,\n consumata,\n costo_degustazione\n)\n SELECT\n v_new_evt_id,\n data,\n ora,\n nome,\n telefono,\n email,\n location,\n n_persone,\n menu,\n n_paganti,\n note,\n n_degustazione,\n consumata,\n costo_degustazione\n FROM\n eventi_det_degust\n WHERE\n id_evento = id_evento_old;\n\n-- Ospiti\n-- Devo fare una update... DIO TRIGGER\nFOR c IN (\n SELECT\n id_evento,\n cod_tipo_ospite,\n numero,\n note\n FROM\n eventi_det_ospiti\n WHERE\n id_evento = id_evento_old\n) LOOP\n UPDATE eventi_det_ospiti\n SET\n numero = c.numero,\n note = c.note\n WHERE\n id_evento = v_new_evt_id\n AND cod_tipo_ospite = c.cod_tipo_ospite;\n\nEND LOOP;\n-- insert into eventi_det_ospiti (ID_EVENTO, COD_TIPO_OSPITE, NUMERO, NOTE)\n-- select v_new_evt_id, COD_TIPO_OSPITE, NUMERO, NOTE\n-- from eventi_det_ospiti\n-- where id_evento = ID_EVENTO_OLD;\n\n-- Prelievi\n/* COME DA RICHIESTA DEL 01/2024 NON COPIO LA LISTA PRELIEVO NELLA NUOVA VERSIONE */\n/* RIATTIVO NUOVAMENTE LA COPIA IL 12/02/2024 */\nINSERT INTO eventi_det_prel (\n id_evento,\n cod_articolo,\n qta,\n note,\n qta_ape,\n qta_sedu,\n qta_bufdol,\n qta_man_ape,\n qta_man_sedu,\n qta_man_bufdol,\n costo_articolo\n)\n SELECT\n v_new_evt_id,\n cod_articolo,\n qta,\n note,\n qta_ape,\n qta_sedu,\n qta_bufdol,\n qta_man_ape,\n qta_man_sedu,\n qta_man_bufdol,\n costo_articolo\n FROM\n eventi_det_prel\n WHERE\n id_evento = id_evento_old;\n\n-- Risorse\nINSERT INTO eventi_det_ris (\n id_evento,\n id_risorsa,\n ore_lav,\n costo,\n note\n)\n SELECT\n v_new_evt_id,\n id_risorsa,\n ore_lav,\n costo,\n note\n FROM\n eventi_det_ris\n WHERE\n id_evento = id_evento_old;\n\n-- Costi\nINSERT INTO eventi_acconti (\n data,\n acconto,\n id_evento,\n a_conferma,\n ordine,\n descrizione\n)\n SELECT\n data,\n acconto,\n v_new_evt_id,\n a_conferma,\n ordine,\n descrizione\n FROM\n eventi_acconti\n WHERE\n id_evento = id_evento_old;\n\n-- Altri Costi\nINSERT INTO eventi_altricosti (\n id_evento,\n descrizione,\n costo,\n quantity\n)\n SELECT\n v_new_evt_id,\n descrizione,\n costo,\n quantity\n FROM\n eventi_altricosti\n WHERE\n id_evento = id_evento_old;\n\n-- Carico il nuovo id nella pagina\nid_evento_new := v_new_evt_id;\n</code></pre> <p>EXCEPTION WHEN OTHERS THEN DELETE FROM eventi WHERE id = v_new_evt_id;</p> <pre><code> COMMIT;\n raise_application_error(-20001, sqlcode\n || ' - '\n || sqlerrm);\n</code></pre> <p>END eventi_copia;```</p>"},{"location":"procedures/EVENTI_RICALCOLA_ACCONTI/","title":"EVENTI_RICALCOLA_ACCONTI","text":""},{"location":"procedures/EVENTI_RICALCOLA_ACCONTI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql procedure EVENTI_RICALCOLA_ACCONTI(p_event_id number) as v_cnt number; v_calc_only_saldo number := 0; v_totale_tipi number; v_totale_degus number; v_totale_ris number; v_totale_ospiti number; v_totale_evento number; v_totale_altricosti number; v_primo_acconto number := 0; v_secondo_acconto number := 0; v_terzo_acconto number := 0; v_prima_perc number := 0.3; v_seconda_perc number := 0.5; v_terza_perc number := 0.2; begin</p> <pre><code>select count(*)\ninto v_cnt\nfrom eventi_acconti\nwhere id_evento = p_event_id\n and \"DATA\" is not null;\n</code></pre> <p>/ if v_cnt &gt; 0 then raise_application_error(-20001, 'Impossibile ricalcolare gli acconti per un evento gi\u00e0 saldato o parzialmente saldato'); end if; / select count(*) into v_cnt from eventi_acconti where id_evento = p_event_id and (ORDINE = 10 OR ORDINE = 20) -- primo acconto (o anche secondo) dato quindi evento confermato and \"DATA\" is not null;</p> <pre><code>if v_cnt &gt; 0 then\n v_calc_only_saldo := 1;\nend if;\n\nselect sum(costo_ivato)\ninto v_totale_tipi\nfrom get_costo_tipi_evt\nwhere id_evento = p_event_id;\n\nselect sum(costo)\ninto v_totale_degus\nfrom get_costo_degus_evt\nwhere id_evento = p_event_id;\n\nselect sum(costo)\ninto v_totale_ris\nfrom get_costo_ris_evt\nwhere id_evento = p_event_id;\n\nselect sum(costo+costo*0.10)\ninto v_totale_ospiti\nfrom get_costo_ospiti_evt\nwhere id_evento = p_event_id;\n\nselect sum((costo * quantity)+(case when costo &gt; 0 then costo * quantity * 0.10 else 0 end))\ninto v_totale_altricosti\nfrom eventi_altricosti\nwhere id_evento = p_event_id;\n\nv_totale_evento :=\n nvl(v_totale_tipi, 0) -\n nvl(v_totale_degus, 0) +\n nvl(v_totale_ris, 0) +\n nvl(v_totale_ospiti, 0) +\n nvl(v_totale_altricosti, 0);\n\nif v_calc_only_saldo = 0 then\n -- Se nessun acconto \u00e8 stato pagato allora ricalcola tutti gli acconti\n delete\n from eventi_acconti\n where id_evento = p_event_id\n and ordine in (10, 20, 30);\n\n insert into eventi_acconti\n (DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)\n values\n ('PRIMA CAPARRA (art.7 punto A del contratto) a conferma evento nella cifra di euro:',\n v_totale_evento * v_prima_perc, p_event_id, 1, 10);\n\n insert into eventi_acconti\n (DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)\n values\n ('SECONDA CAPARRA (art. 7 punto B - circa 60 giorni prima dell''evento) nella cifra di euro:',\n v_totale_evento * v_seconda_perc, p_event_id, 0, 20);\n\n insert into eventi_acconti\n (DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)\n values\n ('SALDO A RICEVIMENTO CONSUNTIVO (art.7 punto c del contratto) 5 giorni prima dell''evento',\n v_totale_evento * v_terza_perc, p_event_id, 0, 30);\n\nelse\n -- Controllo se gli acconti sono stato pagati e in caso ricalcolo soltanto i saldi\n begin\n select acconto\n into v_primo_acconto\n from eventi_acconti\n where id_evento = p_event_id\n and ORDINE = 10\n and data is not null; -- Il primo acconto \u00e8 stato pagato\n exception when no_data_found then\n v_primo_acconto := 0;\n end;\n\n begin\n select acconto\n into v_secondo_acconto\n from eventi_acconti\n where id_evento = p_event_id\n and ORDINE = 20\n and data is not null; -- Il secondo acconto \u00e8 stato pagato\n exception when no_data_found then\n v_secondo_acconto := 0;\n end;\n\n begin\n select acconto\n into v_terzo_acconto\n from eventi_acconti\n where id_evento = p_event_id\n and ORDINE = 30\n and data is not null; -- Il terzo acconto \u00e8 stato pagato\n exception when no_data_found then\n v_terzo_acconto := 0;\n end;\n\n -- Se non hanno pagato il primo acconto lo calcolo in automatico\n if v_primo_acconto = 0 then\n v_primo_acconto := v_totale_evento * v_prima_perc;\n end if;\n\n -- Ricalcolo la percentuale del secondo acconto in base al primo se non \u00e8 stato pagato\n if v_secondo_acconto = 0 then\n v_secondo_acconto := (v_totale_evento - v_primo_acconto) * (v_seconda_perc/(v_seconda_perc + v_terza_perc));\n end if;\n\n -- Calcolo il terzo acconto come la rimanenza tra il totale e il primo + secondo se non \u00e8 stato pagato\n if v_terzo_acconto = 0 then\n v_terzo_acconto := v_totale_evento - (v_primo_acconto + v_secondo_acconto);\n end if;\n\n -- Controllo se i totali acconti superano il totale dell'evento\n if v_primo_acconto &gt; v_totale_evento then\n raise_application_error(-20001, 'Attenzione! Il primo acconto supera il costo totale del''evento');\n end if;\n\n if v_primo_acconto + v_secondo_acconto &gt; v_totale_evento then\n raise_application_error(-20001, 'Attenzione! Il primo e il secondo acconto superano il costo totale del''evento');\n end if;\n\n if v_primo_acconto + v_secondo_acconto + v_terzo_acconto &gt; v_totale_evento then\n raise_application_error(-20001, 'Attenzione! Gli acconti superano il costo totale del''evento');\n end if;\n\n -- Se gli acconti successivi sono validi allora li aggiorno, se l'acconto precendente salda tutto li elimino\n if v_secondo_acconto &gt; 0 then\n update eventi_acconti\n set ACCONTO = v_secondo_acconto\n where id_evento = p_event_id\n and ordine = 20;\n\n if SQL%ROWCOUNT = 0 then\n insert into eventi_acconti\n (DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)\n values\n ('SECONDA CAPARRA (art. 7 punto B - circa 60 giorni prima dell''evento) nella cifra di euro:',\n v_secondo_acconto, p_event_id, 0, 20);\n end if;\n else\n delete\n from eventi_acconti\n where id_evento = p_event_id\n and ordine = 20;\n end if;\n\n if v_terzo_acconto &gt; 0 then\n update eventi_acconti\n set ACCONTO = v_terzo_acconto\n where id_evento = p_event_id\n and ordine = 30;\n\n if SQL%ROWCOUNT = 0 then\n insert into eventi_acconti\n (DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)\n values\n ('SALDO A RICEVIMENTO CONSUNTIVO (art.7 punto c del contratto) ', v_terzo_acconto, p_event_id, 0, 30);\n end if;\n else\n delete\n from eventi_acconti\n where id_evento = p_event_id\n and ordine = 30;\n end if;\n\nend if;\n</code></pre> <p>end;```</p>"},{"location":"procedures/EVENTO_ELIMINA_PRELIEVI/","title":"EVENTO_ELIMINA_PRELIEVI","text":""},{"location":"procedures/EVENTO_ELIMINA_PRELIEVI/#codice-sorgente","title":"Codice Sorgente","text":"<p><code>sql PROCEDURE EVENTO_ELIMINA_PRELIEVI ( P_ID_EVENTO IN NUMBER ) AS BEGIN NULL; END EVENTO_ELIMINA_PRELIEVI;</code></p>"},{"location":"procedures/HTPPRN/","title":"HTPPRN","text":""},{"location":"procedures/HTPPRN/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>PROCEDURE \"HTPPRN\" (pclob in out nocopy clob) is\n v_excel varchar2(32000);\n v_clob clob := pclob;\nbegin\n while length(v_clob) &gt; 0 loop begin\n if length(v_clob) &gt; 32000 then v_excel:= substr(v_clob,1,32000);\n htp.prn(v_excel);\n v_clob:= substr(v_clob,length(v_excel)+1);\n else\n v_excel := v_clob;\n htp.prn(v_excel);\n v_clob:=''; v_excel := ''; end if;\n end;\n end loop;\nend;\n</code></pre>"},{"location":"procedures/LISTE_COPIA/","title":"LISTE_COPIA","text":""},{"location":"procedures/LISTE_COPIA/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql PROCEDURE liste_copia ( id_evento_from IN NUMBER, id_evento_to IN NUMBER, copia_degustazioni IN NUMBER DEFAULT 0, copia_prelievi IN NUMBER DEFAULT 0, copia_risorse IN NUMBER DEFAULT 0, copia_acconti IN NUMBER DEFAULT 0, copia_altricosti IN NUMBER DEFAULT 0 ) AS BEGIN -- Validate that mandatory parameters are provided IF id_evento_from IS NULL OR id_evento_to IS NULL THEN RAISE_APPLICATION_ERROR(-20001, 'Both id_evento_from and id_evento_to must be provided.'); END IF;</p> <pre><code>----------------------------------------------------------------------------\n-- Degustazioni (Tastings)\n----------------------------------------------------------------------------\nIF copia_degustazioni &gt; 0 THEN\n FOR rec IN (\n SELECT\n id,\n data,\n ora,\n nome,\n telefono,\n email,\n location,\n n_persone,\n menu,\n n_paganti,\n note,\n n_degustazione,\n consumata,\n costo_degustazione\n FROM eventi_det_degust\n WHERE id_evento = id_evento_from\n ) LOOP\n -- Try to update using the unique key (assumed here as n_degustazione)\n UPDATE eventi_det_degust\n SET\n data = rec.data,\n ora = rec.ora,\n nome = rec.nome,\n telefono = rec.telefono,\n email = rec.email,\n location = rec.location,\n n_persone = rec.n_persone,\n menu = rec.menu,\n n_paganti = rec.n_paganti,\n note = rec.note,\n consumata = rec.consumata,\n costo_degustazione = rec.costo_degustazione\n WHERE id_evento = id_evento_to\n AND id = rec.id;\n\n IF SQL%ROWCOUNT = 0 THEN\n INSERT INTO eventi_det_degust (\n id_evento,\n data,\n ora,\n nome,\n telefono,\n email,\n location,\n n_persone,\n menu,\n n_paganti,\n note,\n n_degustazione,\n consumata,\n costo_degustazione\n )\n VALUES (\n id_evento_to,\n rec.data,\n rec.ora,\n rec.nome,\n rec.telefono,\n rec.email,\n rec.location,\n rec.n_persone,\n rec.menu,\n rec.n_paganti,\n rec.note,\n rec.n_degustazione,\n rec.consumata,\n rec.costo_degustazione\n );\n END IF;\n END LOOP;\n\n ----------------------------------------------------------------------------\n -- Ospiti (Guests)\n ----------------------------------------------------------------------------\n FOR rec IN (\n SELECT\n cod_tipo_ospite,\n numero,\n note\n FROM eventi_det_ospiti\n WHERE id_evento = id_evento_from\n ) LOOP\n UPDATE eventi_det_ospiti\n SET\n numero = rec.numero,\n note = rec.note\n WHERE id_evento = id_evento_to\n AND cod_tipo_ospite = rec.cod_tipo_ospite;\n\n IF SQL%ROWCOUNT = 0 THEN\n INSERT INTO eventi_det_ospiti (\n id_evento,\n cod_tipo_ospite,\n numero,\n note\n )\n VALUES (\n id_evento_to,\n rec.cod_tipo_ospite,\n rec.numero,\n rec.note\n );\n END IF;\n END LOOP;\nEND IF;\n\n----------------------------------------------------------------------------\n-- Prelievi (Sampling): inserisce solo i record mancanti\n----------------------------------------------------------------------------\nIF copia_prelievi &gt; 0 THEN\n MERGE INTO eventi_det_prel dest\n USING (\n SELECT\n cod_articolo,\n qta,\n note,\n qta_ape,\n qta_sedu,\n qta_bufdol,\n qta_man_ape,\n qta_man_sedu,\n qta_man_bufdol,\n costo_articolo\n FROM eventi_det_prel\n WHERE id_evento = id_evento_from\n ) src\n ON (\n dest.id_evento = id_evento_to\n AND dest.cod_articolo = src.cod_articolo\n )\n WHEN NOT MATCHED THEN\n INSERT (\n id_evento,\n cod_articolo,\n qta,\n note,\n qta_ape,\n qta_sedu,\n qta_bufdol,\n qta_man_ape,\n qta_man_sedu,\n qta_man_bufdol,\n costo_articolo\n )\n VALUES (\n id_evento_to,\n src.cod_articolo,\n src.qta,\n src.note,\n src.qta_ape,\n src.qta_sedu,\n src.qta_bufdol,\n src.qta_man_ape,\n src.qta_man_sedu,\n src.qta_man_bufdol,\n src.costo_articolo\n );\nEND IF;\n\n----------------------------------------------------------------------------\n-- Risorse (Resources)\n----------------------------------------------------------------------------\nIF copia_risorse &gt; 0 THEN\n FOR rec IN (\n SELECT\n id,\n id_risorsa,\n ore_lav,\n costo,\n note\n FROM eventi_det_ris\n WHERE id_evento = id_evento_from\n ) LOOP\n UPDATE eventi_det_ris\n SET\n ore_lav = rec.ore_lav,\n costo = rec.costo,\n note = rec.note\n WHERE id_evento = id_evento_to\n AND id = rec.id;\n\n IF SQL%ROWCOUNT = 0 THEN\n INSERT INTO eventi_det_ris (\n id_evento,\n id_risorsa,\n ore_lav,\n costo,\n note\n )\n VALUES (\n id_evento_to,\n rec.id_risorsa,\n rec.ore_lav,\n rec.costo,\n rec.note\n );\n END IF;\n END LOOP;\nEND IF;\n\n----------------------------------------------------------------------------\n-- Acconti (Payments)\n----------------------------------------------------------------------------\nIF copia_acconti &gt; 0 THEN\n FOR rec IN (\n SELECT\n id,\n data,\n acconto,\n a_conferma,\n ordine,\n descrizione\n FROM eventi_acconti\n WHERE id_evento = id_evento_from\n ) LOOP\n UPDATE eventi_acconti\n SET\n data = rec.data,\n acconto = rec.acconto,\n a_conferma = rec.a_conferma,\n descrizione = rec.descrizione\n WHERE id_evento = id_evento_to\n AND id = rec.id;\n\n IF SQL%ROWCOUNT = 0 THEN\n INSERT INTO eventi_acconti (\n data,\n acconto,\n id_evento,\n a_conferma,\n ordine,\n descrizione\n )\n VALUES (\n rec.data,\n rec.acconto,\n id_evento_to,\n rec.a_conferma,\n rec.ordine,\n rec.descrizione\n );\n END IF;\n END LOOP;\nEND IF;\n\n----------------------------------------------------------------------------\n-- Altri Costi (Other Costs)\n----------------------------------------------------------------------------\nIF copia_altricosti &gt; 0 THEN\n FOR rec IN (\n SELECT\n id,\n descrizione,\n costo,\n quantity\n FROM eventi_altricosti\n WHERE id_evento = id_evento_from\n ) LOOP\n UPDATE eventi_altricosti\n SET\n costo = rec.costo,\n quantity = rec.quantity\n WHERE id_evento = id_evento_to\n AND id = rec.id;\n\n IF SQL%ROWCOUNT = 0 THEN\n INSERT INTO eventi_altricosti (\n id_evento,\n descrizione,\n costo,\n quantity\n )\n VALUES (\n id_evento_to,\n rec.descrizione,\n rec.costo,\n rec.quantity\n );\n END IF;\n END LOOP;\nEND IF;\n</code></pre> <p>END liste_copia;```</p>"},{"location":"procedures/P_CANCEL_SAME_LOCATION_EVENTS/","title":"P_CANCEL_SAME_LOCATION_EVENTS","text":""},{"location":"procedures/P_CANCEL_SAME_LOCATION_EVENTS/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql PROCEDURE \"P_CANCEL_SAME_LOCATION_EVENTS\" (p_good_event_id number) as</p> <p>-- Autore: Daniele Viti -- Data: 17/01/2020 -- Descrizione: Controlla che ci siano pi\u00f9 eventi con la stessa locazione e data di quello in esame e li annulla</p> <pre><code>v_date date;\nv_idloc number;\n</code></pre> <p>begin</p> <pre><code>begin\n -- Seleziono la data e la location per confrontarle dopo\n select data, id_location\n into v_date, v_idloc\n from eventi\n where id = p_good_event_id;\nexception when no_data_found then\n raise_application_error(-20001, 'Impossibile trovare l''evento da confermare');\nend;\n\nfor c in (\n select *\n from eventi\n where data = v_date\n and id_location = v_idloc\n and id != p_good_event_id\n) loop\n -- Imposta l'evento come obsoleto (annullato)\n UPDATE EVENTI\n SET\n FLG_SUPERATO = 1,\n STATO = 900\n WHERE ID = c.id;\nend loop;\n</code></pre> <p>end;```</p>"},{"location":"procedures/ROWSORT_TIPI/","title":"ROWSORT_TIPI","text":""},{"location":"procedures/ROWSORT_TIPI/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql PROCEDURE \"ROWSORT_TIPI\" ( p_direc_cod IN VARCHAR2, o_return OUT CLOB ) AS</p> <pre><code>v_direc VARCHAR2(4);\nv_cod_tipo VARCHAR2(10);\nv_cod_step NUMBER;\nv_cod_step_new NUMBER;\nv_return CLOB;\n</code></pre> <p>BEGIN</p> <pre><code> -- Separo i valori in entrata su p_direc_cod 'direc_cod' in un array ( Es: 'desc_AN' =&gt; [ 'desc', 'AN' ] )\n ---- Seleziono la direzione (asc o desc)\nSELECT\n upper(result)\nINTO v_direc\nFROM\n TABLE ( string_to_table_enum(p_string =&gt; p_direc_cod, v_level =&gt; 0, p_separator =&gt; '_') )\nWHERE\n id = 1;\n\n ---- Seleziono l'cod_tipo della riga da spostare\n\nSELECT\n upper(result)\nINTO v_cod_tipo\nFROM\n TABLE ( string_to_table_enum(p_string =&gt; p_direc_cod, v_level =&gt; 0, p_separator =&gt; '_') )\nWHERE\n id = 2;\n\nIF v_direc = 'ASC' THEN\n\n -- Seleziono i numeri di riga\n SELECT\n cod_step,\n cod_step - 1\n INTO\n v_cod_step,\n v_cod_step_new\n FROM\n tb_tipi_mat\n WHERE\n upper(TRIM(cod_tipo)) = upper(TRIM(v_cod_tipo));\n\n -- Libero i numeri di riga richiesti\n -- diminuendo il numero di riga di un valore inutilizzato (Es: 0.5)\n\n UPDATE tb_tipi_mat\n SET\n cod_step = cod_step - 0.5\n WHERE\n cod_tipo = v_cod_tipo;\n\n UPDATE tb_tipi_mat\n SET\n cod_step = cod_step - 0.5\n WHERE\n cod_step = v_cod_step_new;\n\n -- Sposto la riga precedente al posto di quella selezionata (Es: row 1 diventer\u00e0 row 2)\n\n UPDATE tb_tipi_mat\n SET\n cod_step = v_cod_step\n WHERE\n cod_step = v_cod_step_new - 0.5;\n\n -- Sposto la riga selezionata al nuovo posto\n\n UPDATE tb_tipi_mat\n SET\n cod_step = v_cod_step_new\n WHERE\n cod_tipo = v_cod_tipo;\n\n v_return := 'cod_tipo: '\n || v_cod_tipo\n || ' - From Row '\n || v_cod_step\n || ' - To Row '\n || v_cod_step_new;\n\nELSIF v_direc = 'DESC' THEN\n\n -- Seleziono i numeri di riga\n SELECT\n cod_step,\n cod_step + 1\n INTO\n v_cod_step,\n v_cod_step_new\n FROM\n tb_tipi_mat\n WHERE\n upper(TRIM(cod_tipo)) = upper(TRIM(v_cod_tipo));\n\n -- Libero i numeri di riga richiesti\n -- diminuendo il numero di riga di un valore inutilizzato (Es: 0.5)\n\n UPDATE tb_tipi_mat\n SET\n cod_step = cod_step + 0.5\n WHERE\n cod_tipo = v_cod_tipo;\n\n UPDATE tb_tipi_mat\n SET\n cod_step = cod_step + 0.5\n WHERE\n cod_step = v_cod_step_new;\n\n -- Sposto la riga precedente al posto di quella selezionata (Es: row 1 diventer\u00e0 row 2)\n\n UPDATE tb_tipi_mat\n SET\n cod_step = v_cod_step\n WHERE\n cod_step = v_cod_step_new + 0.5;\n\n -- Sposto la riga selezionata al nuovo posto\n\n UPDATE tb_tipi_mat\n SET\n cod_step = v_cod_step_new\n WHERE\n cod_tipo = v_cod_tipo;\n\n v_return := 'cod_tipo: '\n || v_cod_tipo\n || ' - From row. '\n || v_cod_step\n || ' - To row: '\n || v_cod_step_new;\n\nEND IF;\n\no_return := v_return;\n</code></pre> <p>END;```</p>"},{"location":"procedures/SEND_DATA_TO_DROPBOX/","title":"SEND_DATA_TO_DROPBOX","text":""},{"location":"procedures/SEND_DATA_TO_DROPBOX/#codice-sorgente","title":"Codice Sorgente","text":"<p>```sql PROCEDURE \"SEND_DATA_TO_DROPBOX\" (ondemand boolean := false) AS v_queryres clob := EMPTY_CLOB(); v_file_name varchar2(255);</p> <pre><code>l_file UTL_FILE.FILE_TYPE;\nl_buffer RAW(32767);\nl_amount BINARY_INTEGER := 32767;\nl_pos INTEGER := 1;\nl_blob BLOB := EMPTY_BLOB();\nl_blob_len INTEGER;\n</code></pre> <p>BEGIN</p> <pre><code>if ondemand then\n for c in (\n select 'test' as a from dual\n union all\n select 'test2' as a from dual\n ) loop\n v_queryres := v_queryres || c.a;\n end loop;\nelse\n v_queryres := 'test';\nend if;\n\nl_blob := CLOB2BLOB(v_queryres);\n\nl_blob_len := DBMS_LOB.getlength(l_blob);\n\nif ondemand then\n v_file_name := 'backup_ondemand_'||to_char(sysdate, 'YYYYMMDDHH24MISS')||'.sql';\nelse\n v_file_name := 'backup_'||to_char(sysdate, 'YYYYMMDD')||'.sql';\nend if;\n\nl_file := UTL_FILE.fopen('DROPBOXBCK', v_file_name, 'wb', 32767);\n\n-- Read chunks of the BLOB and write them to the file\n-- until complete.\nWHILE l_pos &lt;= l_blob_len LOOP\n DBMS_LOB.read(l_blob, l_amount, l_pos, l_buffer);\n UTL_FILE.put_raw(l_file, l_buffer, TRUE);\n l_pos := l_pos + l_amount;\nEND LOOP;\n\n-- Close the file.\nUTL_FILE.fclose(l_file);\n</code></pre> <p>EXCEPTION WHEN OTHERS THEN -- Close the file if something goes wrong. IF UTL_FILE.is_open(l_file) THEN UTL_FILE.fclose(l_file); END IF; RAISE;</p> <p>END SEND_DATA_TO_DROPBOX;```</p>"},{"location":"procedures/XLOG/","title":"XLOG","text":""},{"location":"procedures/XLOG/#codice-sorgente","title":"Codice Sorgente","text":"<p><code>sql PROCEDURE \"XLOG\" ( p_module IN VARCHAR2, p_msg IN VARCHAR2, p_type IN VARCHAR2 DEFAULT 'DEBUG', p_level PLS_INTEGER DEFAULT 15 ) IS BEGIN xlib_log.m (p_module =&gt; p_module, p_msg =&gt; p_msg, p_type =&gt; p_type, p_level =&gt; p_level ); END xlog;</code></p>"},{"location":"sequences/","title":"Sequences","text":"Nome Min Max Increment Last Number Cache Cycle ARTICOLI_DET_REGOLE_SEQ 1 9999999999999999999999999999 1 1 20 N CLIENTI_SEQ 1 9999999999999999999999999999 1 1 20 N CLIENTI_SEQ1 1 9999999999999999999999999999 1 61 20 N CLIENTI_SEQ2 1 9999999999999999999999999999 1 61 20 N DEPT_SEQ 1 9999999999999999999999999999 1 50 20 N EMP_SEQ 1 9999999999999999999999999999 1 8000 20 N EVENTI_ACCONTI_SEQ 1 9999999999999999999999999999 1 131158 20 N EVENTI_ALLEG_SEQ 1 9999999999999999999999999999 1 401 20 N EVENTI_ALTRICOSTI_SEQ 1 9999999999999999999999999999 1 5984 0 N EVENTI_DET_DEGUST_SEQ 1 9999999999999999999999999999 1 19008 20 N EVENTI_DET_PREL_SEQ 1 9999999999999999999999999999 1 181233 20 N EVENTI_DET_RIS_SEQ 1 9999999999999999999999999999 1 500 20 N EVENTI_SEQ 3503 9999999999999999999999999999 1 7808 0 N GL_SCHEMA_CHANGES_SEQ 1 9999999999999999999999999999 1 28 0 N LOCATION_SEQ 1 9999999999999999999999999999 1 8507 20 N LOCATION_SEQ1 1 9999999999999999999999999999 1 1261 20 N PERCORSI_SEQ 1 9999999999999999999999999999 1 21 20 N RISORSE_SEQ 1 9999999999999999999999999999 1 401 20 N RISORSE_SEQ1 1 9999999999999999999999999999 1 21 20 N RISORSE_SEQ2 1 9999999999999999999999999999 1 1 20 N TB_TIPI_PASTO_SEQ 1 9999999999999999999999999999 1 21 20 N XLIB_SEQ 1 9999999999999999999999999999 1 21 20 N"},{"location":"tables/","title":"Tabelle Database","text":"<p>Questa cartella contiene la documentazione di tutte le 32 tabelle del database.</p>"},{"location":"tables/#tabelle-business-principali","title":"Tabelle Business Principali","text":"Tabella Descrizione EVENTI Tabella principale degli eventi catering EVENTI_DET_PREL Liste prelievo articoli per evento EVENTI_DET_OSPITI Breakdown ospiti per tipologia EVENTI_DET_RIS Risorse (personale) assegnate all'evento EVENTI_DET_DEGUST Degustazioni pre-evento EVENTI_ACCONTI Gestione acconti e pagamenti EVENTI_ALTRICOSTI Costi aggiuntivi non categorizzati EVENTI_ALLEG Allegati (file) associati all'evento"},{"location":"tables/#tabelle-anagrafiche","title":"Tabelle Anagrafiche","text":"Tabella Descrizione ARTICOLI Catalogo articoli/materiali con immagini ARTICOLI_DET_REGOLE Regole calcolo per articoli COSTI_ARTICOLI Storico costi unitari articoli CLIENTI Anagrafica clienti LOCATION Location per eventi RISORSE Anagrafica personale/collaboratori"},{"location":"tables/#tabelle-di-lookup","title":"Tabelle di Lookup","text":"Tabella Descrizione TB_TIPI_MAT Tipi di materiale (macro-categorie) TB_CODICI_CATEG Categorie articoli con coefficienti TB_TIPI_EVENTO Tipologie di evento TB_TIPI_OSPITI Tipologie ospiti (Adulti, Kinder, Baby, Staff) TB_TIPI_RISORSA Tipologie di risorsa/personale TB_TIPI_PASTO Tipologie pasto (Pranzo/Cena) TB_CALENDAR_LOCKS Limiti giornalieri eventi TB_CONFIG Parametri configurazione"},{"location":"tables/#tabelle-di-sistema","title":"Tabelle di Sistema","text":"Tabella Descrizione USERS_READONLY Permessi utenti (read-only flag) XLIB_LOGS Log applicazione XLIB_COMPONENTS Componenti registrati XLIB_JASPERREPORTS_CONF Configurazione JasperReports XLIB_JASPERREPORTS_DEMOS Demo report GL_SCHEMA_CHANGES Log modifiche schema"},{"location":"tables/#tabelle-temporaneebackup","title":"Tabelle Temporanee/Backup","text":"Tabella Descrizione TB_CODICI_CATEG_BKP Backup categorie TB_TIPI_MAT_BKP Backup tipi materiale TMP_IMPORTA_ARTICOLI Import temporaneo articoli TMP_IMPORT_ART Import temporaneo articoli (2)"},{"location":"tables/#relazioni-principali","title":"Relazioni Principali","text":"<pre><code>CLIENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI\nLOCATION (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI\nTB_TIPI_EVENTO (1) \u2500\u2500\u2500\u25ba (N) EVENTI\n\nEVENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_DET_PREL\nEVENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_DET_OSPITI\nEVENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_DET_RIS\nEVENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_DET_DEGUST\nEVENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_ACCONTI\nEVENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_ALTRICOSTI\nEVENTI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_ALLEG\n\nARTICOLI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_DET_PREL\nARTICOLI (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) COSTI_ARTICOLI\n\nTB_CODICI_CATEG (1) \u2500\u2500\u25ba (N) ARTICOLI\nTB_TIPI_MAT (1) \u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) TB_CODICI_CATEG\n\nRISORSE (1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25ba (N) EVENTI_DET_RIS\nTB_TIPI_OSPITI (1) \u2500\u2500\u2500\u25ba (N) EVENTI_DET_OSPITI\n</code></pre>"},{"location":"tables/ARTICOLI/","title":"ARTICOLI","text":""},{"location":"tables/ARTICOLI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_ARTICOLO VARCHAR2(10) N DESCRIZIONE VARCHAR2(4000) Y COD_CATEG VARCHAR2(10) Y RAW_DATA BLOB Y CHARSET VARCHAR2(4000) Y LAST_UPDATE DATE Y FILENAME VARCHAR2(4000) Y MIMETYPE VARCHAR2(4000) Y COD_RELATIVO VARCHAR2(10) Y COEFF NUMBER Y 1 COEFF_A NUMBER Y 1 COEFF_S NUMBER Y 1 COEFF_B NUMBER Y 1 QTA_STD_A NUMBER Y QTA_STD_S NUMBER Y QTA_STD_B NUMBER Y FLG_CUCINA NUMBER Y 0 QTA_GIAC NUMBER Y 9999 RANK NUMBER Y 0 PERC_OSPITI NUMBER N 100 PERC_IVA NUMBER N 10 FLG_QTA_TYPE VARCHAR2(1) Y 'S'"},{"location":"tables/ARTICOLI/#primary-key","title":"Primary Key","text":"<p><code>COD_ARTICOLO</code></p>"},{"location":"tables/ARTICOLI/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref ARTICOLI_COD_REL COD_ARTICOLO ARTICOLI COD_ARTICOLO"},{"location":"tables/ARTICOLI/#indici","title":"Indici","text":"Nome Unique Colonne ARTICOLI_PK UNIQUE COD_ARTICOLO"},{"location":"tables/ARTICOLI_DET_REGOLE/","title":"ARTICOLI_DET_REGOLE","text":""},{"location":"tables/ARTICOLI_DET_REGOLE/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_ARTICOLO VARCHAR2(10) N ID NUMBER N COD_RELATIVO VARCHAR2(10) Y COEFF NUMBER Y 1"},{"location":"tables/ARTICOLI_DET_REGOLE/#primary-key","title":"Primary Key","text":"<p><code>ID, COD_ARTICOLO</code></p>"},{"location":"tables/ARTICOLI_DET_REGOLE/#indici","title":"Indici","text":"Nome Unique Colonne ARTICOLI_DET_REGOLE_PK UNIQUE ID, COD_ARTICOLO"},{"location":"tables/CLIENTI/","title":"CLIENTI","text":""},{"location":"tables/CLIENTI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N CLIENTE VARCHAR2(100) Y NOME_RIF VARCHAR2(100) Y COGNOME_RIF VARCHAR2(100) Y RAGSOC VARCHAR2(100) Y PIVA VARCHAR2(20) Y INDIRIZZO VARCHAR2(100) Y TEL1 VARCHAR2(20) Y TEL2 VARCHAR2(20) Y MAIL VARCHAR2(100) Y"},{"location":"tables/CLIENTI/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/CLIENTI/#indici","title":"Indici","text":"Nome Unique Colonne CLIENTI_PK UNIQUE ID"},{"location":"tables/COSTI_ARTICOLI/","title":"COSTI_ARTICOLI","text":""},{"location":"tables/COSTI_ARTICOLI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_ARTICOLO VARCHAR2(10) N DATA_COSTO DATE N DESCRIZIONE VARCHAR2(255) Y COSTO_UNI NUMBER Y"},{"location":"tables/COSTI_ARTICOLI/#primary-key","title":"Primary Key","text":"<p><code>COD_ARTICOLO, DATA_COSTO</code></p>"},{"location":"tables/COSTI_ARTICOLI/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref COSTI_ARTICOLI_FK1 COD_ARTICOLO ARTICOLI COD_ARTICOLO"},{"location":"tables/COSTI_ARTICOLI/#indici","title":"Indici","text":"Nome Unique Colonne COSTI_ARTICOLI_PK UNIQUE COD_ARTICOLO, DATA_COSTO"},{"location":"tables/EVENTI/","title":"EVENTI","text":""},{"location":"tables/EVENTI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N DESCRIZIONE VARCHAR2(4000) Y COD_TIPO VARCHAR2(10) Y CLIENTE VARCHAR2(100) Y INDIRIZZO VARCHAR2(200) Y DATA DATE Y TOT_OSPITI NUMBER Y NULL STATO NUMBER Y 0 TORTA_A VARCHAR2(4000) Y NOTE VARCHAR2(4000) Y DATA_DOC DATE Y APX_USER VARCHAR2(20) Y ID_CLIENTE NUMBER Y ID_LOCATION NUMBER Y FLG_TEMPLATE NUMBER Y 0 ORA_CERIMONIA DATE Y ORA_EVENTO DATE Y PERC_SEDUTE_APER NUMBER Y CONFETTATA_A VARCHAR2(4000) Y STAMPA_MENU VARCHAR2(100) Y ALLERGIE VARCHAR2(4000) Y EXTRA_INFO VARCHAR2(1000) Y EXTRA_COSTI VARCHAR2(1000) Y NUM_LISTA NUMBER Y 0 DISTANZA_LOCATION VARCHAR2(1000) Y PRIMI VARCHAR2(4000) Y SECONDI VARCHAR2(4000) Y VINI VARCHAR2(4000) Y CARICOSPOSI VARCHAR2(4000) Y CARICOAPOLL VARCHAR2(4000) Y STILE_COLORI VARCHAR2(255) Y ALLEST_BUFF VARCHAR2(4000) Y GIRO_BRACCIO VARCHAR2(255) Y GRAN_BUFFET_A VARCHAR2(4000) Y SERVIZIO_TAVOLO_A VARCHAR2(4000) Y BUFFET_DOLCI_A VARCHAR2(4000) Y CLIENTE_TEL VARCHAR2(255) Y CLIENTE_EMAIL VARCHAR2(255) Y REFERENTE_TEL VARCHAR2(255) Y BUFFET_INIZIALE VARCHAR2(4000) Y BUFFET_FINALE VARCHAR2(4000) Y TIPOL_TAV_SPOSI VARCHAR2(255) Y TIPOL_TAV_OSPITI VARCHAR2(255) Y SEDIA VARCHAR2(255) Y TOVAGLIA VARCHAR2(255) Y TOVAGLIOLO VARCHAR2(255) Y RUNNER VARCHAR2(255) Y SOTTOPIATTI VARCHAR2(255) Y PIATTINO_PANE VARCHAR2(255) Y POSATE VARCHAR2(255) Y BICCHIERI VARCHAR2(255) Y NUM_FLORIST VARCHAR2(255) Y NUM_MUSICISTI VARCHAR2(255) Y NUM_FOTOGRAFI VARCHAR2(255) Y NUM_ALTRI VARCHAR2(4000) Y BUFFET VARCHAR2(255) Y BUFFET_SEDIE VARCHAR2(255) Y BUFFET_TAVOLI VARCHAR2(255) Y CONFETTATA_B VARCHAR2(4000) Y GRAN_BUFFET_B VARCHAR2(4000) Y SERVIZIO_TAVOLO_B VARCHAR2(4000) Y BUFFET_DOLCI_B VARCHAR2(4000) Y TORTA_B VARCHAR2(4000) Y TORTA VARCHAR2(4000) Y CONFETTATA VARCHAR2(4000) Y ALTRO VARCHAR2(4000) Y FLG_SUPERATO NUMBER Y 0 DATA_SCAD_PREVENTIVO DATE Y PIATTI VARCHAR2(4000) Y NOTE_INVIO VARCHAR2(1000) Y PRE_BOUV_A VARCHAR2(4000) Y PRE_BOUV_B VARCHAR2(4000) Y ALTRO_A VARCHAR2(4000) Y ALTRO_B VARCHAR2(4000) Y DATORASCARICO DATE Y DATORASCARICO_NOTE VARCHAR2(4000) Y IS_TEMPLATE NUMBER N 0 ID_EVT_PADRE NUMBER Y ID_EVT_FIGLIO NUMBER Y VERS_NUMBER NUMBER N 0 VERS_TOKEN VARCHAR2(255) Y DISABLED NUMBER N 0 DELETED NUMBER N 0 DELETED_BY VARCHAR2(255) Y DELETED_DATE DATE Y NULL ORA_FINE_CERIMONIA DATE Y ORA_FINE_EVENTO DATE Y MAIL_ENABLED NUMBER N 0 CONTRATTO_FIRMATO NUMBER N 0"},{"location":"tables/EVENTI/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/EVENTI/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref EVENTI_CLIENTE_FK ID_CLIENTE CLIENTI ID EVENTI_LOCATION_FK ID_LOCATION LOCATION ID EVENTI_TIPO_FK COD_TIPO TB_TIPI_EVENTO COD_TIPO"},{"location":"tables/EVENTI/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_IDX1 UNIQUE ID, ID_EVT_PADRE EVENTI_IDX2 UNIQUE ID, ID_EVT_FIGLIO EVENTI_ID_EVT_FIGLIO_IDX NONUNIQUE ID_EVT_FIGLIO EVENTI_ID_EVT_PADRE_IDX NONUNIQUE ID_EVT_PADRE EVENTI_INDEX1 NONUNIQUE DATA, STATO EVENTI_INDEX2 NONUNIQUE STATO EVENTI_IS_TEMPLATE_IDX NONUNIQUE IS_TEMPLATE EVENTI_PK UNIQUE ID EVENTI_VERS_NUMBER_IDX NONUNIQUE VERS_NUMBER EVENTI_VERS_TOKEN_IDX NONUNIQUE VERS_TOKEN"},{"location":"tables/EVENTI_ACCONTI/","title":"EVENTI_ACCONTI","text":""},{"location":"tables/EVENTI_ACCONTI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N DATA DATE Y NULL ACCONTO NUMBER N ID_EVENTO NUMBER N A_CONFERMA NUMBER N 0 ORDINE NUMBER N 0 DESCRIZIONE VARCHAR2(255) Y"},{"location":"tables/EVENTI_ACCONTI/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/EVENTI_ACCONTI/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref EVENTI_ACCONTI_FK1 ID_EVENTO EVENTI ID"},{"location":"tables/EVENTI_ACCONTI/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_ACCONTI_PK UNIQUE ID"},{"location":"tables/EVENTI_ALLEG/","title":"EVENTI_ALLEG","text":""},{"location":"tables/EVENTI_ALLEG/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N EVENT_ID NUMBER N RAW_DATA BLOB Y CHARSET VARCHAR2(255) Y MIME_TYPE VARCHAR2(255) Y LAST_UPDATE DATE Y sysdate FILENAME VARCHAR2(255) Y"},{"location":"tables/EVENTI_ALLEG/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/EVENTI_ALLEG/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_ALLEG_INDEX1 NONUNIQUE EVENT_ID EVENTI_ALLEG_PK UNIQUE ID"},{"location":"tables/EVENTI_ALTRICOSTI/","title":"EVENTI_ALTRICOSTI","text":""},{"location":"tables/EVENTI_ALTRICOSTI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N ID_EVENTO NUMBER N DESCRIZIONE VARCHAR2(255) N COSTO NUMBER N QUANTITY NUMBER Y 1 ORDINE NUMBER N 0"},{"location":"tables/EVENTI_ALTRICOSTI/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/EVENTI_ALTRICOSTI/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref EVENTI_ALTRICOSTI_FK1 ID_EVENTO EVENTI ID"},{"location":"tables/EVENTI_ALTRICOSTI/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_ALTRICOSTI_PK UNIQUE ID"},{"location":"tables/EVENTI_DET_DEGUST/","title":"EVENTI_DET_DEGUST","text":""},{"location":"tables/EVENTI_DET_DEGUST/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID_EVENTO NUMBER N ID NUMBER N DATA DATE Y ORA VARCHAR2(20) Y NOME VARCHAR2(1000) Y TELEFONO VARCHAR2(20) Y EMAIL VARCHAR2(20) Y LOCATION VARCHAR2(1000) Y N_PERSONE NUMBER Y MENU VARCHAR2(1000) Y N_PAGANTI NUMBER Y NOTE VARCHAR2(4000) Y N_DEGUSTAZIONE NUMBER Y CONSUMATA NUMBER N 0 COSTO_DEGUSTAZIONE NUMBER Y DETRAIBILE NUMBER N 0"},{"location":"tables/EVENTI_DET_DEGUST/#primary-key","title":"Primary Key","text":"<p><code>ID_EVENTO, ID</code></p>"},{"location":"tables/EVENTI_DET_DEGUST/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_DET_DEGUST_PK UNIQUE ID_EVENTO, ID"},{"location":"tables/EVENTI_DET_OSPITI/","title":"EVENTI_DET_OSPITI","text":""},{"location":"tables/EVENTI_DET_OSPITI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID_EVENTO NUMBER N COD_TIPO_OSPITE VARCHAR2(10) N NUMERO NUMBER Y 0 NOTE VARCHAR2(4000) Y COSTO NUMBER Y 0 SCONTO NUMBER Y 0 ORDINE NUMBER Y"},{"location":"tables/EVENTI_DET_OSPITI/#primary-key","title":"Primary Key","text":"<p><code>ID_EVENTO, COD_TIPO_OSPITE</code></p>"},{"location":"tables/EVENTI_DET_OSPITI/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref EVENTI_DET_OSPITI_IDEV_FK ID_EVENTO EVENTI ID EVENTI_DET_OSPITI_TIPO_FK COD_TIPO_OSPITE TB_TIPI_OSPITI COD_TIPO"},{"location":"tables/EVENTI_DET_OSPITI/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_DET_OSPITI_PK UNIQUE ID_EVENTO, COD_TIPO_OSPITE"},{"location":"tables/EVENTI_DET_PREL/","title":"EVENTI_DET_PREL","text":""},{"location":"tables/EVENTI_DET_PREL/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID_EVENTO NUMBER N ID NUMBER N COD_ARTICOLO VARCHAR2(10) N QTA NUMBER Y 0 NOTE VARCHAR2(4000) Y QTA_APE NUMBER Y 0 QTA_SEDU NUMBER Y 0 QTA_BUFDOL NUMBER Y 0 QTA_MAN_APE NUMBER Y 0 QTA_MAN_SEDU NUMBER Y 0 QTA_MAN_BUFDOL NUMBER Y 0 COSTO_ARTICOLO NUMBER Y PERC_OSPITI NUMBER Y ORDINE NUMBER N 0"},{"location":"tables/EVENTI_DET_PREL/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/EVENTI_DET_PREL/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref EVENTI_DET_PREL_ART_FK COD_ARTICOLO ARTICOLI COD_ARTICOLO EVENTI_DET_PREL_IDEV_FK ID_EVENTO EVENTI ID"},{"location":"tables/EVENTI_DET_PREL/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_DET_PREL_IDX_COD_ART UNIQUE ID_EVENTO, COD_ARTICOLO EVENTI_DET_PREL_PK UNIQUE ID"},{"location":"tables/EVENTI_DET_RIS/","title":"EVENTI_DET_RIS","text":""},{"location":"tables/EVENTI_DET_RIS/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID_EVENTO NUMBER N ID_RISORSA NUMBER N ORE_LAV NUMBER Y ID NUMBER Y COSTO NUMBER Y 0 NOTE VARCHAR2(300) Y"},{"location":"tables/EVENTI_DET_RIS/#primary-key","title":"Primary Key","text":"<p><code>ID_EVENTO, ID_RISORSA</code></p>"},{"location":"tables/EVENTI_DET_RIS/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref EVENTI_DET_PERS_IDEV_FK ID_EVENTO EVENTI ID EVENTI_DET_PERS_IDRIS_FK ID_RISORSA RISORSE ID"},{"location":"tables/EVENTI_DET_RIS/#indici","title":"Indici","text":"Nome Unique Colonne EVENTI_DET_PERS_PK UNIQUE ID_EVENTO, ID_RISORSA"},{"location":"tables/GL_SCHEMA_CHANGES/","title":"GL_SCHEMA_CHANGES","text":""},{"location":"tables/GL_SCHEMA_CHANGES/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N VYEAR NUMBER N VMONTH NUMBER N VMAJOR NUMBER N VMINOR NUMBER N VTYPE VARCHAR2(1) N VERSION_NAME VARCHAR2(255) N DATE_APPLIED DATE Y"},{"location":"tables/GL_SCHEMA_CHANGES/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/GL_SCHEMA_CHANGES/#indici","title":"Indici","text":"Nome Unique Colonne GL_SCHEMA_CHANGES_IDX1 NONUNIQUE VYEAR GL_SCHEMA_CHANGES_IDX2 NONUNIQUE VMONTH GL_SCHEMA_CHANGES_IDX3 NONUNIQUE VMAJOR GL_SCHEMA_CHANGES_IDX4 NONUNIQUE VMINOR GL_SCHEMA_CHANGES_IDX5 NONUNIQUE VTYPE GL_SCHEMA_CHANGES_IDX6 NONUNIQUE DATE_APPLIED GL_SCHEMA_CHANGES_PK UNIQUE ID GL_SCHEMA_CHANGES_UK1 UNIQUE VERSION_NAME GL_SCHEMA_CHANGES_UK2 UNIQUE VYEAR, VMONTH, VMAJOR, VMINOR, VTYPE"},{"location":"tables/LOCATION/","title":"LOCATION","text":""},{"location":"tables/LOCATION/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N LOCATION VARCHAR2(200) Y INDIRIZZO VARCHAR2(200) Y REFERENTE VARCHAR2(100) Y NOTE VARCHAR2(4000) Y NOTE2 VARCHAR2(4000) Y"},{"location":"tables/LOCATION/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/LOCATION/#indici","title":"Indici","text":"Nome Unique Colonne LOCATION_PK UNIQUE ID"},{"location":"tables/RISORSE/","title":"RISORSE","text":""},{"location":"tables/RISORSE/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N NOME VARCHAR2(50) Y COGNOME VARCHAR2(50) Y COD_TIPO VARCHAR2(10) Y LIVELLO NUMBER Y INDIRIZZO VARCHAR2(1000) Y TELEFONO VARCHAR2(100) Y CODFISC VARCHAR2(100) Y IBAN VARCHAR2(100) Y DATA_ASSUNZIONE DATE Y DATA_FINE_RAP DATE Y COD_AZIENDA VARCHAR2(10) Y COSTO_ORARIO NUMBER Y COSTO_PRESTAZIONE NUMBER Y"},{"location":"tables/RISORSE/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/RISORSE/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref RISORSE_TIPO_FK COD_TIPO TB_TIPI_RISORSA COD_TIPO"},{"location":"tables/RISORSE/#indici","title":"Indici","text":"Nome Unique Colonne RISORSE_PK UNIQUE ID"},{"location":"tables/TB_CALENDAR_LOCKS/","title":"TB_CALENDAR_LOCKS","text":""},{"location":"tables/TB_CALENDAR_LOCKS/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default GIORNO DATE N MAX_EVENTI NUMBER N"},{"location":"tables/TB_CALENDAR_LOCKS/#primary-key","title":"Primary Key","text":"<p><code>GIORNO</code></p>"},{"location":"tables/TB_CALENDAR_LOCKS/#indici","title":"Indici","text":"Nome Unique Colonne TB_CALENDAR_LOCKS_PK UNIQUE GIORNO"},{"location":"tables/TB_CODICI_CATEG/","title":"TB_CODICI_CATEG","text":""},{"location":"tables/TB_CODICI_CATEG/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_CATEG VARCHAR2(10) N COD_TIPO VARCHAR2(10) N DESCRIZIONE VARCHAR2(1000) Y TIPO_RIEPILOGO VARCHAR2(20) Y COEFF_A NUMBER Y 0 COEFF_S NUMBER Y 0 COEFF_B NUMBER Y 0 SHOW_PRINT NUMBER N 0"},{"location":"tables/TB_CODICI_CATEG/#primary-key","title":"Primary Key","text":"<p><code>COD_CATEG</code></p>"},{"location":"tables/TB_CODICI_CATEG/#foreign-keys","title":"Foreign Keys","text":"Constraint Colonna Tabella Ref Colonna Ref TB_CODICI_CATEG_TIPO_FK COD_TIPO TB_TIPI_MAT COD_TIPO"},{"location":"tables/TB_CODICI_CATEG/#indici","title":"Indici","text":"Nome Unique Colonne TB_CODICI_CATEG_PK UNIQUE COD_CATEG"},{"location":"tables/TB_CODICI_CATEG_BKP/","title":"TB_CODICI_CATEG_BKP","text":""},{"location":"tables/TB_CODICI_CATEG_BKP/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_CATEG VARCHAR2(10) N COD_TIPO VARCHAR2(10) N DESCRIZIONE VARCHAR2(1000) Y TIPO_RIEPILOGO VARCHAR2(20) Y"},{"location":"tables/TB_CONFIG/","title":"TB_CONFIG","text":""},{"location":"tables/TB_CONFIG/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default NAME VARCHAR2(255) N VALUE NUMBER Y NULL STRVALUE VARCHAR2(255) Y"},{"location":"tables/TB_TIPI_EVENTO/","title":"TB_TIPI_EVENTO","text":""},{"location":"tables/TB_TIPI_EVENTO/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_TIPO VARCHAR2(10) N DESCRIZIONE VARCHAR2(100) Y LIVELLO NUMBER Y TIPO_PASTO VARCHAR2(1) Y"},{"location":"tables/TB_TIPI_EVENTO/#primary-key","title":"Primary Key","text":"<p><code>COD_TIPO</code></p>"},{"location":"tables/TB_TIPI_EVENTO/#indici","title":"Indici","text":"Nome Unique Colonne TB_TIPI_EVENTO_PK UNIQUE COD_TIPO"},{"location":"tables/TB_TIPI_MAT/","title":"TB_TIPI_MAT","text":""},{"location":"tables/TB_TIPI_MAT/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_TIPO VARCHAR2(10) N DESCRIZIONE VARCHAR2(1000) Y COD_STEP NUMBER N"},{"location":"tables/TB_TIPI_MAT/#primary-key","title":"Primary Key","text":"<p><code>COD_TIPO</code></p>"},{"location":"tables/TB_TIPI_MAT/#indici","title":"Indici","text":"Nome Unique Colonne TB_TIPI_MATERIALE_PK UNIQUE COD_TIPO TB_TIPI_MAT_COD_STEP UNIQUE COD_STEP"},{"location":"tables/TB_TIPI_MAT_BKP/","title":"TB_TIPI_MAT_BKP","text":""},{"location":"tables/TB_TIPI_MAT_BKP/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_TIPO VARCHAR2(10) N DESCRIZIONE VARCHAR2(1000) Y COD_STEP NUMBER N"},{"location":"tables/TB_TIPI_OSPITI/","title":"TB_TIPI_OSPITI","text":""},{"location":"tables/TB_TIPI_OSPITI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_TIPO VARCHAR2(10) N DESCRIZIONE VARCHAR2(100) Y"},{"location":"tables/TB_TIPI_OSPITI/#primary-key","title":"Primary Key","text":"<p><code>COD_TIPO</code></p>"},{"location":"tables/TB_TIPI_OSPITI/#indici","title":"Indici","text":"Nome Unique Colonne TB_TIPI_OSPITI_PK UNIQUE COD_TIPO"},{"location":"tables/TB_TIPI_PASTO/","title":"TB_TIPI_PASTO","text":""},{"location":"tables/TB_TIPI_PASTO/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default ID NUMBER N DESCRIZIONE VARCHAR2(20) N"},{"location":"tables/TB_TIPI_PASTO/#primary-key","title":"Primary Key","text":"<p><code>ID</code></p>"},{"location":"tables/TB_TIPI_PASTO/#indici","title":"Indici","text":"Nome Unique Colonne TB_TIPI_PASTO_PK UNIQUE ID"},{"location":"tables/TB_TIPI_RISORSA/","title":"TB_TIPI_RISORSA","text":""},{"location":"tables/TB_TIPI_RISORSA/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_TIPO VARCHAR2(10) N DESCRIZIONE VARCHAR2(100) Y"},{"location":"tables/TB_TIPI_RISORSA/#primary-key","title":"Primary Key","text":"<p><code>COD_TIPO</code></p>"},{"location":"tables/TB_TIPI_RISORSA/#indici","title":"Indici","text":"Nome Unique Colonne TB_TIPI_RISORSA_PK UNIQUE COD_TIPO"},{"location":"tables/TMP_IMPORTA_ARTICOLI/","title":"TMP_IMPORTA_ARTICOLI","text":""},{"location":"tables/TMP_IMPORTA_ARTICOLI/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_TIPO VARCHAR2(100) Y DESCR_TIPO VARCHAR2(100) Y COD_CATEG VARCHAR2(100) Y DESCR_CATEG VARCHAR2(100) Y COD_ARTICOLO VARCHAR2(100) Y DESCRIZIONE VARCHAR2(100) Y"},{"location":"tables/TMP_IMPORT_ART/","title":"TMP_IMPORT_ART","text":""},{"location":"tables/TMP_IMPORT_ART/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COD_TIPO VARCHAR2(100) Y DESCRI_TIPO VARCHAR2(100) Y COD_CATEG VARCHAR2(100) Y DESCRI_CATEG VARCHAR2(100) Y COD_ARTICOLO VARCHAR2(100) Y DESCRIZIONE VARCHAR2(100) Y"},{"location":"tables/USERS_READONLY/","title":"USERS_READONLY","text":""},{"location":"tables/USERS_READONLY/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default USERNAME VARCHAR2(255) N FLGWRITE NUMBER N 0"},{"location":"tables/USERS_READONLY/#primary-key","title":"Primary Key","text":"<p><code>USERNAME</code></p>"},{"location":"tables/USERS_READONLY/#indici","title":"Indici","text":"Nome Unique Colonne USERS_READONLY_PK UNIQUE USERNAME"},{"location":"tables/XLIB_COMPONENTS/","title":"XLIB_COMPONENTS","text":""},{"location":"tables/XLIB_COMPONENTS/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default COMP_ID NUMBER N COMP_NAME VARCHAR2(400) Y COMP_VERSION VARCHAR2(200) Y COMP_VERSION_LABEL VARCHAR2(200) Y COMP_DEPENDS_ON VARCHAR2(4000) Y"},{"location":"tables/XLIB_COMPONENTS/#primary-key","title":"Primary Key","text":"<p><code>COMP_ID</code></p>"},{"location":"tables/XLIB_COMPONENTS/#indici","title":"Indici","text":"Nome Unique Colonne XLIB_COMPONENTS_PK UNIQUE COMP_ID XLIB_COMPONENTS_U01 UNIQUE COMP_NAME"},{"location":"tables/XLIB_JASPERREPORTS_CONF/","title":"XLIB_JASPERREPORTS_CONF","text":""},{"location":"tables/XLIB_JASPERREPORTS_CONF/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default CONF_ID VARCHAR2(20) N 'MAIN' CONF_PROTOCOL VARCHAR2(20) N CONF_SERVER VARCHAR2(200) N CONF_PORT VARCHAR2(20) N CONF_CONTEXT_PATH VARCHAR2(100) N CONF_WALLET_PATH VARCHAR2(4000) Y CONF_WALLET_PWD VARCHAR2(500) Y CONF_HTTP_TRANSFER_TIMEOUT NUMBER Y 60"},{"location":"tables/XLIB_JASPERREPORTS_CONF/#primary-key","title":"Primary Key","text":"<p><code>CONF_ID</code></p>"},{"location":"tables/XLIB_JASPERREPORTS_CONF/#indici","title":"Indici","text":"Nome Unique Colonne XLIB_JASPERREPORTS_CONF_PK UNIQUE CONF_ID"},{"location":"tables/XLIB_JASPERREPORTS_DEMOS/","title":"XLIB_JASPERREPORTS_DEMOS","text":""},{"location":"tables/XLIB_JASPERREPORTS_DEMOS/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default DEMO_CODE VARCHAR2(80) N DEMO_TITLE VARCHAR2(400) Y DEMO_REPORT_NAME VARCHAR2(1600) Y DEMO_DESCRIPTION VARCHAR2(4000) Y DEMO_REPORT_FORMAT VARCHAR2(200) Y DEMO_DATA_SOURCE VARCHAR2(400) Y DEMO_REPORT_LOCALE VARCHAR2(200) Y DEMO_REPORT_ENCODING VARCHAR2(200) Y DEMO_OUT_FILENAME VARCHAR2(2000) Y DEMO_PARAM1_LABEL VARCHAR2(200) Y DEMO_PARAM1_VALUE VARCHAR2(4000) Y DEMO_PARAM2_LABEL VARCHAR2(200) Y DEMO_PARAM2_VALUE VARCHAR2(4000) Y DEMO_PARAM3_LABEL VARCHAR2(200) Y DEMO_PARAM3_VALUE VARCHAR2(4000) Y DEMO_REPORT_TIME_ZONE VARCHAR2(200) Y"},{"location":"tables/XLIB_JASPERREPORTS_DEMOS/#primary-key","title":"Primary Key","text":"<p><code>DEMO_CODE</code></p>"},{"location":"tables/XLIB_JASPERREPORTS_DEMOS/#indici","title":"Indici","text":"Nome Unique Colonne XLIB_DEMO_PK UNIQUE DEMO_CODE"},{"location":"tables/XLIB_LOGS/","title":"XLIB_LOGS","text":""},{"location":"tables/XLIB_LOGS/#struttura","title":"Struttura","text":"Colonna Tipo Nullable Default LOG_ID NUMBER N LOG_MODULE VARCHAR2(400) Y LOG_MSG VARCHAR2(4000) Y LOG_TYPE VARCHAR2(80) Y 'DEBUG' LOG_LEVEL NUMBER Y 15 LOG_CREATED_ON DATE Y LOG_CREATED_BY VARCHAR2(400) Y"},{"location":"tables/XLIB_LOGS/#primary-key","title":"Primary Key","text":"<p><code>LOG_ID</code></p>"},{"location":"tables/XLIB_LOGS/#indici","title":"Indici","text":"Nome Unique Colonne XLIB_LOGS_IDX1 NONUNIQUE LOG_TYPE XLIB_LOGS_IDX2 NONUNIQUE LOG_MODULE XLIB_LOGS_PK UNIQUE LOG_ID"},{"location":"triggers/","title":"Triggers Database","text":"<p>Questa cartella contiene la documentazione di tutti i 19 triggers del database (esclusi quelli di sistema APEX).</p>"},{"location":"triggers/#triggers-generazione-id","title":"Triggers Generazione ID","text":"<p>Questi triggers generano automaticamente gli ID tramite sequence.</p> Trigger Tabella Sequence Evento EVENTI_TRG EVENTI EVENTI_SEQ BEFORE INSERT EVENTI_DET_PREL_TRG EVENTI_DET_PREL EVENTI_DET_PREL_SEQ BEFORE INSERT EVENTI_DET_RIS_TRG EVENTI_DET_RIS EVENTI_DET_RIS_SEQ BEFORE INSERT EVENTI_DET_DEGUST_TRG EVENTI_DET_DEGUST EVENTI_DET_DEGUST_SEQ BEFORE INSERT EVENTI_ACCONTI_TRG EVENTI_ACCONTI EVENTI_ACCONTI_SEQ BEFORE INSERT EVENTI_ALTRICOSTI_TRG EVENTI_ALTRICOSTI EVENTI_ALTRICOSTI_SEQ BEFORE INSERT EVENTI_ALLEG_TRG EVENTI_ALLEG EVENTI_ALLEG_SEQ BEFORE INSERT CLIENTI_TRG CLIENTI CLIENTI_SEQ2 BEFORE INSERT LOCATION_TRG LOCATION LOCATION_SEQ BEFORE INSERT RISORSE_TRG RISORSE RISORSE_SEQ BEFORE INSERT ARTICOLI_DET_REGOLE_TRG ARTICOLI_DET_REGOLE ARTICOLI_DET_REGOLE_SEQ BEFORE INSERT TB_TIPI_PASTO_TRG TB_TIPI_PASTO TB_TIPI_PASTO_SEQ BEFORE INSERT"},{"location":"triggers/#triggers-business-logic","title":"Triggers Business Logic","text":"Trigger Tabella Descrizione EVENTI_TRG EVENTI Inizializza STATO=100, DATA_DOC, VERS_TOKEN EVENTI_AI_TRG EVENTI Crea 4 record ospiti default (AFTER INSERT) EVENTI_DET_OSPITI_TRG_AI EVENTI_DET_OSPITI Gestione aggiornamento ospiti EVENTI_DET_PREL_QTA_TOT_TRG EVENTI_DET_PREL Calcola QTA totale su UPDATE"},{"location":"triggers/#triggers-ordinamento","title":"Triggers Ordinamento","text":"Trigger Tabella Descrizione ADD_COD_STEP TB_TIPI_MAT Assegna COD_STEP progressivo ON_DELETE_REORDER TB_TIPI_MAT Riordina COD_STEP dopo DELETE"},{"location":"triggers/#triggers-sistema","title":"Triggers Sistema","text":"Trigger Tabella Descrizione BI_GL_SCHEMA_CHANGES GL_SCHEMA_CHANGES Log modifiche schema XLIB_LOGS_BI_TRG XLIB_LOGS Timestamp log"},{"location":"triggers/#dettaglio-triggers-critici","title":"Dettaglio Triggers Critici","text":""},{"location":"triggers/#eventi_trg","title":"EVENTI_TRG","text":"<pre><code>BEFORE INSERT ON EVENTI FOR EACH ROW\n</code></pre> <p>Logica: 1. Genera ID da sequence 2. Imposta <code>DATA_DOC = SYSDATE</code> 3. Se INSERT: - <code>STATO = NVL(:NEW.STATO, 100)</code> - Se <code>VERS_NUMBER = 0</code>: genera <code>VERS_TOKEN</code> random</p>"},{"location":"triggers/#eventi_ai_trg","title":"EVENTI_AI_TRG","text":"<pre><code>AFTER INSERT ON EVENTI FOR EACH ROW\n</code></pre> <p>Logica: Inserisce automaticamente i 4 tipi ospiti: - COD_TIPO_OSPITE = 8 (Adulti), ORDINE = 1 - COD_TIPO_OSPITE = 5 (Kinder), ORDINE = 2 - COD_TIPO_OSPITE = 6 (Baby), ORDINE = 3 - COD_TIPO_OSPITE = 7 (Staff), ORDINE = 4</p>"},{"location":"triggers/#eventi_det_prel_qta_tot_trg","title":"EVENTI_DET_PREL_QTA_TOT_TRG","text":"<pre><code>BEFORE UPDATE ON EVENTI_DET_PREL FOR EACH ROW\n</code></pre> <p>Logica: <pre><code>:NEW.QTA := :NEW.QTA_APE + :NEW.QTA_SEDU + :NEW.QTA_BUFDOL \n + :NEW.QTA_MAN_APE + :NEW.QTA_MAN_SEDU + :NEW.QTA_MAN_BUFDOL\n</code></pre></p>"},{"location":"triggers/#migrazione-net","title":"Migrazione .NET","text":""},{"location":"triggers/#sostituzione-sequence-identity","title":"Sostituzione Sequence \u2192 Identity","text":"<pre><code>// Entity Framework Configuration\nmodelBuilder.Entity&lt;Evento&gt;()\n .Property(e =&gt; e.Id)\n .UseIdentityColumn();\n</code></pre>"},{"location":"triggers/#sostituzione-trigger-savechanges-interceptor","title":"Sostituzione Trigger \u2192 SaveChanges Interceptor","text":"<pre><code>public class EventiSaveChangesInterceptor : SaveChangesInterceptor\n{\n public override ValueTask&lt;InterceptionResult&lt;int&gt;&gt; SavingChangesAsync(\n DbContextEventData eventData,\n InterceptionResult&lt;int&gt; result,\n CancellationToken cancellationToken = default)\n {\n var context = eventData.Context;\n\n foreach (var entry in context.ChangeTracker.Entries&lt;Evento&gt;())\n {\n if (entry.State == EntityState.Added)\n {\n // Logica EVENTI_TRG\n entry.Entity.Stato ??= 100;\n entry.Entity.DataDoc = DateTime.Now;\n if (entry.Entity.VersNumber == 0)\n {\n entry.Entity.VersToken = GenerateRandomToken();\n }\n }\n else if (entry.State == EntityState.Modified)\n {\n entry.Entity.DataDoc = DateTime.Now;\n }\n }\n\n // Logica EVENTI_DET_PREL_QTA_TOT_TRG\n foreach (var entry in context.ChangeTracker.Entries&lt;EventiDetPrel&gt;())\n {\n if (entry.State == EntityState.Modified || entry.State == EntityState.Added)\n {\n entry.Entity.Qta = entry.Entity.CalcolaQuantitaTotale();\n }\n }\n\n return base.SavingChangesAsync(eventData, result, cancellationToken);\n }\n}\n</code></pre>"},{"location":"triggers/#creazione-ospiti-default","title":"Creazione Ospiti Default","text":"<pre><code>public override async Task&lt;int&gt; SaveChangesAsync(CancellationToken ct = default)\n{\n var newEvents = ChangeTracker.Entries&lt;Evento&gt;()\n .Where(e =&gt; e.State == EntityState.Added)\n .Select(e =&gt; e.Entity)\n .ToList();\n\n var result = await base.SaveChangesAsync(ct);\n\n // Logica EVENTI_AI_TRG\n foreach (var evento in newEvents)\n {\n var tipiOspiti = new[] { (8, 1), (5, 2), (6, 3), (7, 4) };\n foreach (var (tipo, ordine) in tipiOspiti)\n {\n EventiDetOspiti.Add(new EventiDetOspiti\n {\n IdEvento = evento.Id,\n CodTipoOspite = tipo.ToString(),\n Numero = 0,\n Ordine = ordine\n });\n }\n await base.SaveChangesAsync(ct);\n }\n\n return result;\n}\n</code></pre>"},{"location":"triggers/ADD_COD_STEP/","title":"ADD_COD_STEP","text":""},{"location":"triggers/ADD_COD_STEP/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: TB_TIPI_MAT</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/ADD_COD_STEP/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"ADD_COD_STEP\" \nBEFORE INSERT ON TB_TIPI_MAT \n\nFOR EACH ROW \nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.cod_step IS NULL THEN\n select max(cod_step)+1\n into :NEW.cod_step\n from tb_tipi_mat\n where cod_step not in (9999999, -1, 0);\n END IF;\n END COLUMN_SEQUENCES;\nEND;\n</code></pre>"},{"location":"triggers/ARTICOLI_DET_REGOLE_TRG/","title":"ARTICOLI_DET_REGOLE_TRG","text":""},{"location":"triggers/ARTICOLI_DET_REGOLE_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: ARTICOLI_DET_REGOLE</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/ARTICOLI_DET_REGOLE_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"ARTICOLI_DET_REGOLE_TRG\" \nBEFORE INSERT ON ARTICOLI_DET_REGOLE \nFOR EACH ROW \nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT ARTICOLI_DET_REGOLE_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n END COLUMN_SEQUENCES;\nEND;\n</code></pre>"},{"location":"triggers/BI_GL_SCHEMA_CHANGES/","title":"BI_GL_SCHEMA_CHANGES","text":""},{"location":"triggers/BI_GL_SCHEMA_CHANGES/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: GL_SCHEMA_CHANGES</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/BI_GL_SCHEMA_CHANGES/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"BI_GL_SCHEMA_CHANGES\" \nbefore insert on gl_schema_changes\nfor each row\nBEGIN\n select gl_schema_changes_seq.nextval into :new.id from dual;\n :NEW.VERSION_NAME := :NEW.VYEAR||'.'||:NEW.VMONTH||'.'||:NEW.VMAJOR||'.'||:NEW.VMINOR||:NEW.VTYPE;\nend;\n</code></pre>"},{"location":"triggers/CLIENTI_TRG/","title":"CLIENTI_TRG","text":""},{"location":"triggers/CLIENTI_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: CLIENTI</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/CLIENTI_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"CLIENTI_TRG\" \nBEFORE INSERT ON CLIENTI \nFOR EACH ROW \nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT CLIENTI_SEQ2.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n END COLUMN_SEQUENCES;\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_ACCONTI_TRG/","title":"EVENTI_ACCONTI_TRG","text":""},{"location":"triggers/EVENTI_ACCONTI_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_ACCONTI</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_ACCONTI_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_ACCONTI_TRG\" \nBEFORE INSERT ON EVENTI_ACCONTI \nFOR EACH ROW \nBEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT EVENTI_ACCONTI_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_AI_TRG/","title":"EVENTI_AI_TRG","text":""},{"location":"triggers/EVENTI_AI_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI</li> <li>Evento: INSERT</li> <li>Tipo: AFTER EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_AI_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_AI_TRG\" \nAFTER INSERT ON EVENTI \nFOR EACH ROW \nBEGIN\n\n if inserting then\n\n-- execute immediate 'alter trigger \"APCB\".\"EVENTI_DET_OSPITI_TRG_AI\" disable';\n\n --default su righe ospiti\n INSERT INTO eventi_det_ospiti (\n id_evento,\n cod_tipo_ospite,\n numero,\n note,\n ordine\n ) \n SELECT :NEW.ID, 5, 0, '', 2 FROM DUAL\n UNION\n SELECT :NEW.ID, 6, 0, '', 3 FROM DUAL\n UNION\n SELECT :NEW.ID, 7, 0, '', 4 FROM DUAL\n UNION\n SELECT :NEW.ID, 8, 0, '', 1 FROM DUAL;\n\n end if;\n\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_ALLEG_TRG/","title":"EVENTI_ALLEG_TRG","text":""},{"location":"triggers/EVENTI_ALLEG_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_ALLEG</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_ALLEG_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_ALLEG_TRG\" \nBEFORE INSERT ON EVENTI_ALLEG \nFOR EACH ROW \nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT EVENTI_ALLEG_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n END COLUMN_SEQUENCES;\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_ALTRICOSTI_TRG/","title":"EVENTI_ALTRICOSTI_TRG","text":""},{"location":"triggers/EVENTI_ALTRICOSTI_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_ALTRICOSTI</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_ALTRICOSTI_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_ALTRICOSTI_TRG\" \nBEFORE INSERT ON eventi_altricosti \nFOR EACH ROW \nBEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT eventi_altricosti_seq.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_DET_DEGUST_TRG/","title":"EVENTI_DET_DEGUST_TRG","text":""},{"location":"triggers/EVENTI_DET_DEGUST_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_DET_DEGUST</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_DET_DEGUST_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_DET_DEGUST_TRG\" \nBEFORE INSERT ON EVENTI_DET_DEGUST \nFOR EACH ROW \nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT EVENTI_DET_DEGUST_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n END COLUMN_SEQUENCES;\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_DET_OSPITI_TRG_AI/","title":"EVENTI_DET_OSPITI_TRG_AI","text":""},{"location":"triggers/EVENTI_DET_OSPITI_TRG_AI/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_DET_OSPITI</li> <li>Evento: UPDATE</li> <li>Tipo: AFTER EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_DET_OSPITI_TRG_AI/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_DET_OSPITI_TRG_AI\" \n--AFTER INSERT OR UPDATE OR DELETE ON EVENTI_DET_OSPITI \nAFTER UPDATE ON EVENTI_DET_OSPITI \nFOR EACH ROW \n\n-- solo update, tutti i tipi ospiti vengono inseriti con l'inserimento della testata dell'evento con QTA def = 0\n\ndeclare\n\nv_cod_art varchar2(10);\nv_coeff number;\nv_ospiti number;\nv_azione varchar2(10);\nv_id_evento number;\nv_count number;\n\nBEGIN\n\n v_azione := '';\n v_id_evento := nvl(:NEW.ID_EVENTO,:OLD.ID_EVENTO);\n\n --RAISE_APPLICATION_ERROR(-20001,'ididididididid: ' + to_char('hhhhhhhhhhh') );\n\n if DELETING THEN\n --RAISE_APPLICATION_ERROR(-20000, ':NEW.NUMERO' || :NEW.NUMERO || ':OLD.NUMERO' || :OLD.NUMERO); \n v_azione := 'DELETE';\n v_id_evento := :OLD.ID_EVENTO;\n elsif INSERTING THEN\n v_azione := 'INSERT';\n v_id_evento := :NEW.ID_EVENTO; \n END IF;\n--/*\n --Controllo esistenza id testata (caso default righe dett)\n-- v_count := 0;\n-- select count(*) into v_count \n-- from eventi where id = :NEW.ID_EVENTO;\n\n-- if v_count &gt; 0 then\n\n --RAISE_APPLICATION_ERROR(-20000,'id: ' + to_char(v_id_evento) + ' :NEW.NUMERO' || to_char(:NEW.NUMERO) || ' :OLD.NUMERO' || to_char(:OLD.NUMERO) + ' azione: ' + v_azione);\n --Calcola la qta tot ospiti di Testata:\n --EVENTI_AGGIORNA_N_OSPITI(v_id_evento,:NEW.NUMERO,:OLD.NUMERO,v_azione); \n\n-- end if;\n--*/ \n exception when others\n then\n RAISE_APPLICATION_ERROR(-20000, 'Errore: ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64)); \n\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_DET_PREL_QTA_TOT_TRG/","title":"EVENTI_DET_PREL_QTA_TOT_TRG","text":""},{"location":"triggers/EVENTI_DET_PREL_QTA_TOT_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_DET_PREL</li> <li>Evento: UPDATE</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_DET_PREL_QTA_TOT_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_DET_PREL_QTA_TOT_TRG\" \nBEFORE UPDATE ON EVENTI_DET_PREL \nFOR EACH ROW \n\nBEGIN\n\n :NEW.QTA := :NEW.QTA_APE + :NEW.QTA_SEDU + :NEW.QTA_BUFDOL + :NEW.QTA_MAN_APE + :NEW.QTA_MAN_SEDU + :NEW.QTA_MAN_BUFDOL;\n\n exception when others\n then\n RAISE_APPLICATION_ERROR(-20000, 'Errore in aggiornamento QTA da prelevare: ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64)); \n\n return; \n\n\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_DET_PREL_TRG/","title":"EVENTI_DET_PREL_TRG","text":""},{"location":"triggers/EVENTI_DET_PREL_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_DET_PREL</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_DET_PREL_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_DET_PREL_TRG\" \nbefore INSERT ON EVENTI_DET_PREL \nFOR EACH ROW \ndeclare\nBEGIN\n IF INSERTING THEN\n SELECT EVENTI_DET_PREL_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_DET_RIS_TRG/","title":"EVENTI_DET_RIS_TRG","text":""},{"location":"triggers/EVENTI_DET_RIS_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI_DET_RIS</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_DET_RIS_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"EVENTI_DET_RIS_TRG\" \nBEFORE INSERT ON EVENTI_DET_RIS \nFOR EACH ROW \n\nDECLARE\n\n v_costo_orario number;\n v_costo_prestazione number;\n\nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT EVENTI_DET_RIS_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n END COLUMN_SEQUENCES;\n\n /*\n --default su costo\n begin\n select nvl(costo_orario,0), nvl(costo_prestazione,0)\n into v_costo_orario, v_costo_prestazione \n from risorse r\n where r.id = :NEW.ID_RISORSA; \n\n :NEW.COSTO := :NEW.ORE_LAV * v_costo_orario;\n\n exception when others\n then RAISE_APPLICATION_ERROR(-20000, 'Errore: Inserimento costo risorsa'); \n end;\n */\n\nEND;\n</code></pre>"},{"location":"triggers/EVENTI_TRG/","title":"EVENTI_TRG","text":""},{"location":"triggers/EVENTI_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: EVENTI</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/EVENTI_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"EVENTI_TRG\" \nBEFORE INSERT ON EVENTI \nFOR EACH ROW \nBEGIN\n IF INSERTING THEN\n SELECT EVENTI_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n\n if inserting or updating then\n --aggiornamento data_doc (data redazione) \n :NEW.DATA_DOC := sysdate; \n end if;\n\n if inserting THEN \n :NEW.STATO := nvl(:NEW.STATO, 100);\n IF nvl(:NEW.vers_number, 0) = 0 THEN\n :NEW.vers_token := DBMS_RANDOM.STRING ('A' , DBMS_RANDOM.VALUE (64, 255));\n END IF;\n end if;\n\nEND;\n</code></pre>"},{"location":"triggers/LOCATION_TRG/","title":"LOCATION_TRG","text":""},{"location":"triggers/LOCATION_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: LOCATION</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/LOCATION_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"LOCATION_TRG\" \nBEFORE INSERT ON LOCATION \nFOR EACH ROW \nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT LOCATION_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n END COLUMN_SEQUENCES;\nEND;\n</code></pre>"},{"location":"triggers/ON_DELETE_REORDER/","title":"ON_DELETE_REORDER","text":""},{"location":"triggers/ON_DELETE_REORDER/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: TB_TIPI_MAT</li> <li>Evento: DELETE</li> <li>Tipo: AFTER EACH ROW</li> <li>Stato: DISABLED</li> </ul>"},{"location":"triggers/ON_DELETE_REORDER/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"ON_DELETE_REORDER\" \nafter DELETE ON TB_TIPI_MAT \nFOR EACH ROW\nBEGIN\n\n FOR TP IN (\n SELECT COD_TIPO, COD_STEP - 1 AS COD_STEP_NEW\n FROM TB_TIPI_MAT T\n WHERE COD_STEP &gt; :OLD.COD_STEP\n AND COD_STEP NOT IN (-2, -1, 0, 9999999)\n )LOOP\n UPDATE TB_TIPI_MAT\n SET COD_STEP = TP.COD_STEP_NEW\n WHERE COD_TIPO = TP.COD_TIPO;\n END LOOP;\n\nEND;\n</code></pre>"},{"location":"triggers/RISORSE_TRG/","title":"RISORSE_TRG","text":""},{"location":"triggers/RISORSE_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: RISORSE</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/RISORSE_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"RISORSE_TRG\" \nBEFORE INSERT ON RISORSE \nFOR EACH ROW \nBEGIN\n &lt;&lt;COLUMN_SEQUENCES&gt;&gt;\n BEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT RISORSE_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\n END COLUMN_SEQUENCES;\nEND;\n</code></pre>"},{"location":"triggers/TB_TIPI_PASTO_TRG/","title":"TB_TIPI_PASTO_TRG","text":""},{"location":"triggers/TB_TIPI_PASTO_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: TB_TIPI_PASTO</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/TB_TIPI_PASTO_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER TB_TIPI_PASTO_TRG \nBEFORE INSERT ON TB_TIPI_PASTO \nFOR EACH ROW \nBEGIN\n IF INSERTING AND :NEW.ID IS NULL THEN\n SELECT TB_TIPI_PASTO_SEQ.NEXTVAL INTO :NEW.ID FROM SYS.DUAL;\n END IF;\nEND;\n</code></pre>"},{"location":"triggers/XLIB_LOGS_BI_TRG/","title":"XLIB_LOGS_BI_TRG","text":""},{"location":"triggers/XLIB_LOGS_BI_TRG/#informazioni","title":"Informazioni","text":"<ul> <li>Tabella: XLIB_LOGS</li> <li>Evento: INSERT</li> <li>Tipo: BEFORE EACH ROW</li> <li>Stato: ENABLED</li> </ul>"},{"location":"triggers/XLIB_LOGS_BI_TRG/#codice-sorgente","title":"Codice Sorgente","text":"<pre><code>TRIGGER \"APOLLINARECATERINGPROD\".\"XLIB_LOGS_BI_TRG\" \n BEFORE INSERT\n ON XLIB_LOGS\n REFERENCING NEW AS NEW OLD AS OLD\n FOR EACH ROW\nBEGIN\n IF :NEW.log_id IS NULL\n THEN\n SELECT XLIB_SEQ.NEXTVAL\n INTO :NEW.log_id\n FROM DUAL;\n END IF;\nEND;\n</code></pre>"},{"location":"types/","title":"Tipi Custom Database","text":"<p>Questa cartella contiene la documentazione di tutti i 10 tipi custom del database (esclusi i tipi PLJSON).</p>"},{"location":"types/#tipi-per-funzioni-pipelined","title":"Tipi per Funzioni Pipelined","text":"<p>Questi tipi sono utilizzati dalle funzioni che ritornano tabelle (pipelined functions).</p>"},{"location":"types/#f_get_ospiti","title":"F_GET_OSPITI","text":"Tipo Descrizione T_DET_OSPITI_ROW Tipo OBJECT per singola riga T_DET_OSPITI_TAB Tipo TABLE OF T_DET_OSPITI_ROW <pre><code>-- Struttura T_DET_OSPITI_ROW\nCREATE TYPE T_DET_OSPITI_ROW AS OBJECT (\n ID_EVENTO NUMBER,\n TOT_ADULTI NUMBER,\n TOT_KINDER NUMBER,\n TOT_BABY NUMBER,\n TOT_STAFF NUMBER,\n TOT_INVITATI NUMBER,\n NOTE_ADULTI VARCHAR2(1000),\n NOTE_KINDER VARCHAR2(1000),\n NOTE_BABY VARCHAR2(1000),\n NOTE_STAFF VARCHAR2(1000)\n);\n\n-- Struttura T_DET_OSPITI_TAB\nCREATE TYPE T_DET_OSPITI_TAB AS TABLE OF T_DET_OSPITI_ROW;\n</code></pre>"},{"location":"types/#f_rep_allestimenti","title":"F_REP_ALLESTIMENTI","text":"Tipo Descrizione T_REP_ALLESTIMENTI_ROW Tipo OBJECT per singola riga T_REP_ALLESTIMENTI_TAB Tipo TABLE OF T_REP_ALLESTIMENTI_ROW"},{"location":"types/#f_rep_cucina","title":"F_REP_CUCINA","text":"Tipo Descrizione T_REP_CUCINA_ROW Tipo OBJECT per singola riga T_REP_CUCINA_TAB Tipo TABLE OF T_REP_CUCINA_ROW"},{"location":"types/#tipi-utility","title":"Tipi Utility","text":"Tipo Descrizione STRING_LIST Tipo TABLE OF VARCHAR2 per liste stringhe ENUM_TABLE_OBJECT Tipo OBJECT per STRING_TO_TABLE_ENUM ENUM_TABLE_TYPE Tipo TABLE OF ENUM_TABLE_OBJECT XLIB_VC2_ARRAY_T Array di VARCHAR2 per XLIB"},{"location":"types/#utilizzo-in-query","title":"Utilizzo in Query","text":"<pre><code>-- Esempio uso F_GET_OSPITI\nSELECT * FROM TABLE(F_GET_OSPITI(123));\n\n-- Esempio uso STRING_TO_TABLE_ENUM\nSELECT * FROM TABLE(STRING_TO_TABLE_ENUM('A:B:C', 0, ':'));\n</code></pre>"},{"location":"types/#migrazione-net","title":"Migrazione .NET","text":"<p>In .NET i tipi Oracle pipelined vengono sostituiti con classi DTO e IEnumerable/IAsyncEnumerable.</p>"},{"location":"types/#esempio-t_det_ospiti_row-dto","title":"Esempio T_DET_OSPITI_ROW \u2192 DTO","text":"<pre><code>public class DettaglioOspitiDto\n{\n public int IdEvento { get; set; }\n public int TotAdulti { get; set; }\n public int TotKinder { get; set; }\n public int TotBaby { get; set; }\n public int TotStaff { get; set; }\n public int TotInvitati { get; set; }\n public string NoteAdulti { get; set; }\n public string NoteKinder { get; set; }\n public string NoteBaby { get; set; }\n public string NoteStaff { get; set; }\n}\n</code></pre>"},{"location":"types/#esempio-f_get_ospiti-metodo-service","title":"Esempio F_GET_OSPITI \u2192 Metodo Service","text":"<pre><code>public async Task&lt;DettaglioOspitiDto&gt; GetOspitiAsync(int idEvento)\n{\n var ospiti = await _context.EventiDetOspiti\n .Where(o =&gt; o.IdEvento == idEvento)\n .ToListAsync();\n\n return new DettaglioOspitiDto\n {\n IdEvento = idEvento,\n TotAdulti = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"8\")?.Numero ?? 0,\n TotKinder = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"5\")?.Numero ?? 0,\n TotBaby = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"6\")?.Numero ?? 0,\n TotStaff = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"7\")?.Numero ?? 0,\n TotInvitati = ospiti.Sum(o =&gt; o.Numero ?? 0),\n NoteAdulti = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"8\")?.Note,\n NoteKinder = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"5\")?.Note,\n NoteBaby = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"6\")?.Note,\n NoteStaff = ospiti.FirstOrDefault(o =&gt; o.CodTipoOspite == \"7\")?.Note\n };\n}\n</code></pre>"},{"location":"types/#esempio-string_to_table_enum-extension-method","title":"Esempio STRING_TO_TABLE_ENUM \u2192 Extension Method","text":"<pre><code>public static class StringExtensions\n{\n public static IEnumerable&lt;string&gt; ToTableEnum(this string input, char delimiter = ':')\n {\n if (string.IsNullOrEmpty(input))\n yield break;\n\n foreach (var item in input.Split(delimiter))\n {\n yield return item.Trim();\n }\n }\n}\n\n// Uso\nvar items = \"A:B:C\".ToTableEnum(':');\n</code></pre>"},{"location":"types/ENUM_TABLE_OBJECT/","title":"ENUM_TABLE_OBJECT","text":""},{"location":"types/ENUM_TABLE_OBJECT/#definizione","title":"Definizione","text":"<p><code>sql TYPE \"ENUM_TABLE_OBJECT\" AS OBJECT ( ID NUMBER, RESULT VARCHAR2(4000) );</code></p>"},{"location":"types/ENUM_TABLE_TYPE/","title":"ENUM_TABLE_TYPE","text":""},{"location":"types/ENUM_TABLE_TYPE/#definizione","title":"Definizione","text":"<pre><code>TYPE \"ENUM_TABLE_TYPE\" AS TABLE OF ENUM_TABLE_OBJECT;\n</code></pre>"},{"location":"types/STRING_LIST/","title":"STRING_LIST","text":""},{"location":"types/STRING_LIST/#definizione","title":"Definizione","text":"<pre><code>TYPE \"STRING_LIST\" as table of varchar2(32767);\n</code></pre>"},{"location":"types/T_DET_OSPITI_ROW/","title":"T_DET_OSPITI_ROW","text":""},{"location":"types/T_DET_OSPITI_ROW/#definizione","title":"Definizione","text":"<pre><code>TYPE \"T_DET_OSPITI_ROW\" AS OBJECT (\n id_evento number,\n TOT_ADULTI number,\n TOT_KINDER number,\n TOT_BABY number,\n TOT_STAFF number,\n TOT_INVITATI number,\n NOTE_ADULTI varchar2(1000),\n NOTE_KINDER varchar2(1000),\n NOTE_BABY varchar2(1000),\n NOTE_STAFF varchar2(1000) \n);\n</code></pre>"},{"location":"types/T_DET_OSPITI_TAB/","title":"T_DET_OSPITI_TAB","text":""},{"location":"types/T_DET_OSPITI_TAB/#definizione","title":"Definizione","text":"<pre><code>TYPE \"T_DET_OSPITI_TAB\" IS TABLE OF t_det_ospiti_row;\n</code></pre>"},{"location":"types/T_REP_ALLESTIMENTI_ROW/","title":"T_REP_ALLESTIMENTI_ROW","text":""},{"location":"types/T_REP_ALLESTIMENTI_ROW/#definizione","title":"Definizione","text":"<pre><code>TYPE \"T_REP_ALLESTIMENTI_ROW\" AS OBJECT (\n D1 varchar2(100), \n D2 varchar2(100),\n D3 varchar2(100),\n D4 varchar2(100), \n D5 varchar2(100), \n D6 varchar2(100), \n D7 varchar2(100), \n D8 varchar2(100), \n D9 varchar2(100), \n D10 varchar2(100), \n D11 varchar2(100), \n D12 varchar2(100), \n\n L1 varchar2(100), \n L2 varchar2(100), \n L3 varchar2(100), \n L4 varchar2(100), \n L5 varchar2(100), \n L6 varchar2(100), \n L7 varchar2(100), \n L8 varchar2(100), \n L9 varchar2(100), \n L10 varchar2(100), \n L11 varchar2(100), \n L12 varchar2(100),\n\n TOV_TO1 varchar2(1000), \n TOV_TO2 varchar2(1000), \n TOV_TO3 varchar2(1000), \n TOV_TO4 varchar2(1000), \n TOV_TO5 varchar2(1000), \n TOV_TO6 varchar2(1000), \n TOV_TO7 varchar2(1000), \n TOV_TO8 varchar2(1000), \n TOV_TO9 varchar2(1000), \n TOV_TO10 varchar2(1000), \n TOV_TO11 varchar2(1000), \n TOV_TO12 varchar2(1000), \n\n C1 varchar2(1000), \n C2 varchar2(1000), \n C3 varchar2(1000), \n C4 varchar2(1000), \n C5 varchar2(1000), \n C6 varchar2(1000), \n C7 varchar2(1000), \n C8 varchar2(1000), \n C9 varchar2(1000), \n C10 varchar2(1000), \n C11 varchar2(1000), \n C12 varchar2(1000),\n\n TOV_LO1 varchar2(1000), \n TOV_LO2 varchar2(1000), \n TOV_LO3 varchar2(1000), \n TOV_LO4 varchar2(1000), \n TOV_LO5 varchar2(1000), \n TOV_LO6 varchar2(1000), \n TOV_LO7 varchar2(1000), \n TOV_LO8 varchar2(1000), \n TOV_LO9 varchar2(1000), \n TOV_LO10 varchar2(1000), \n TOV_LO11 varchar2(1000), \n TOV_LO12 varchar2(1000), \n\n A_G1 varchar2(1000), \n A_G2 varchar2(1000), \n A_G3 varchar2(1000), \n A_G4 varchar2(1000), \n A_G5 varchar2(1000), \n A_G6 varchar2(1000), \n A_G7 varchar2(1000), \n A_G8 varchar2(1000), \n A_G9 varchar2(1000), \n A_G10 varchar2(1000), \n A_G11 varchar2(1000), \n A_G12 varchar2(1000), \n\n A_O1 varchar2(1000), \n A_O2 varchar2(1000), \n A_O3 varchar2(1000), \n A_O4 varchar2(1000), \n A_O5 varchar2(1000), \n A_O6 varchar2(1000), \n A_O7 varchar2(1000), \n A_O8 varchar2(1000), \n A_O9 varchar2(1000), \n A_O10 varchar2(1000), \n A_O11 varchar2(1000), \n A_O12 varchar2(1000), \n\n A_R1 varchar2(1000), \n A_R2 varchar2(1000), \n A_R3 varchar2(1000), \n A_R4 varchar2(1000), \n A_R5 varchar2(1000), \n A_R6 varchar2(1000), \n A_R7 varchar2(1000), \n A_R8 varchar2(1000), \n A_R9 varchar2(1000), \n A_R10 varchar2(1000), \n A_R11 varchar2(1000), \n A_R12 varchar2(1000), \n\n T1 varchar2(1000), \n T2 varchar2(1000), \n T3 varchar2(1000), \n T4 varchar2(1000), \n T5 varchar2(1000), \n T6 varchar2(1000), \n T7 varchar2(1000), \n T8 varchar2(1000), \n T9 varchar2(1000), \n T10 varchar2(1000), \n T11 varchar2(1000), \n T12 varchar2(1000),\n\n SM1 varchar2(1000), \n SM2 varchar2(1000), \n SM3 varchar2(1000), \n SM4 varchar2(1000), \n SM5 varchar2(1000), \n SM6 varchar2(1000), \n SM7 varchar2(1000), \n SM8 varchar2(1000), \n SM9 varchar2(1000), \n SM10 varchar2(1000), \n SM11 varchar2(1000), \n SM12 varchar2(1000) \n);\n</code></pre>"},{"location":"types/T_REP_ALLESTIMENTI_TAB/","title":"T_REP_ALLESTIMENTI_TAB","text":""},{"location":"types/T_REP_ALLESTIMENTI_TAB/#definizione","title":"Definizione","text":"<pre><code>TYPE \"T_REP_ALLESTIMENTI_TAB\" IS TABLE OF t_rep_allestimenti_row;\n</code></pre>"},{"location":"types/T_REP_CUCINA_ROW/","title":"T_REP_CUCINA_ROW","text":""},{"location":"types/T_REP_CUCINA_ROW/#definizione","title":"Definizione","text":"<pre><code>TYPE \"T_REP_CUCINA_ROW\" AS OBJECT (\n data date,\n LOCATION varchar2(4000),\n cliente varchar2(4000),\n DESCRIZIONE varchar2(4000),\n ORA_CERIMONIA varchar2(4000),\n ORA_EVENTO varchar2(4000),\n TOT_ADULTI number,\n TOT_KINDER number,\n TOT_BABY number,\n TOT_STAFF number,\n TOT_INVITATI number,\n ALLERGIE varchar2(4000),\n TORTA varchar2(4000),\n CONFETTATA varchar2(4000),\n STAMPA_MENU varchar2(4000),\n ANGOLI varchar2(4000),\n EXTRA_INFO varchar2(4000),\n NOTE_ADULTI varchar2(4000),\n NOTE_KINDER varchar2(4000),\n NOTE_BABY varchar2(4000),\n NOTE_STAFF varchar2(4000),\n cliente_mail varchar2(4000),\n cliente_tel varchar2(4000),\n referente_tel varchar2(4000),\n distanza_location varchar2(4000),\n buffet_iniziale varchar2(4000),\n buffet_finale varchar2(4000),\n primi varchar2(4000),\n secondi varchar2(4000),\n vini varchar2(4000),\n extra_costi varchar2(4000),\n event_id number\n )\n</code></pre>"},{"location":"types/T_REP_CUCINA_TAB/","title":"T_REP_CUCINA_TAB","text":""},{"location":"types/T_REP_CUCINA_TAB/#definizione","title":"Definizione","text":"<p><code>sql TYPE \"T_REP_CUCINA_TAB\" IS TABLE OF t_rep_cucina_row</code></p>"},{"location":"types/XLIB_VC2_ARRAY_T/","title":"XLIB_VC2_ARRAY_T","text":""},{"location":"types/XLIB_VC2_ARRAY_T/#definizione","title":"Definizione","text":"<p><code>sql TYPE \"XLIB_VC2_ARRAY_T\" AS TABLE OF VARCHAR2 (32767 CHAR)</code></p>"},{"location":"views/","title":"Viste Database","text":"<p>Questa cartella contiene la documentazione di tutte le 26 viste del database.</p>"},{"location":"views/#viste-per-calcolo-costi","title":"Viste per Calcolo Costi","text":"Vista Descrizione GET_COSTO_ART_BY_EVT Calcola costo articoli per singolo evento GET_COSTO_ART_EVT Aggregazione costi articoli per evento GET_COSTO_CATEG_EVT Costi aggregati per categoria GET_COSTO_DEGUS_EVT Costo degustazioni (da detrarre) GET_COSTO_OSPITI_EVT Costo per ospiti con sconti GET_COSTO_RIS_EVT Costo risorse/personale GET_COSTO_TIPI_EVT Costi aggregati per tipo materiale GET_ULTIMI_COSTI Ultimo costo registrato per articolo"},{"location":"views/#viste-per-dati-evento","title":"Viste per Dati Evento","text":"Vista Descrizione GET_EVT_DATA Dati completi evento con join GET_EVT_DATA_PRINT Dati evento formattati per stampa GET_PREL_ART_TOT Totali quantit\u00e0 prelievo calcolate GET_PREL_BY_EVT Prelievi per evento con descrizioni"},{"location":"views/#viste-calendario-e-stati","title":"Viste Calendario e Stati","text":"Vista Descrizione VW_CALENDARIO_EVENTI Vista per calendario con colori e CSS VW_EVENT_COLOR Mapping stati \u2192 colori VW_EVENT_COLOR_OLD Vecchia logica colori (deprecata) VW_EVENTI_STATUSES Elenco stati distinti con colori"},{"location":"views/#viste-giacenze-e-impegni","title":"Viste Giacenze e Impegni","text":"Vista Descrizione V_IMPEGNI_ARTICOLI Quantit\u00e0 impegnate per articolo/data V_IMPEGNI_ARTICOLI_LOC Impegni con dettaglio location"},{"location":"views/#viste-report","title":"Viste Report","text":"Vista Descrizione V_REP_ALLESTIMENTI Dati per report allestimenti VW_REP_DEGUSTAZIONI Dati per report degustazioni V_GRIGLIA Vista griglia settimanale GET_REPORT_CONSUNTIVO_PER_DATA Report consuntivo dettagliato"},{"location":"views/#viste-utenti-e-permessi","title":"Viste Utenti e Permessi","text":"Vista Descrizione GET_CONSUNTIVI_USERS Utenti con accesso consuntivi GET_GESTORI_USERS Utenti con ruolo gestore GET_USERS_LIST Lista utenti APEX workspace"},{"location":"views/#viste-pagamenti","title":"Viste Pagamenti","text":"Vista Descrizione GET_EVENTI_DA_PAGARE_ENTRO_65GG Eventi con caparre non pagate"},{"location":"views/#note-tecniche","title":"Note Tecniche","text":""},{"location":"views/#calcolo-totale-evento","title":"Calcolo Totale Evento","text":"<p>Il totale evento viene calcolato sommando diverse viste: <pre><code>TOTALE = GET_COSTO_TIPI_EVT \n - GET_COSTO_DEGUS_EVT (detrazione)\n + GET_COSTO_RIS_EVT \n + GET_COSTO_OSPITI_EVT (+ 10% IVA)\n + EVENTI_ALTRICOSTI (+ 10% IVA se &gt; 0)\n</code></pre></p>"},{"location":"views/#v_impegni_articoli","title":"V_IMPEGNI_ARTICOLI","text":"<p>Questa vista \u00e8 fondamentale per il controllo giacenze: - Include solo eventi con stato 200-400 - Esclude eventi con versioni successive (<code>ID_EVT_FIGLIO IS NULL</code>) - Usata dalla funzione <code>F_GET_QTA_IMPEGNATA</code></p>"},{"location":"views/#vw_calendario_eventi","title":"VW_CALENDARIO_EVENTI","text":"<p>Costruisce la descrizione dinamica per il calendario: - Numero progressivo evento nel giorno - Indicatore preventivo scaduto (<code>!!!</code>) - Indicatore contratto non firmato (<code>*</code>) - Location e numero ospiti adulti - Classe CSS per colorazione</p>"},{"location":"views/GET_CONSUNTIVI_USERS/","title":"GET_CONSUNTIVI_USERS","text":""},{"location":"views/GET_CONSUNTIVI_USERS/#colonne","title":"Colonne","text":"Colonna Tipo USERS VARCHAR2(4000)"},{"location":"views/GET_CONSUNTIVI_USERS/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_CONSUNTIVI_USERS AS\nselect result as users from table(string_to_table_enum(get_param_value('PERMES_CONSUNTIVI'), 0, ':'))\n</code></pre>"},{"location":"views/GET_COSTO_ART_BY_EVT/","title":"GET_COSTO_ART_BY_EVT","text":""},{"location":"views/GET_COSTO_ART_BY_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER COD_ARTICOLO VARCHAR2(10) COSTO_UNI NUMBER NUMERO NUMBER COSTO_CALC NUMBER COSTO_CALC_IVA NUMBER"},{"location":"views/GET_COSTO_ART_BY_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_COSTO_ART_BY_EVT AS\nSELECT p.id_evento, ca.COD_ARTICOLO, nvl(p.COSTO_ARTICOLO, ca.costo_uni) as costo_uni,\n(\n case when a.flg_qta_type = 'S' then nvl(qta_std_prel_tot, 0) else 1 end\n *\n case when a.flg_qta_type = 'C' then nvl(qta_coeff_prel_tot, 0) else 1 end\n *\n case when a.flg_qta_type = 'P' then nvl(qta_prec_prel_tot, 0) else 1 end\n) as numero,\nNVL(p.COSTO_ARTICOLO, ca.COSTO_UNI)\n*\n(\n case when a.flg_qta_type = 'S' then nvl(qta_std_prel_tot, 0) else 1 end\n *\n case when a.flg_qta_type = 'C' then nvl(qta_coeff_prel_tot, 0) else 1 end\n *\n case when a.flg_qta_type = 'P' then nvl(qta_prec_prel_tot, 0) else 1 end\n) as costo_calc,\n(NVL(p.COSTO_ARTICOLO, ca.COSTO_UNI)+NVL(p.COSTO_ARTICOLO, ca.COSTO_UNI)*(a.perc_iva/100))\n*\n(\n case when a.flg_qta_type = 'S' then nvl(qta_std_prel_tot, 0) else 1 end\n *\n case when a.flg_qta_type = 'C' then nvl(qta_coeff_prel_tot, 0) else 1 end\n *\n case when a.flg_qta_type = 'P' then nvl(qta_prec_prel_tot, 0) else 1 end\n)\nas costo_calc_iva\nFROM ARTICOLI a\nleft JOIN COSTI_ARTICOLI ca ON a.COD_ARTICOLO = ca.COD_ARTICOLO\nleft join get_prel_art_tot p on a.cod_articolo = p.cod_articolo\nleft join eventi ed on ed.id = p.id_evento\nleft join eventi e on e.id = p.id_evento and e.data in (SELECT b.DATA_COSTO FROM COSTI_ARTICOLI b where b.cod_articolo = a.cod_articolo)\nleft join EVENTI_DET_OSPITI d on d.id_evento = nvl(e.id, ed.id) and d.cod_tipo_ospite = 8 -- adulti (se non trovo un evento per quel costo articolo lo devo ignorare)\nWHERE (e.id is not null and ca.DATA_COSTO = nvl(e.data, (SELECT max(b.DATA_COSTO) FROM COSTI_ARTICOLI b where b.cod_articolo = a.cod_articolo)))\nor (e.id is null and ca.cod_articolo is not null and ca.DATA_COSTO = nvl(e.data, (SELECT max(b.DATA_COSTO) FROM COSTI_ARTICOLI b where b.cod_articolo = a.cod_articolo)))\n</code></pre>"},{"location":"views/GET_COSTO_ART_EVT/","title":"GET_COSTO_ART_EVT","text":""},{"location":"views/GET_COSTO_ART_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER COD_ARTICOLO VARCHAR2(10) NUMERO NUMBER COSTO_UNI NUMBER COSTO NUMBER COSTO_IVATO NUMBER"},{"location":"views/GET_COSTO_ART_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_COSTO_ART_EVT AS\nSELECT\nedp.ID_EVENTO,\na.COD_ARTICOLO,\nsum(ca.numero) as numero,\nsum(ca.costo_uni) as costo_uni,\nSUM(ca.costo_calc) AS costo,\nSUM(ca.costo_calc_iva) AS costo_ivato\nFROM EVENTI e\njoin EVENTI_DET_OSPITI edoa on edoa.id_evento = e.id and edoa.cod_tipo_ospite = 8 -- adulti\nJOIN EVENTI_DET_PREL edp ON edp.ID_EVENTO = e.ID\nJOIN ARTICOLI a ON a.COD_ARTICOLO = edp.COD_ARTICOLO\nLEFT JOIN GET_COSTO_ART_BY_EVT ca ON ca.COD_ARTICOLO = a.COD_ARTICOLO AND ca.id_evento = e.id\nLEFT JOIN GET_ULTIMI_COSTI guc ON guc.COD_ARTICOLO = a.COD_ARTICOLO\nGROUP BY edp.ID_EVENTO, a.COD_ARTICOLO\n</code></pre>"},{"location":"views/GET_COSTO_CATEG_EVT/","title":"GET_COSTO_CATEG_EVT","text":""},{"location":"views/GET_COSTO_CATEG_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER COD_CATEG VARCHAR2(10) NUMERO NUMBER COSTO_UNI NUMBER COSTO NUMBER COSTO_IVATO NUMBER"},{"location":"views/GET_COSTO_CATEG_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_COSTO_CATEG_EVT AS\nSELECT\nedp.ID_EVENTO,\ntcc.COD_CATEG,\nsum(ca.numero) as numero,\nsum(ca.costo_uni) as costo_uni,\nSUM(ca.costo_calc) AS costo,\nSUM(ca.costo_calc_iva) AS costo_ivato\nFROM EVENTI e \njoin EVENTI_DET_OSPITI edoa on edoa.id_evento = e.id and edoa.cod_tipo_ospite = 8 -- adulti\nJOIN EVENTI_DET_PREL edp ON edp.ID_EVENTO = e.ID\nJOIN ARTICOLI a ON a.COD_ARTICOLO = edp.COD_ARTICOLO\nJOIN TB_CODICI_CATEG tcc ON tcc.COD_CATEG = a.COD_CATEG\nJOIN TB_TIPI_MAT ttm ON ttm.COD_TIPO = tcc.COD_TIPO\nLEFT JOIN GET_COSTO_ART_BY_EVT ca ON ca.COD_ARTICOLO = a.COD_ARTICOLO AND ca.id_evento = e.id\nLEFT JOIN GET_ULTIMI_COSTI guc ON guc.COD_ARTICOLO = a.COD_ARTICOLO\nWHERE ttm.COD_TIPO = 'SP'\nGROUP BY edp.ID_EVENTO, tcc.COD_CATEG\n</code></pre>"},{"location":"views/GET_COSTO_DEGUS_EVT/","title":"GET_COSTO_DEGUS_EVT","text":""},{"location":"views/GET_COSTO_DEGUS_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER COSTO NUMBER NUMERO NUMBER"},{"location":"views/GET_COSTO_DEGUS_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_COSTO_DEGUS_EVT AS\nselect \"ID_EVENTO\",\"COSTO\",\"NUMERO\" from (\n SELECT\n edd.ID_EVENTO,\n --SUM(nvl(n_paganti, 0)*NVL(edd.COSTO_DEGUSTAZIONE, 0)) AS costo,\n --sum(nvl(n_paganti, 0)) as numero\n SUM(2*NVL(edd.COSTO_DEGUSTAZIONE, 0)) AS costo,\n sum(2) as numero\n FROM EVENTI e\n JOIN EVENTI_DET_DEGUST edd ON edd.ID_EVENTO = e.ID\n JOIN TB_TIPI_MAT ttm ON ttm.COD_TIPO = 'DEGUS'\n WHERE ttm.COD_TIPO = 'DEGUS'\n and edd.detraibile = 1\n GROUP BY edd.ID_EVENTO\n)\nwhere costo &gt; 0\n</code></pre>"},{"location":"views/GET_COSTO_OSPITI_EVT/","title":"GET_COSTO_OSPITI_EVT","text":""},{"location":"views/GET_COSTO_OSPITI_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER NUMERO NUMBER COSTO NUMBER"},{"location":"views/GET_COSTO_OSPITI_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_COSTO_OSPITI_EVT AS\nSELECT edr.ID_EVENTO, sum(edr.numero) as numero, SUM(edr.numero * (edr.COSTO - (edr.COSTO*(edr.sconto/100)))) AS costo\nFROM EVENTI_DET_OSPITI edr\nGROUP BY edr.ID_EVENTO\n</code></pre>"},{"location":"views/GET_COSTO_RIS_EVT/","title":"GET_COSTO_RIS_EVT","text":""},{"location":"views/GET_COSTO_RIS_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER COSTO NUMBER"},{"location":"views/GET_COSTO_RIS_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_COSTO_RIS_EVT AS\nSELECT edr.ID_EVENTO, SUM(edr.COSTO) AS costo\nFROM EVENTI_DET_RIS edr\nGROUP BY edr.ID_EVENTO\n</code></pre>"},{"location":"views/GET_COSTO_TIPI_EVT/","title":"GET_COSTO_TIPI_EVT","text":""},{"location":"views/GET_COSTO_TIPI_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER COD_TIPO VARCHAR2(10) NUMERO NUMBER COSTO_UNI NUMBER COSTO NUMBER COSTO_IVATO NUMBER"},{"location":"views/GET_COSTO_TIPI_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_COSTO_TIPI_EVT AS\nSELECT\nedp.ID_EVENTO,\nttm.COD_TIPO,\nsum(ca.numero) as numero,\nsum(ca.costo_uni) as costo_uni,\nSUM(ca.costo_calc) AS costo,\nSUM(ca.costo_calc_iva) AS costo_ivato\nFROM EVENTI e \njoin EVENTI_DET_OSPITI edoa on edoa.id_evento = e.id and edoa.cod_tipo_ospite = 8 -- adulti\nJOIN EVENTI_DET_PREL edp ON edp.ID_EVENTO = e.ID\nJOIN ARTICOLI a ON a.COD_ARTICOLO = edp.COD_ARTICOLO\nJOIN TB_CODICI_CATEG tcc ON tcc.COD_CATEG = a.COD_CATEG\nJOIN TB_TIPI_MAT ttm ON ttm.COD_TIPO = tcc.COD_TIPO\nLEFT JOIN GET_COSTO_ART_BY_EVT ca ON ca.COD_ARTICOLO = a.COD_ARTICOLO AND ca.id_evento = e.id\nLEFT JOIN GET_ULTIMI_COSTI guc ON guc.COD_ARTICOLO = a.COD_ARTICOLO\nGROUP BY edp.ID_EVENTO, ttm.COD_TIPO\n</code></pre>"},{"location":"views/GET_EVENTI_DA_PAGARE_ENTRO_65GG/","title":"GET_EVENTI_DA_PAGARE_ENTRO_65GG","text":""},{"location":"views/GET_EVENTI_DA_PAGARE_ENTRO_65GG/#colonne","title":"Colonne","text":"Colonna Tipo ID NUMBER CLIENTE VARCHAR2(100) DATA DATE LOCATION VARCHAR2(200) DESCRIZIONE_TIPO_EVENTO VARCHAR2(100) STATO NUMBER TOTALE_CAPARRE_DOVUTE NUMBER TOTALE_VERSATO NUMBER"},{"location":"views/GET_EVENTI_DA_PAGARE_ENTRO_65GG/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_EVENTI_DA_PAGARE_ENTRO_65GG AS\nSELECT\n e.ID,\n e.CLIENTE,\n e.DATA,\n loc.LOCATION, -- Campo aggiornato per mostrare il nome della location\n te.DESCRIZIONE AS DESCRIZIONE_TIPO_EVENTO,\n e.STATO,\n NVL(caparre.TOTALE_DOVUTO, 0) AS TOTALE_CAPARRE_DOVUTE,\n NVL(pagamenti.TOTALE_PAGATO, 0) AS TOTALE_VERSATO\nFROM\n EVENTI e\nLEFT JOIN\n TB_TIPI_EVENTO te ON e.COD_TIPO = te.COD_TIPO\nLEFT JOIN\n LOCATION loc ON e.ID_LOCATION = loc.ID -- JOIN aggiunta per la tabella LOCATION\nLEFT JOIN\n (\n -- Calcola il totale dovuto per la prima e seconda caparra (importi positivi)\n SELECT\n ID_EVENTO,\n SUM(ACCONTO) AS TOTALE_DOVUTO\n FROM\n EVENTI_ACCONTI\n WHERE\n ORDINE IN (10, 20)\n GROUP BY\n ID_EVENTO\n ) caparre ON e.ID = caparre.ID_EVENTO\nLEFT JOIN\n (\n -- Calcola il totale versato, invertendo il segno della somma (gli importi sono negativi)\n SELECT\n ID_EVENTO,\n SUM(ACCONTO) * -1 AS TOTALE_PAGATO\n FROM\n EVENTI_ACCONTI\n WHERE\n ORDINE &gt;= 1000\n GROUP BY\n ID_EVENTO\n ) pagamenti ON e.ID = pagamenti.ID_EVENTO\nWHERE\n -- Lo stato deve essere 'Scheda Confermata'\n e.STATO = 300\n -- Filtra per eventi futuri entro 65 giorni\n AND e.DATA BETWEEN SYSDATE AND SYSDATE + 65\n\n -- ====================================================================================\n -- CONDIZIONE DI PAGAMENTO CON TOLLERANZA\n AND NVL(pagamenti.TOTALE_PAGATO, 0) &lt; (NVL(caparre.TOTALE_DOVUTO, 0) * (1 - /* TOLLERANZA */ 10 /* % */ / 100))\n -- ====================================================================================\n\n -- Assicuriamoci di considerare solo eventi per cui \u00e8 richiesta almeno una caparra\n AND caparre.TOTALE_DOVUTO IS NOT NULL AND caparre.TOTALE_DOVUTO &gt; 0\nORDER BY\n e.DATA\n</code></pre>"},{"location":"views/GET_EVT_DATA/","title":"GET_EVT_DATA","text":""},{"location":"views/GET_EVT_DATA/#colonne","title":"Colonne","text":"Colonna Tipo ID NUMBER DESCRIZIONE VARCHAR2(4000) COD_TIPO VARCHAR2(10) CLIENTE VARCHAR2(100) INDIRIZZO VARCHAR2(200) DATA DATE DATA_CHAR VARCHAR2(10) TOT_OSPITI NUMBER STATO NUMBER TORTA_A VARCHAR2(4000) NOTE VARCHAR2(4000) DATA_DOC DATE APX_USER VARCHAR2(20) ID_CLIENTE NUMBER ID_LOCATION NUMBER FLG_TEMPLATE NUMBER ORA_CERIMONIA DATE ORA_EVENTO DATE PERC_SEDUTE_APER NUMBER CONFETTATA_A VARCHAR2(4000) STAMPA_MENU VARCHAR2(100) ALLERGIE VARCHAR2(4000) EXTRA_INFO VARCHAR2(1000) EXTRA_COSTI VARCHAR2(1000) NUM_LISTA NUMBER DISTANZA_LOCATION VARCHAR2(1000) PRIMI VARCHAR2(4000) SECONDI VARCHAR2(4000) VINI VARCHAR2(4000) CARICOSPOSI VARCHAR2(4000) CARICOAPOLL VARCHAR2(4000) STILE_COLORI VARCHAR2(255) ALLEST_BUFF VARCHAR2(4000) GIRO_BRACCIO VARCHAR2(255) GRAN_BUFFET_A VARCHAR2(4000) SERVIZIO_TAVOLO_A VARCHAR2(4000) BUFFET_DOLCI_A VARCHAR2(4000) CLIENTE_TEL VARCHAR2(255) CLIENTE_EMAIL VARCHAR2(255) REFERENTE_TEL VARCHAR2(255) BUFFET_INIZIALE VARCHAR2(4000) BUFFET_FINALE VARCHAR2(4000) TIPOL_TAV_SPOSI VARCHAR2(255) TIPOL_TAV_OSPITI VARCHAR2(255) SEDIA VARCHAR2(255) TOVAGLIA VARCHAR2(255) TOVAGLIOLO VARCHAR2(255) RUNNER VARCHAR2(255) SOTTOPIATTI VARCHAR2(255) PIATTINO_PANE VARCHAR2(255) POSATE VARCHAR2(255) BICCHIERI VARCHAR2(255) NUM_FLORIST VARCHAR2(255) NUM_MUSICISTI VARCHAR2(255) NUM_FOTOGRAFI VARCHAR2(255) NUM_ALTRI VARCHAR2(4000) BUFFET VARCHAR2(255) BUFFET_SEDIE VARCHAR2(255) BUFFET_TAVOLI VARCHAR2(255) CONFETTATA_B VARCHAR2(4000) GRAN_BUFFET_B VARCHAR2(4000) SERVIZIO_TAVOLO_B VARCHAR2(4000) BUFFET_DOLCI_B VARCHAR2(4000) TORTA_B VARCHAR2(4000) TORTA VARCHAR2(4000) CONFETTATA VARCHAR2(4000) ALTRO VARCHAR2(4000) FLG_SUPERATO NUMBER DATA_SCAD_PREVENTIVO DATE PIATTI VARCHAR2(4000) NOTE_INVIO VARCHAR2(1000) PRE_BOUV_A VARCHAR2(4000) PRE_BOUV_B VARCHAR2(4000) ALTRO_A VARCHAR2(4000) ALTRO_B VARCHAR2(4000) DATORASCARICO DATE DATORASCARICO_NOTE VARCHAR2(4000) IS_TEMPLATE NUMBER ID_EVT_PADRE NUMBER ID_EVT_FIGLIO NUMBER LOCATION VARCHAR2(200) TIPO_PASTO VARCHAR2(6) DESCRIZIONE_TIPO VARCHAR2(100)"},{"location":"views/GET_EVT_DATA/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_EVT_DATA AS\nselect\ne.ID,\ne.DESCRIZIONE,\ne.COD_TIPO,\ne.CLIENTE,\ne.INDIRIZZO,\ne.data,\nto_char(e.DATA, 'dd-mm-yyyy') as data_char,\ne.TOT_OSPITI,\ne.STATO,\ne.TORTA_A,\ne.NOTE,\ne.DATA_DOC,\ne.APX_USER,\ne.ID_CLIENTE,\ne.ID_LOCATION,\ne.FLG_TEMPLATE,\ne.ORA_CERIMONIA,\ne.ORA_EVENTO,\ne.PERC_SEDUTE_APER,\ne.CONFETTATA_A,\ne.STAMPA_MENU,\ne.ALLERGIE,\ne.EXTRA_INFO,\ne.EXTRA_COSTI,\ne.NUM_LISTA,\ne.DISTANZA_LOCATION,\ne.PRIMI,\ne.SECONDI,\ne.VINI,\ne.CARICOSPOSI,\ne.CARICOAPOLL,\ne.STILE_COLORI,\ne.ALLEST_BUFF,\ne.GIRO_BRACCIO,\ne.GRAN_BUFFET_A,\ne.SERVIZIO_TAVOLO_A,\ne.BUFFET_DOLCI_A,\ne.CLIENTE_TEL,\ne.CLIENTE_EMAIL,\ne.REFERENTE_TEL,\ne.BUFFET_INIZIALE,\ne.BUFFET_FINALE,\ne.TIPOL_TAV_SPOSI,\ne.TIPOL_TAV_OSPITI,\ne.SEDIA,\ne.TOVAGLIA,\ne.TOVAGLIOLO,\ne.RUNNER,\ne.SOTTOPIATTI,\ne.PIATTINO_PANE,\ne.POSATE,\ne.BICCHIERI,\ne.NUM_FLORIST,\ne.NUM_MUSICISTI,\ne.NUM_FOTOGRAFI,\ne.NUM_ALTRI,\ne.BUFFET,\ne.BUFFET_SEDIE,\ne.BUFFET_TAVOLI,\ne.CONFETTATA_B,\ne.GRAN_BUFFET_B,\ne.SERVIZIO_TAVOLO_B,\ne.BUFFET_DOLCI_B,\ne.TORTA_B,\ne.TORTA,\ne.CONFETTATA,\ne.ALTRO,\ne.FLG_SUPERATO,\ne.DATA_SCAD_PREVENTIVO,\ne.PIATTI,\ne.NOTE_INVIO,\ne.PRE_BOUV_A,\ne.PRE_BOUV_B,\ne.ALTRO_A,\ne.ALTRO_B,\ne.DATORASCARICO,\ne.DATORASCARICO_NOTE,\ne.IS_TEMPLATE,\ne.ID_EVT_PADRE,\ne.ID_EVT_FIGLIO,\nl.location,\ndecode(p.tipo_pasto, 'C', 'Cena', 'P', 'Pranzo', 'Altro') as tipo_pasto,\np.descrizione as descrizione_tipo\nfrom eventi e\nleft join location l on e.id_location = l.id\nleft join tb_tipi_evento p on p.cod_tipo = e.cod_tipo\n</code></pre>"},{"location":"views/GET_EVT_DATA_PRINT/","title":"GET_EVT_DATA_PRINT","text":""},{"location":"views/GET_EVT_DATA_PRINT/#colonne","title":"Colonne","text":"Colonna Tipo ID NUMBER DESCRIZIONE VARCHAR2(4000) COD_TIPO VARCHAR2(10) CLIENTE VARCHAR2(100) INDIRIZZO VARCHAR2(200) DATA DATE DATA_CHAR VARCHAR2(10) TOT_OSPITI NUMBER STATO NUMBER TORTA_A VARCHAR2(4000) NOTE VARCHAR2(4000) DATA_DOC DATE APX_USER VARCHAR2(20) ID_CLIENTE NUMBER ID_LOCATION NUMBER FLG_TEMPLATE NUMBER ORA_CERIMONIA DATE ORA_EVENTO DATE PERC_SEDUTE_APER NUMBER CONFETTATA_A VARCHAR2(4000) STAMPA_MENU VARCHAR2(100) ALLERGIE VARCHAR2(4000) EXTRA_INFO VARCHAR2(1000) EXTRA_COSTI VARCHAR2(1000) NUM_LISTA NUMBER DISTANZA_LOCATION VARCHAR2(1000) PRIMI VARCHAR2(4000) SECONDI VARCHAR2(4000) VINI VARCHAR2(4000) CARICOSPOSI VARCHAR2(4000) CARICOAPOLL VARCHAR2(4000) STILE_COLORI VARCHAR2(255) ALLEST_BUFF VARCHAR2(4000) GIRO_BRACCIO VARCHAR2(255) GRAN_BUFFET_A VARCHAR2(4000) SERVIZIO_TAVOLO_A VARCHAR2(4000) BUFFET_DOLCI_A VARCHAR2(4000) CLIENTE_TEL VARCHAR2(255) CLIENTE_EMAIL VARCHAR2(255) REFERENTE_TEL VARCHAR2(255) BUFFET_INIZIALE VARCHAR2(4000) BUFFET_FINALE VARCHAR2(4000) TIPOL_TAV_SPOSI VARCHAR2(255) TIPOL_TAV_OSPITI VARCHAR2(255) SEDIA VARCHAR2(255) TOVAGLIA VARCHAR2(255) TOVAGLIOLO VARCHAR2(255) RUNNER VARCHAR2(255) SOTTOPIATTI VARCHAR2(255) PIATTINO_PANE VARCHAR2(255) POSATE VARCHAR2(255) BICCHIERI VARCHAR2(255) NUM_FLORIST VARCHAR2(255) NUM_MUSICISTI VARCHAR2(255) NUM_FOTOGRAFI VARCHAR2(255) NUM_ALTRI VARCHAR2(4000) BUFFET VARCHAR2(255) BUFFET_SEDIE VARCHAR2(255) BUFFET_TAVOLI VARCHAR2(255) CONFETTATA_B VARCHAR2(4000) GRAN_BUFFET_B VARCHAR2(4000) SERVIZIO_TAVOLO_B VARCHAR2(4000) BUFFET_DOLCI_B VARCHAR2(4000) TORTA_B VARCHAR2(4000) TORTA VARCHAR2(4000) CONFETTATA VARCHAR2(4000) ALTRO VARCHAR2(4000) FLG_SUPERATO NUMBER DATA_SCAD_PREVENTIVO DATE PIATTI VARCHAR2(4000) NOTE_INVIO VARCHAR2(1000) PRE_BOUV_A VARCHAR2(4000) PRE_BOUV_B VARCHAR2(4000) ALTRO_A VARCHAR2(4000) ALTRO_B VARCHAR2(4000) DATORASCARICO DATE DATORASCARICO_NOTE VARCHAR2(4000) IS_TEMPLATE NUMBER ID_EVT_PADRE NUMBER ID_EVT_FIGLIO NUMBER LOCATION VARCHAR2(200) TIPO_PASTO VARCHAR2(6) DESCRIZIONE_TIPO VARCHAR2(100) PRELIEVO_ANGOLI_INIZIALI VARCHAR2(4000) PRELIEVO_ANGOLI_FINALI VARCHAR2(4000) PRELIEVO_SERVIZIO_TAVOLA VARCHAR2(4000) PRELIEVO_VINI VARCHAR2(4000)"},{"location":"views/GET_EVT_DATA_PRINT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_EVT_DATA_PRINT AS\nselect e.\"ID\",e.\"DESCRIZIONE\",e.\"COD_TIPO\",e.\"CLIENTE\",e.\"INDIRIZZO\",e.\"DATA\",e.\"DATA_CHAR\",e.\"TOT_OSPITI\",e.\"STATO\",e.\"TORTA_A\",e.\"NOTE\",e.\"DATA_DOC\",e.\"APX_USER\",e.\"ID_CLIENTE\",e.\"ID_LOCATION\",e.\"FLG_TEMPLATE\",e.\"ORA_CERIMONIA\",e.\"ORA_EVENTO\",e.\"PERC_SEDUTE_APER\",e.\"CONFETTATA_A\",e.\"STAMPA_MENU\",e.\"ALLERGIE\",e.\"EXTRA_INFO\",e.\"EXTRA_COSTI\",e.\"NUM_LISTA\",e.\"DISTANZA_LOCATION\",e.\"PRIMI\",e.\"SECONDI\",e.\"VINI\",e.\"CARICOSPOSI\",e.\"CARICOAPOLL\",e.\"STILE_COLORI\",e.\"ALLEST_BUFF\",e.\"GIRO_BRACCIO\",e.\"GRAN_BUFFET_A\",e.\"SERVIZIO_TAVOLO_A\",e.\"BUFFET_DOLCI_A\",e.\"CLIENTE_TEL\",e.\"CLIENTE_EMAIL\",e.\"REFERENTE_TEL\",e.\"BUFFET_INIZIALE\",e.\"BUFFET_FINALE\",e.\"TIPOL_TAV_SPOSI\",e.\"TIPOL_TAV_OSPITI\",e.\"SEDIA\",e.\"TOVAGLIA\",e.\"TOVAGLIOLO\",e.\"RUNNER\",e.\"SOTTOPIATTI\",e.\"PIATTINO_PANE\",e.\"POSATE\",e.\"BICCHIERI\",e.\"NUM_FLORIST\",e.\"NUM_MUSICISTI\",e.\"NUM_FOTOGRAFI\",e.\"NUM_ALTRI\",e.\"BUFFET\",e.\"BUFFET_SEDIE\",e.\"BUFFET_TAVOLI\",e.\"CONFETTATA_B\",e.\"GRAN_BUFFET_B\",e.\"SERVIZIO_TAVOLO_B\",e.\"BUFFET_DOLCI_B\",e.\"TORTA_B\",e.\"TORTA\",e.\"CONFETTATA\",e.\"ALTRO\",e.\"FLG_SUPERATO\",e.\"DATA_SCAD_PREVENTIVO\",e.\"PIATTI\",e.\"NOTE_INVIO\",e.\"PRE_BOUV_A\",e.\"PRE_BOUV_B\",e.\"ALTRO_A\",e.\"ALTRO_B\",e.\"DATORASCARICO\",e.\"DATORASCARICO_NOTE\",e.\"IS_TEMPLATE\",e.\"ID_EVT_PADRE\",e.\"ID_EVT_FIGLIO\",e.\"LOCATION\",e.\"TIPO_PASTO\",e.\"DESCRIZIONE_TIPO\",\n(select LISTAGG('\u2022 ' || g.descrizione_articolo, chr(13)) WITHIN GROUP (ORDER BY g.ordine ASC) from get_prel_by_evt g where g.id_evento = e.id and g.cod_tipo = 'AN') as prelievo_angoli_iniziali,\n(select LISTAGG('\u2022 ' || g.descrizione_articolo, chr(13)) WITHIN GROUP (ORDER BY g.ordine ASC) from get_prel_by_evt g where g.id_evento = e.id and g.cod_tipo = 'ANG-FIN') as prelievo_angoli_finali,\n(select LISTAGG('\u2022 ' || g.descrizione_articolo, chr(13)) WITHIN GROUP (ORDER BY g.ordine ASC) from get_prel_by_evt g where g.id_evento = e.id and g.cod_tipo = 'MENU') as prelievo_servizio_tavola,\n(select LISTAGG('\u2022 ' || g.descrizione_articolo, chr(13)) WITHIN GROUP (ORDER BY g.ordine ASC) from get_prel_by_evt g where g.id_evento = e.id and g.cod_tipo = 'BEV SED') as prelievo_vini\nfrom get_evt_data e\nleft join location l on e.id_location = l.id\n</code></pre>"},{"location":"views/GET_GESTORI_USERS/","title":"GET_GESTORI_USERS","text":""},{"location":"views/GET_GESTORI_USERS/#colonne","title":"Colonne","text":"Colonna Tipo USERS VARCHAR2(4000)"},{"location":"views/GET_GESTORI_USERS/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_GESTORI_USERS AS\nselect result as users from table(string_to_table_enum(get_param_value('PERMES_GESTORI'), 0, ':'))\n</code></pre>"},{"location":"views/GET_PREL_ART_TOT/","title":"GET_PREL_ART_TOT","text":""},{"location":"views/GET_PREL_ART_TOT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER ID NUMBER COD_ARTICOLO VARCHAR2(10) QTA NUMBER NOTE VARCHAR2(4000) QTA_APE NUMBER QTA_SEDU NUMBER QTA_BUFDOL NUMBER QTA_MAN_APE NUMBER QTA_MAN_SEDU NUMBER QTA_MAN_BUFDOL NUMBER COSTO_ARTICOLO NUMBER PERC_OSPITI NUMBER QTA_STD_PREL_TOT NUMBER QTA_COEFF_PREL_TOT NUMBER QTA_PREC_PREL_TOT NUMBER"},{"location":"views/GET_PREL_ART_TOT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_PREL_ART_TOT AS\nselect p.\"ID_EVENTO\",p.\"ID\",p.\"COD_ARTICOLO\",p.\"QTA\",p.\"NOTE\",p.\"QTA_APE\",p.\"QTA_SEDU\",p.\"QTA_BUFDOL\",p.\"QTA_MAN_APE\",p.\"QTA_MAN_SEDU\",p.\"QTA_MAN_BUFDOL\",p.\"COSTO_ARTICOLO\",p.\"PERC_OSPITI\",\np.QTA_APE + p.QTA_SEDU + p.QTA_BUFDOL + p.QTA_MAN_APE + p.QTA_MAN_SEDU + p.QTA_MAN_BUFDOL as qta_std_prel_tot,\np.QTA_APE*nvl(a.coeff_a, 1) + p.QTA_SEDU*nvl(a.coeff_s, 1) + p.QTA_BUFDOL*nvl(a.coeff_b, 1) + p.QTA_MAN_APE*nvl(a.coeff_a, 1) + p.QTA_MAN_SEDU*nvl(a.coeff_s, 1) + p.QTA_MAN_BUFDOL*nvl(a.coeff_b, 1) as qta_coeff_prel_tot,\nnvl(d.numero, 1)*nvl(nvl2(p.perc_ospiti, p.perc_ospiti/100, a.perc_ospiti/100), 0) as qta_prec_prel_tot\nfrom eventi_det_prel p\njoin articoli a on p.cod_articolo = a.cod_articolo\njoin EVENTI_DET_OSPITI d on d.id_evento = p.id_evento and d.cod_tipo_ospite = 8\n</code></pre>"},{"location":"views/GET_PREL_BY_EVT/","title":"GET_PREL_BY_EVT","text":""},{"location":"views/GET_PREL_BY_EVT/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER COD_TIPO VARCHAR2(10) DESCRIZIONE_TIPO VARCHAR2(1000) COD_CATEG VARCHAR2(10) DESCRIZIONE_CATEGORIA VARCHAR2(1000) COD_RELATIVO VARCHAR2(10) COD_ARTICOLO VARCHAR2(10) DESCRIZIONE_ARTICOLO VARCHAR2(4000) ORDINE NUMBER"},{"location":"views/GET_PREL_BY_EVT/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_PREL_BY_EVT AS\nselect\ne.id as id_evento,\nm.cod_tipo,\nm.descrizione as descrizione_tipo,\na.cod_categ,\ng.descrizione as descrizione_categoria,\na.cod_relativo,\na.cod_articolo,\ntrim(a.descrizione) || ' - ' || trim(d.note) as descrizione_articolo,\nd.ordine\nfrom eventi e\njoin eventi_det_prel d on e.id = d.id_evento\njoin articoli a on a.cod_articolo = d.cod_articolo\njoin tb_codici_categ g on g.cod_categ = a.cod_categ\njoin tb_tipi_mat m on m.cod_tipo = g.cod_tipo\nwhere g.show_print = 1\norder by d.ordine\n</code></pre>"},{"location":"views/GET_REPORT_CONSUNTIVO_PER_DATA/","title":"GET_REPORT_CONSUNTIVO_PER_DATA","text":""},{"location":"views/GET_REPORT_CONSUNTIVO_PER_DATA/#colonne","title":"Colonne","text":"Colonna Tipo ORDINE NUMBER ID NUMBER DATA DATE TIPO VARCHAR2(4000) NUMERO NUMBER COSTO NUMBER SCONTO NUMBER PERCIVA NUMBER TOTALE NUMBER IVA NUMBER TOTALE_IVATO NUMBER"},{"location":"views/GET_REPORT_CONSUNTIVO_PER_DATA/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_REPORT_CONSUNTIVO_PER_DATA AS\nselect\nedo.ordine,\ne.id,\ne.data,\nnvl2(edo.note, tto.descrizione || ': ' || edo.note, tto.descrizione) as tipo,\nnullif(edo.numero, 0) as numero,\nnullif(edo.costo, 0) as costo,\nnullif(edo.sconto, 0) as sconto,\nnullif(case when edo.numero &gt; 0 then 0.10 else 0 end, 0) as perciva,\nnullif(edo.numero * (edo.COSTO - (edo.COSTO*(edo.sconto/100))), 0) as totale,\nnullif((edo.numero * (edo.COSTO - (edo.COSTO*(edo.sconto/100))) * 0.10), 0) as iva,\nedo.numero * (edo.COSTO - (edo.COSTO*(edo.sconto/100))) + (edo.numero * (edo.COSTO - (edo.COSTO*(edo.sconto/100))) * 0.10) as totale_ivato\nfrom eventi e\nleft join eventi_det_ospiti edo on edo.id_evento = e.id\nleft join tb_tipi_ospiti tto on tto.cod_tipo = edo.cod_tipo_ospite\nwhere edo.ordine != 3\n\nunion all\n\nselect\nrownum+49 as ordine,\ne.id_evento as id,\nd.data,\n'Degustazioni effettuate' as tipo,\nnullif(numero, 0) as numero,\nnullif(costo, 0) as costo,\nnull as sconto,\nnull as perciva,\nnullif(costo*-1, 0) as totale,\nnull as iva,\ncosto*-1 as totale_ivato\nfrom get_costo_degus_evt e\njoin eventi d on d.id = e.id_evento\n\nunion all\n\nselect rownum+99 as ordine, t.\"ID\",t.\"DATA\",t.\"TIPO\",t.\"NUMERO\",t.\"COSTO\",t.\"SCONTO\",t.\"PERCIVA\",t.\"TOTALE\",t.\"IVA\",t.\"TOTALE_IVATO\" from (\n select\n e.id_evento as id,\n d.data,\n replace(REGEXP_REPLACE(replace(a.descrizione, ' ', '_'), '[^0-9A-Za-z_()]', ''), '_', ' ') as tipo,\n nullif(e.numero, 0) as numero,\n nullif(e.costo_uni, 0) as costo,\n null as sconto,\n nullif(case when e.COSTO &gt; 0 then (a.perc_iva/100) else 0 end, 0) as perciva,\n nullif(e.COSTO, 0) as totale,\n nullif(case when e.COSTO &gt; 0 then e.COSTO_IVATO - e.COSTO else 0 end, 0) as iva,\n nullif(case when e.COSTO &gt; 0 then e.COSTO_IVATO else 0 end, 0) as totale_ivato\n from get_costo_art_evt e\n join articoli a on e.cod_articolo = a.cod_articolo\n join EVENTI_DET_OSPITI edoa on edoa.id_evento = e.id_evento and edoa.cod_tipo_ospite = 8\n join tb_codici_categ g on g.cod_categ = a.cod_categ\n join eventi d on d.id = e.id_evento\n where nvl(e.COSTO, 0) &gt; 0\n and g.show_print = 1\n\n union all\n\n select\n e.id_evento as id,\n d.data,\n 'Altri Articoli (dettaglio a pagina 3)' as tipo,\n null as numero,\n null as costo,\n null as sconto,\n null as perciva,\n nullif(sum(e.COSTO), 0) as totale,\n nullif(sum(case when e.COSTO &gt; 0 then e.COSTO_IVATO - e.COSTO else 0 end), 0) as iva,\n nullif(sum(case when e.COSTO &gt; 0 then e.COSTO_IVATO else 0 end), 0) as totale_ivato\n from get_costo_art_evt e\n join articoli a on e.cod_articolo = a.cod_articolo\n join EVENTI_DET_OSPITI edoa on edoa.id_evento = e.id_evento and edoa.cod_tipo_ospite = 8\n join tb_codici_categ g on g.cod_categ = a.cod_categ\n join eventi d on d.id = e.id_evento\n where nvl(e.COSTO, 0) &gt; 0\n and g.show_print = 0\n group by 'Altri Articoli', e.id_evento, d.data, 0, 0, 0, 0\n) t\n\nunion all\n\nselect\nea.ordine+199 as ordine,\ne.id,\ne.data,\nea.descrizione as tipo,\nea.quantity as numero,\nnullif(ea.costo, 0) as costo,\nnull as sconto,\nnullif(case when ea.costo &gt; 0 then 0.1 else 0 end, 0) as perciva,\nnullif(ea.costo * ea.quantity, 0) as totale,\nnullif(case when ea.COSTO &gt; 0 then (ea.costo * ea.quantity) * 0.10 else 0 end, 0) as iva,\nnullif(case when ea.COSTO &gt; 0 then (ea.costo * ea.quantity) + ((ea.costo * ea.quantity) * 0.10) else (ea.costo * ea.quantity) end, 0) as totale_ivato\nfrom eventi e\nleft join eventi_altricosti ea on ea.id_evento = e.id\nwhere ea.costo is not null\norder by 1\n</code></pre>"},{"location":"views/GET_ULTIMI_COSTI/","title":"GET_ULTIMI_COSTI","text":""},{"location":"views/GET_ULTIMI_COSTI/#colonne","title":"Colonne","text":"Colonna Tipo COD_ARTICOLO VARCHAR2(10) COSTO_UNI NUMBER"},{"location":"views/GET_ULTIMI_COSTI/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_ULTIMI_COSTI AS\nSELECT a.COD_ARTICOLO, a.costo_uni\nFROM COSTI_ARTICOLI a\nWHERE a.DATA_COSTO = (SELECT max(b.DATA_COSTO) FROM COSTI_ARTICOLI b where b.cod_articolo = a.cod_articolo)\n</code></pre>"},{"location":"views/GET_USERS_LIST/","title":"GET_USERS_LIST","text":""},{"location":"views/GET_USERS_LIST/#colonne","title":"Colonne","text":"Colonna Tipo USERS VARCHAR2(100)"},{"location":"views/GET_USERS_LIST/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW GET_USERS_LIST AS\nselect user_name as users\nfrom APEX_WORKSPACE_APEX_USERS\nwhere workspace_name = USER\n</code></pre>"},{"location":"views/VW_CALENDARIO_EVENTI/","title":"VW_CALENDARIO_EVENTI","text":""},{"location":"views/VW_CALENDARIO_EVENTI/#colonne","title":"Colonne","text":"Colonna Tipo WEEK VARCHAR2(2) GIORNO VARCHAR2(1) DATA DATE DESCRI VARCHAR2(294) ID NUMBER STATUS VARCHAR2(28) COLOR CHAR(7) CSS_CLASS VARCHAR2(47) STATO NUMBER LOCATION VARCHAR2(200)"},{"location":"views/VW_CALENDARIO_EVENTI/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW VW_CALENDARIO_EVENTI AS\nselect to_char(data,'IW') week,to_char(data,'d', 'NLS_DATE_LANGUAGE = italian') giorno, \n e.data,\n -- Daniele Trombettoni 15/03/2020\n -- Conteggio eventi giornalieri e stato \n (case when F_EVENTO_SCADUTO(e.data_scad_preventivo, e.stato, 0, 299) = 1 then '!!! ' end) || ROW_NUMBER() OVER (PARTITION BY e.data, e.stato ORDER BY e.id )|| ') ' || (case when e.contratto_firmato = 0 and e.stato &gt;= 300 then '* ' else '' end) || l.LOCATION || ' Os:'|| F_GET_TOT_OSPITI(e.id, 8) ||(case when tp.TIPO_PASTO is not null then '/' else null end)|| tp.TIPO_PASTO descri, \n --l.LOCATION descri,\n e.id,\n c.status,\n -- Daniele Viti 18/01/2020\n -- Aggiunto il controllo sul numero di eventi massimi per giorno\n -- 20200315 - disattivo temporaneamente il cambio di colore rosso \n --case when (select count(*) from eventi ev where ev.data = e.data) &gt; 7 then '#ff2e2e' else c.color end as color\n c.color as color,\n case c.STATUS\n when 'Scheda Quasi Confermata'\n then 'apex-cal-SchedaQuasiConfermata' || (case when F_EVENTO_SCADUTO(e.data_scad_preventivo, e.stato, 0, 299) = 1 then ' apex-cal-Scaduto' end)\n when 'Scheda Confermata'\n then 'apex-cal-SchedaConfermata' || (case when F_EVENTO_SCADUTO(e.data_scad_preventivo, e.stato, 0, 299) = 1 then ' apex-cal-Scaduto' end)\n when 'Preventivo'\n then 'apex-cal-Preventivo' || (case when F_EVENTO_SCADUTO(e.data_scad_preventivo, e.stato, 0, 299) = 1 then ' apex-cal-Scaduto' end)\n when 'Scheda Evento (preparazione)'\n then 'apex-cal-Preparazione'\n when 'Confermato'\n then 'apex-cal-Confermato'\n end as css_class,\n e.stato,\n l.LOCATION\nfrom eventi e\nleft join tb_tipi_evento tp on tp.cod_tipo = e.cod_tipo\nleft join location l on e.id_location = l.id\nleft join vw_event_color c on e.id = c.id\n-- 20200315 - escludo nn accettato/superato\nwhere e.stato != 900 \nand disabled = 0\nand nvl(is_template, 0) = 0\nand e.ID_EVT_FIGLIO is null\nand deleted = 0\norder by e.stato\n</code></pre>"},{"location":"views/VW_EVENTI_STATUSES/","title":"VW_EVENTI_STATUSES","text":""},{"location":"views/VW_EVENTI_STATUSES/#colonne","title":"Colonne","text":"Colonna Tipo STATO NUMBER COLOR CHAR(7) COLOR_SLANG VARCHAR2(7)"},{"location":"views/VW_EVENTI_STATUSES/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW VW_EVENTI_STATUSES AS\nselect distinct e.stato, v.color, v.color_slang\nfrom eventi e\njoin vw_event_color v on v.id = e.id\norder by 1\n</code></pre>"},{"location":"views/VW_EVENT_COLOR/","title":"VW_EVENT_COLOR","text":""},{"location":"views/VW_EVENT_COLOR/#colonne","title":"Colonne","text":"Colonna Tipo ID NUMBER STATUS VARCHAR2(28) COLOR CHAR(7) COLOR_SLANG VARCHAR2(7)"},{"location":"views/VW_EVENT_COLOR/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW VW_EVENT_COLOR AS\nselect e.id ,\n case when e.stato = 900\n then 'Prev non Accettato/Superato'\n when e.stato = 100\n then 'Preventivo' \n when e.stato = 200\n then 'Scheda Evento (preparazione)' \n when e.stato = 300\n then 'Scheda Confermata' \n when e.stato = 350\n then 'Scheda Quasi Confermata' \n when e.stato = 400\n then 'Confermato' \n end as status, \n case when e.stato = 900\n then '#913096'\n when e.stato = 100\n then '#ffffff' \n when e.stato = 200\n then '#CAE3FC' \n when e.stato = 300 \n then '#FFFFB8' \n when e.stato = 350 \n then '#FFCD59' \n when e.stato = 400\n then '#B8FFB8' \n end as color, \n case when e.stato = 900\n then 'viola'\n when e.stato = 100\n then 'bianco' \n when e.stato = 200\n then 'celeste' \n when e.stato = 300 \n then 'giallo' \n when e.stato = 350 \n then 'arancio' \n when e.stato = 400\n then 'verde' \n end as color_slang\n from eventi e\n</code></pre>"},{"location":"views/VW_EVENT_COLOR_OLD/","title":"VW_EVENT_COLOR_OLD","text":""},{"location":"views/VW_EVENT_COLOR_OLD/#colonne","title":"Colonne","text":"Colonna Tipo ID NUMBER STATUS VARCHAR2(28) COLOR CHAR(7)"},{"location":"views/VW_EVENT_COLOR_OLD/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW VW_EVENT_COLOR_OLD AS\nselect e.id ,\n case when e.flg_superato = 1 \n then 'Prev non Accettato/Superato'\n when e.stato = 0 and d.id_evento is null \n then 'Preventivo' \n when e.stato = 0\n then 'Scheda Evento (preparazione)' \n when e.stato = 10 \n then 'Scheda Confermata' \n when e.stato = 20 \n then 'Confermato' \n end as status, \n case when e.flg_superato = 1 \n then '#913096'\n when e.stato = 0 and d.id_evento is null \n then '#ffffff' \n when e.stato = 0\n then '#CAE3FC' \n when e.stato = 10 \n then '#FFFFB8' \n when e.stato = 20 \n then '#B8FFB8' \n end as color\n from eventi e\n left join (select max(data) data_deg , id_evento \n from eventi_det_degust\n group by id_evento\n ) d on e.id = d.id_evento\n</code></pre>"},{"location":"views/VW_REP_DEGUSTAZIONI/","title":"VW_REP_DEGUSTAZIONI","text":""},{"location":"views/VW_REP_DEGUSTAZIONI/#colonne","title":"Colonne","text":"Colonna Tipo ID_EVENTO NUMBER ID NUMBER DATA DATE ORA VARCHAR2(20) NOME VARCHAR2(100) TELEFONO VARCHAR2(255) EMAIL VARCHAR2(255) LOCATION VARCHAR2(200) N_PERSONE NUMBER MENU VARCHAR2(1000) N_PAGANTI NUMBER NOTE VARCHAR2(4000) N_DEGUSTAZIONE NUMBER DES_EVENTO VARCHAR2(407) DATA_EVENTO DATE LOCATION_DEG VARCHAR2(1000) COUNT_RIGA NUMBER STATO NUMBER STATUS VARCHAR2(28) SCADUTO CHAR(2) TIPO_PASTO VARCHAR2(6) DESCRIZIONE_TIPO VARCHAR2(100)"},{"location":"views/VW_REP_DEGUSTAZIONI/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW VW_REP_DEGUSTAZIONI AS\nselect \nd.ID_EVENTO,\nd.ID,\nd.DATA,\nd.ORA,\ne.CLIENTE NOME,\ne.cliente_tel as TELEFONO,\ne.cliente_email as EMAIL,\nl.LOCATION,\nd.N_PERSONE,\nd.MENU,\nd.N_PAGANTI,\nd.NOTE,\nd.N_DEGUSTAZIONE,\ne.data || ' - ' || t.DESCRIZIONE || ' - ' || l.location || ' - ' || substr(cliente,1,20) des_evento,\ne.data as data_evento,\nd.location as location_deg,\n1 AS COUNT_RIGA,\ne.stato as stato,\nc.status,\n case when e.data_scad_preventivo &lt;= trunc(sysdate) \n then CASE WHEN e.stato &gt;= 400 THEN 'NO' ELSE 'SI' END \n else 'NO' \n end scaduto,\ndecode(p.tipo_pasto, 'C', 'Cena', 'P', 'Pranzo', 'Altro') as tipo_pasto,\np.descrizione as descrizione_tipo\nfrom eventi e\nleft join EVENTI_DET_DEGUST d on d.id_evento = e.id\nleft join vw_event_color c on d.id_evento = c.id\nleft join tb_tipi_evento t on e.cod_tipo = t.COD_TIPO\nleft join location l on e.id_location = l.ID\nleft join tb_tipi_evento p on p.cod_tipo = e.cod_tipo\nwhere e.disabled = 0 \n and e.deleted = 0\n and e.stato &lt; 900\norder by d.data, d.ora\n</code></pre>"},{"location":"views/V_GRIGLIA/","title":"V_GRIGLIA","text":""},{"location":"views/V_GRIGLIA/#colonne","title":"Colonne","text":"Colonna Tipo ID NUMBER TIPO_RIEPILOGO VARCHAR2(20) RNK NUMBER DES_TIPO VARCHAR2(1000) LUN VARCHAR2(4000) MAR VARCHAR2(4000) MER VARCHAR2(4000) GIO VARCHAR2(4000) VEN_1 VARCHAR2(4000) VEN_2 VARCHAR2(4000) SAB_1 VARCHAR2(4000) SAB_2 VARCHAR2(4000) DOM_1 VARCHAR2(4000) DOM_2 VARCHAR2(4000)"},{"location":"views/V_GRIGLIA/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW V_GRIGLIA AS\nwith t as (\n select to_char(data,'IW') week,\n -- to_char(data,'d', 'NLS_DATE_LANGUAGE = italian') giorno, \n to_char(data,'d') giorno, \n -- to_char(data,'d', 'NLS_DATE_LANGUAGE = italian') * 100000 + E.ID giorno, \n E.ID ,\n DENSE_RANK() OVER (PARTITION BY to_char(data,'d', 'NLS_DATE_LANGUAGE = italian') * 100000 ORDER BY e.id) rnk,\n e.data,e.descrizione,\n p.cod_articolo,\n a.descrizione des_art,\n a.cod_categ,\n c.descrizione des_categ,\n c.cod_tipo ,\n t.descrizione des_tipo,\n c.tipo_riepilogo\n from eventi e\n join eventi_det_prel p on e.id = p.id_evento\n join articoli a on p.cod_articolo = a.cod_articolo\n join tb_codici_categ c on a.cod_categ = c.cod_categ\n join tb_tipi_mat t on c.cod_tipo = t.cod_tipo\n -- where to_char(data,'IW') = to_char(to_date(:P14_SETTIMANA,'DD-MON-YYYY'),'IW') \n where to_char(data,'IW') = to_char(to_date('05-MAY-2018','DD-MON-YYYY'),'IW') \n\n )\n, t_des as (\n select ID,rnk,\n t.tipo_riepilogo,\n t.DES_TIPO, \n t.descrizione,\n case when giorno = 1 then t.DES_ART end DOM_1,\n case when giorno = 1 then t.DES_ART end DOM_2,\n case when giorno = 2 then t.DES_ART end LUN,\n case when giorno = 3 then t.DES_ART end MAR,\n case when giorno = 4 then t.DES_ART end MER,\n case when giorno = 5 then t.DES_ART end GIO,\n case when giorno = 6 and rnk =1 then t.DES_ART else '1-' end VEN_1,\n case when giorno = 6 and rnk =2 then t.DES_ART else '2-' end VEN_2,\n case when giorno = 7 then t.DES_ART else '1-' end SAB_1,\n case when giorno = 7 then t.DES_ART else '2-' end SAB_2 \n from t\n ) \nselect id, tipo_riepilogo,rnk, DES_TIPO,LUN, MAR, MER, GIO, VEN_1,VEN_2, SAB_1, SAB_2, DOM_1, DOM_2\n from t_des\n</code></pre>"},{"location":"views/V_IMPEGNI_ARTICOLI/","title":"V_IMPEGNI_ARTICOLI","text":""},{"location":"views/V_IMPEGNI_ARTICOLI/#colonne","title":"Colonne","text":"Colonna Tipo DATA DATE COD_ARTICOLO VARCHAR2(10) QTA_IMP NUMBER QTA_APE NUMBER QTA_SEDU NUMBER QTA_BUFDOL NUMBER"},{"location":"views/V_IMPEGNI_ARTICOLI/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW V_IMPEGNI_ARTICOLI AS\nselect e.data,p.cod_articolo,\n sum(p.qta) qta_imp,\n sum(p.qta_ape) qta_ape,\n sum(p.qta_sedu) qta_sedu,\n sum(p.qta_bufdol) qta_bufdol\n from eventi_det_prel p\n join eventi e on p.id_evento = e.id\n where e.data &gt;= trunc(sysdate)\n and e.stato between 200 and 400\n and e.id_evt_figlio is null\n group by e.data,cod_articolo\n order by cod_articolo,e.data\n</code></pre>"},{"location":"views/V_IMPEGNI_ARTICOLI_LOC/","title":"V_IMPEGNI_ARTICOLI_LOC","text":""},{"location":"views/V_IMPEGNI_ARTICOLI_LOC/#colonne","title":"Colonne","text":"Colonna Tipo DATA DATE LOCATION VARCHAR2(200) COD_ARTICOLO VARCHAR2(10) DESCRIZIONE VARCHAR2(4000) TOT_OSPITI NUMBER QTA_GIAC NUMBER QTA_IMP NUMBER QTA_RES NUMBER QTA_APE NUMBER QTA_SEDU NUMBER QTA_BUFDOL NUMBER DESCRI_CATEG VARCHAR2(1013) DESCRI_TIPO VARCHAR2(1013)"},{"location":"views/V_IMPEGNI_ARTICOLI_LOC/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW V_IMPEGNI_ARTICOLI_LOC AS\nwith t as (\nselect e.data, l.LOCATION,p.cod_articolo,a.DESCRIZIONE,e.TOT_OSPITI,\n sum(a.QTA_GIAC) qta_giac,\n sum(p.qta) qta_imp,\n sum(a.QTA_GIAC) - f_get_qta_impegnata(p.cod_articolo,e.data) qta_res,\n sum(p.qta_ape) qta_ape,\n sum(p.qta_sedu) qta_sedu,\n sum(p.qta_bufdol) qta_bufdol\n from eventi_det_prel p\n left\n join articoli a on p.COD_ARTICOLO = a.COD_ARTICOLO\n join eventi e on p.id_evento = e.id\n left\n join location l on e.id_location = l.id\n where e.stato between 200 and 400\n and e.id_evt_figlio is null\n group by e.data, l.LOCATION,p.cod_articolo,a.DESCRIZIONE,e.TOT_OSPITI\n order by e.data, l.LOCATION,p.cod_articolo\n)\nselect t.\"DATA\",t.\"LOCATION\",t.\"COD_ARTICOLO\",t.\"DESCRIZIONE\",t.\"TOT_OSPITI\",t.\"QTA_GIAC\",t.\"QTA_IMP\",t.\"QTA_RES\",t.\"QTA_APE\",t.\"QTA_SEDU\",t.\"QTA_BUFDOL\",\ng.cod_categ || ' - ' || g.descrizione as descri_categ,\nu.cod_tipo || ' - ' || u.descrizione as descri_tipo\nfrom t\njoin articoli a on a.COD_ARTICOLO = t.COD_ARTICOLO\njoin tb_codici_categ g on g.COD_CATEG = a.COD_CATEG\njoin tb_tipi_mat u on u.cod_tipo = g.cod_tipo\n</code></pre>"},{"location":"views/V_REP_ALLESTIMENTI/","title":"V_REP_ALLESTIMENTI","text":""},{"location":"views/V_REP_ALLESTIMENTI/#colonne","title":"Colonne","text":"Colonna Tipo D1 DATE D2 DATE D3 DATE D4 DATE D5 DATE D6 DATE D7 DATE D8 DATE D9 DATE D10 DATE D11 DATE D12 DATE L1 VARCHAR2(200) L2 VARCHAR2(200) L3 VARCHAR2(200) L4 VARCHAR2(200) L5 VARCHAR2(200) L6 VARCHAR2(200) L7 VARCHAR2(200) L8 VARCHAR2(200) L9 VARCHAR2(200) L10 VARCHAR2(200) L11 VARCHAR2(200) L12 VARCHAR2(200) T1 VARCHAR2(4000) T2 VARCHAR2(4000) T3 VARCHAR2(4000) T4 VARCHAR2(4000) T5 VARCHAR2(4000) T6 VARCHAR2(4000) T7 VARCHAR2(4000) T8 VARCHAR2(4000) T9 VARCHAR2(4000) T10 VARCHAR2(4000) T11 VARCHAR2(4000) T12 VARCHAR2(4000) C1 VARCHAR2(4000) C2 VARCHAR2(4000) C3 VARCHAR2(4000) C4 VARCHAR2(4000) C5 VARCHAR2(4000) C6 VARCHAR2(4000) C7 VARCHAR2(4000) C8 VARCHAR2(4000) C9 VARCHAR2(4000) C10 VARCHAR2(4000) C11 VARCHAR2(4000) C12 VARCHAR2(4000)"},{"location":"views/V_REP_ALLESTIMENTI/#definizione","title":"Definizione","text":"<pre><code>CREATE OR REPLACE VIEW V_REP_ALLESTIMENTI AS\nwith t as (select e.id, e.data, l.location, e.torta, e.confettata\n from eventi e\n left join location l on e.id_location = l.id\n where data &gt;= sysdate \n order by data \n )\n, q as (select t.* , rownum as order_id\n from t \n order by data\n )\n, r as (select -- q.* ,\n case when order_id =1 then data else null end as data1,\n case when order_id =2 then data else null end as data2,\n case when order_id =3 then data else null end as data3,\n case when order_id =4 then data else null end as data4,\n case when order_id =5 then data else null end as data5,\n case when order_id =6 then data else null end as data6,\n case when order_id =7 then data else null end as data7,\n case when order_id =8 then data else null end as data8,\n case when order_id =9 then data else null end as data9,\n case when order_id =10 then data else null end as data10,\n case when order_id =11 then data else null end as data11,\n case when order_id =12 then data else null end as data12,\n\n case when order_id =1 then location else null end as location1,\n case when order_id =2 then location else null end as location2,\n case when order_id =3 then location else null end as location3,\n case when order_id =4 then location else null end as location4,\n case when order_id =5 then location else null end as location5,\n case when order_id =6 then location else null end as location6,\n case when order_id =7 then location else null end as location7,\n case when order_id =8 then location else null end as location8,\n case when order_id =9 then location else null end as location9,\n case when order_id =10 then location else null end as location10,\n case when order_id =11 then location else null end as location11,\n case when order_id =12 then location else null end as location12,\n\n case when order_id =1 then torta else null end as torta1,\n case when order_id =2 then torta else null end as torta2,\n case when order_id =3 then torta else null end as torta3,\n case when order_id =4 then torta else null end as torta4,\n case when order_id =5 then torta else null end as torta5,\n case when order_id =6 then torta else null end as torta6,\n case when order_id =7 then torta else null end as torta7,\n case when order_id =8 then torta else null end as torta8,\n case when order_id =9 then torta else null end as torta9,\n case when order_id =10 then torta else null end as torta10,\n case when order_id =11 then torta else null end as torta11,\n case when order_id =12 then torta else null end as torta12,\n\n case when order_id =1 then confettata else null end as confettata1,\n case when order_id =2 then confettata else null end as confettata2,\n case when order_id =3 then confettata else null end as confettata3,\n case when order_id =4 then confettata else null end as confettata4,\n case when order_id =5 then confettata else null end as confettata5,\n case when order_id =6 then confettata else null end as confettata6,\n case when order_id =7 then confettata else null end as confettata7,\n case when order_id =8 then confettata else null end as confettata8,\n case when order_id =9 then confettata else null end as confettata9,\n case when order_id =10 then confettata else null end as confettata10,\n case when order_id =11 then confettata else null end as confettata11,\n case when order_id =12 then confettata else null end as confettata12 \n from q\n )\nselect min(data1) as d1,\n min(data2) as d2,\n min(data3) as d3,\n min(data4) as d4,\n min(data5) as d5,\n min(data6) as d6,\n min(data7) as d7,\n min(data8) as d8,\n min(data9) as d9,\n min(data10) as d10,\n min(data11) as d11,\n min(data12) as d12,\n\n min(location1) as l1,\n min(location2) as l2,\n min(location3) as l3,\n min(location4) as l4,\n min(location5) as l5,\n min(location6) as l6,\n min(location7) as l7,\n min(location8) as l8,\n min(location9) as l9,\n min(location10) as l10,\n min(location11) as l11,\n min(location12) as l12,\n\n min(torta1) as t1,\n min(torta2) as t2,\n min(torta3) as t3,\n min(torta4) as t4,\n min(torta5) as t5,\n min(torta6) as t6,\n min(torta7) as t7,\n min(torta8) as t8,\n min(torta9) as t9,\n min(torta10) as t10,\n min(torta11) as t11,\n min(torta12) as t12,\n\n min(confettata1) as c1,\n min(confettata2) as c2,\n min(confettata3) as c3,\n min(confettata4) as c4,\n min(confettata5) as c5,\n min(confettata6) as c6,\n min(confettata7) as c7,\n min(confettata8) as c8,\n min(confettata9) as c9,\n min(confettata10) as c10,\n min(confettata11) as c11,\n min(confettata12) as c12 \n\n from r\n</code></pre>"}]}