extracted objects
This commit is contained in:
336
docs/APPLICATION_OVERVIEW.md
Normal file
336
docs/APPLICATION_OVERVIEW.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# Apollinare Catering & Banqueting - Application Overview
|
||||
|
||||
## Descrizione Applicazione Attuale
|
||||
|
||||
### Cos'è Apollinare
|
||||
|
||||
**Apollinare Catering & Banqueting Management Software** è 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.
|
||||
|
||||
L'applicazione è attualmente in uso presso Apollinare Catering (Italia) ed è stata sviluppata su piattaforma Oracle APEX 21.1.0.
|
||||
|
||||
### Funzionalità Principali
|
||||
|
||||
#### 1. Gestione Eventi
|
||||
|
||||
Il cuore dell'applicazione è la gestione degli eventi di catering:
|
||||
|
||||
- **Creazione Evento**: Wizard guidato per la creazione di nuovi eventi
|
||||
- **Dati Evento**: Data, orario cerimonia, orario evento, location, cliente
|
||||
- **Tipologie**: Matrimoni, battesimi, comunioni, cresime, eventi aziendali, feste private
|
||||
- **Tipo Pasto**: Pranzo, cena, pranzo buffet, cena buffet
|
||||
|
||||
#### 2. Workflow Stati Evento
|
||||
|
||||
L'evento attraversa diverse fasi:
|
||||
|
||||
```
|
||||
PREVENTIVO (100) → Cliente interessato, preventivo in preparazione
|
||||
↓
|
||||
SCHEDA (200) → Degustazione effettuata, scheda evento in preparazione
|
||||
↓
|
||||
CONFERMATA (300) → Prima caparra ricevuta
|
||||
↓
|
||||
QUASI CONFERMATO (350) → In attesa conferma definitiva
|
||||
↓
|
||||
CONFERMATO (400) → Evento confermato, in esecuzione
|
||||
↓
|
||||
SUPERATO (900) → Evento concluso o annullato
|
||||
```
|
||||
|
||||
#### 3. Gestione Ospiti
|
||||
|
||||
Sistema sofisticato per la gestione degli ospiti:
|
||||
|
||||
- **Tipi Ospiti**: Adulti, bambini, staff, fornitori esterni
|
||||
- **Conteggi Separati**: Seduti vs buffet, adulti vs bambini
|
||||
- **Coefficienti**: Ogni tipo ospite ha coefficienti per il calcolo quantità
|
||||
|
||||
#### 4. Lista Prelievo (Pick List)
|
||||
|
||||
Gestione automatizzata del materiale necessario:
|
||||
|
||||
- **Articoli**: Catalogo completo con immagini, quantità standard, coefficienti
|
||||
- **Categorie**: Posate, piatti, bicchieri, tovagliato, decorazioni, attrezzature cucina
|
||||
- **Calcolo Automatico**: Le quantità vengono calcolate automaticamente in base a:
|
||||
- Numero ospiti per tipo
|
||||
- Coefficienti categoria (A=Adulti, S=Seduti, B=Buffet)
|
||||
- Quantità standard articolo
|
||||
- **Disponibilità**: Verifica impegni articoli su altri eventi nella stessa data
|
||||
|
||||
#### 5. Gestione Risorse (Staff)
|
||||
|
||||
Pianificazione del personale:
|
||||
|
||||
- **Tipi Risorsa**: Camerieri, cuochi, barman, responsabili sala
|
||||
- **Assegnazione**: Assegnazione risorse per evento
|
||||
- **Report**: Riepilogo impegni risorse per data
|
||||
|
||||
#### 6. Sistema Acconti e Pagamenti
|
||||
|
||||
Gestione finanziaria completa:
|
||||
|
||||
- **Caparre Automatiche**: Sistema 30% - 50% - 20%
|
||||
- **Tracking Pagamenti**: Monitoraggio stato pagamenti
|
||||
- **Solleciti**: Identificazione eventi con pagamenti in scadenza (65 giorni)
|
||||
- **Email Automatiche**: Notifiche automatiche per pagamenti
|
||||
|
||||
#### 7. Reporting
|
||||
|
||||
Sistema di reportistica integrato:
|
||||
|
||||
- **Scheda Evento**: PDF completo per cliente
|
||||
- **Preventivo**: Documento commerciale
|
||||
- **Riepilogo Cucina**: Per lo staff di cucina
|
||||
- **Riepilogo Allestimenti**: Per team setup
|
||||
- **Griglia Eventi**: Vista calendario operativa
|
||||
- **Report Costi**: Analisi costi per evento/categoria
|
||||
|
||||
#### 8. Calendario
|
||||
|
||||
Vista calendario interattiva:
|
||||
|
||||
- **Visualizzazione**: Eventi per giorno/settimana/mese
|
||||
- **Colori Stati**: Codifica colore per stato evento
|
||||
- **Limiti**: Controllo numero massimo eventi per data
|
||||
- **Conflitti**: Verifica location già impegnate
|
||||
|
||||
#### 9. Gestione Degustazioni
|
||||
|
||||
Per eventi come matrimoni:
|
||||
|
||||
- **Pianificazione**: Data e dettagli degustazione
|
||||
- **Tracking**: Stato degustazione
|
||||
- **Note**: Preferenze e allergie
|
||||
|
||||
#### 10. Template Eventi
|
||||
|
||||
Sistema di template per velocizzare la creazione:
|
||||
|
||||
- **Template Predefiniti**: Configurazioni standard per tipologie evento
|
||||
- **Duplicazione**: Copia evento esistente come base
|
||||
- **Versionamento**: Sistema di versioni per tracciare modifiche
|
||||
|
||||
---
|
||||
|
||||
## Proposta SaaS: CaterPro
|
||||
|
||||
### Vision
|
||||
|
||||
Trasformare Apollinare in **CaterPro**, una piattaforma SaaS multi-tenant per la gestione di aziende di catering e banqueting, mantenendo le funzionalità core ma aggiungendo caratteristiche enterprise.
|
||||
|
||||
### Target Market
|
||||
|
||||
1. **Piccole Aziende di Catering** (1-10 dipendenti)
|
||||
- Piano Basic
|
||||
- Gestione eventi semplificata
|
||||
- Fino a 50 eventi/mese
|
||||
|
||||
2. **Medie Aziende di Catering** (10-50 dipendenti)
|
||||
- Piano Professional
|
||||
- Multi-location
|
||||
- Fino a 200 eventi/mese
|
||||
|
||||
3. **Grandi Aziende / Catene** (50+ dipendenti)
|
||||
- Piano Enterprise
|
||||
- Multi-brand, multi-country
|
||||
- Eventi illimitati
|
||||
|
||||
### Architettura SaaS
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CaterPro Cloud │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Tenant A │ │ Tenant B │ │ Tenant C │ ... │
|
||||
│ │ (Catering │ │ (Wedding │ │ (Corporate │ │
|
||||
│ │ Roma) │ │ Planner) │ │ Events) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Shared Services │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Auth/IAM │ │ Billing │ │Analytics │ │ API │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Infrastructure │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ .NET 8 │ │ React │ │PostgreSQL│ │ Azure │ │
|
||||
│ │ API │ │ SPA │ │ /Oracle │ │ Cloud │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Funzionalità SaaS Aggiuntive
|
||||
|
||||
#### Multi-Tenancy
|
||||
- **Isolamento Dati**: Ogni cliente ha i propri dati completamente isolati
|
||||
- **Customizzazione**: Logo, colori, branding personalizzabile
|
||||
- **Subdomain**: cliente.caterpro.com
|
||||
|
||||
#### Gestione Utenti Avanzata
|
||||
- **Ruoli Predefiniti**: Admin, Manager, Operatore, Cucina, Solo Lettura
|
||||
- **Ruoli Custom**: Creazione ruoli personalizzati
|
||||
- **SSO**: Integrazione Azure AD, Google Workspace
|
||||
- **2FA**: Autenticazione a due fattori
|
||||
|
||||
#### Integrazioni
|
||||
- **Calendario**: Google Calendar, Outlook, Apple Calendar
|
||||
- **Pagamenti**: Stripe, PayPal, bonifici SEPA
|
||||
- **Contabilità**: Export per Fatture in Cloud, QuickBooks, Xero
|
||||
- **CRM**: Salesforce, HubSpot
|
||||
- **E-commerce**: Preventivi online, pagamenti online
|
||||
|
||||
#### Mobile App
|
||||
- **App iOS/Android**: Per staff in mobilità
|
||||
- **Check-in Ospiti**: QR code per eventi
|
||||
- **Inventario Mobile**: Scansione barcode articoli
|
||||
- **Foto Evento**: Upload diretto da app
|
||||
|
||||
#### Analytics & BI
|
||||
- **Dashboard Real-time**: KPI principali
|
||||
- **Report Avanzati**: Analisi trend, stagionalità
|
||||
- **Forecasting**: Previsioni ricavi
|
||||
- **Export**: Excel, PDF, API
|
||||
|
||||
#### Automazioni
|
||||
- **Email Marketing**: Campagne automatiche
|
||||
- **Reminder**: Notifiche scadenze, follow-up
|
||||
- **Workflow**: Automazione processi custom
|
||||
- **Webhooks**: Integrazione con sistemi esterni
|
||||
|
||||
### Pricing Model
|
||||
|
||||
#### Basic - €49/mese
|
||||
- 1 utente admin + 2 operatori
|
||||
- 50 eventi/mese
|
||||
- 500 articoli catalogo
|
||||
- Report base
|
||||
- Email support
|
||||
|
||||
#### Professional - €149/mese
|
||||
- 5 utenti inclusi (+€15/utente aggiuntivo)
|
||||
- 200 eventi/mese
|
||||
- Articoli illimitati
|
||||
- Multi-location (fino a 3)
|
||||
- Report avanzati
|
||||
- Integrazioni base
|
||||
- Chat support
|
||||
|
||||
#### Enterprise - €399/mese
|
||||
- Utenti illimitati
|
||||
- Eventi illimitati
|
||||
- Location illimitate
|
||||
- API access
|
||||
- Integrazioni premium
|
||||
- White-label option
|
||||
- SLA garantito
|
||||
- Account manager dedicato
|
||||
|
||||
#### Add-ons
|
||||
- **Mobile App**: +€29/mese
|
||||
- **E-commerce Module**: +€49/mese
|
||||
- **Advanced Analytics**: +€39/mese
|
||||
- **Custom Integrations**: Su richiesta
|
||||
|
||||
### Stack Tecnologico Proposto
|
||||
|
||||
#### Backend (.NET 8)
|
||||
```
|
||||
├── CaterPro.API # Web API REST
|
||||
├── CaterPro.Core # Domain models, interfaces
|
||||
├── CaterPro.Application # Business logic, CQRS
|
||||
├── CaterPro.Infrastructure # Data access, external services
|
||||
├── CaterPro.Identity # Authentication/Authorization
|
||||
└── CaterPro.Workers # Background jobs
|
||||
```
|
||||
|
||||
#### Frontend (React TypeScript)
|
||||
```
|
||||
├── src/
|
||||
│ ├── components/ # Reusable UI components
|
||||
│ ├── features/ # Feature-based modules
|
||||
│ │ ├── events/ # Event management
|
||||
│ │ ├── inventory/ # Article/inventory
|
||||
│ │ ├── calendar/ # Calendar views
|
||||
│ │ ├── reports/ # Reporting
|
||||
│ │ └── settings/ # Configuration
|
||||
│ ├── hooks/ # Custom React hooks
|
||||
│ ├── services/ # API services
|
||||
│ ├── store/ # Redux/Zustand state
|
||||
│ └── utils/ # Utilities
|
||||
```
|
||||
|
||||
#### Database
|
||||
- **Primary**: PostgreSQL (per SaaS cost-efficiency)
|
||||
- **Alternative**: Oracle (per clienti enterprise on-premise)
|
||||
- **Cache**: Redis
|
||||
- **Search**: Elasticsearch (per ricerca articoli/eventi)
|
||||
|
||||
#### Infrastructure
|
||||
- **Cloud**: Azure / AWS
|
||||
- **Container**: Docker + Kubernetes
|
||||
- **CI/CD**: GitHub Actions / Azure DevOps
|
||||
- **Monitoring**: Application Insights / DataDog
|
||||
|
||||
### Roadmap Migrazione
|
||||
|
||||
#### Fase 1: Core Migration (3-4 mesi)
|
||||
- [ ] Setup architettura .NET 8
|
||||
- [ ] Migrazione modelli dati
|
||||
- [ ] API REST per entità principali
|
||||
- [ ] Frontend React base
|
||||
- [ ] Autenticazione JWT
|
||||
|
||||
#### Fase 2: Feature Parity (2-3 mesi)
|
||||
- [ ] Gestione eventi completa
|
||||
- [ ] Sistema calcolo quantità
|
||||
- [ ] Workflow stati
|
||||
- [ ] Report PDF
|
||||
- [ ] Calendario
|
||||
|
||||
#### Fase 3: SaaS Features (2-3 mesi)
|
||||
- [ ] Multi-tenancy
|
||||
- [ ] Billing integration
|
||||
- [ ] User management avanzato
|
||||
- [ ] Customization engine
|
||||
|
||||
#### Fase 4: Advanced Features (3-4 mesi)
|
||||
- [ ] Mobile app
|
||||
- [ ] Integrazioni terze parti
|
||||
- [ ] Analytics avanzati
|
||||
- [ ] E-commerce module
|
||||
|
||||
### Vantaggi Competitivi
|
||||
|
||||
1. **Esperienza Reale**: Basato su software in produzione da anni
|
||||
2. **Specifico per Settore**: Non un gestionale generico adattato
|
||||
3. **Calcolo Automatico**: Algoritmo quantità unico nel settore
|
||||
4. **Workflow Collaudato**: Processo testato su centinaia di eventi
|
||||
5. **Localizzazione**: Già disponibile in italiano, facilmente estendibile
|
||||
|
||||
### Competitor Analysis
|
||||
|
||||
| Feature | CaterPro | Caterease | Total Party Planner | Better Cater |
|
||||
|---------|----------|-----------|---------------------|--------------|
|
||||
| Gestione Eventi | ✅ | ✅ | ✅ | ✅ |
|
||||
| Calcolo Auto Quantità | ✅ | ❌ | ❌ | Parziale |
|
||||
| Multi-tenant | ✅ | ❌ | ❌ | ✅ |
|
||||
| Mobile App | ✅ | ✅ | ❌ | ✅ |
|
||||
| Italiano | ✅ | ❌ | ❌ | ❌ |
|
||||
| API Pubbliche | ✅ | Parziale | ❌ | ✅ |
|
||||
| Prezzo Entry | €49 | $75 | $50 | $99 |
|
||||
|
||||
---
|
||||
|
||||
## Conclusioni
|
||||
|
||||
L'applicazione Apollinare rappresenta un'eccellente base per lo sviluppo di una soluzione SaaS nel settore catering. Le funzionalità core sono mature e testate, la business logic è ben documentata, e l'architettura può essere modernizzata mantenendo la compatibilità con i processi esistenti.
|
||||
|
||||
La migrazione a .NET + React TypeScript permetterà:
|
||||
- Scalabilità orizzontale per SaaS
|
||||
- Developer experience moderna
|
||||
- Ecosystem di librerie più ampio
|
||||
- Deployment cloud-native
|
||||
- Costi operativi ridotti
|
||||
|
||||
Il mercato italiano del catering è frammentato e sottosevito da soluzioni software moderne, rappresentando un'opportunità significativa per un prodotto SaaS verticale ben eseguito.
|
||||
422
docs/README.md
Normal file
422
docs/README.md
Normal file
@@ -0,0 +1,422 @@
|
||||
# Apollinare Catering - Documentazione Completa
|
||||
|
||||
Questa documentazione contiene l'estrazione completa di tutti gli oggetti del database Oracle e dell'applicazione APEX di Apollinare Catering & Banqueting.
|
||||
|
||||
## [Application Overview](APPLICATION_OVERVIEW.md)
|
||||
|
||||
**Apollinare Catering & Banqueting Management Software** è 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.
|
||||
|
||||
### Funzionalità Principali
|
||||
|
||||
| Area | Descrizione |
|
||||
| --------------------- | ------------------------------------------- |
|
||||
| **Gestione Eventi** | Creazione, workflow stati, versioning |
|
||||
| **Gestione Ospiti** | Tipologie ospiti, conteggi, coefficienti |
|
||||
| **Lista Prelievo** | Calcolo automatico quantità 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 |
|
||||
|
||||
### Proposta SaaS: CaterPro
|
||||
|
||||
La documentazione include una proposta per trasformare Apollinare in **CaterPro**, una piattaforma SaaS multi-tenant:
|
||||
|
||||
- **Target**: Piccole, medie e grandi aziende di catering
|
||||
- **Stack**: .NET 8 + React TypeScript + PostgreSQL/Oracle
|
||||
- **Pricing**: Da €49/mese (Basic) a €399/mese (Enterprise)
|
||||
- **Roadmap**: 10-14 mesi per feature parity + SaaS
|
||||
|
||||
Leggi la [documentazione completa](APPLICATION_OVERVIEW.md) per dettagli su architettura, funzionalità e roadmap.
|
||||
|
||||
---
|
||||
|
||||
## Struttura della Documentazione
|
||||
|
||||
```
|
||||
docs/
|
||||
├── apex/ # Applicazione APEX
|
||||
│ ├── README.md # Overview applicazione
|
||||
│ ├── pages/ # 56 pagine
|
||||
│ ├── processes/ # 98 processi
|
||||
│ ├── lovs/ # 12 List of Values
|
||||
│ ├── javascript/ # Librerie JavaScript
|
||||
│ ├── authorization/ # 5 schemi autorizzazione
|
||||
│ ├── dynamic-actions/ # Azioni dinamiche
|
||||
│ ├── items/ # Items condivisi
|
||||
│ ├── regions/ # Regioni condivise
|
||||
│ └── navigation/ # Navigazione
|
||||
├── tables/ # 32 tabelle
|
||||
├── views/ # 26 viste
|
||||
├── procedures/ # 11 stored procedures
|
||||
├── functions/ # 23 funzioni
|
||||
├── packages/ # 17 packages
|
||||
├── triggers/ # 19 triggers
|
||||
├── sequences/ # 22 sequences
|
||||
└── types/ # 10 tipi custom
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## APEX Application Documentation
|
||||
|
||||
### [APEX Application Overview](apex/README.md)
|
||||
|
||||
**Application:** APCB Project (ID: 112)
|
||||
**APEX Version:** 21.1.0
|
||||
**Schema:** APOLLINARECATERINGPROD
|
||||
|
||||
| Component | Count |
|
||||
| --------------- | ----- |
|
||||
| Pages | 56 |
|
||||
| Items | 302 |
|
||||
| Processes | 98 |
|
||||
| Regions | 151 |
|
||||
| Buttons | 119 |
|
||||
| Dynamic Actions | 62 |
|
||||
| LOVs | 12 |
|
||||
|
||||
### Key APEX Documentation
|
||||
|
||||
- [APEX README](apex/README.md) - Application overview and navigation
|
||||
- [Processes Documentation](apex/processes/README.md) - All 98 processes with PL/SQL code
|
||||
- [LOVs Documentation](apex/lovs/README.md) - 12 List of Values definitions
|
||||
- [JavaScript Libraries](apex/javascript/README.md) - Custom ajaxUtils.js and iframeObj.js
|
||||
- [Authorization Schemes](apex/authorization/README.md) - 5 security schemes
|
||||
|
||||
### Critical APEX Pages
|
||||
|
||||
| Page | Name | Description |
|
||||
| ------ | ---------------- | ------------------------------------------------- |
|
||||
| 1 | Home | Dashboard principale |
|
||||
| **22** | **Nuovo Evento** | **Pagina più complessa (108 items, 32 processi)** |
|
||||
| 9 | Liste | Lista eventi |
|
||||
| 12 | Calendario | Calendario eventi |
|
||||
| 35 | Schede | Schede evento |
|
||||
|
||||
---
|
||||
|
||||
## Indice per Categoria
|
||||
|
||||
### [Tabelle](tables/README.md) (32)
|
||||
|
||||
Tabelle principali del dominio business:
|
||||
|
||||
- [EVENTI](tables/EVENTI.md) - Tabella principale eventi
|
||||
- [EVENTI_DET_PREL](tables/EVENTI_DET_PREL.md) - Liste prelievo
|
||||
- [EVENTI_DET_OSPITI](tables/EVENTI_DET_OSPITI.md) - Dettaglio ospiti
|
||||
- [EVENTI_DET_RIS](tables/EVENTI_DET_RIS.md) - Risorse assegnate
|
||||
- [EVENTI_DET_DEGUST](tables/EVENTI_DET_DEGUST.md) - Degustazioni
|
||||
- [EVENTI_ACCONTI](tables/EVENTI_ACCONTI.md) - Gestione acconti/pagamenti
|
||||
- [EVENTI_ALTRICOSTI](tables/EVENTI_ALTRICOSTI.md) - Altri costi
|
||||
- [EVENTI_ALLEG](tables/EVENTI_ALLEG.md) - Allegati
|
||||
- [ARTICOLI](tables/ARTICOLI.md) - Catalogo articoli
|
||||
- [COSTI_ARTICOLI](tables/COSTI_ARTICOLI.md) - Storico costi
|
||||
- [CLIENTI](tables/CLIENTI.md) - Anagrafica clienti
|
||||
- [LOCATION](tables/LOCATION.md) - Location eventi
|
||||
- [RISORSE](tables/RISORSE.md) - Personale
|
||||
|
||||
Tabelle di lookup:
|
||||
|
||||
- [TB_TIPI_MAT](tables/TB_TIPI_MAT.md) - Tipi materiale
|
||||
- [TB_CODICI_CATEG](tables/TB_CODICI_CATEG.md) - Categorie
|
||||
- [TB_TIPI_EVENTO](tables/TB_TIPI_EVENTO.md) - Tipi evento
|
||||
- [TB_TIPI_OSPITI](tables/TB_TIPI_OSPITI.md) - Tipi ospiti
|
||||
- [TB_TIPI_RISORSA](tables/TB_TIPI_RISORSA.md) - Tipi risorsa
|
||||
- [TB_TIPI_PASTO](tables/TB_TIPI_PASTO.md) - Tipi pasto
|
||||
- [TB_CALENDAR_LOCKS](tables/TB_CALENDAR_LOCKS.md) - Limiti calendario
|
||||
- [TB_CONFIG](tables/TB_CONFIG.md) - Configurazioni
|
||||
|
||||
Tabelle di sistema:
|
||||
|
||||
- [USERS_READONLY](tables/USERS_READONLY.md) - Permessi utenti
|
||||
- [XLIB_LOGS](tables/XLIB_LOGS.md) - Log applicazione
|
||||
- [XLIB_COMPONENTS](tables/XLIB_COMPONENTS.md) - Componenti
|
||||
- [XLIB_JASPERREPORTS_CONF](tables/XLIB_JASPERREPORTS_CONF.md) - Config report
|
||||
- [XLIB_JASPERREPORTS_DEMOS](tables/XLIB_JASPERREPORTS_DEMOS.md) - Demo report
|
||||
|
||||
### [Viste](views/README.md) (26)
|
||||
|
||||
Viste per calcolo costi:
|
||||
|
||||
- [GET_COSTO_ART_BY_EVT](views/GET_COSTO_ART_BY_EVT.md) - Costo articoli per evento
|
||||
- [GET_COSTO_ART_EVT](views/GET_COSTO_ART_EVT.md) - Costo articoli aggregato
|
||||
- [GET_COSTO_CATEG_EVT](views/GET_COSTO_CATEG_EVT.md) - Costo per categoria
|
||||
- [GET_COSTO_DEGUS_EVT](views/GET_COSTO_DEGUS_EVT.md) - Costo degustazioni
|
||||
- [GET_COSTO_OSPITI_EVT](views/GET_COSTO_OSPITI_EVT.md) - Costo ospiti
|
||||
- [GET_COSTO_RIS_EVT](views/GET_COSTO_RIS_EVT.md) - Costo risorse
|
||||
- [GET_COSTO_TIPI_EVT](views/GET_COSTO_TIPI_EVT.md) - Costo per tipo
|
||||
- [GET_ULTIMI_COSTI](views/GET_ULTIMI_COSTI.md) - Ultimi costi articoli
|
||||
|
||||
Viste per eventi:
|
||||
|
||||
- [GET_EVT_DATA](views/GET_EVT_DATA.md) - Dati evento completi
|
||||
- [GET_EVT_DATA_PRINT](views/GET_EVT_DATA_PRINT.md) - Dati per stampa
|
||||
- [GET_PREL_ART_TOT](views/GET_PREL_ART_TOT.md) - Totali prelievo
|
||||
- [GET_PREL_BY_EVT](views/GET_PREL_BY_EVT.md) - Prelievi per evento
|
||||
|
||||
Viste per calendario e stato:
|
||||
|
||||
- [VW_CALENDARIO_EVENTI](views/VW_CALENDARIO_EVENTI.md) - Vista calendario
|
||||
- [VW_EVENT_COLOR](views/VW_EVENT_COLOR.md) - Colori stati
|
||||
- [VW_EVENTI_STATUSES](views/VW_EVENTI_STATUSES.md) - Stati eventi
|
||||
|
||||
Viste per giacenze:
|
||||
|
||||
- [V_IMPEGNI_ARTICOLI](views/V_IMPEGNI_ARTICOLI.md) - Impegni articoli
|
||||
- [V_IMPEGNI_ARTICOLI_LOC](views/V_IMPEGNI_ARTICOLI_LOC.md) - Impegni per location
|
||||
|
||||
Viste per report:
|
||||
|
||||
- [V_REP_ALLESTIMENTI](views/V_REP_ALLESTIMENTI.md) - Report allestimenti
|
||||
- [VW_REP_DEGUSTAZIONI](views/VW_REP_DEGUSTAZIONI.md) - Report degustazioni
|
||||
- [V_GRIGLIA](views/V_GRIGLIA.md) - Vista griglia
|
||||
- [GET_REPORT_CONSUNTIVO_PER_DATA](views/GET_REPORT_CONSUNTIVO_PER_DATA.md) - Consuntivo
|
||||
|
||||
Viste per utenti/permessi:
|
||||
|
||||
- [GET_CONSUNTIVI_USERS](views/GET_CONSUNTIVI_USERS.md) - Utenti consuntivi
|
||||
- [GET_GESTORI_USERS](views/GET_GESTORI_USERS.md) - Utenti gestori
|
||||
- [GET_USERS_LIST](views/GET_USERS_LIST.md) - Lista utenti
|
||||
|
||||
Viste per pagamenti:
|
||||
|
||||
- [GET_EVENTI_DA_PAGARE_ENTRO_65GG](views/GET_EVENTI_DA_PAGARE_ENTRO_65GG.md) - Eventi da sollecitare
|
||||
|
||||
### [Stored Procedures](procedures/README.md) (11)
|
||||
|
||||
Business logic principale:
|
||||
|
||||
- [EVENTI_AGGIORNA_QTA_LISTA](procedures/EVENTI_AGGIORNA_QTA_LISTA.md) - Ricalcolo quantità lista prelievo
|
||||
- [EVENTI_AGGIORNA_TOT_OSPITI](procedures/EVENTI_AGGIORNA_TOT_OSPITI.md) - Aggiorna totale ospiti
|
||||
- [EVENTI_COPIA](procedures/EVENTI_COPIA.md) - Duplicazione evento
|
||||
- [EVENTI_RICALCOLA_ACCONTI](procedures/EVENTI_RICALCOLA_ACCONTI.md) - Ricalcolo acconti
|
||||
- [EVENTO_ELIMINA_PRELIEVI](procedures/EVENTO_ELIMINA_PRELIEVI.md) - Elimina prelievi
|
||||
- [LISTE_COPIA](procedures/LISTE_COPIA.md) - Copia liste tra eventi
|
||||
- [P_CANCEL_SAME_LOCATION_EVENTS](procedures/P_CANCEL_SAME_LOCATION_EVENTS.md) - Annulla eventi stessa location
|
||||
|
||||
Utility:
|
||||
|
||||
- [ROWSORT_TIPI](procedures/ROWSORT_TIPI.md) - Ordinamento tipi
|
||||
- [HTPPRN](procedures/HTPPRN.md) - Stampa HTTP
|
||||
- [SEND_DATA_TO_DROPBOX](procedures/SEND_DATA_TO_DROPBOX.md) - Export Dropbox
|
||||
- [XLOG](procedures/XLOG.md) - Logging
|
||||
|
||||
### [Funzioni](functions/README.md) (23)
|
||||
|
||||
Calcolo quantità e disponibilità:
|
||||
|
||||
- [F_GET_QTA_IMPEGNATA](functions/F_GET_QTA_IMPEGNATA.md) - Quantità impegnata
|
||||
- [F_GET_TOT_OSPITI](functions/F_GET_TOT_OSPITI.md) - Totale ospiti
|
||||
- [F_GET_OSPITI](functions/F_GET_OSPITI.md) - Dettaglio ospiti (pipelined)
|
||||
- [F_LIST_PRELIEVO_ADD_ARTICOLO](functions/F_LIST_PRELIEVO_ADD_ARTICOLO.md) - Aggiunta articolo
|
||||
|
||||
Calcolo costi:
|
||||
|
||||
- [F_GET_COSTO_ARTICOLO](functions/F_GET_COSTO_ARTICOLO.md) - Costo articolo a data
|
||||
|
||||
Validazioni:
|
||||
|
||||
- [F_EVENTO_SCADUTO](functions/F_EVENTO_SCADUTO.md) - Verifica scadenza
|
||||
- [F_MAX_NUMERO_EVENTI_RAGGIUNTO](functions/F_MAX_NUMERO_EVENTI_RAGGIUNTO.md) - Limite eventi
|
||||
- [F_MAX_NUM_EVENTI_CONFERMATI](functions/F_MAX_NUM_EVENTI_CONFERMATI.md) - Limite confermati
|
||||
- [F_CI_SONO_EVENTI_CONFERMATI](functions/F_CI_SONO_EVENTI_CONFERMATI.md) - Check confermati
|
||||
|
||||
Report:
|
||||
|
||||
- [F_REP_ALLESTIMENTI](functions/F_REP_ALLESTIMENTI.md) - Report allestimenti
|
||||
- [F_REP_CUCINA](functions/F_REP_CUCINA.md) - Report cucina
|
||||
- [F_GET_ANGOLO_ALLESTIMENTO](functions/F_GET_ANGOLO_ALLESTIMENTO.md) - Angolo allestimento
|
||||
- [F_GET_ANGOLO_ALLESTIMENTO_OB](functions/F_GET_ANGOLO_ALLESTIMENTO_OB.md) - Angolo open bar
|
||||
- [F_GET_TOVAGLIATO_ALLESTIMENTO](functions/F_GET_TOVAGLIATO_ALLESTIMENTO.md) - Tovagliato
|
||||
|
||||
Autorizzazioni:
|
||||
|
||||
- [F_USER_IN_ROLE](functions/F_USER_IN_ROLE.md) - Verifica ruolo utente
|
||||
- [F_USER_IN_ROLE_STR](functions/F_USER_IN_ROLE_STR.md) - Ruolo utente (stringa)
|
||||
|
||||
Utility:
|
||||
|
||||
- [F_DAY_TO_NAME](functions/F_DAY_TO_NAME.md) - Giorno in italiano
|
||||
- [STRING_TO_TABLE_ENUM](functions/STRING_TO_TABLE_ENUM.md) - Stringa a tabella
|
||||
- [GET_PARAM_VALUE](functions/GET_PARAM_VALUE.md) - Valore parametro
|
||||
- [SPLIT](functions/SPLIT.md) - Split stringa
|
||||
- [MY_INSTR](functions/MY_INSTR.md) - Instr custom
|
||||
- [CLOB2BLOB](functions/CLOB2BLOB.md) - Conversione CLOB
|
||||
- [EXTDATE_GET_ITA](functions/EXTDATE_GET_ITA.md) - Data in italiano
|
||||
|
||||
### [Packages](packages/README.md) (17)
|
||||
|
||||
Business:
|
||||
|
||||
- [MAIL_PKG](packages/MAIL_PKG.md) - Gestione invio email automatiche
|
||||
|
||||
Utility esterne:
|
||||
|
||||
- [UTL_BASE64](packages/UTL_BASE64.md) - Encoding Base64
|
||||
|
||||
JasperReports:
|
||||
|
||||
- [XLIB_JASPERREPORTS](packages/XLIB_JASPERREPORTS.md) - Integrazione JasperReports
|
||||
- [XLIB_JASPERREPORTS_IMG](packages/XLIB_JASPERREPORTS_IMG.md) - Immagini report
|
||||
|
||||
HTTP/Componenti:
|
||||
|
||||
- [XLIB_HTTP](packages/XLIB_HTTP.md) - Chiamate HTTP
|
||||
- [XLIB_COMPONENT](packages/XLIB_COMPONENT.md) - Componenti
|
||||
- [XLIB_LOG](packages/XLIB_LOG.md) - Logging
|
||||
|
||||
JSON (libreria PLJSON):
|
||||
|
||||
- [PLJSON_DYN](packages/PLJSON_DYN.md)
|
||||
- [PLJSON_EXT](packages/PLJSON_EXT.md)
|
||||
- [PLJSON_HELPER](packages/PLJSON_HELPER.md)
|
||||
- [PLJSON_ML](packages/PLJSON_ML.md)
|
||||
- [PLJSON_OBJECT_CACHE](packages/PLJSON_OBJECT_CACHE.md)
|
||||
- [PLJSON_PARSER](packages/PLJSON_PARSER.md)
|
||||
- [PLJSON_PRINTER](packages/PLJSON_PRINTER.md)
|
||||
- [PLJSON_UT](packages/PLJSON_UT.md)
|
||||
- [PLJSON_UTIL_PKG](packages/PLJSON_UTIL_PKG.md)
|
||||
- [PLJSON_XML](packages/PLJSON_XML.md)
|
||||
|
||||
### [Triggers](triggers/README.md) (19)
|
||||
|
||||
Generazione ID:
|
||||
|
||||
- [EVENTI_TRG](triggers/EVENTI_TRG.md) - ID eventi + inizializzazione
|
||||
- [EVENTI_AI_TRG](triggers/EVENTI_AI_TRG.md) - Creazione ospiti default
|
||||
- [EVENTI_DET_PREL_TRG](triggers/EVENTI_DET_PREL_TRG.md) - ID prelievi
|
||||
- [EVENTI_DET_RIS_TRG](triggers/EVENTI_DET_RIS_TRG.md) - ID risorse
|
||||
- [EVENTI_DET_DEGUST_TRG](triggers/EVENTI_DET_DEGUST_TRG.md) - ID degustazioni
|
||||
- [EVENTI_ACCONTI_TRG](triggers/EVENTI_ACCONTI_TRG.md) - ID acconti
|
||||
- [EVENTI_ALTRICOSTI_TRG](triggers/EVENTI_ALTRICOSTI_TRG.md) - ID altri costi
|
||||
- [EVENTI_ALLEG_TRG](triggers/EVENTI_ALLEG_TRG.md) - ID allegati
|
||||
- [CLIENTI_TRG](triggers/CLIENTI_TRG.md) - ID clienti
|
||||
- [LOCATION_TRG](triggers/LOCATION_TRG.md) - ID location
|
||||
- [RISORSE_TRG](triggers/RISORSE_TRG.md) - ID risorse
|
||||
- [ARTICOLI_DET_REGOLE_TRG](triggers/ARTICOLI_DET_REGOLE_TRG.md) - ID regole articoli
|
||||
- [TB_TIPI_PASTO_TRG](triggers/TB_TIPI_PASTO_TRG.md) - ID tipi pasto
|
||||
|
||||
Business logic:
|
||||
|
||||
- [EVENTI_DET_OSPITI_TRG_AI](triggers/EVENTI_DET_OSPITI_TRG_AI.md) - Aggiornamento ospiti
|
||||
- [EVENTI_DET_PREL_QTA_TOT_TRG](triggers/EVENTI_DET_PREL_QTA_TOT_TRG.md) - Calcolo quantità totale
|
||||
|
||||
Ordinamento:
|
||||
|
||||
- [ADD_COD_STEP](triggers/ADD_COD_STEP.md) - Ordine tipi materiale
|
||||
- [ON_DELETE_REORDER](triggers/ON_DELETE_REORDER.md) - Riordino dopo delete
|
||||
|
||||
Sistema:
|
||||
|
||||
- [BI_GL_SCHEMA_CHANGES](triggers/BI_GL_SCHEMA_CHANGES.md) - Log modifiche schema
|
||||
- [XLIB_LOGS_BI_TRG](triggers/XLIB_LOGS_BI_TRG.md) - Log applicazione
|
||||
|
||||
### [Sequences](sequences/README.md) (22)
|
||||
|
||||
Tutte le sequence del database.
|
||||
|
||||
### [Types](types/README.md) (10)
|
||||
|
||||
Tipi custom:
|
||||
|
||||
- [T_DET_OSPITI_ROW](types/T_DET_OSPITI_ROW.md) / [T_DET_OSPITI_TAB](types/T_DET_OSPITI_TAB.md) - Tipo per F_GET_OSPITI
|
||||
- [T_REP_ALLESTIMENTI_ROW](types/T_REP_ALLESTIMENTI_ROW.md) / [T_REP_ALLESTIMENTI_TAB](types/T_REP_ALLESTIMENTI_TAB.md) - Tipo per F_REP_ALLESTIMENTI
|
||||
- [T_REP_CUCINA_ROW](types/T_REP_CUCINA_ROW.md) / [T_REP_CUCINA_TAB](types/T_REP_CUCINA_TAB.md) - Tipo per F_REP_CUCINA
|
||||
- [STRING_LIST](types/STRING_LIST.md) - Lista stringhe
|
||||
- [ENUM_TABLE_OBJECT](types/ENUM_TABLE_OBJECT.md) / [ENUM_TABLE_TYPE](types/ENUM_TABLE_TYPE.md) - Tipi per STRING_TO_TABLE_ENUM
|
||||
- [XLIB_VC2_ARRAY_T](types/XLIB_VC2_ARRAY_T.md) - Array varchar2
|
||||
|
||||
---
|
||||
|
||||
## Schema ER Semplificato
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ CLIENTI │
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ LOCATION │◄────│ EVENTI │────►│TB_TIPI_EVENTO│
|
||||
└─────────────┘ └──────┬──────┘ └─────────────┘
|
||||
│
|
||||
┌─────────────────┼─────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│EVENTI_DET_OSPITI│ │ EVENTI_DET_PREL │ │ EVENTI_DET_RIS │
|
||||
└─────────────────┘ └────────┬────────┘ └────────┬────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ TB_TIPI_OSPITI │ │ ARTICOLI │ │ RISORSE │
|
||||
└─────────────────┘ └────────┬────────┘ └─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ TB_CODICI_CATEG │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ TB_TIPI_MAT │
|
||||
└─────────────────┘
|
||||
|
||||
┌─────────────────┬─────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│EVENTI_DET_DEGUST│ │ EVENTI_ACCONTI │ │EVENTI_ALTRICOSTI│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Workflow Stati Evento
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ PREVENTIVO │ (100) - Bianco
|
||||
└──────┬───────┘
|
||||
│ Degustazione
|
||||
▼
|
||||
┌──────────────┐
|
||||
│SCHEDA EVENTO │ (200) - Celeste
|
||||
│(preparazione)│
|
||||
└──────┬───────┘
|
||||
│ Prima caparra
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ SCHEDA │ (300) - Giallo
|
||||
│ CONFERMATA │
|
||||
└──────┬───────┘
|
||||
│ Quasi confermato
|
||||
▼
|
||||
┌──────────────┐
|
||||
│SCHEDA QUASI │ (350) - Arancio
|
||||
│ CONFERMATA │
|
||||
└──────┬───────┘
|
||||
│ Conferma definitiva
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ CONFERMATO │ (400) - Verde
|
||||
└──────────────┘
|
||||
|
||||
│ Rifiuto/Scadenza
|
||||
▼
|
||||
┌──────────────┐
|
||||
│NON ACCETTATO/│ (900) - Viola
|
||||
│ SUPERATO │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
## Note per lo Sviluppo
|
||||
|
||||
1. **Packages PLJSON\_\***: Libreria esterna per parsing JSON, può essere sostituita con funzionalità native .NET
|
||||
|
||||
2. **Packages XLIB\_\***: Componenti per integrazione JasperReports, da valutare sostituzione con report .NET
|
||||
|
||||
3. **Trigger per ID**: In .NET usare Identity columns o GUID
|
||||
|
||||
4. **Calcolo quantità**: La logica in `EVENTI_AGGIORNA_QTA_LISTA` è critica e deve essere portata fedelmente
|
||||
|
||||
5. **Sistema acconti**: Le percentuali 30%-50%-20% sono hardcoded, valutare parametrizzazione
|
||||
195
docs/apex/README.md
Normal file
195
docs/apex/README.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# APEX Application Documentation
|
||||
|
||||
## Application Overview
|
||||
|
||||
| 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 & Banqueting - Management Software |
|
||||
| **Last Updated By** | MONIA |
|
||||
| **Last Update** | 2025-11-24 14:06:02 |
|
||||
|
||||
## Application Statistics
|
||||
|
||||
| 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 |
|
||||
|
||||
## Navigation Structure
|
||||
|
||||
### Desktop Navigation Menu
|
||||
|
||||
```
|
||||
Home (Page 1)
|
||||
├── Articoli (Page 2)
|
||||
│ └── Impegni Articoli (Page 39)
|
||||
├── Categorie (Page 4)
|
||||
├── Tipi (Page 6)
|
||||
├── Clienti (Page 17)
|
||||
├── Location (Page 15)
|
||||
├── Risorse (Page 31)
|
||||
├── Permessi (Page 47) [Admin Only]
|
||||
├── Gestione Dati (Page 45) [Admin Only]
|
||||
├── Job Schedulati (Page 49)
|
||||
├── Mail Inviate (Page 50)
|
||||
└── Mail In Attesa (Page 51)
|
||||
|
||||
Eventi
|
||||
├── Tipi Evento (Page 13) [Admin Only]
|
||||
├── Nuovo Evento (Page 22) [Admin Only]
|
||||
├── Schede/Schede Confermate (Page 35)
|
||||
├── Liste (Page 9) [Admin Only]
|
||||
├── Calendario Eventi (Page 12)
|
||||
├── Degustazioni (Page 27)
|
||||
└── Template Eventi (Page 48) [Admin Only]
|
||||
|
||||
Riepiloghi/Report
|
||||
├── Griglia (Page 16) [Admin Only]
|
||||
├── Riepilogo Cucina (Page 25)
|
||||
├── Torte e Costi Extra (Page 28) [Admin Only]
|
||||
├── Riepilogo Allestimenti (Page 30)
|
||||
└── Riepilogo Risorse (Page 38)
|
||||
```
|
||||
|
||||
## Page Categories
|
||||
|
||||
### Master Data Pages
|
||||
| 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 |
|
||||
|
||||
### Event Management Pages
|
||||
| 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 |
|
||||
|
||||
### Report Pages
|
||||
| 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 |
|
||||
|
||||
### Administration Pages
|
||||
| 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 |
|
||||
|
||||
## Page 22 (Nuovo Evento) - Most Complex Page
|
||||
|
||||
Page 22 is the main event management page with the highest complexity:
|
||||
|
||||
| Component | Count |
|
||||
|-----------|-------|
|
||||
| Items | 108 |
|
||||
| Regions | 33 |
|
||||
| Buttons | 32 |
|
||||
| Processes | 32 |
|
||||
| Dynamic Actions | Multiple |
|
||||
|
||||
### Key Features:
|
||||
- Multiple Interactive Grids (master-detail)
|
||||
- Guest type management with quantity recalculations
|
||||
- Resource assignments
|
||||
- Pick list management with coefficient-based calculations
|
||||
- Event status workflow management
|
||||
- Template support
|
||||
- Versioning system
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
```
|
||||
docs/apex/
|
||||
├── README.md (this file)
|
||||
├── pages/ # Individual page documentation
|
||||
├── processes/ # Process documentation
|
||||
├── lovs/ # List of Values documentation
|
||||
├── javascript/ # JavaScript libraries
|
||||
├── authorization/ # Authorization schemes
|
||||
├── dynamic-actions/ # Dynamic actions
|
||||
├── items/ # Shared items
|
||||
├── regions/ # Shared regions
|
||||
└── navigation/ # Navigation components
|
||||
```
|
||||
|
||||
## Key Files
|
||||
|
||||
- [LOVs Documentation](lovs/README.md) - List of Values definitions
|
||||
- [Processes Documentation](processes/README.md) - PL/SQL processes
|
||||
- [JavaScript Libraries](javascript/README.md) - Custom JavaScript
|
||||
- [Authorization Schemes](authorization/README.md) - Security settings
|
||||
- [Page 22 Documentation](pages/PAGE_022.md) - Main event form
|
||||
|
||||
## Event Status Workflow
|
||||
|
||||
```
|
||||
100 (Preventivo/Quote)
|
||||
↓ [Continue Event]
|
||||
200 (Scheda/Preparazione)
|
||||
↓ [Return to Preparazione]
|
||||
300 (Confermata/Quasi)
|
||||
↓ [Almost Continue Event]
|
||||
350 (Quasi Confermato)
|
||||
↓ [Confirm Event]
|
||||
400 (Confermato/Confirmed)
|
||||
↓ [Set Obsoleto]
|
||||
900 (Superato/Expired)
|
||||
```
|
||||
|
||||
## Authorization Schemes
|
||||
|
||||
| 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) |
|
||||
296
docs/apex/authorization/README.md
Normal file
296
docs/apex/authorization/README.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# Authorization Schemes Documentation
|
||||
|
||||
This document describes the 5 authorization schemes used in the APEX application for access control.
|
||||
|
||||
## Overview
|
||||
|
||||
| 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... |
|
||||
|
||||
---
|
||||
|
||||
## Admin_auth_schema
|
||||
|
||||
**Type:** NATIVE_EXISTS
|
||||
**Caching:** BY_USER_BY_PAGE_VIEW
|
||||
|
||||
**SQL Query:**
|
||||
```sql
|
||||
select 1 from dual
|
||||
where lower(:APP_USER) in ('admin','monia','andrea','maria','sabrina','nicole','cucina','developer','elia.ballarani');
|
||||
```
|
||||
|
||||
**Authorized Users:**
|
||||
- admin
|
||||
- monia
|
||||
- andrea
|
||||
- maria
|
||||
- sabrina
|
||||
- nicole
|
||||
- cucina
|
||||
- developer
|
||||
- elia.ballarani
|
||||
|
||||
**Usage:** General administrative access to most management pages.
|
||||
|
||||
---
|
||||
|
||||
## User Read/Write
|
||||
|
||||
**Type:** NATIVE_FUNCTION_BODY
|
||||
**Caching:** BY_USER_BY_PAGE_VIEW
|
||||
|
||||
**PL/SQL Function:**
|
||||
```plsql
|
||||
declare
|
||||
v_readonly number;
|
||||
begin
|
||||
select 1
|
||||
into v_readonly
|
||||
from users_readonly
|
||||
where username = :APP_USER
|
||||
and flgwrite = 0;
|
||||
|
||||
return false;
|
||||
exception when no_data_found then
|
||||
return true;
|
||||
end;
|
||||
```
|
||||
|
||||
**Logic:**
|
||||
- Checks `USERS_READONLY` table
|
||||
- If user exists with `FLGWRITE = 0` → Returns FALSE (read-only mode)
|
||||
- If user not found → Returns TRUE (write access)
|
||||
|
||||
**Usage:** Controls whether user can modify data or only view.
|
||||
|
||||
---
|
||||
|
||||
## Consuntivi
|
||||
|
||||
**Type:** NATIVE_EXISTS
|
||||
**Caching:** BY_USER_BY_PAGE_VIEW
|
||||
|
||||
**SQL Query:**
|
||||
```sql
|
||||
select 1 from dual
|
||||
where :APP_USER in (select users from get_consuntivi_users);
|
||||
```
|
||||
|
||||
**Data Source:** `GET_CONSUNTIVI_USERS` view
|
||||
|
||||
**Usage:** Access to financial summary pages and cost management.
|
||||
|
||||
---
|
||||
|
||||
## Gestori
|
||||
|
||||
**Type:** NATIVE_EXISTS
|
||||
**Caching:** BY_USER_BY_PAGE_VIEW
|
||||
|
||||
**SQL Query:**
|
||||
```sql
|
||||
select 1 from dual
|
||||
where :APP_USER in (select users from get_gestori_users);
|
||||
```
|
||||
|
||||
**Data Source:** `GET_GESTORI_USERS` view
|
||||
|
||||
**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)
|
||||
|
||||
---
|
||||
|
||||
## Solo Admins
|
||||
|
||||
**Type:** NATIVE_EXISTS
|
||||
**Caching:** BY_USER_BY_PAGE_VIEW
|
||||
|
||||
**SQL Query:**
|
||||
```sql
|
||||
select 1 from dual
|
||||
where lower(:APP_USER) in ('admin', 'monia');
|
||||
```
|
||||
|
||||
**Authorized Users:**
|
||||
- admin
|
||||
- monia
|
||||
|
||||
**Usage:** Highest level of access. Reserved for:
|
||||
- Permessi (Page 47)
|
||||
- Gestione Dati (Page 45)
|
||||
- Critical configuration pages
|
||||
|
||||
---
|
||||
|
||||
## Application-Level Processes
|
||||
|
||||
### SET_USER_READONLY
|
||||
|
||||
**Process Point:** Before Header (runs on every page)
|
||||
**Sequence:** 1
|
||||
|
||||
```plsql
|
||||
begin
|
||||
select 1
|
||||
into :APP_READ_ONLY
|
||||
from users_readonly
|
||||
where username = :APP_USER
|
||||
and flgwrite = 0;
|
||||
exception when no_data_found then
|
||||
:APP_READ_ONLY := 0;
|
||||
end;
|
||||
```
|
||||
|
||||
**Sets:** `APP_READ_ONLY` application item
|
||||
- Value `1` = Read-only mode
|
||||
- Value `0` = Full access
|
||||
|
||||
This is checked in page processes with condition:
|
||||
```plsql
|
||||
:APP_READ_ONLY = 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### SET_ITEM_SESSION
|
||||
|
||||
**Process Point:** On Demand
|
||||
**Security:** MUST_NOT_BE_PUBLIC_USER
|
||||
|
||||
```plsql
|
||||
declare
|
||||
v_itemList varchar2(32000);
|
||||
begin
|
||||
v_itemList := APEX_UTIL.TABLE_TO_STRING(APEX_APPLICATION.G_F01);
|
||||
|
||||
for c in (
|
||||
select
|
||||
(select result from table(STRING_TO_TABLE_ENUM(a.result, 1, '='))) as item,
|
||||
(select result from table(STRING_TO_TABLE_ENUM(a.result, 2, '='))) as val
|
||||
from table(STRING_TO_TABLE_ENUM(v_itemList)) a
|
||||
)
|
||||
loop
|
||||
APEX_UTIL.set_session_state(
|
||||
p_name => c.item,
|
||||
p_value => c.val
|
||||
);
|
||||
end loop;
|
||||
end;
|
||||
```
|
||||
|
||||
**Usage:** Called by `setSessionState()` JavaScript function to update APEX session state for multiple items.
|
||||
|
||||
---
|
||||
|
||||
## Application Items
|
||||
|
||||
### APP_READ_ONLY
|
||||
|
||||
**Protection Level:** Internal
|
||||
**Escape on HTTP Output:** No
|
||||
|
||||
Stores the read-only flag for the current user session.
|
||||
|
||||
### APP_VERSION
|
||||
|
||||
Application version identifier.
|
||||
|
||||
---
|
||||
|
||||
## Authorization Hierarchy
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Solo Admins │
|
||||
│ (admin, monia) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Admin_auth_schema │
|
||||
│ (admin, monia, andrea, maria, sabrina, nicole, │
|
||||
│ cucina, developer, elia.ballarani) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Gestori │
|
||||
│ (from GET_GESTORI_USERS view) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Consuntivi │
|
||||
│ (from GET_CONSUNTIVI_USERS view) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ User Read/Write │
|
||||
│ (based on USERS_READONLY.FLGWRITE flag) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Authenticated Users │
|
||||
│ (basic application access) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Objects for Authorization
|
||||
|
||||
### USERS_READONLY Table
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| USERNAME | VARCHAR2 | APEX username |
|
||||
| FLGWRITE | NUMBER | 0 = read-only, 1 = write |
|
||||
|
||||
### GET_GESTORI_USERS View
|
||||
|
||||
Returns list of users with manager permissions.
|
||||
|
||||
### GET_CONSUNTIVI_USERS View
|
||||
|
||||
Returns list of users with financial access.
|
||||
|
||||
---
|
||||
|
||||
## Migration Notes
|
||||
|
||||
When migrating to .NET + React:
|
||||
|
||||
1. **Authentication**
|
||||
- Implement JWT or cookie-based authentication
|
||||
- Consider integration with existing Oracle users or migrate to new system
|
||||
|
||||
2. **Authorization**
|
||||
- Map authorization schemes to .NET roles/claims
|
||||
- Implement policy-based authorization in .NET
|
||||
|
||||
3. **Role Mapping**
|
||||
```csharp
|
||||
public enum UserRole
|
||||
{
|
||||
User, // Basic authenticated user
|
||||
ReadOnly, // Read-only access
|
||||
Consuntivi, // Financial access
|
||||
Gestori, // Manager level
|
||||
Admin, // Admin_auth_schema equivalent
|
||||
SuperAdmin // Solo Admins equivalent
|
||||
}
|
||||
```
|
||||
|
||||
4. **Frontend Authorization**
|
||||
- Store user roles in JWT/session
|
||||
- Implement route guards in React
|
||||
- Conditionally render UI elements based on permissions
|
||||
|
||||
5. **Backend Authorization**
|
||||
```csharp
|
||||
[Authorize(Policy = "Gestori")]
|
||||
public class EventController : Controller
|
||||
{
|
||||
[Authorize(Policy = "SoloAdmins")]
|
||||
public IActionResult DeleteEvent(int id) { ... }
|
||||
}
|
||||
```
|
||||
53282
docs/apex/f112.sql
Normal file
53282
docs/apex/f112.sql
Normal file
File diff suppressed because it is too large
Load Diff
330
docs/apex/javascript/README.md
Normal file
330
docs/apex/javascript/README.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# JavaScript Libraries Documentation
|
||||
|
||||
This document describes the custom JavaScript libraries used in the APEX application.
|
||||
|
||||
## Static Application Files
|
||||
|
||||
| File Name | Description |
|
||||
|-----------|-------------|
|
||||
| ajaxUtils.js | AJAX utilities for dynamic updates and server communication |
|
||||
| iframeObj.js | Jasper Reports integration wrapper |
|
||||
|
||||
---
|
||||
|
||||
## ajaxUtils.js
|
||||
|
||||
Custom AJAX utility library for managing server-side communication and UI feedback.
|
||||
|
||||
### Functions
|
||||
|
||||
#### `notifica(pText, pType = null)`
|
||||
|
||||
Central dynamic notification function.
|
||||
|
||||
**Parameters:**
|
||||
- `pText` (string): Message text to display
|
||||
- `pType` (string, optional): Notification type - 'alert', 'success', 'error', 'warning', 'info'
|
||||
|
||||
**Behavior:**
|
||||
- Clears existing errors
|
||||
- If `pType` is provided, shows error notification at page level
|
||||
- If `pType` is null, shows success message
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
notifica("Record saved successfully"); // Success message
|
||||
notifica("Error occurred", "error"); // Error message
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `setSessionState(elemList, pCallback = null)`
|
||||
|
||||
Sets APEX session state for multiple items.
|
||||
|
||||
**Parameters:**
|
||||
- `elemList` (string): Comma-separated list of item IDs (without P prefix)
|
||||
- `pCallback` (function, optional): Callback function after session state is set
|
||||
|
||||
**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 `SET_ITEM_SESSION` to update session state
|
||||
5. Executes callback with data and elements dictionary
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
setSessionState("P22_EVENT_ID,P22_CLIENTE", function(pData, elems) {
|
||||
console.log("Session state updated");
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `ajaxExec(pName, clickObj, pParams, pCallback, pConfirm, pLoading, pAsync, pType)`
|
||||
|
||||
Generic AJAX execution wrapper for APEX server processes.
|
||||
|
||||
**Parameters:**
|
||||
- `pName` (string): APEX process name to execute
|
||||
- `clickObj` (jQuery object): Button/element that triggered the action
|
||||
- `pParams` (object): Parameters to pass to the process
|
||||
- `pCallback` (function): Callback function on success/error
|
||||
- `pConfirm` (string): Confirmation message (uses native confirm dialog)
|
||||
- `pLoading` (boolean): Show loading popup
|
||||
- `pAsync` (boolean): Execute asynchronously
|
||||
- `pType` (string): Response data type (default: 'text')
|
||||
|
||||
**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
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
ajaxExec("SAVE_EVENT", clickBtn, {x01: eventId}, function(data, btn, params) {
|
||||
notifica("Event saved");
|
||||
}, "Are you sure?", true);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `execProcessAsync(pName, pParams, pPreExec, pCallback, pItems = null, clickObj = null, pConfirm = null, pLoading = null)`
|
||||
|
||||
Wrapper for async process execution with optional session state update.
|
||||
|
||||
**Parameters:**
|
||||
- `pName` (string): Process name
|
||||
- `pParams` (object): Process parameters
|
||||
- `pPreExec` (function): Function to execute before AJAX call
|
||||
- `pCallback` (function): Callback after process execution
|
||||
- `pItems` (string): Items to set in session state first
|
||||
- `clickObj`: Clicked element
|
||||
- `pConfirm` (string): Confirmation message
|
||||
- `pLoading` (boolean): Show loading indicator
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
execProcessAsync("UPDATE_QTY", {x01: itemId}, null, function(data) {
|
||||
apex.region("LIST_PREL").refresh();
|
||||
}, "P22_EVENT_ID");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `execQueryAsync(pQuery, pPreExec, pCallback, clickObj = null, pConfirm = null, pItems = null, pLoading = null)`
|
||||
|
||||
Executes a SQL query asynchronously.
|
||||
|
||||
**Parameters:**
|
||||
- `pQuery` (string): SQL query to execute
|
||||
- `pPreExec` (function): Pre-execution function
|
||||
- `pCallback` (function): Callback with query results
|
||||
- `clickObj`: Clicked element
|
||||
- `pConfirm` (string): Confirmation message
|
||||
- `pItems` (string): Items to set in session state
|
||||
- `pLoading` (boolean): Show loading indicator
|
||||
|
||||
**Note:** Calls the `EXEC_QUERY` APEX process with the query in `x01` parameter.
|
||||
|
||||
---
|
||||
|
||||
## iframeObj.js
|
||||
|
||||
JavaScript wrapper for embedding Jasper Reports in iframes.
|
||||
|
||||
### Configuration
|
||||
|
||||
```javascript
|
||||
var j_datasource = "default"; // Jasper datasource name
|
||||
var j_username = "jasperadmin"; // Jasper server username
|
||||
var j_password = "jasperadmin"; // Jasper server password
|
||||
var j_def_outp = "pdf"; // Default output format (HTML, PDF)
|
||||
```
|
||||
|
||||
### Iframe Class
|
||||
|
||||
#### Constructor
|
||||
|
||||
```javascript
|
||||
var Iframe = function(parentObj, id, attr) { ... }
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `parentObj`: Parent DOM element
|
||||
- `id`: Iframe element ID
|
||||
- `attr`: Additional attributes
|
||||
|
||||
### Methods
|
||||
|
||||
#### `setCss(css)`
|
||||
|
||||
Sets CSS styles on the iframe.
|
||||
|
||||
**Parameters:**
|
||||
- `css` (object): CSS properties dictionary
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
iframe.setCss({ width: "100%", height: "600px", border: "none" });
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `setUrl(Url)`
|
||||
|
||||
Sets the iframe source URL.
|
||||
|
||||
---
|
||||
|
||||
#### `getUrl()`
|
||||
|
||||
Returns the current iframe URL.
|
||||
|
||||
---
|
||||
|
||||
#### `refresh()`
|
||||
|
||||
Reloads the iframe content.
|
||||
|
||||
---
|
||||
|
||||
#### `hide()`
|
||||
|
||||
Hides the iframe (display: none).
|
||||
|
||||
---
|
||||
|
||||
#### `show()`
|
||||
|
||||
Shows the iframe (display: block).
|
||||
|
||||
---
|
||||
|
||||
#### `jasperReport(dir, datasource, params, output, username, password)`
|
||||
|
||||
Generates a Jasper Reports URL and loads it in the iframe.
|
||||
|
||||
**Parameters:**
|
||||
- `dir` (string, required): Report path in Jasper server
|
||||
- `datasource` (string): Data source name (default: "default")
|
||||
- `params` (object): Report parameters as key-value pairs
|
||||
- `output` (string): Output format - 'pdf' or 'html' (default: 'pdf')
|
||||
- `username` (string): Jasper server username
|
||||
- `password` (string): Jasper server password
|
||||
|
||||
**URL Format:**
|
||||
```
|
||||
/jri/report?_repName={dir}&_repFormat={output}&_dataSource={datasource}&_repLocale=it_IT&_repTimeZone=Europe/Rome&{params}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
var rptFrame = new Iframe(container, "reportFrame");
|
||||
rptFrame.jasperReport(
|
||||
"apcb/scheda_evento_rpt",
|
||||
"default",
|
||||
{ P_EVENT_ID: eventId, P_TIPO: "PREVENTIVO" },
|
||||
"pdf"
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage in APEX Pages
|
||||
|
||||
### Time Input Masks
|
||||
|
||||
The application uses inputmask library for time fields:
|
||||
|
||||
```javascript
|
||||
Inputmask("99:99", {
|
||||
placeholder: "HH:MM"
|
||||
}).mask($("#P22_ORA_INI_EVENTO"));
|
||||
```
|
||||
|
||||
### SweetAlert2 Integration
|
||||
|
||||
Used for enhanced confirmation dialogs:
|
||||
|
||||
```javascript
|
||||
Swal.fire({
|
||||
title: 'Conferma',
|
||||
text: 'Vuoi continuare?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// proceed
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Interactive Grid Refresh
|
||||
|
||||
```javascript
|
||||
// Refresh a specific interactive grid
|
||||
apex.region("LISTA_PRELIEVO").refresh();
|
||||
|
||||
// Refresh with callback
|
||||
apex.region("OSPITI").widget().interactiveGrid("getViews", "grid").model.fetchRecords();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration Notes
|
||||
|
||||
When migrating to React TypeScript:
|
||||
|
||||
1. **AJAX Utilities** - Replace with:
|
||||
- Axios or fetch for HTTP requests
|
||||
- React Query or SWR for data fetching
|
||||
- Toast library (react-toastify) for notifications
|
||||
|
||||
2. **Session State** - Replace with:
|
||||
- React Context or Redux for state management
|
||||
- URL parameters for shareable state
|
||||
- Session storage for persistence
|
||||
|
||||
3. **Jasper Reports** - Options:
|
||||
- Keep Jasper and embed via iframe
|
||||
- Migrate to SSRS, Crystal Reports
|
||||
- Use PDF libraries (QuestPDF, iTextSharp)
|
||||
- Use React-PDF for client-side PDF generation
|
||||
|
||||
4. **Input Masks** - Use:
|
||||
- react-input-mask
|
||||
- @react-input/mask
|
||||
- Material-UI TextField with InputProps
|
||||
|
||||
5. **SweetAlert2** - Replace with:
|
||||
- MUI Dialog components
|
||||
- react-confirm-alert
|
||||
- Custom modal component
|
||||
|
||||
### Example React Migration
|
||||
|
||||
```typescript
|
||||
// ajaxUtils.js equivalent in React
|
||||
import { toast } from 'react-toastify';
|
||||
import axios from 'axios';
|
||||
|
||||
export const notifica = (text: string, type?: 'success' | 'error' | 'warning' | 'info') => {
|
||||
if (type) {
|
||||
toast[type](text);
|
||||
} else {
|
||||
toast.success(text);
|
||||
}
|
||||
};
|
||||
|
||||
export const executeProcess = async <T>(
|
||||
processName: string,
|
||||
params: Record<string, any>
|
||||
): Promise<T> => {
|
||||
const response = await axios.post(`/api/processes/${processName}`, params);
|
||||
return response.data;
|
||||
};
|
||||
```
|
||||
242
docs/apex/lovs/README.md
Normal file
242
docs/apex/lovs/README.md
Normal file
@@ -0,0 +1,242 @@
|
||||
# List of Values (LOVs) Documentation
|
||||
|
||||
This document contains all 12 List of Values defined in the APEX application.
|
||||
|
||||
## Overview
|
||||
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
## ARTICOLI
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select /*a.cod_categ || ' - ' || c.descrizione || ' - ' ||*/ a.DESCRIZIONE as descrizione, a.COD_ARTICOLO
|
||||
from articoli a
|
||||
join tb_codici_categ c on a.cod_categ = c.cod_categ
|
||||
order by 1
|
||||
```
|
||||
|
||||
**Usage:** Selecting articles in pick lists and event details.
|
||||
|
||||
---
|
||||
|
||||
## CATEGORIE
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
SELECT descrizione as d,
|
||||
cod_categ as r
|
||||
FROM tb_codici_categ
|
||||
ORDER BY 1
|
||||
```
|
||||
|
||||
**Usage:** Filtering articles by category, category selection in forms.
|
||||
|
||||
---
|
||||
|
||||
## CLIENTI
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select CLIENTE, ID
|
||||
from clienti
|
||||
```
|
||||
|
||||
**Usage:** Client selection in event forms.
|
||||
|
||||
---
|
||||
|
||||
## LOCATION
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select location || ' - ' || indirizzo, id
|
||||
from location
|
||||
```
|
||||
|
||||
**Usage:** Location selection in event forms. Displays location name with address.
|
||||
|
||||
---
|
||||
|
||||
## RISORSE
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select NOME || ' ' || COGNOME d, id r
|
||||
from risorse
|
||||
```
|
||||
|
||||
**Usage:** Resource (staff) assignment in events. Displays full name.
|
||||
|
||||
---
|
||||
|
||||
## STATO_EVENTO
|
||||
|
||||
**Source Type:** Static
|
||||
|
||||
**Values:**
|
||||
|
||||
| Display Value | Return Value | Sequence |
|
||||
|---------------|--------------|----------|
|
||||
| Scheda Evento (Preparazione) | 0 | 10 |
|
||||
| Preventivo | 10 | 20 |
|
||||
| Confermato | 20 | 30 |
|
||||
|
||||
**Note:** The actual status values in the database have been expanded:
|
||||
- 100 = Preventivo
|
||||
- 200 = Scheda
|
||||
- 300 = Confermata
|
||||
- 350 = Quasi Confermato
|
||||
- 400 = Confermato
|
||||
- 900 = Superato
|
||||
|
||||
**Usage:** Event status display and selection.
|
||||
|
||||
---
|
||||
|
||||
## TIPI MAT
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
SELECT descrizione as d,
|
||||
cod_tipo as r
|
||||
FROM tb_tipi_mat
|
||||
ORDER BY 1
|
||||
```
|
||||
|
||||
**Usage:** Material type filtering in pick lists. Controls the step-by-step wizard flow.
|
||||
|
||||
---
|
||||
|
||||
## TIPI RISORSE
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select descrizione, cod_tipo
|
||||
from tb_tipi_risorsa
|
||||
```
|
||||
|
||||
**Usage:** Resource type classification (camerieri, cuochi, etc.).
|
||||
|
||||
---
|
||||
|
||||
## TIPO_EVENTO
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select trim(DESCRIZIONE) || decode(tipo_pasto, 'C', ' - Cena', 'P', ' - Pranzo', null) as d,
|
||||
COD_TIPO as r
|
||||
from tb_tipi_evento
|
||||
```
|
||||
|
||||
**Usage:** Event type selection. Displays description with meal type indicator (Pranzo/Cena).
|
||||
|
||||
---
|
||||
|
||||
## TIPO_OSPITI
|
||||
|
||||
**Source Type:** SQL Query (LEGACY_SQL)
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select descrizione as d,
|
||||
cod_tipo as r
|
||||
from tb_tipi_ospiti
|
||||
order by 1
|
||||
```
|
||||
|
||||
**Usage:** Guest type selection in event guest details.
|
||||
|
||||
---
|
||||
|
||||
## TIPO_PASTO
|
||||
|
||||
**Source Type:** Static
|
||||
|
||||
**Values:**
|
||||
|
||||
| Display Value | Return Value | Sequence |
|
||||
|---------------|--------------|----------|
|
||||
| Pranzo | P | 1 |
|
||||
| Cena | C | 2 |
|
||||
| Pranzo Buffet | A | 3 |
|
||||
| Cena Buffet | B | 4 |
|
||||
|
||||
**Usage:** Meal type classification for events and event types.
|
||||
|
||||
---
|
||||
|
||||
## USERS
|
||||
|
||||
**Source Type:** SQL Query
|
||||
|
||||
**Query:**
|
||||
```sql
|
||||
select user_name D, user_name R
|
||||
from WWV_FLOW_USERS
|
||||
```
|
||||
|
||||
**Return Column:** R
|
||||
**Display Column:** D
|
||||
|
||||
**Usage:** User selection for permissions and assignments.
|
||||
|
||||
---
|
||||
|
||||
## Migration Notes
|
||||
|
||||
When migrating to React TypeScript:
|
||||
|
||||
1. **Static LOVs** (STATO_EVENTO, TIPO_PASTO) can be implemented as TypeScript enums or const objects
|
||||
2. **SQL-based LOVs** should be converted to API endpoints
|
||||
3. Consider caching strategy for frequently used LOVs (CATEGORIE, TIPI MAT, etc.)
|
||||
4. TIPO_EVENTO uses Oracle `decode()` function - convert to CASE WHEN or handle in API
|
||||
|
||||
### Example TypeScript Implementation
|
||||
|
||||
```typescript
|
||||
// Static LOV - TIPO_PASTO
|
||||
export const TIPO_PASTO = {
|
||||
PRANZO: { value: 'P', label: 'Pranzo' },
|
||||
CENA: { value: 'C', label: 'Cena' },
|
||||
PRANZO_BUFFET: { value: 'A', label: 'Pranzo Buffet' },
|
||||
CENA_BUFFET: { value: 'B', label: 'Cena Buffet' },
|
||||
} as const;
|
||||
|
||||
// Dynamic LOV - API endpoint
|
||||
// GET /api/lovs/articoli
|
||||
// GET /api/lovs/categorie
|
||||
// GET /api/lovs/clienti
|
||||
// etc.
|
||||
```
|
||||
5
docs/apex/pages/PAGE_002.md
Normal file
5
docs/apex/pages/PAGE_002.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Page 2 - Articoli Rpt
|
||||
|
||||
## Items (1)
|
||||
|
||||
- `P2_IMMAGINE`
|
||||
25
docs/apex/pages/PAGE_003.md
Normal file
25
docs/apex/pages/PAGE_003.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Page 3 - Articoli
|
||||
|
||||
## Items (21)
|
||||
|
||||
- `P3_COD_ARTICOLO`
|
||||
- `P3_COD_CATEG`
|
||||
- `P3_COD_RELATIVO`
|
||||
- `P3_COEFF`
|
||||
- `P3_COEFF_A`
|
||||
- `P3_COEFF_B`
|
||||
- `P3_COEFF_S`
|
||||
- `P3_DESCRIZIONE`
|
||||
- `P3_FLG_CUCINA`
|
||||
- `P3_IMMAGINE`
|
||||
- `P3_IMMAGINE_DISPLAY`
|
||||
- `P3_PERC_IVA`
|
||||
- `P3_PERC_OSPITI`
|
||||
- `P3_QTAGIAC`
|
||||
- `P3_QTAIMP`
|
||||
- `P3_QTA_STD_A`
|
||||
- `P3_QTA_STD_B`
|
||||
- `P3_QTA_STD_S`
|
||||
- `P3_RANK`
|
||||
- `P3_ROWID`
|
||||
- `P3_TIPO_QTA`
|
||||
13
docs/apex/pages/PAGE_005.md
Normal file
13
docs/apex/pages/PAGE_005.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Page 5 - Categorie
|
||||
|
||||
## Items (9)
|
||||
|
||||
- `P5_COD_CATEG`
|
||||
- `P5_COD_TIPO`
|
||||
- `P5_COEFF_A`
|
||||
- `P5_COEFF_B`
|
||||
- `P5_COEFF_S`
|
||||
- `P5_DESCRIZIONE`
|
||||
- `P5_ROWID`
|
||||
- `P5_SHOW_PRINT`
|
||||
- `P5_TIPO_RIEPILOGO`
|
||||
7
docs/apex/pages/PAGE_007.md
Normal file
7
docs/apex/pages/PAGE_007.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Page 7 - Tipi
|
||||
|
||||
## Items (3)
|
||||
|
||||
- `P7_COD_TIPO`
|
||||
- `P7_DESCRIZIONE`
|
||||
- `P7_ROWID`
|
||||
39
docs/apex/pages/PAGE_008.md
Normal file
39
docs/apex/pages/PAGE_008.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Page 8 - Creazione Evento
|
||||
|
||||
## Items (35)
|
||||
|
||||
- `P8_ALLERGIE`
|
||||
- `P8_CATEG`
|
||||
- `P8_CATEG_FILTER`
|
||||
- `P8_CLIENTE`
|
||||
- `P8_CLIENTE_DISPLAY`
|
||||
- `P8_COD_TIPO`
|
||||
- `P8_COD_TIPO_DISPLAY`
|
||||
- `P8_COD_TIPO_FILTER`
|
||||
- `P8_CONFETTATA`
|
||||
- `P8_DATA`
|
||||
- `P8_DATA_DISPLAY`
|
||||
- `P8_DESCRIZIONE`
|
||||
- `P8_DESCRIZIONE_DISPLAY`
|
||||
- `P8_EVENT_ID`
|
||||
- `P8_FLG_TEMPLATE`
|
||||
- `P8_ID_IMAGE_SHOW`
|
||||
- `P8_INDIRIZZO`
|
||||
- `P8_INDIRIZZO_DISPLAY`
|
||||
- `P8_LOCATION`
|
||||
- `P8_LOCATION_DISPLAY`
|
||||
- `P8_MAXSTEP`
|
||||
- `P8_NOTE`
|
||||
- `P8_NOTE_DISPLAY`
|
||||
- `P8_ORA_INI_CER`
|
||||
- `P8_ORA_INI_EVT`
|
||||
- `P8_PERC_SEDUTE`
|
||||
- `P8_STAMPA_MENU`
|
||||
- `P8_STEP`
|
||||
- `P8_TAVOLI_NR`
|
||||
- `P8_TORTA`
|
||||
- `P8_TORTA_DISPLAY`
|
||||
- `P8_TOT_ADULTI`
|
||||
- `P8_TOT_BABY`
|
||||
- `P8_TOT_KINDER`
|
||||
- `P8_TOT_OSPITI`
|
||||
6
docs/apex/pages/PAGE_010.md
Normal file
6
docs/apex/pages/PAGE_010.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 10 - Anteprima Immagine
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P10_IMMAGINE`
|
||||
- `P10_ROWID`
|
||||
5
docs/apex/pages/PAGE_011.md
Normal file
5
docs/apex/pages/PAGE_011.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Page 11 - Stampa Riepilogo
|
||||
|
||||
## Items (1)
|
||||
|
||||
- `P11_EVENT_ID`
|
||||
9
docs/apex/pages/PAGE_014.md
Normal file
9
docs/apex/pages/PAGE_014.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Page 14 - Tipi Evento
|
||||
|
||||
## Items (5)
|
||||
|
||||
- `P14_COD_TIPO`
|
||||
- `P14_DESCRIZIONE`
|
||||
- `P14_LIVELLO`
|
||||
- `P14_ROWID`
|
||||
- `P14_TIPO_PASTO`
|
||||
5
docs/apex/pages/PAGE_016.md
Normal file
5
docs/apex/pages/PAGE_016.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Page 16 - Griglia
|
||||
|
||||
## Items (1)
|
||||
|
||||
- `P16_SETTIMANA`
|
||||
14
docs/apex/pages/PAGE_018.md
Normal file
14
docs/apex/pages/PAGE_018.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Page 18 - Clienti
|
||||
|
||||
## Items (10)
|
||||
|
||||
- `P18_CLIENTE`
|
||||
- `P18_COGNOME_RIF`
|
||||
- `P18_INDIRIZZO`
|
||||
- `P18_MAIL`
|
||||
- `P18_NOME_RIF`
|
||||
- `P18_PIVA`
|
||||
- `P18_RAGSOC`
|
||||
- `P18_ROWID`
|
||||
- `P18_TEL1`
|
||||
- `P18_TEL2`
|
||||
20
docs/apex/pages/PAGE_019.md
Normal file
20
docs/apex/pages/PAGE_019.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Page 19 - Articoli Popup
|
||||
|
||||
## Items (16)
|
||||
|
||||
- `P19_COD_ARTICOLO`
|
||||
- `P19_COD_CATEG`
|
||||
- `P19_COD_RELATIVO`
|
||||
- `P19_COEFF`
|
||||
- `P19_COEFF_A`
|
||||
- `P19_COEFF_B`
|
||||
- `P19_COEFF_S`
|
||||
- `P19_DESCRIZIONE`
|
||||
- `P19_FLG_CUCINA`
|
||||
- `P19_IMMAGINE`
|
||||
- `P19_IMMAGINE_DISPLAY`
|
||||
- `P19_QTA_STD_A`
|
||||
- `P19_QTA_STD_B`
|
||||
- `P19_QTA_STD_S`
|
||||
- `P19_ROWID`
|
||||
- `P19_TIPO_QTA`
|
||||
11
docs/apex/pages/PAGE_020.md
Normal file
11
docs/apex/pages/PAGE_020.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Page 20 - Location
|
||||
|
||||
## Items (7)
|
||||
|
||||
- `P20_ID`
|
||||
- `P20_INDIRIZZO`
|
||||
- `P20_LOCATION`
|
||||
- `P20_NOTE`
|
||||
- `P20_NOTE2`
|
||||
- `P20_REFERENTE`
|
||||
- `P20_ROWID`
|
||||
5
docs/apex/pages/PAGE_021.md
Normal file
5
docs/apex/pages/PAGE_021.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Page 21 - Costi Articolo
|
||||
|
||||
## Items (1)
|
||||
|
||||
- `P21_COD_ARTICOLO`
|
||||
112
docs/apex/pages/PAGE_022.md
Normal file
112
docs/apex/pages/PAGE_022.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Page 22 - Evento
|
||||
|
||||
## Items (108)
|
||||
|
||||
- `P22_ALLERGIE`
|
||||
- `P22_ALLEST_BUFF`
|
||||
- `P22_ALTRO`
|
||||
- `P22_ALTRO_A`
|
||||
- `P22_ALTRO_B`
|
||||
- `P22_ARTICOLO_ADD`
|
||||
- `P22_ARTICOLO_REMOVE`
|
||||
- `P22_BICCHIERI`
|
||||
- `P22_BUFFET_DOLCI_A`
|
||||
- `P22_BUFFET_DOLCI_B`
|
||||
- `P22_BUFFET_FINALE`
|
||||
- `P22_BUFFET_FINALE_DISPLAY`
|
||||
- `P22_BUFFET_INIZIALE`
|
||||
- `P22_BUFFET_INIZIALE_DISPLAY`
|
||||
- `P22_CARICOAPOLL`
|
||||
- `P22_CARICOSPOSI`
|
||||
- `P22_CATEG`
|
||||
- `P22_CATEG_FILTER`
|
||||
- `P22_CLIENTE`
|
||||
- `P22_CLIENTE_EMAIL`
|
||||
- `P22_CLIENTE_TEL`
|
||||
- `P22_COD_TIPO`
|
||||
- `P22_COD_TIPO_FILTER`
|
||||
- `P22_COLOR`
|
||||
- `P22_CONSUNTIVO_MORE_DETAILS`
|
||||
- `P22_CONTRATTO_FIRMATO`
|
||||
- `P22_DATA`
|
||||
- `P22_DATA_DOC`
|
||||
- `P22_DATA_SCAD_PREVENTIVO`
|
||||
- `P22_DATORASCARICO`
|
||||
- `P22_DATORASCARICO_NOTE`
|
||||
- `P22_DELETED`
|
||||
- `P22_DELETED_BY`
|
||||
- `P22_DELETED_DATE`
|
||||
- `P22_DESCRIZIONE`
|
||||
- `P22_DISABLED`
|
||||
- `P22_DISTANZA_LOCATION`
|
||||
- `P22_EVENT_ID`
|
||||
- `P22_EVENT_ID_DISPLAY`
|
||||
- `P22_EXTRA`
|
||||
- `P22_EXTRA_COSTI`
|
||||
- `P22_FLG_SUPERATO`
|
||||
- `P22_FLG_TEMPLATE`
|
||||
- `P22_GGSETT`
|
||||
- `P22_GRAN_BUFFET_A`
|
||||
- `P22_GRAN_BUFFET_B`
|
||||
- `P22_ID_EVT_FIGLIO`
|
||||
- `P22_ID_EVT_PADRE`
|
||||
- `P22_ID_IMAGE_SHOW`
|
||||
- `P22_INDIRIZZO`
|
||||
- `P22_IS_TEMPLATE`
|
||||
- `P22_LISTA_PRINT`
|
||||
- `P22_LOCATION`
|
||||
- `P22_LOCATION_DESCRI`
|
||||
- `P22_MAIL_ENABLED`
|
||||
- `P22_MAXSTEP`
|
||||
- `P22_NEW`
|
||||
- `P22_NEW_EVENT_ID`
|
||||
- `P22_NOTE`
|
||||
- `P22_NOTE_INVIO`
|
||||
- `P22_NUMALTRI`
|
||||
- `P22_NUMDEGUSTAZIONI`
|
||||
- `P22_NUM_LISTA`
|
||||
- `P22_ORA_CERIMONIA`
|
||||
- `P22_ORA_EVENTO`
|
||||
- `P22_ORA_FINE_CERIMONIA`
|
||||
- `P22_ORA_FINE_EVENTO`
|
||||
- `P22_ORA_FI_CER`
|
||||
- `P22_ORA_FI_EVENTO`
|
||||
- `P22_ORA_INI_CER`
|
||||
- `P22_ORA_INI_EVENTO`
|
||||
- `P22_PERC_SEDUTE`
|
||||
- `P22_PERMES_CONSUNTIVI_REPORT`
|
||||
- `P22_PIATTI`
|
||||
- `P22_PIATTINO_PANE`
|
||||
- `P22_POSATE`
|
||||
- `P22_PRE_BOUV_A`
|
||||
- `P22_PRE_BOUV_B`
|
||||
- `P22_PRIMI`
|
||||
- `P22_PRIMI_DISPLAY`
|
||||
- `P22_REFERENTE_TEL`
|
||||
- `P22_RISORSA_ADD`
|
||||
- `P22_RISORSA_REMOVE`
|
||||
- `P22_RUNNER`
|
||||
- `P22_SCADUTO`
|
||||
- `P22_SECONDI`
|
||||
- `P22_SEDIA`
|
||||
- `P22_SERVIZIO_TAVOLO_A`
|
||||
- `P22_SERVIZIO_TAVOLO_B`
|
||||
- `P22_SOTTOPIATTI`
|
||||
- `P22_STATO`
|
||||
- `P22_STATUS`
|
||||
- `P22_STEP`
|
||||
- `P22_STILE_COLORI`
|
||||
- `P22_TIPOL_TAV_OSPITI`
|
||||
- `P22_TIPOL_TAV_SPOSI`
|
||||
- `P22_TIPORIS_FILTER`
|
||||
- `P22_TORTA`
|
||||
- `P22_TORTA_A`
|
||||
- `P22_TORTA_B`
|
||||
- `P22_TOT_OSPITI`
|
||||
- `P22_TOVAGLIA`
|
||||
- `P22_TOVAGLIOLO`
|
||||
- `P22_VERSION_DISPLAY`
|
||||
- `P22_VERS_NUMBER`
|
||||
- `P22_VERS_TOKEN`
|
||||
- `P22_VINI`
|
||||
- `P22_VINI_DISPLAY`
|
||||
6
docs/apex/pages/PAGE_024.md
Normal file
6
docs/apex/pages/PAGE_024.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 24 - Stampa Riepilogo Extra
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P24_DATA_FI`
|
||||
- `P24_DATA_IN`
|
||||
6
docs/apex/pages/PAGE_025.md
Normal file
6
docs/apex/pages/PAGE_025.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 25 - Cucina
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P25_DATA_FI`
|
||||
- `P25_DATA_IN`
|
||||
6
docs/apex/pages/PAGE_026.md
Normal file
6
docs/apex/pages/PAGE_026.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 26 - Stampa Riepilogo Cucina
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P26_DATA_FI`
|
||||
- `P26_DATA_IN`
|
||||
6
docs/apex/pages/PAGE_027.md
Normal file
6
docs/apex/pages/PAGE_027.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 27 - Degustazioni_Lista
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P27_DATA_FI`
|
||||
- `P27_DATA_IN`
|
||||
6
docs/apex/pages/PAGE_028.md
Normal file
6
docs/apex/pages/PAGE_028.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 28 - Torte e Costi Extra
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P28_DATA_FI`
|
||||
- `P28_DATA_IN`
|
||||
6
docs/apex/pages/PAGE_029.md
Normal file
6
docs/apex/pages/PAGE_029.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 29 - Stampa Riepilogo Allestimenti
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P29_DATA_FI`
|
||||
- `P29_DATA_IN`
|
||||
6
docs/apex/pages/PAGE_030.md
Normal file
6
docs/apex/pages/PAGE_030.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 30 - Riepilogo Allestimenti
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P30_DATA_FI`
|
||||
- `P30_DATA_IN`
|
||||
18
docs/apex/pages/PAGE_032.md
Normal file
18
docs/apex/pages/PAGE_032.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Page 32 - Degustazioni
|
||||
|
||||
## Items (14)
|
||||
|
||||
- `P32_DATA`
|
||||
- `P32_EMAIL`
|
||||
- `P32_ID`
|
||||
- `P32_ID_EVENTO`
|
||||
- `P32_LOCATION`
|
||||
- `P32_MENU`
|
||||
- `P32_NOME`
|
||||
- `P32_NOTE`
|
||||
- `P32_N_DEGUSTAZIONE`
|
||||
- `P32_N_PAGANTI`
|
||||
- `P32_N_PERSONE`
|
||||
- `P32_ORA`
|
||||
- `P32_ROWID`
|
||||
- `P32_TELEFONO`
|
||||
6
docs/apex/pages/PAGE_033.md
Normal file
6
docs/apex/pages/PAGE_033.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 33 - Stampa Scheda Evento
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P33_EVENT_ID`
|
||||
- `P33_LISTA`
|
||||
6
docs/apex/pages/PAGE_035.md
Normal file
6
docs/apex/pages/PAGE_035.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 35 - Lista Schede Evento
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P35_DATEFROM`
|
||||
- `P35_DATETO`
|
||||
6
docs/apex/pages/PAGE_036.md
Normal file
6
docs/apex/pages/PAGE_036.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 36 - Stampa Riepilogo Degustazioni
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P36_DATA_FI`
|
||||
- `P36_DATA_IN`
|
||||
7
docs/apex/pages/PAGE_038.md
Normal file
7
docs/apex/pages/PAGE_038.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Page 38 - Riepilogo Risorse
|
||||
|
||||
## Items (3)
|
||||
|
||||
- `P38_COD_AZIENDA`
|
||||
- `P38_DATA_FI`
|
||||
- `P38_DATA_IN`
|
||||
8
docs/apex/pages/PAGE_039.md
Normal file
8
docs/apex/pages/PAGE_039.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Page 39 - Impegni Articoli
|
||||
|
||||
## Items (4)
|
||||
|
||||
- `P39_COD_ARTICOLO`
|
||||
- `P39_DATA_FI`
|
||||
- `P39_DATA_IN`
|
||||
- `P39_SHOW_HISTORY`
|
||||
7
docs/apex/pages/PAGE_040.md
Normal file
7
docs/apex/pages/PAGE_040.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Page 40 - Stampa Riepilogo Risorse
|
||||
|
||||
## Items (3)
|
||||
|
||||
- `P40_COD_AZIENDA`
|
||||
- `P40_DATA_FI`
|
||||
- `P40_DATA_IN`
|
||||
5
docs/apex/pages/PAGE_041.md
Normal file
5
docs/apex/pages/PAGE_041.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Page 41 - Backup
|
||||
|
||||
## Items (1)
|
||||
|
||||
- `P41_BCKPASSWORD`
|
||||
12
docs/apex/pages/PAGE_042.md
Normal file
12
docs/apex/pages/PAGE_042.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Page 42 - Nuovo Allegato Evento
|
||||
|
||||
## Items (8)
|
||||
|
||||
- `P42_CHARSET`
|
||||
- `P42_EVENT_ID`
|
||||
- `P42_FILENAME`
|
||||
- `P42_FILESIZELIMITKB`
|
||||
- `P42_ID`
|
||||
- `P42_LAST_UPDATE`
|
||||
- `P42_MIME_TYPE`
|
||||
- `P42_RAW_DATA`
|
||||
5
docs/apex/pages/PAGE_043.md
Normal file
5
docs/apex/pages/PAGE_043.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Page 43 - Registro Acconti Evento
|
||||
|
||||
## Items (1)
|
||||
|
||||
- `P43_ID_EVENTO`
|
||||
5
docs/apex/pages/PAGE_044.md
Normal file
5
docs/apex/pages/PAGE_044.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Page 44 - Registro Altri Costi
|
||||
|
||||
## Items (1)
|
||||
|
||||
- `P44_ID_EVENTO`
|
||||
8
docs/apex/pages/PAGE_045.md
Normal file
8
docs/apex/pages/PAGE_045.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Page 45 - GestioneDati
|
||||
|
||||
## Items (4)
|
||||
|
||||
- `P45_CONSUNTIVI_A`
|
||||
- `P45_CONSUNTIVI_DA`
|
||||
- `P45_EVENTI_A`
|
||||
- `P45_EVENTI_DA`
|
||||
6
docs/apex/pages/PAGE_046.md
Normal file
6
docs/apex/pages/PAGE_046.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 46 - Imposta Blocco Calendario
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P46_GIORNO`
|
||||
- `P46_MAX_EVENTI`
|
||||
6
docs/apex/pages/PAGE_047.md
Normal file
6
docs/apex/pages/PAGE_047.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 47 - Permessi
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P47_CONSUNTIVI_USERS`
|
||||
- `P47_GESTORI_USERS`
|
||||
10
docs/apex/pages/PAGE_052.md
Normal file
10
docs/apex/pages/PAGE_052.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Page 52 - send_mail_modal
|
||||
|
||||
## Items (6)
|
||||
|
||||
- `P52_DATA_FROM`
|
||||
- `P52_DATA_FROM_DISPLAY`
|
||||
- `P52_DATA_TO`
|
||||
- `P52_DATA_TO_DISPLAY`
|
||||
- `P52_MAIL_BODY`
|
||||
- `P52_MAIL_SUBJECT`
|
||||
11
docs/apex/pages/PAGE_053.md
Normal file
11
docs/apex/pages/PAGE_053.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Page 53 - COPIA_LISTA_PAGE
|
||||
|
||||
## Items (7)
|
||||
|
||||
- `P53_COPIA_ACCONTI`
|
||||
- `P53_COPIA_ALTRICOSTI`
|
||||
- `P53_COPIA_DEGUSTAZIONI`
|
||||
- `P53_COPIA_PRELIEVI`
|
||||
- `P53_COPIA_RISORSE`
|
||||
- `P53_EVENTO_FROM`
|
||||
- `P53_EVENTO_TO`
|
||||
6
docs/apex/pages/PAGE_101.md
Normal file
6
docs/apex/pages/PAGE_101.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Page 101 - Login Page
|
||||
|
||||
## Items (2)
|
||||
|
||||
- `P101_PASSWORD`
|
||||
- `P101_USERNAME`
|
||||
7
docs/apex/pages/PAGE_999.md
Normal file
7
docs/apex/pages/PAGE_999.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Page 999 - Stampa Preventivo
|
||||
|
||||
## Items (3)
|
||||
|
||||
- `P999_EVENT_ID`
|
||||
- `P999_MORE_DETAILS`
|
||||
- `P999_SHOW_ECONOMICS`
|
||||
558
docs/apex/processes/README.md
Normal file
558
docs/apex/processes/README.md
Normal file
@@ -0,0 +1,558 @@
|
||||
# APEX Processes Documentation
|
||||
|
||||
This document contains all 98 processes defined in the APEX application, organized by page.
|
||||
|
||||
## Process Overview
|
||||
|
||||
| Process Type | Count |
|
||||
|--------------|-------|
|
||||
| NATIVE_FORM_INIT | Multiple |
|
||||
| NATIVE_FORM_DML | Multiple |
|
||||
| NATIVE_PLSQL | Multiple |
|
||||
| NATIVE_IG_DML | Multiple |
|
||||
| NATIVE_SESSION_STATE | Multiple |
|
||||
|
||||
---
|
||||
|
||||
## Shared (Application-Level) Processes
|
||||
|
||||
### SET_USER_READONLY
|
||||
|
||||
**Process Point:** Before Header (runs on every page)
|
||||
**Type:** NATIVE_PLSQL
|
||||
|
||||
Sets the `APP_READ_ONLY` application item based on user permissions.
|
||||
|
||||
```plsql
|
||||
begin
|
||||
if F_USER_IN_ROLE(:APP_USER, 'READONLY') then
|
||||
:APP_READ_ONLY := 1;
|
||||
else
|
||||
:APP_READ_ONLY := 0;
|
||||
end if;
|
||||
end;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Page 3 - Articoli (Article Form)
|
||||
|
||||
### Fetch Row from ARTICOLI
|
||||
**Process Point:** After Header
|
||||
**Type:** NATIVE_FORM_INIT
|
||||
|
||||
Initializes form with article data.
|
||||
|
||||
### Process Row of ARTICOLI
|
||||
**Process Point:** After Submit
|
||||
**Type:** NATIVE_FORM_DML
|
||||
|
||||
Saves/updates article record.
|
||||
|
||||
### Delete Image
|
||||
**Process Point:** After Submit
|
||||
**Type:** NATIVE_PLSQL
|
||||
**Button:** Delete Image
|
||||
|
||||
```plsql
|
||||
begin
|
||||
update articoli
|
||||
set
|
||||
raw_data = null,
|
||||
last_update = null,
|
||||
charset = null,
|
||||
mimetype = null,
|
||||
filename = null
|
||||
where rowid = :P3_ROWID;
|
||||
end;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Page 22 - Nuovo Evento (Main Event Form)
|
||||
|
||||
Page 22 is the most complex page with 32 processes.
|
||||
|
||||
### After Header Processes
|
||||
|
||||
#### Get Event Details
|
||||
**Sequence:** 10
|
||||
**Type:** NATIVE_FORM_INIT
|
||||
|
||||
Fetches event record into form items.
|
||||
|
||||
#### Set Ospiti on load
|
||||
**Sequence:** 20
|
||||
**Type:** NATIVE_PLSQL
|
||||
|
||||
```plsql
|
||||
begin
|
||||
EVENTI_AGGIORNA_TOT_OSPITI(:P22_EVENT_ID);
|
||||
end;
|
||||
```
|
||||
|
||||
#### Default Values
|
||||
**Sequence:** 40
|
||||
**Type:** NATIVE_PLSQL
|
||||
|
||||
```plsql
|
||||
begin
|
||||
select trim(l.location)
|
||||
into :P22_LOCATION_DESCRI
|
||||
from eventi e
|
||||
join location l on l.id = e.id_location
|
||||
where e.id = :P22_EVENT_ID;
|
||||
exception when no_data_found then
|
||||
null;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Normalizza dati
|
||||
**Sequence:** 50
|
||||
**Type:** NATIVE_PLSQL
|
||||
|
||||
Formats time values for display:
|
||||
|
||||
```plsql
|
||||
:P22_ORA_INI_CER := to_char(to_date(:P22_ORA_CERIMONIA, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');
|
||||
:P22_ORA_INI_EVENTO := to_char(to_date(:P22_ORA_EVENTO, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');
|
||||
:P22_ORA_FI_CER := to_char(to_date(:ORA_FINE_CERIMONIA, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');
|
||||
:P22_ORA_FI_EVENTO := to_char(to_date(:ORA_FINE_EVENTO, 'DD-MM-YYYY HH24:MI'), 'hh24:mi');
|
||||
```
|
||||
|
||||
#### New Template Default Data
|
||||
**Sequence:** 60
|
||||
**Condition:** P22_IS_TEMPLATE is not null
|
||||
|
||||
```plsql
|
||||
:P22_DATA := sysdate;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### After Submit Processes
|
||||
|
||||
#### Set Date Default if Template
|
||||
**Sequence:** 10
|
||||
**Condition:** P22_IS_TEMPLATE is not null
|
||||
|
||||
```plsql
|
||||
:P22_DATA := sysdate;
|
||||
```
|
||||
|
||||
#### Delete Template
|
||||
**Sequence:** 20
|
||||
**Button:** Delete Template
|
||||
**Condition:** P22_IS_TEMPLATE is not null
|
||||
|
||||
```plsql
|
||||
delete from eventi where id = :P22_EVENT_ID;
|
||||
```
|
||||
|
||||
#### Genera Evento da Template
|
||||
**Sequence:** 30
|
||||
**Button:** Generate from Template
|
||||
**Condition:** P22_IS_TEMPLATE is not null
|
||||
|
||||
```plsql
|
||||
EVENTI_COPIA
|
||||
(
|
||||
ID_EVENTO_OLD => :P22_EVENT_ID,
|
||||
NUOVA_VERSIONE => 0,
|
||||
ID_EVENTO_NEW => :P22_EVENT_ID
|
||||
);
|
||||
```
|
||||
|
||||
#### Formatta Ore Inizio
|
||||
**Sequence:** 40
|
||||
|
||||
Combines date and time for storage:
|
||||
|
||||
```plsql
|
||||
:P22_ORA_EVENTO := :P22_DATA || ' ' || :P22_ORA_INI_EVENTO;
|
||||
:P22_ORA_CERIMONIA := :P22_DATA || ' ' || :P22_ORA_INI_CER;
|
||||
```
|
||||
|
||||
#### Prepara Acconti Automatici
|
||||
**Sequence:** 50
|
||||
**Condition:** REQUEST in ('PREPARA_ACCONTI', 'PRINT_PREVENTIVO')
|
||||
|
||||
```plsql
|
||||
EVENTI_RICALCOLA_ACCONTI(p_event_id => :P22_EVENT_ID);
|
||||
```
|
||||
|
||||
**Comment:** Default 3 deposits: 30%, 50%, 20%
|
||||
|
||||
#### Go Forward
|
||||
**Sequence:** 60
|
||||
**Button:** NEXT
|
||||
|
||||
Navigates to next wizard step:
|
||||
|
||||
```plsql
|
||||
declare
|
||||
v_step number;
|
||||
begin
|
||||
begin
|
||||
select min(cod_step)
|
||||
into v_step
|
||||
from tb_tipi_mat
|
||||
where cod_step > TO_NUMBER(:P22_STEP);
|
||||
end;
|
||||
|
||||
begin
|
||||
select cod_tipo
|
||||
into :P22_COD_TIPO_FILTER
|
||||
from tb_tipi_mat
|
||||
where cod_step = v_step;
|
||||
exception when no_data_found
|
||||
then raise_application_error(-20001, 'Errore sconosciuto');
|
||||
end;
|
||||
|
||||
:P22_STEP := v_step;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Go Backward
|
||||
**Sequence:** 70
|
||||
**Button:** PREVIOUS
|
||||
|
||||
Navigates to previous wizard step.
|
||||
|
||||
#### Tipo Ospiti - Save Interactive Grid Data
|
||||
**Sequence:** 80
|
||||
**Region:** Guest Types Grid
|
||||
**Type:** NATIVE_IG_DML
|
||||
**Condition:** APP_READ_ONLY = 0
|
||||
|
||||
Saves guest type records.
|
||||
|
||||
#### Tipo Ospiti - Aggiorna Lista Prelievo
|
||||
**Sequence:** 90
|
||||
**Type:** NATIVE_PLSQL
|
||||
**Condition:** APP_READ_ONLY = 0
|
||||
|
||||
Recalculates pick list quantities after guest changes:
|
||||
|
||||
```plsql
|
||||
EVENTI_AGGIORNA_QTA_LISTA(
|
||||
P_ID_EVENTO => :P22_EVENT_ID
|
||||
);
|
||||
```
|
||||
|
||||
#### Degustazioni - Save Interactive Grid Data
|
||||
**Sequence:** 100
|
||||
**Region:** Tastings Grid
|
||||
**Type:** NATIVE_IG_DML
|
||||
|
||||
#### Delete Eventi Childs
|
||||
**Sequence:** 110
|
||||
**Button:** DELETE
|
||||
**Condition:** NEVER (disabled)
|
||||
|
||||
```plsql
|
||||
begin
|
||||
delete from eventi_det_ospiti
|
||||
where id_evento = :P22_EVENT_ID;
|
||||
|
||||
delete from eventi_det_prel
|
||||
where id_evento = :P22_EVENT_ID;
|
||||
|
||||
delete from eventi_det_ris
|
||||
where id_evento = :P22_EVENT_ID;
|
||||
|
||||
delete from eventi_det_degust
|
||||
where id_evento = :P22_EVENT_ID;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Set Obsoleto
|
||||
**Sequence:** 120
|
||||
**Button:** Set Obsolete
|
||||
**Condition:** APP_READ_ONLY = 0
|
||||
|
||||
Marks event as expired/cancelled:
|
||||
|
||||
```plsql
|
||||
begin
|
||||
UPDATE EVENTI
|
||||
SET FLG_SUPERATO = 1, STATO = 900, MAIL_ENABLED = 0
|
||||
WHERE ID = :P22_EVENT_ID;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Salva Evento
|
||||
**Sequence:** 130
|
||||
**Condition:** Complex (handles CREATE, SAVE, DELETE)
|
||||
|
||||
Main event save process. Full implementation handles:
|
||||
- All event fields mapping
|
||||
- Email validation
|
||||
- Status-based logic
|
||||
- Versioning support
|
||||
- Soft delete
|
||||
|
||||
Key excerpts:
|
||||
|
||||
```plsql
|
||||
declare
|
||||
r_eventi eventi%rowtype;
|
||||
begin
|
||||
if :REQUEST = 'PREVIOUS' or :REQUEST = 'NEXT'
|
||||
then
|
||||
return;
|
||||
end if;
|
||||
|
||||
if(:P22_DATA is null)
|
||||
then
|
||||
raise_application_error(-20001, 'Inserire la data evento');
|
||||
end if;
|
||||
|
||||
-- Set all row fields
|
||||
r_eventi."ID" := :P22_EVENT_ID;
|
||||
r_eventi.DESCRIZIONE := :P22_DESCRIZIONE;
|
||||
r_eventi.COD_TIPO := :P22_COD_TIPO;
|
||||
-- ... (all other fields)
|
||||
|
||||
-- Email validation
|
||||
IF REGEXP_LIKE(:P22_CLIENTE_EMAIL, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
|
||||
OR :P22_CLIENTE_EMAIL IS NULL THEN
|
||||
r_eventi.CLIENTE_EMAIL := :P22_CLIENTE_EMAIL;
|
||||
ELSE
|
||||
RAISE_APPLICATION_ERROR(-20005, 'Formato email cliente non valido');
|
||||
END IF;
|
||||
|
||||
-- Versioning
|
||||
r_eventi.VERS_NUMBER := nvl(:P22_VERS_NUMBER, 0);
|
||||
r_eventi.VERS_TOKEN := :P22_VERS_TOKEN;
|
||||
|
||||
case :REQUEST
|
||||
when 'SAVE' then
|
||||
update eventi set row = r_eventi where id = :P22_EVENT_ID;
|
||||
when 'CREATE' then
|
||||
insert into eventi values r_eventi returning id into :P22_EVENT_ID;
|
||||
when 'DELETE' then
|
||||
if r_eventi.ID_EVT_FIGLIO is not null or r_eventi.ID_EVT_PADRE is not null
|
||||
then
|
||||
raise_application_error(-20001, 'Impossibile eliminare un evento...');
|
||||
end if;
|
||||
update eventi
|
||||
set deleted = 1,
|
||||
deleted_by = :APP_USER,
|
||||
deleted_date = sysdate
|
||||
where id = r_eventi."ID";
|
||||
else
|
||||
null;
|
||||
end case;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Nuova Versione
|
||||
**Sequence:** 140
|
||||
**Button:** New Version
|
||||
|
||||
Creates a new version of the event:
|
||||
|
||||
```plsql
|
||||
EVENTI_COPIA
|
||||
(
|
||||
ID_EVENTO_OLD => :P22_EVENT_ID,
|
||||
NUOVA_VERSIONE => 1,
|
||||
ID_EVENTO_NEW => :P22_NEW_EVENT_ID
|
||||
);
|
||||
```
|
||||
|
||||
#### Lista Prelievo - Save Interactive Grid Data
|
||||
**Sequence:** 150
|
||||
**Type:** NATIVE_IG_DML
|
||||
**Table:** EVENTI_DET_PREL
|
||||
|
||||
Saves pick list records.
|
||||
|
||||
#### Continue Event
|
||||
**Sequence:** 160
|
||||
**Button:** Continue
|
||||
|
||||
Advances event to "Confermata" status (300):
|
||||
|
||||
```plsql
|
||||
declare
|
||||
v_count number;
|
||||
v_count_evt number;
|
||||
begin
|
||||
-- Check if confirmed event exists for same location/date
|
||||
select count(*) into v_count
|
||||
from eventi
|
||||
where data = (select data from eventi where id = :P22_EVENT_ID)
|
||||
and stato = 300
|
||||
and id_location = (select id_location from eventi where id = :P22_EVENT_ID);
|
||||
|
||||
if v_count > 0 then
|
||||
raise_application_error(-20001, 'Esiste un evento Confermato per la location - Impossibile proseguire');
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- Update status
|
||||
update eventi
|
||||
set stato = 300
|
||||
where id = :P22_EVENT_ID;
|
||||
|
||||
-- Check total confirmed events for date
|
||||
select count(*) into v_count_evt
|
||||
from eventi
|
||||
where data = (select data from eventi where id = :P22_EVENT_ID)
|
||||
and stato = 300;
|
||||
|
||||
if v_count_evt > 6 then
|
||||
RAISE_APPLICATION_ERROR(-20000, 'Ci sono già 6 eventi Confermati per la data');
|
||||
end if;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Almost Continue Event
|
||||
**Sequence:** 170
|
||||
**Button:** Almost Continue
|
||||
|
||||
Sets status to "Quasi Confermato" (350):
|
||||
|
||||
```plsql
|
||||
begin
|
||||
update eventi
|
||||
set stato = 350
|
||||
where id = :P22_EVENT_ID;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Confirm Event
|
||||
**Sequence:** 180
|
||||
**Button:** Confirm
|
||||
**Condition:** APP_READ_ONLY = 0
|
||||
|
||||
Final confirmation (status 400) and cancels competing events:
|
||||
|
||||
```plsql
|
||||
begin
|
||||
update eventi
|
||||
set stato = 400
|
||||
where id = :P22_EVENT_ID;
|
||||
|
||||
-- Cancel events with same date and location
|
||||
p_cancel_same_location_events(
|
||||
p_good_event_id => :P22_EVENT_ID
|
||||
);
|
||||
end;
|
||||
```
|
||||
|
||||
#### Unconfirm Event
|
||||
**Sequence:** 190
|
||||
**Button:** Unconfirm
|
||||
|
||||
Returns event to initial status (100):
|
||||
|
||||
```plsql
|
||||
begin
|
||||
update eventi
|
||||
set stato = 100
|
||||
where id = :P22_EVENT_ID;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Reopen Event
|
||||
**Sequence:** 200
|
||||
**Button:** Reopen
|
||||
|
||||
Clears the expired flag:
|
||||
|
||||
```plsql
|
||||
begin
|
||||
update eventi
|
||||
set flg_superato = 0
|
||||
where id = :P22_EVENT_ID;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Return to Preparazione
|
||||
**Sequence:** 210
|
||||
**Button:** Return to Preparation
|
||||
|
||||
Sets status back to preparation (200):
|
||||
|
||||
```plsql
|
||||
begin
|
||||
update eventi
|
||||
set stato = 200
|
||||
where id = :P22_EVENT_ID;
|
||||
end;
|
||||
```
|
||||
|
||||
#### Risorse - Save Interactive Grid Data
|
||||
**Sequence:** 220
|
||||
**Type:** NATIVE_IG_DML
|
||||
|
||||
Saves resource assignments.
|
||||
|
||||
#### Aggiorna QTA Lista
|
||||
**Sequence:** 230
|
||||
**Condition:** APP_READ_ONLY = 0 AND REQUEST = 'AGGIORNA_QTA'
|
||||
|
||||
Manual quantity recalculation:
|
||||
|
||||
```plsql
|
||||
EVENTI_AGGIORNA_QTA_LISTA(
|
||||
P_ID_EVENTO => :P22_EVENT_ID
|
||||
);
|
||||
```
|
||||
|
||||
#### Restore Deleted Event
|
||||
**Sequence:** 240
|
||||
|
||||
Restores soft-deleted event.
|
||||
|
||||
---
|
||||
|
||||
## Event Status Workflow Summary
|
||||
|
||||
| Status Code | Status Name | Italian | Next Action |
|
||||
|-------------|-------------|---------|-------------|
|
||||
| 100 | Preventivo | Quote | Continue Event → 300 |
|
||||
| 200 | Scheda | Preparation | - |
|
||||
| 300 | Confermata | Confirmed (Pending) | Almost Continue → 350 |
|
||||
| 350 | Quasi | Almost Confirmed | Confirm → 400 |
|
||||
| 400 | Confermato | Confirmed | - |
|
||||
| 900 | Superato | Expired/Cancelled | Reopen → clears flag |
|
||||
|
||||
---
|
||||
|
||||
## Common Process Patterns
|
||||
|
||||
### Read-Only Check
|
||||
All write processes include this condition:
|
||||
```plsql
|
||||
:APP_READ_ONLY = 0
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
Standard error pattern:
|
||||
```plsql
|
||||
exception when no_data_found then
|
||||
raise_application_error(-20001, 'Error message in Italian');
|
||||
```
|
||||
|
||||
### Interactive Grid Save
|
||||
Standard IG DML process:
|
||||
- Type: NATIVE_IG_DML
|
||||
- Attributes: REGION_SOURCE, Allow Insert (Y), Allow Update (Y), Allow Delete (Y)
|
||||
|
||||
---
|
||||
|
||||
## Migration Notes
|
||||
|
||||
When migrating these processes to .NET:
|
||||
|
||||
1. **Form Initialization** - Use API endpoints to fetch entity data
|
||||
2. **Form DML** - Implement CRUD endpoints with proper validation
|
||||
3. **Custom PL/SQL** - Convert to C# methods or stored procedures
|
||||
4. **IG DML** - Implement batch update endpoints for grid data
|
||||
5. **Session State** - Use application state management (Redux, Context)
|
||||
6. **Validation** - Implement in both frontend and backend
|
||||
7. **Workflow** - Consider state machine pattern for event status
|
||||
22
docs/functions/CLOB2BLOB.md
Normal file
22
docs/functions/CLOB2BLOB.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# CLOB2BLOB
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION "CLOB2BLOB" (AClob CLOB) return BLOB is
|
||||
Result BLOB;
|
||||
o1 integer;
|
||||
o2 integer;
|
||||
c integer;
|
||||
w integer;
|
||||
begin
|
||||
o1 := 1;
|
||||
o2 := 1;
|
||||
c := 0;
|
||||
w := 0;
|
||||
DBMS_LOB.CreateTemporary(Result, true);
|
||||
DBMS_LOB.ConvertToBlob(Result, AClob, length(AClob), o1, o2, 0, c, w);
|
||||
return(Result);
|
||||
end clob2blob;
|
||||
|
||||
```
|
||||
10
docs/functions/EXTDATE_GET_ITA.md
Normal file
10
docs/functions/EXTDATE_GET_ITA.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# EXTDATE_GET_ITA
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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;```
|
||||
37
docs/functions/F_CI_SONO_EVENTI_CONFERMATI.md
Normal file
37
docs/functions/F_CI_SONO_EVENTI_CONFERMATI.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# F_CI_SONO_EVENTI_CONFERMATI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION F_CI_SONO_EVENTI_CONFERMATI
|
||||
(
|
||||
P_EVT_DATE IN DATE
|
||||
, P_LOCATION_ID IN NUMBER
|
||||
, P_BYPASS IN NUMBER
|
||||
) RETURN NUMBER AS
|
||||
|
||||
v_evt_cnt number;
|
||||
|
||||
BEGIN
|
||||
|
||||
-- function bypass
|
||||
if P_BYPASS > 0 then
|
||||
return 0;
|
||||
end if;
|
||||
|
||||
select
|
||||
count(e.id) as evt_cnt
|
||||
into v_evt_cnt
|
||||
from eventi e
|
||||
join vw_event_color c on c.id = e.id
|
||||
where e.data = P_EVT_DATE
|
||||
and e.id_location = P_LOCATION_ID
|
||||
and c.status = 'Confermato';
|
||||
|
||||
if v_evt_cnt > 0 then
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
end if;
|
||||
|
||||
END F_CI_SONO_EVENTI_CONFERMATI;```
|
||||
45
docs/functions/F_DAY_TO_NAME.md
Normal file
45
docs/functions/F_DAY_TO_NAME.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# F_DAY_TO_NAME
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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';
|
||||
|
||||
if v_language = 'AMERICAN' then
|
||||
case v_day_number
|
||||
when 1 then return 'Domenica';
|
||||
when 2 then return 'Lunedì';
|
||||
when 3 then return 'Martedì';
|
||||
when 4 then return 'Mercoledì';
|
||||
when 5 then return 'Giovedì';
|
||||
when 6 then return 'Venerdì';
|
||||
when 7 then return 'Sabato';
|
||||
end case;
|
||||
else
|
||||
case v_day_number
|
||||
when 1 then return 'Lunedì';
|
||||
when 2 then return 'Martedì';
|
||||
when 3 then return 'Mercoledì';
|
||||
when 4 then return 'Giovedì';
|
||||
when 5 then return 'Venerdì';
|
||||
when 6 then return 'Sabato';
|
||||
when 7 then return 'Domenica';
|
||||
end case;
|
||||
end if;
|
||||
END F_DAY_TO_NAME;```
|
||||
22
docs/functions/F_EVENTO_SCADUTO.md
Normal file
22
docs/functions/F_EVENTO_SCADUTO.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# F_EVENTO_SCADUTO
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION F_EVENTO_SCADUTO
|
||||
(
|
||||
DATA_SCADENZA IN DATE,
|
||||
STATO_EVENTO IN NUMBER,
|
||||
STATO_FROM IN NUMBER,
|
||||
STATO_TO IN NUMBER
|
||||
) RETURN NUMBER AS
|
||||
BEGIN
|
||||
if trunc(DATA_SCADENZA) <= trunc(sysdate)
|
||||
and STATO_EVENTO between STATO_FROM and STATO_TO
|
||||
then
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
end if;
|
||||
END F_EVENTO_SCADUTO;
|
||||
```
|
||||
31
docs/functions/F_GET_ANGOLO_ALLESTIMENTO.md
Normal file
31
docs/functions/F_GET_ANGOLO_ALLESTIMENTO.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# F_GET_ANGOLO_ALLESTIMENTO
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION "F_GET_ANGOLO_ALLESTIMENTO" (
|
||||
p_filtro VARCHAR2,
|
||||
p_id NUMBER
|
||||
) RETURN VARCHAR2 AS
|
||||
|
||||
TYPE ref_cur IS REF CURSOR;
|
||||
c_data ref_cur;
|
||||
v_val VARCHAR2(1000);
|
||||
v_filtro VARCHAR2(100);
|
||||
v_id NUMBER;
|
||||
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;
|
||||
|
||||
FETCH c_data INTO v_val;
|
||||
CLOSE c_data;
|
||||
RETURN v_val;
|
||||
END;```
|
||||
34
docs/functions/F_GET_ANGOLO_ALLESTIMENTO_OB.md
Normal file
34
docs/functions/F_GET_ANGOLO_ALLESTIMENTO_OB.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# F_GET_ANGOLO_ALLESTIMENTO_OB
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION "F_GET_ANGOLO_ALLESTIMENTO_OB" (
|
||||
p_filtro VARCHAR2,
|
||||
p_id NUMBER
|
||||
) RETURN VARCHAR2
|
||||
--ANGOLI OPEN BAR
|
||||
AS
|
||||
|
||||
TYPE ref_cur IS REF CURSOR;
|
||||
c_data ref_cur;
|
||||
v_val VARCHAR2(1000);
|
||||
v_filtro VARCHAR2(100);
|
||||
v_id NUMBER;
|
||||
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;
|
||||
|
||||
FETCH c_data INTO v_val;
|
||||
CLOSE c_data;
|
||||
RETURN v_val;
|
||||
END;```
|
||||
37
docs/functions/F_GET_COSTO_ARTICOLO.md
Normal file
37
docs/functions/F_GET_COSTO_ARTICOLO.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# F_GET_COSTO_ARTICOLO
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
function f_get_costo_articolo(p_cod_articolo varchar2, p_date date)
|
||||
return number
|
||||
as
|
||||
v_costo number := null;
|
||||
begin
|
||||
|
||||
-- Cerco il costo alla data
|
||||
begin
|
||||
SELECT a.costo_uni
|
||||
into v_costo
|
||||
FROM COSTI_ARTICOLI a
|
||||
where a.data_costo = p_date
|
||||
and a.cod_articolo = p_cod_articolo;
|
||||
exception when no_data_found then
|
||||
v_costo := null;
|
||||
end;
|
||||
|
||||
-- Se non lo trovo prendo l'ultimo costo
|
||||
begin
|
||||
SELECT a.costo_uni
|
||||
into v_costo
|
||||
FROM COSTI_ARTICOLI a
|
||||
WHERE a.DATA_COSTO = (SELECT max(b.DATA_COSTO) FROM COSTI_ARTICOLI b where b.cod_articolo = a.cod_articolo)
|
||||
and a.cod_articolo = p_cod_articolo;
|
||||
exception when no_data_found then
|
||||
v_costo := null;
|
||||
end;
|
||||
|
||||
-- se non trovo niente torno 0
|
||||
return nvl(v_costo, 0);
|
||||
end;
|
||||
```
|
||||
164
docs/functions/F_GET_OSPITI.md
Normal file
164
docs/functions/F_GET_OSPITI.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# F_GET_OSPITI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION "F_GET_OSPITI" (
|
||||
p_id_evento IN NUMBER
|
||||
) RETURN t_det_ospiti_tab
|
||||
PIPELINED
|
||||
AS
|
||||
|
||||
v_data DATE;
|
||||
v_location VARCHAR2(100);
|
||||
v_cliente VARCHAR2(100);
|
||||
v_descrizione VARCHAR2(100);
|
||||
v_ora_cerimonia VARCHAR2(10);
|
||||
v_ora_evento VARCHAR2(10);
|
||||
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(1000);
|
||||
v_confettata VARCHAR2(100);
|
||||
v_stampa_menu VARCHAR2(100);
|
||||
v_angoli VARCHAR2(1000);
|
||||
v_extra_info VARCHAR2(1000);
|
||||
v_note_adulti VARCHAR2(1000);
|
||||
v_note_kinder VARCHAR2(1000);
|
||||
v_note_baby VARCHAR2(1000);
|
||||
v_note_staff VARCHAR2(1000);
|
||||
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 := '';
|
||||
|
||||
--ospiti
|
||||
SELECT
|
||||
nvl(SUM(o.numero),
|
||||
0)
|
||||
INTO v_tot_adulti
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 8; -- adulti
|
||||
|
||||
BEGIN
|
||||
SELECT
|
||||
o.note
|
||||
INTO v_note_adulti
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 8; -- adulti
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
SELECT
|
||||
nvl(SUM(o.numero),
|
||||
0)
|
||||
INTO v_tot_kinder
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 5; --Kinder
|
||||
|
||||
BEGIN
|
||||
SELECT
|
||||
o.note
|
||||
INTO v_note_kinder
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 5; --Kinder
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
SELECT
|
||||
nvl(SUM(o.numero),
|
||||
0)
|
||||
INTO v_tot_baby
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 6; -- Baby
|
||||
|
||||
BEGIN
|
||||
SELECT
|
||||
o.note
|
||||
INTO v_note_baby
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 6; -- Baby
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
SELECT
|
||||
nvl(SUM(o.numero),
|
||||
0)
|
||||
INTO v_tot_staff
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 7; -- Staff
|
||||
|
||||
BEGIN
|
||||
SELECT
|
||||
o.note
|
||||
INTO v_note_staff
|
||||
FROM
|
||||
eventi_det_ospiti o
|
||||
WHERE
|
||||
o.id_evento = p_id_evento
|
||||
AND o.cod_tipo_ospite = 7; -- Staff
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
SELECT
|
||||
nvl(e.tot_ospiti, 0)
|
||||
INTO v_tot_invitati
|
||||
FROM
|
||||
eventi e
|
||||
WHERE
|
||||
e.id = p_id_evento;
|
||||
|
||||
PIPE ROW ( t_det_ospiti_row(p_id_evento, v_tot_adulti, v_tot_kinder, v_tot_baby, v_tot_staff,
|
||||
v_tot_invitati, v_note_adulti, v_note_kinder, v_note_baby, v_note_staff) );
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
NULL;
|
||||
END;
|
||||
|
||||
RETURN;
|
||||
END;```
|
||||
36
docs/functions/F_GET_QTA_IMPEGNATA.md
Normal file
36
docs/functions/F_GET_QTA_IMPEGNATA.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# F_GET_QTA_IMPEGNATA
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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 <= p_data --
|
||||
AND data BETWEEN p_data_from AND v_data_to; -- qta impegnata per quella data
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
v_qta := 0;
|
||||
END;
|
||||
|
||||
RETURN v_qta;
|
||||
END;```
|
||||
31
docs/functions/F_GET_TOT_OSPITI.md
Normal file
31
docs/functions/F_GET_TOT_OSPITI.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# F_GET_TOT_OSPITI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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 );
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
v_tot := 0;
|
||||
END;
|
||||
|
||||
RETURN v_tot;
|
||||
END;```
|
||||
34
docs/functions/F_GET_TOVAGLIATO_ALLESTIMENTO.md
Normal file
34
docs/functions/F_GET_TOVAGLIATO_ALLESTIMENTO.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# F_GET_TOVAGLIATO_ALLESTIMENTO
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION "F_GET_TOVAGLIATO_ALLESTIMENTO" (
|
||||
p_filtro VARCHAR2,
|
||||
p_id NUMBER
|
||||
) RETURN VARCHAR2 AS
|
||||
|
||||
TYPE ref_cur IS REF CURSOR;
|
||||
c_data ref_cur;
|
||||
v_val VARCHAR2(1000);
|
||||
v_filtro VARCHAR2(100);
|
||||
v_id NUMBER;
|
||||
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ù articoli fare list_agg op loop
|
||||
and e.id = to_number(:id)'
|
||||
USING v_filtro, v_id;
|
||||
|
||||
FETCH c_data INTO v_val;
|
||||
CLOSE c_data;
|
||||
RETURN v_val;
|
||||
END;```
|
||||
84
docs/functions/F_LIST_PRELIEVO_ADD_ARTICOLO.md
Normal file
84
docs/functions/F_LIST_PRELIEVO_ADD_ARTICOLO.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# F_LIST_PRELIEVO_ADD_ARTICOLO
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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
|
||||
|
||||
v_cod_art := p_articolo_add;
|
||||
v_qta_da_imp := nvl(p_qta_aperitivo, 0) + nvl(p_qta_seduto, 0) + nvl(p_qta_dolci, 0);
|
||||
|
||||
begin
|
||||
|
||||
select trunc(data) as data
|
||||
into v_data_evento
|
||||
from eventi where id = p_event_id;
|
||||
exception when no_data_found then
|
||||
rollback;
|
||||
RETURN '{"type":"error","code":"'||SQLCODE||'","stack":"'||SQLERRM||'","message":"Evento non trovato"}';
|
||||
end;
|
||||
begin
|
||||
select qta_giac
|
||||
into v_qta_giac
|
||||
from articoli
|
||||
where COD_ARTICOLO = v_cod_art;
|
||||
exception when no_data_found then
|
||||
rollback;
|
||||
RETURN '{"type":"error","code":"'||SQLCODE||'","stack":"'||SQLERRM||'","message":"Articolo non trovato"}';
|
||||
end;
|
||||
|
||||
|
||||
select count(*)
|
||||
into v_num_evt_imp
|
||||
from V_IMPEGNI_ARTICOLI
|
||||
where COD_ARTICOLO = v_cod_art
|
||||
and data between v_data_evento - 2 and v_data_evento + 2;
|
||||
|
||||
v_qta_imp := nvl(f_get_qta_impegnata (v_cod_art, v_data_evento - 2, v_data_evento + 2 ) , 0);
|
||||
|
||||
--insert impegno articolo
|
||||
begin
|
||||
insert into eventi_det_prel (id_evento, cod_articolo,QTA_MAN_APE,QTA_MAN_SEDU,QTA_MAN_BUFDOL, COSTO_ARTICOLO)
|
||||
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));
|
||||
|
||||
-- aggiorna liste prelievo
|
||||
EVENTI_AGGIORNA_QTA_LISTA(
|
||||
P_ID_EVENTO => p_event_id
|
||||
);
|
||||
|
||||
-- Controlla banalmente se sono stati prelevati su altri eventi
|
||||
if v_qta_imp + v_qta_da_imp > v_qta_giac then
|
||||
RETURN '{"type":"warning","message":"Attenzione: Non hai abbastanza articoli di questo tipo a magazzino"}';
|
||||
end if;
|
||||
|
||||
-- Se trovo articoli già impegnati in quel giorno mostro un messaggio - 16/11/2022
|
||||
-- Continuo lo stesso ma do un messaggio di errore anzichè di successo
|
||||
if(v_qta_imp > 0 and v_num_evt_imp > 0) then
|
||||
RETURN '{"type":"warning","code":"'||SQLCODE||'","stack":"'||SQLERRM||'","message":"Attenzione! Articolo '||p_articolo_add||' già impegnato '||v_num_evt_imp||' '||(case when v_num_evt_imp > 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')||'"}';
|
||||
end if;
|
||||
|
||||
RETURN '{"type":"success","message":"Articolo aggiunto con successo"}';
|
||||
exception when others then
|
||||
RETURN '{"type":"success","message":"Articolo aggiunto con errori: '||replace(replace(SQLERRM, 'ORA-20000: Errore:', ''), '-20000 - ', '')||'"}';
|
||||
end;
|
||||
|
||||
rollback;
|
||||
return '{"type":"error","code":"","stack":"","message":"Errore sconosciuto"}';
|
||||
end f_list_prelievo_add_articolo;```
|
||||
38
docs/functions/F_MAX_NUMERO_EVENTI_RAGGIUNTO.md
Normal file
38
docs/functions/F_MAX_NUMERO_EVENTI_RAGGIUNTO.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# F_MAX_NUMERO_EVENTI_RAGGIUNTO
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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;
|
||||
|
||||
-- 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
|
||||
|
||||
-- Step 3: Compare the event count with the max_eventi and return the appropriate result
|
||||
IF v_event_count >= 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;
|
||||
|
||||
END F_MAX_NUMERO_EVENTI_RAGGIUNTO;```
|
||||
36
docs/functions/F_MAX_NUM_EVENTI_CONFERMATI.md
Normal file
36
docs/functions/F_MAX_NUM_EVENTI_CONFERMATI.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# F_MAX_NUM_EVENTI_CONFERMATI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION F_MAX_NUM_EVENTI_CONFERMATI
|
||||
(
|
||||
P_EVT_DATE IN DATE
|
||||
, P_MAX_EVT_NUM NUMBER
|
||||
, P_BYPASS IN NUMBER
|
||||
) RETURN NUMBER AS
|
||||
|
||||
v_evt_cnt number;
|
||||
|
||||
BEGIN
|
||||
|
||||
-- function bypass
|
||||
if P_BYPASS > 0 then
|
||||
return 0;
|
||||
end if;
|
||||
|
||||
select
|
||||
count(e.id) as evt_cnt
|
||||
into v_evt_cnt
|
||||
from eventi e
|
||||
join vw_event_color c on c.id = e.id
|
||||
where e.data = P_EVT_DATE
|
||||
and c.status = 'Confermato';
|
||||
|
||||
if v_evt_cnt >= P_MAX_EVT_NUM then
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
end if;
|
||||
|
||||
END F_MAX_NUM_EVENTI_CONFERMATI;```
|
||||
433
docs/functions/F_REP_ALLESTIMENTI.md
Normal file
433
docs/functions/F_REP_ALLESTIMENTI.md
Normal file
@@ -0,0 +1,433 @@
|
||||
# F_REP_ALLESTIMENTI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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
|
||||
|
||||
v_data_in varchar2(100);
|
||||
v_data_fi varchar2(100);
|
||||
|
||||
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 >= 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,
|
||||
|
||||
case when order_id =1 then data else null end as data1,
|
||||
case when order_id =2 then data else null end as data2,
|
||||
case when order_id =3 then data else null end as data3,
|
||||
case when order_id =4 then data else null end as data4,
|
||||
case when order_id =5 then data else null end as data5,
|
||||
case when order_id =6 then data else null end as data6,
|
||||
case when order_id =7 then data else null end as data7,
|
||||
case when order_id =8 then data else null end as data8,
|
||||
case when order_id =9 then data else null end as data9,
|
||||
case when order_id =10 then data else null end as data10,
|
||||
case when order_id =11 then data else null end as data11,
|
||||
case when order_id =12 then data else null end as data12,
|
||||
|
||||
case when order_id =1 then location else null end as location1,
|
||||
case when order_id =2 then location else null end as location2,
|
||||
case when order_id =3 then location else null end as location3,
|
||||
case when order_id =4 then location else null end as location4,
|
||||
case when order_id =5 then location else null end as location5,
|
||||
case when order_id =6 then location else null end as location6,
|
||||
case when order_id =7 then location else null end as location7,
|
||||
case when order_id =8 then location else null end as location8,
|
||||
case when order_id =9 then location else null end as location9,
|
||||
case when order_id =10 then location else null end as location10,
|
||||
case when order_id =11 then location else null end as location11,
|
||||
case when order_id =12 then location else null end as location12,
|
||||
|
||||
case when order_id =1 then torta else null end as torta1,
|
||||
case when order_id =2 then torta else null end as torta2,
|
||||
case when order_id =3 then torta else null end as torta3,
|
||||
case when order_id =4 then torta else null end as torta4,
|
||||
case when order_id =5 then torta else null end as torta5,
|
||||
case when order_id =6 then torta else null end as torta6,
|
||||
case when order_id =7 then torta else null end as torta7,
|
||||
case when order_id =8 then torta else null end as torta8,
|
||||
case when order_id =9 then torta else null end as torta9,
|
||||
case when order_id =10 then torta else null end as torta10,
|
||||
case when order_id =11 then torta else null end as torta11,
|
||||
case when order_id =12 then torta else null end as torta12,
|
||||
|
||||
case when order_id =1 then confettata else null end as confettata1,
|
||||
case when order_id =2 then confettata else null end as confettata2,
|
||||
case when order_id =3 then confettata else null end as confettata3,
|
||||
case when order_id =4 then confettata else null end as confettata4,
|
||||
case when order_id =5 then confettata else null end as confettata5,
|
||||
case when order_id =6 then confettata else null end as confettata6,
|
||||
case when order_id =7 then confettata else null end as confettata7,
|
||||
case when order_id =8 then confettata else null end as confettata8,
|
||||
case when order_id =9 then confettata else null end as confettata9,
|
||||
case when order_id =10 then confettata else null end as confettata10,
|
||||
case when order_id =11 then confettata else null end as confettata11,
|
||||
case when order_id =12 then confettata else null end as confettata12,
|
||||
|
||||
case when order_id =1 then stampa_menu else null end as stampa_menu1,
|
||||
case when order_id =2 then stampa_menu else null end as stampa_menu2,
|
||||
case when order_id =3 then stampa_menu else null end as stampa_menu3,
|
||||
case when order_id =4 then stampa_menu else null end as stampa_menu4,
|
||||
case when order_id =5 then stampa_menu else null end as stampa_menu5,
|
||||
case when order_id =6 then stampa_menu else null end as stampa_menu6,
|
||||
case when order_id =7 then stampa_menu else null end as stampa_menu7,
|
||||
case when order_id =8 then stampa_menu else null end as stampa_menu8,
|
||||
case when order_id =9 then stampa_menu else null end as stampa_menu9,
|
||||
case when order_id =10 then stampa_menu else null end as stampa_menu10,
|
||||
case when order_id =11 then stampa_menu else null end as stampa_menu11,
|
||||
case when order_id =12 then stampa_menu else null end as stampa_menu12
|
||||
from q
|
||||
)
|
||||
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,
|
||||
|
||||
min(data1) as d1,
|
||||
min(data2) as d2,
|
||||
min(data3) as d3,
|
||||
min(data4) as d4,
|
||||
min(data5) as d5,
|
||||
min(data6) as d6,
|
||||
min(data7) as d7,
|
||||
min(data8) as d8,
|
||||
min(data9) as d9,
|
||||
min(data10) as d10,
|
||||
min(data11) as d11,
|
||||
min(data12) as d12,
|
||||
|
||||
min(location1) as l1,
|
||||
min(location2) as l2,
|
||||
min(location3) as l3,
|
||||
min(location4) as l4,
|
||||
min(location5) as l5,
|
||||
min(location6) as l6,
|
||||
min(location7) as l7,
|
||||
min(location8) as l8,
|
||||
min(location9) as l9,
|
||||
min(location10) as l10,
|
||||
min(location11) as l11,
|
||||
min(location12) as l12,
|
||||
|
||||
min(torta1) as t1,
|
||||
min(torta2) as t2,
|
||||
min(torta3) as t3,
|
||||
min(torta4) as t4,
|
||||
min(torta5) as t5,
|
||||
min(torta6) as t6,
|
||||
min(torta7) as t7,
|
||||
min(torta8) as t8,
|
||||
min(torta9) as t9,
|
||||
min(torta10) as t10,
|
||||
min(torta11) as t11,
|
||||
min(torta12) as t12,
|
||||
|
||||
min(confettata1) as c1,
|
||||
min(confettata2) as c2,
|
||||
min(confettata3) as c3,
|
||||
min(confettata4) as c4,
|
||||
min(confettata5) as c5,
|
||||
min(confettata6) as c6,
|
||||
min(confettata7) as c7,
|
||||
min(confettata8) as c8,
|
||||
min(confettata9) as c9,
|
||||
min(confettata10) as c10,
|
||||
min(confettata11) as c11,
|
||||
min(confettata12) as c12,
|
||||
|
||||
min(stampa_menu1) as SM1,
|
||||
min(stampa_menu2) as SM2,
|
||||
min(stampa_menu3) as SM3,
|
||||
min(stampa_menu4) as SM4,
|
||||
min(stampa_menu5) as SM5,
|
||||
min(stampa_menu6) as SM6,
|
||||
min(stampa_menu7) as SM7,
|
||||
min(stampa_menu8) as SM8,
|
||||
min(stampa_menu9) as SM9,
|
||||
min(stampa_menu10) as SM10,
|
||||
min(stampa_menu11) as SM11,
|
||||
min(stampa_menu12) as SM12
|
||||
from r;
|
||||
|
||||
c_evt c_evento%ROWTYPE;
|
||||
|
||||
type v_TOVAGLIATO_AR IS VARRAY(12) OF VARCHAR2(4000);
|
||||
v_TOVAGLIATO v_TOVAGLIATO_AR;
|
||||
|
||||
C1 varchar2(100);
|
||||
C2 varchar2(100);
|
||||
C3 varchar2(100);
|
||||
C4 varchar2(100);
|
||||
C5 varchar2(100);
|
||||
C6 varchar2(100);
|
||||
C7 varchar2(100);
|
||||
C8 varchar2(100);
|
||||
C9 varchar2(100);
|
||||
C10 varchar2(100);
|
||||
C11 varchar2(100);
|
||||
C12 varchar2(100);
|
||||
|
||||
type v_TOVAGLIOLO_AR IS VARRAY(12) OF VARCHAR2(1000);
|
||||
v_TOVAGLIOLO v_TOVAGLIOLO_AR;
|
||||
|
||||
type v_AN_GELATO_AR IS VARRAY(12) OF VARCHAR2(1000);
|
||||
v_AN_GELATO v_AN_GELATO_AR;
|
||||
type v_AN_GELATO2_AR IS VARRAY(12) OF VARCHAR2(1000);
|
||||
v_AN_GELATO2 v_AN_GELATO2_AR;
|
||||
|
||||
type v_AN_OPENBAR_AR IS VARRAY(12) OF VARCHAR2(1000);
|
||||
v_AN_OPENBAR v_AN_OPENBAR_AR;
|
||||
type v_AN_RUM_AR IS VARRAY(12) OF VARCHAR2(1000);
|
||||
v_AN_RUM v_AN_RUM_AR;
|
||||
|
||||
T1 varchar2(100);
|
||||
T2 varchar2(100);
|
||||
T3 varchar2(100);
|
||||
T4 varchar2(100);
|
||||
T5 varchar2(100);
|
||||
T6 varchar2(100);
|
||||
T7 varchar2(100);
|
||||
T8 varchar2(100);
|
||||
T9 varchar2(100);
|
||||
T10 varchar2(100);
|
||||
T11 varchar2(100);
|
||||
T12 varchar2(100);
|
||||
|
||||
v_appo varchar2(100);
|
||||
|
||||
v_dato varchar2(100);
|
||||
v_id_str varchar2(100);
|
||||
v_id number;
|
||||
v_qry varchar2(1000);
|
||||
|
||||
type v_IDEVT_AR IS VARRAY(12) OF number;
|
||||
v_IDEVT v_IDEVT_AR;
|
||||
|
||||
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;
|
||||
|
||||
v_TOVAGLIATO := v_TOVAGLIATO_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
v_TOVAGLIOLO := v_TOVAGLIOLO_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
v_AN_GELATO := v_AN_GELATO_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
v_AN_GELATO2 := v_AN_GELATO2_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
v_AN_OPENBAR := v_AN_OPENBAR_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
v_AN_RUM := v_AN_RUM_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
v_IDEVT := v_IDEVT_AR(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
|
||||
|
||||
open c_evento;
|
||||
fetch c_evento into c_evt;
|
||||
--exit when c_evento%NOTFOUND;
|
||||
|
||||
--caricare su vettore gli id:
|
||||
v_IDEVT(1) := c_evt.id1;
|
||||
v_IDEVT(2) := c_evt.id2;
|
||||
v_IDEVT(3) := c_evt.id3;
|
||||
v_IDEVT(4) := c_evt.id4;
|
||||
v_IDEVT(5) := c_evt.id5;
|
||||
v_IDEVT(6) := c_evt.id6;
|
||||
v_IDEVT(7) := c_evt.id7;
|
||||
v_IDEVT(8) := c_evt.id8;
|
||||
v_IDEVT(9) := c_evt.id9;
|
||||
v_IDEVT(10) := c_evt.id10;
|
||||
v_IDEVT(11) := c_evt.id11;
|
||||
v_IDEVT(12) := c_evt.id12;
|
||||
|
||||
FOR i in 1 .. 12 LOOP
|
||||
v_dato := '';
|
||||
|
||||
v_id := to_char(v_IDEVT(i));
|
||||
|
||||
v_TOVAGLIATO(i) := f_get_tovagliato_allestimento ('TVB', v_IDEVT(i) ) ;
|
||||
v_AN_GELATO(i) := f_get_angolo_allestimento ('AN-GELAT', v_IDEVT(i) ) ;
|
||||
v_AN_GELATO2(i) := f_get_angolo_allestimento ('AN-GEL-BOM', v_IDEVT(i) ) ;
|
||||
--v_AN_OPENBAR(i) := f_get_angolo_allestimento ('OPEN-B', v_IDEVT(i) ) ;
|
||||
v_AN_OPENBAR(i) := f_get_angolo_allestimento_OB ('%OPEN BAR%', v_IDEVT(i) ) ;
|
||||
v_AN_RUM(i) := f_get_angolo_allestimento ('AN-RUM-CI', v_IDEVT(i) ) ;
|
||||
|
||||
END LOOP;
|
||||
|
||||
PIPE ROW(t_rep_allestimenti_row(c_evt.D1 ,
|
||||
c_evt.D2 ,
|
||||
c_evt.D3 ,
|
||||
c_evt.D4 ,
|
||||
c_evt.D5 ,
|
||||
c_evt.D6 ,
|
||||
c_evt.D7 ,
|
||||
c_evt.D8 ,
|
||||
c_evt.D9 ,
|
||||
c_evt.D10 ,
|
||||
c_evt.D11 ,
|
||||
c_evt.D12 ,
|
||||
|
||||
c_evt.L1 ,
|
||||
c_evt.L2 ,
|
||||
c_evt.L3 ,
|
||||
c_evt.L4 ,
|
||||
c_evt.L5 ,
|
||||
c_evt.L6 ,
|
||||
c_evt.L7 ,
|
||||
c_evt.L8 ,
|
||||
c_evt.L9 ,
|
||||
c_evt.L10 ,
|
||||
c_evt.L11 ,
|
||||
c_evt.L12 ,
|
||||
|
||||
v_TOVAGLIATO(1),
|
||||
v_TOVAGLIATO(2),
|
||||
v_TOVAGLIATO(3),
|
||||
v_TOVAGLIATO(4),
|
||||
v_TOVAGLIATO(5),
|
||||
v_TOVAGLIATO(6),
|
||||
v_TOVAGLIATO(7),
|
||||
v_TOVAGLIATO(8),
|
||||
v_TOVAGLIATO(9),
|
||||
v_TOVAGLIATO(10),
|
||||
v_TOVAGLIATO(11),
|
||||
v_TOVAGLIATO(12),
|
||||
|
||||
c_evt.C1 ,
|
||||
c_evt.C2 ,
|
||||
c_evt.C3 ,
|
||||
c_evt.C4 ,
|
||||
c_evt.C5 ,
|
||||
c_evt.C6 ,
|
||||
c_evt.C7 ,
|
||||
c_evt.C8 ,
|
||||
c_evt.C9 ,
|
||||
c_evt.C10 ,
|
||||
c_evt.C11 ,
|
||||
c_evt.C12 ,
|
||||
|
||||
v_TOVAGLIOLO(1),
|
||||
v_TOVAGLIOLO(2),
|
||||
v_TOVAGLIOLO(3),
|
||||
v_TOVAGLIOLO(4),
|
||||
v_TOVAGLIOLO(5),
|
||||
v_TOVAGLIOLO(6),
|
||||
v_TOVAGLIOLO(7),
|
||||
v_TOVAGLIOLO(8),
|
||||
v_TOVAGLIOLO(9),
|
||||
v_TOVAGLIOLO(10),
|
||||
v_TOVAGLIOLO(11),
|
||||
v_TOVAGLIOLO(12),
|
||||
|
||||
v_AN_GELATO(1) || ', ' || v_AN_GELATO2(1),
|
||||
v_AN_GELATO(2) || ', ' || v_AN_GELATO2(2),
|
||||
v_AN_GELATO(3) || ', ' || v_AN_GELATO2(3),
|
||||
v_AN_GELATO(4) || ', ' || v_AN_GELATO2(4),
|
||||
v_AN_GELATO(5) || ', ' || v_AN_GELATO2(5),
|
||||
v_AN_GELATO(6) || ', ' || v_AN_GELATO2(6),
|
||||
v_AN_GELATO(7) || ', ' || v_AN_GELATO2(7),
|
||||
v_AN_GELATO(8) || ', ' || v_AN_GELATO2(8),
|
||||
v_AN_GELATO(9) || ', ' || v_AN_GELATO2(9),
|
||||
v_AN_GELATO(10) || ', ' || v_AN_GELATO2(10),
|
||||
v_AN_GELATO(11) || ', ' || v_AN_GELATO2(11),
|
||||
v_AN_GELATO(12) || ', ' || v_AN_GELATO2(12),
|
||||
|
||||
v_AN_OPENBAR(1),
|
||||
v_AN_OPENBAR(2),
|
||||
v_AN_OPENBAR(3),
|
||||
v_AN_OPENBAR(4),
|
||||
v_AN_OPENBAR(5),
|
||||
v_AN_OPENBAR(6),
|
||||
v_AN_OPENBAR(7),
|
||||
v_AN_OPENBAR(8),
|
||||
v_AN_OPENBAR(9),
|
||||
v_AN_OPENBAR(10),
|
||||
v_AN_OPENBAR(11),
|
||||
v_AN_OPENBAR(12),
|
||||
|
||||
v_AN_RUM(1),
|
||||
v_AN_RUM(2),
|
||||
v_AN_RUM(3),
|
||||
v_AN_RUM(4),
|
||||
v_AN_RUM(5),
|
||||
v_AN_RUM(6),
|
||||
v_AN_RUM(7),
|
||||
v_AN_RUM(8),
|
||||
v_AN_RUM(9),
|
||||
v_AN_RUM(10),
|
||||
v_AN_RUM(11),
|
||||
v_AN_RUM(12),
|
||||
|
||||
c_evt.T1 ,
|
||||
c_evt.T2 ,
|
||||
c_evt.T3 ,
|
||||
c_evt.T4 ,
|
||||
c_evt.T5 ,
|
||||
c_evt.T6 ,
|
||||
c_evt.T7 ,
|
||||
c_evt.T8 ,
|
||||
c_evt.T9 ,
|
||||
c_evt.T10 ,
|
||||
c_evt.T11 ,
|
||||
c_evt.T12 ,
|
||||
|
||||
c_evt.SM1 ,
|
||||
c_evt.SM2 ,
|
||||
c_evt.SM3 ,
|
||||
c_evt.SM4 ,
|
||||
c_evt.SM5 ,
|
||||
c_evt.SM6 ,
|
||||
c_evt.SM7 ,
|
||||
c_evt.SM8 ,
|
||||
c_evt.SM9 ,
|
||||
c_evt.SM10 ,
|
||||
c_evt.SM11 ,
|
||||
c_evt.SM12
|
||||
));
|
||||
|
||||
close c_evento;
|
||||
|
||||
RETURN;
|
||||
|
||||
END;```
|
||||
245
docs/functions/F_REP_CUCINA.md
Normal file
245
docs/functions/F_REP_CUCINA.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# F_REP_CUCINA
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION "F_REP_CUCINA" (p_data_in IN varchar2,p_data_fi IN varchar2)
|
||||
RETURN t_rep_cucina_tab PIPELINED AS
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
BEGIN
|
||||
|
||||
for c in c_evento
|
||||
loop
|
||||
|
||||
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 := '';
|
||||
|
||||
v_cliente_email := c.cliente_email;
|
||||
v_cliente_tel := c.cliente_tel;
|
||||
v_referente_tel := c.referente_tel;
|
||||
v_distanza_location := c.distanza_location;
|
||||
v_buffet_iniziale := c.buffet_iniziale;
|
||||
v_buffet_finale := c.buffet_finale;
|
||||
v_primi := c.primi;
|
||||
v_secondi := c.secondi;
|
||||
v_vini := c.vini;
|
||||
v_extra_costi := c.extra_costi;
|
||||
v_event_id := c.id;
|
||||
|
||||
--ospiti
|
||||
select nvl(sum(o.NUMERO),0)
|
||||
into v_TOT_ADULTI
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
--join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 8; -- adulti
|
||||
|
||||
begin
|
||||
select o.NOTE
|
||||
into v_NOTE_ADULTI
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 8; -- adulti
|
||||
|
||||
exception when no_data_found then null;
|
||||
end;
|
||||
|
||||
select nvl(sum(o.NUMERO),0)
|
||||
into v_TOT_KINDER
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
--join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 5; --Kinder
|
||||
|
||||
begin
|
||||
select o.NOTE
|
||||
into v_NOTE_KINDER
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 5; --Kinder
|
||||
|
||||
exception when no_data_found then null;
|
||||
end;
|
||||
|
||||
select nvl(sum(o.NUMERO),0)
|
||||
into v_TOT_BABY
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
--join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 6; -- Baby
|
||||
|
||||
begin
|
||||
select o.NOTE
|
||||
into v_NOTE_BABY
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 6; -- Baby
|
||||
|
||||
exception when no_data_found then null;
|
||||
end;
|
||||
|
||||
select nvl(sum(o.NUMERO),0)
|
||||
into v_TOT_STAFF
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
--join tb_tipi_ospiti tos on o.cod_tipo_ospite = tos.COD_TIPO
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 7; -- Staff
|
||||
|
||||
begin
|
||||
select o.NOTE
|
||||
into v_NOTE_STAFF
|
||||
from eventi e
|
||||
join eventi_det_ospiti o on e.id = o.id_evento
|
||||
where e.id = c.id
|
||||
and o.cod_tipo_ospite = 7; -- Staff
|
||||
|
||||
exception when no_data_found then null;
|
||||
end;
|
||||
|
||||
select nvl(e.tot_ospiti,0)
|
||||
into v_TOT_INVITATI
|
||||
from eventi e
|
||||
where e.id = c.id;
|
||||
|
||||
--angoli "speciali"
|
||||
v_angoli := '';
|
||||
for a in ( select trim(substr(a.descrizione || ' - ' || p.note,1,1000)) descrizione from eventi e
|
||||
join eventi_det_prel p on e.id=p.id_evento
|
||||
join articoli a on p.cod_articolo=a.cod_articolo
|
||||
where a.flg_cucina = 1
|
||||
and e.id = c.id
|
||||
)
|
||||
loop
|
||||
v_angoli := a.descrizione || ', ' || v_angoli ;
|
||||
end loop;
|
||||
|
||||
PIPE ROW(t_rep_cucina_row( c.data,c.location,c.cliente,
|
||||
c.DESCRIZIONE,
|
||||
to_char(c.ORA_CERIMONIA,'HH24:MI'),
|
||||
to_char(c.ORA_EVENTO,'HH24:MI'),
|
||||
v_TOT_ADULTI ,
|
||||
v_TOT_KINDER ,
|
||||
v_TOT_BABY ,
|
||||
v_TOT_STAFF ,
|
||||
v_TOT_INVITATI ,
|
||||
c.ALLERGIE ,
|
||||
c.TORTA ,
|
||||
c.CONFETTATA ,
|
||||
c.STAMPA_MENU ,
|
||||
v_angoli,
|
||||
c.extra_info ,
|
||||
|
||||
v_NOTE_ADULTI ,
|
||||
v_NOTE_KINDER ,
|
||||
v_NOTE_BABY ,
|
||||
v_NOTE_STAFF ,
|
||||
v_cliente_email ,
|
||||
v_cliente_tel ,
|
||||
v_referente_tel ,
|
||||
v_distanza_location ,
|
||||
v_buffet_iniziale ,
|
||||
v_buffet_finale ,
|
||||
v_primi ,
|
||||
v_secondi ,
|
||||
v_vini ,
|
||||
v_extra_costi ,
|
||||
v_event_id
|
||||
));
|
||||
|
||||
--exception when others
|
||||
-- then null;
|
||||
|
||||
exception when others
|
||||
then
|
||||
RAISE_APPLICATION_ERROR(-20000, 'Errore: ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64));
|
||||
|
||||
end;
|
||||
|
||||
end loop;
|
||||
|
||||
RETURN;
|
||||
|
||||
END;```
|
||||
20
docs/functions/F_USER_IN_ROLE.md
Normal file
20
docs/functions/F_USER_IN_ROLE.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# F_USER_IN_ROLE
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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);
|
||||
|
||||
return case when v_has_role > 0 then 1 else 0 end;
|
||||
END F_USER_IN_ROLE;```
|
||||
15
docs/functions/F_USER_IN_ROLE_STR.md
Normal file
15
docs/functions/F_USER_IN_ROLE_STR.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# F_USER_IN_ROLE_STR
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION F_USER_IN_ROLE_STR
|
||||
(
|
||||
P_USER IN VARCHAR2
|
||||
, P_ROLE IN VARCHAR2
|
||||
) RETURN VARCHAR2 AS
|
||||
v_has_role number := 0;
|
||||
BEGIN
|
||||
return case when F_USER_IN_ROLE(P_USER, P_ROLE) > 0 then 'true' else 'false' end;
|
||||
END F_USER_IN_ROLE_STR;
|
||||
```
|
||||
19
docs/functions/GET_PARAM_VALUE.md
Normal file
19
docs/functions/GET_PARAM_VALUE.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# GET_PARAM_VALUE
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
function get_param_value(p_name varchar2)
|
||||
return varchar2 as
|
||||
v_result varchar2(255);
|
||||
begin
|
||||
select strvalue
|
||||
into v_result
|
||||
from tb_config
|
||||
where upper(name) = upper(p_name);
|
||||
|
||||
return v_result;
|
||||
exception when others then
|
||||
return null;
|
||||
end;
|
||||
```
|
||||
36
docs/functions/MY_INSTR.md
Normal file
36
docs/functions/MY_INSTR.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# MY_INSTR
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
function my_instr( p_value varchar2,
|
||||
p_delim varchar2 )
|
||||
return number
|
||||
as
|
||||
|
||||
i number;
|
||||
|
||||
l_length number;
|
||||
|
||||
begin
|
||||
|
||||
if p_value is null then
|
||||
return null;
|
||||
end if;
|
||||
|
||||
i := 1;
|
||||
|
||||
l_length := length(p_value);
|
||||
|
||||
for i in 1..l_length
|
||||
loop
|
||||
if substr(p_value, i, length(p_delim)) = p_delim then
|
||||
return i;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
end;
|
||||
```
|
||||
127
docs/functions/README.md
Normal file
127
docs/functions/README.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Funzioni Database
|
||||
|
||||
Questa cartella contiene la documentazione di tutte le 23 funzioni del database.
|
||||
|
||||
## Funzioni Calcolo Quantità e Disponibilità
|
||||
|
||||
| Funzione | Ritorno | Descrizione |
|
||||
|----------|---------|-------------|
|
||||
| [F_GET_QTA_IMPEGNATA](F_GET_QTA_IMPEGNATA.md) | NUMBER | Quantità impegnata di un articolo in un range di date |
|
||||
| [F_GET_TOT_OSPITI](F_GET_TOT_OSPITI.md) | NUMBER | Totale ospiti per evento (opzionale per tipo) |
|
||||
| [F_GET_OSPITI](F_GET_OSPITI.md) | TABLE | Dettaglio ospiti per evento (funzione pipelined) |
|
||||
| [F_LIST_PRELIEVO_ADD_ARTICOLO](F_LIST_PRELIEVO_ADD_ARTICOLO.md) | VARCHAR2 (JSON) | Aggiunge articolo alla lista prelievo con validazioni |
|
||||
|
||||
## Funzioni Calcolo Costi
|
||||
|
||||
| Funzione | Ritorno | Descrizione |
|
||||
|----------|---------|-------------|
|
||||
| [F_GET_COSTO_ARTICOLO](F_GET_COSTO_ARTICOLO.md) | NUMBER | Costo unitario articolo a una data specifica |
|
||||
|
||||
## Funzioni Validazione
|
||||
|
||||
| Funzione | Ritorno | Descrizione |
|
||||
|----------|---------|-------------|
|
||||
| [F_EVENTO_SCADUTO](F_EVENTO_SCADUTO.md) | NUMBER (0/1) | Verifica se preventivo è scaduto |
|
||||
| [F_MAX_NUMERO_EVENTI_RAGGIUNTO](F_MAX_NUMERO_EVENTI_RAGGIUNTO.md) | NUMBER (-1/0/1) | Verifica limite eventi giornaliero |
|
||||
| [F_MAX_NUM_EVENTI_CONFERMATI](F_MAX_NUM_EVENTI_CONFERMATI.md) | NUMBER (0/1) | Verifica limite eventi confermati |
|
||||
| [F_CI_SONO_EVENTI_CONFERMATI](F_CI_SONO_EVENTI_CONFERMATI.md) | NUMBER (0/1) | Check esistenza eventi confermati in data/location |
|
||||
|
||||
## Funzioni Report
|
||||
|
||||
| Funzione | Ritorno | Descrizione |
|
||||
|----------|---------|-------------|
|
||||
| [F_REP_ALLESTIMENTI](F_REP_ALLESTIMENTI.md) | TABLE | Dati per report allestimenti (pipelined) |
|
||||
| [F_REP_CUCINA](F_REP_CUCINA.md) | TABLE | Dati per report cucina (pipelined) |
|
||||
| [F_GET_ANGOLO_ALLESTIMENTO](F_GET_ANGOLO_ALLESTIMENTO.md) | VARCHAR2 | Descrizione angolo allestimento |
|
||||
| [F_GET_ANGOLO_ALLESTIMENTO_OB](F_GET_ANGOLO_ALLESTIMENTO_OB.md) | VARCHAR2 | Descrizione angolo open bar |
|
||||
| [F_GET_TOVAGLIATO_ALLESTIMENTO](F_GET_TOVAGLIATO_ALLESTIMENTO.md) | VARCHAR2 | Descrizione tovagliato |
|
||||
|
||||
## Funzioni Autorizzazione
|
||||
|
||||
| Funzione | Ritorno | Descrizione |
|
||||
|----------|---------|-------------|
|
||||
| [F_USER_IN_ROLE](F_USER_IN_ROLE.md) | NUMBER (0/1) | Verifica appartenenza utente a ruolo |
|
||||
| [F_USER_IN_ROLE_STR](F_USER_IN_ROLE_STR.md) | VARCHAR2 | Verifica ruolo (ritorna stringa) |
|
||||
|
||||
## Funzioni Utility
|
||||
|
||||
| Funzione | Ritorno | Descrizione |
|
||||
|----------|---------|-------------|
|
||||
| [F_DAY_TO_NAME](F_DAY_TO_NAME.md) | VARCHAR2 | Converte numero giorno in nome italiano |
|
||||
| [STRING_TO_TABLE_ENUM](STRING_TO_TABLE_ENUM.md) | TABLE | Converte stringa delimitata in tabella |
|
||||
| [GET_PARAM_VALUE](GET_PARAM_VALUE.md) | VARCHAR2 | Recupera valore parametro da TB_CONFIG |
|
||||
| [SPLIT](SPLIT.md) | TABLE | Split stringa in elementi |
|
||||
| [MY_INSTR](MY_INSTR.md) | NUMBER | Funzione INSTR personalizzata |
|
||||
| [CLOB2BLOB](CLOB2BLOB.md) | BLOB | Conversione CLOB → BLOB |
|
||||
| [EXTDATE_GET_ITA](EXTDATE_GET_ITA.md) | VARCHAR2 | Formatta data in italiano esteso |
|
||||
|
||||
## Dettaglio Funzioni Critiche
|
||||
|
||||
### F_GET_QTA_IMPEGNATA
|
||||
|
||||
```sql
|
||||
FUNCTION F_GET_QTA_IMPEGNATA(
|
||||
p_codart VARCHAR2,
|
||||
p_data_from DATE,
|
||||
p_data_to DATE DEFAULT NULL
|
||||
) RETURN NUMBER
|
||||
```
|
||||
|
||||
**Logica:**
|
||||
- Interroga `V_IMPEGNI_ARTICOLI`
|
||||
- Somma quantità impegnate nel range di date
|
||||
- Se `p_data_to` è NULL, usa `p_data_from`
|
||||
|
||||
### F_EVENT0_SCADUTO
|
||||
|
||||
```sql
|
||||
FUNCTION F_EVENTO_SCADUTO(
|
||||
DATA_SCADENZA IN DATE,
|
||||
STATO_EVENTO IN NUMBER,
|
||||
STATO_FROM IN NUMBER,
|
||||
STATO_TO IN NUMBER
|
||||
) RETURN NUMBER
|
||||
```
|
||||
|
||||
**Logica:**
|
||||
- Ritorna 1 se `TRUNC(DATA_SCADENZA) <= TRUNC(SYSDATE)`
|
||||
AND `STATO_EVENTO BETWEEN STATO_FROM AND STATO_TO`
|
||||
- Altrimenti ritorna 0
|
||||
|
||||
### F_LIST_PRELIEVO_ADD_ARTICOLO
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
**Logica:**
|
||||
1. Verifica esistenza evento
|
||||
2. Verifica esistenza articolo
|
||||
3. Recupera giacenza articolo
|
||||
4. Controlla impegni in date vicine (±2 giorni)
|
||||
5. Inserisce record in `EVENTI_DET_PREL`
|
||||
6. Chiama `EVENTI_AGGIORNA_QTA_LISTA`
|
||||
7. Ritorna JSON con esito:
|
||||
- `{"type":"success","message":"..."}`
|
||||
- `{"type":"warning","message":"..."}`
|
||||
- `{"type":"error","code":"...","stack":"...","message":"..."}`
|
||||
|
||||
### F_GET_COSTO_ARTICOLO
|
||||
|
||||
```sql
|
||||
FUNCTION F_GET_COSTO_ARTICOLO(
|
||||
p_cod_articolo VARCHAR2,
|
||||
p_date DATE
|
||||
) RETURN NUMBER
|
||||
```
|
||||
|
||||
**Logica:**
|
||||
1. Cerca costo in `COSTI_ARTICOLI` alla data esatta
|
||||
2. Se non trovato, prende ultimo costo disponibile
|
||||
3. Se non trovato nulla, ritorna 0
|
||||
46
docs/functions/SPLIT.md
Normal file
46
docs/functions/SPLIT.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# SPLIT
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
FUNCTION "SPLIT"
|
||||
(
|
||||
p_list varchar2,
|
||||
p_del varchar2 := ','
|
||||
) return string_list
|
||||
is
|
||||
l_idx integer;
|
||||
l_list varchar2(32767) := p_list;
|
||||
|
||||
l_value varchar2(32767);
|
||||
|
||||
l_retval string_list;
|
||||
begin
|
||||
|
||||
l_retval := string_list();
|
||||
|
||||
loop
|
||||
|
||||
--l_idx := instr(l_list,p_del);
|
||||
l_idx := my_instr(l_list,p_del);
|
||||
|
||||
l_retval.extend;
|
||||
|
||||
if l_idx > 0 then
|
||||
--pipe row(substr(l_list,1,l_idx-1));
|
||||
--l_list := substr(l_list,l_idx+length(p_del));
|
||||
l_retval(l_retval.count) := substr(l_list, 1, l_idx - 1);
|
||||
l_list := substr(l_list,l_idx+length(p_del));
|
||||
else
|
||||
--pipe row(l_list);
|
||||
--exit;
|
||||
l_retval(l_retval.count) := l_list;
|
||||
exit;
|
||||
end if;
|
||||
|
||||
end loop;
|
||||
|
||||
return l_retval;
|
||||
|
||||
end split;
|
||||
```
|
||||
26
docs/functions/STRING_TO_TABLE_ENUM.md
Normal file
26
docs/functions/STRING_TO_TABLE_ENUM.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# STRING_TO_TABLE_ENUM
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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 <= 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;```
|
||||
422
docs/index.md
Normal file
422
docs/index.md
Normal file
@@ -0,0 +1,422 @@
|
||||
# Apollinare Catering - Documentazione Completa
|
||||
|
||||
Questa documentazione contiene l'estrazione completa di tutti gli oggetti del database Oracle e dell'applicazione APEX di Apollinare Catering & Banqueting.
|
||||
|
||||
## [Application Overview](APPLICATION_OVERVIEW.md)
|
||||
|
||||
**Apollinare Catering & Banqueting Management Software** è 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.
|
||||
|
||||
### Funzionalità Principali
|
||||
|
||||
| Area | Descrizione |
|
||||
| --------------------- | ------------------------------------------- |
|
||||
| **Gestione Eventi** | Creazione, workflow stati, versioning |
|
||||
| **Gestione Ospiti** | Tipologie ospiti, conteggi, coefficienti |
|
||||
| **Lista Prelievo** | Calcolo automatico quantità 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 |
|
||||
|
||||
### Proposta SaaS: CaterPro
|
||||
|
||||
La documentazione include una proposta per trasformare Apollinare in **CaterPro**, una piattaforma SaaS multi-tenant:
|
||||
|
||||
- **Target**: Piccole, medie e grandi aziende di catering
|
||||
- **Stack**: .NET 8 + React TypeScript + PostgreSQL/Oracle
|
||||
- **Pricing**: Da €49/mese (Basic) a €399/mese (Enterprise)
|
||||
- **Roadmap**: 10-14 mesi per feature parity + SaaS
|
||||
|
||||
Leggi la [documentazione completa](APPLICATION_OVERVIEW.md) per dettagli su architettura, funzionalità e roadmap.
|
||||
|
||||
---
|
||||
|
||||
## Struttura della Documentazione
|
||||
|
||||
```
|
||||
docs/
|
||||
├── apex/ # Applicazione APEX
|
||||
│ ├── README.md # Overview applicazione
|
||||
│ ├── pages/ # 56 pagine
|
||||
│ ├── processes/ # 98 processi
|
||||
│ ├── lovs/ # 12 List of Values
|
||||
│ ├── javascript/ # Librerie JavaScript
|
||||
│ ├── authorization/ # 5 schemi autorizzazione
|
||||
│ ├── dynamic-actions/ # Azioni dinamiche
|
||||
│ ├── items/ # Items condivisi
|
||||
│ ├── regions/ # Regioni condivise
|
||||
│ └── navigation/ # Navigazione
|
||||
├── tables/ # 32 tabelle
|
||||
├── views/ # 26 viste
|
||||
├── procedures/ # 11 stored procedures
|
||||
├── functions/ # 23 funzioni
|
||||
├── packages/ # 17 packages
|
||||
├── triggers/ # 19 triggers
|
||||
├── sequences/ # 22 sequences
|
||||
└── types/ # 10 tipi custom
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## APEX Application Documentation
|
||||
|
||||
### [APEX Application Overview](apex/README.md)
|
||||
|
||||
**Application:** APCB Project (ID: 112)
|
||||
**APEX Version:** 21.1.0
|
||||
**Schema:** APOLLINARECATERINGPROD
|
||||
|
||||
| Component | Count |
|
||||
| --------------- | ----- |
|
||||
| Pages | 56 |
|
||||
| Items | 302 |
|
||||
| Processes | 98 |
|
||||
| Regions | 151 |
|
||||
| Buttons | 119 |
|
||||
| Dynamic Actions | 62 |
|
||||
| LOVs | 12 |
|
||||
|
||||
### Key APEX Documentation
|
||||
|
||||
- [APEX README](apex/README.md) - Application overview and navigation
|
||||
- [Processes Documentation](apex/processes/README.md) - All 98 processes with PL/SQL code
|
||||
- [LOVs Documentation](apex/lovs/README.md) - 12 List of Values definitions
|
||||
- [JavaScript Libraries](apex/javascript/README.md) - Custom ajaxUtils.js and iframeObj.js
|
||||
- [Authorization Schemes](apex/authorization/README.md) - 5 security schemes
|
||||
|
||||
### Critical APEX Pages
|
||||
|
||||
| Page | Name | Description |
|
||||
| ------ | ---------------- | ------------------------------------------------- |
|
||||
| 1 | Home | Dashboard principale |
|
||||
| **22** | **Nuovo Evento** | **Pagina più complessa (108 items, 32 processi)** |
|
||||
| 9 | Liste | Lista eventi |
|
||||
| 12 | Calendario | Calendario eventi |
|
||||
| 35 | Schede | Schede evento |
|
||||
|
||||
---
|
||||
|
||||
## Indice per Categoria
|
||||
|
||||
### [Tabelle](tables/README.md) (32)
|
||||
|
||||
Tabelle principali del dominio business:
|
||||
|
||||
- [EVENTI](tables/EVENTI.md) - Tabella principale eventi
|
||||
- [EVENTI_DET_PREL](tables/EVENTI_DET_PREL.md) - Liste prelievo
|
||||
- [EVENTI_DET_OSPITI](tables/EVENTI_DET_OSPITI.md) - Dettaglio ospiti
|
||||
- [EVENTI_DET_RIS](tables/EVENTI_DET_RIS.md) - Risorse assegnate
|
||||
- [EVENTI_DET_DEGUST](tables/EVENTI_DET_DEGUST.md) - Degustazioni
|
||||
- [EVENTI_ACCONTI](tables/EVENTI_ACCONTI.md) - Gestione acconti/pagamenti
|
||||
- [EVENTI_ALTRICOSTI](tables/EVENTI_ALTRICOSTI.md) - Altri costi
|
||||
- [EVENTI_ALLEG](tables/EVENTI_ALLEG.md) - Allegati
|
||||
- [ARTICOLI](tables/ARTICOLI.md) - Catalogo articoli
|
||||
- [COSTI_ARTICOLI](tables/COSTI_ARTICOLI.md) - Storico costi
|
||||
- [CLIENTI](tables/CLIENTI.md) - Anagrafica clienti
|
||||
- [LOCATION](tables/LOCATION.md) - Location eventi
|
||||
- [RISORSE](tables/RISORSE.md) - Personale
|
||||
|
||||
Tabelle di lookup:
|
||||
|
||||
- [TB_TIPI_MAT](tables/TB_TIPI_MAT.md) - Tipi materiale
|
||||
- [TB_CODICI_CATEG](tables/TB_CODICI_CATEG.md) - Categorie
|
||||
- [TB_TIPI_EVENTO](tables/TB_TIPI_EVENTO.md) - Tipi evento
|
||||
- [TB_TIPI_OSPITI](tables/TB_TIPI_OSPITI.md) - Tipi ospiti
|
||||
- [TB_TIPI_RISORSA](tables/TB_TIPI_RISORSA.md) - Tipi risorsa
|
||||
- [TB_TIPI_PASTO](tables/TB_TIPI_PASTO.md) - Tipi pasto
|
||||
- [TB_CALENDAR_LOCKS](tables/TB_CALENDAR_LOCKS.md) - Limiti calendario
|
||||
- [TB_CONFIG](tables/TB_CONFIG.md) - Configurazioni
|
||||
|
||||
Tabelle di sistema:
|
||||
|
||||
- [USERS_READONLY](tables/USERS_READONLY.md) - Permessi utenti
|
||||
- [XLIB_LOGS](tables/XLIB_LOGS.md) - Log applicazione
|
||||
- [XLIB_COMPONENTS](tables/XLIB_COMPONENTS.md) - Componenti
|
||||
- [XLIB_JASPERREPORTS_CONF](tables/XLIB_JASPERREPORTS_CONF.md) - Config report
|
||||
- [XLIB_JASPERREPORTS_DEMOS](tables/XLIB_JASPERREPORTS_DEMOS.md) - Demo report
|
||||
|
||||
### [Viste](views/README.md) (26)
|
||||
|
||||
Viste per calcolo costi:
|
||||
|
||||
- [GET_COSTO_ART_BY_EVT](views/GET_COSTO_ART_BY_EVT.md) - Costo articoli per evento
|
||||
- [GET_COSTO_ART_EVT](views/GET_COSTO_ART_EVT.md) - Costo articoli aggregato
|
||||
- [GET_COSTO_CATEG_EVT](views/GET_COSTO_CATEG_EVT.md) - Costo per categoria
|
||||
- [GET_COSTO_DEGUS_EVT](views/GET_COSTO_DEGUS_EVT.md) - Costo degustazioni
|
||||
- [GET_COSTO_OSPITI_EVT](views/GET_COSTO_OSPITI_EVT.md) - Costo ospiti
|
||||
- [GET_COSTO_RIS_EVT](views/GET_COSTO_RIS_EVT.md) - Costo risorse
|
||||
- [GET_COSTO_TIPI_EVT](views/GET_COSTO_TIPI_EVT.md) - Costo per tipo
|
||||
- [GET_ULTIMI_COSTI](views/GET_ULTIMI_COSTI.md) - Ultimi costi articoli
|
||||
|
||||
Viste per eventi:
|
||||
|
||||
- [GET_EVT_DATA](views/GET_EVT_DATA.md) - Dati evento completi
|
||||
- [GET_EVT_DATA_PRINT](views/GET_EVT_DATA_PRINT.md) - Dati per stampa
|
||||
- [GET_PREL_ART_TOT](views/GET_PREL_ART_TOT.md) - Totali prelievo
|
||||
- [GET_PREL_BY_EVT](views/GET_PREL_BY_EVT.md) - Prelievi per evento
|
||||
|
||||
Viste per calendario e stato:
|
||||
|
||||
- [VW_CALENDARIO_EVENTI](views/VW_CALENDARIO_EVENTI.md) - Vista calendario
|
||||
- [VW_EVENT_COLOR](views/VW_EVENT_COLOR.md) - Colori stati
|
||||
- [VW_EVENTI_STATUSES](views/VW_EVENTI_STATUSES.md) - Stati eventi
|
||||
|
||||
Viste per giacenze:
|
||||
|
||||
- [V_IMPEGNI_ARTICOLI](views/V_IMPEGNI_ARTICOLI.md) - Impegni articoli
|
||||
- [V_IMPEGNI_ARTICOLI_LOC](views/V_IMPEGNI_ARTICOLI_LOC.md) - Impegni per location
|
||||
|
||||
Viste per report:
|
||||
|
||||
- [V_REP_ALLESTIMENTI](views/V_REP_ALLESTIMENTI.md) - Report allestimenti
|
||||
- [VW_REP_DEGUSTAZIONI](views/VW_REP_DEGUSTAZIONI.md) - Report degustazioni
|
||||
- [V_GRIGLIA](views/V_GRIGLIA.md) - Vista griglia
|
||||
- [GET_REPORT_CONSUNTIVO_PER_DATA](views/GET_REPORT_CONSUNTIVO_PER_DATA.md) - Consuntivo
|
||||
|
||||
Viste per utenti/permessi:
|
||||
|
||||
- [GET_CONSUNTIVI_USERS](views/GET_CONSUNTIVI_USERS.md) - Utenti consuntivi
|
||||
- [GET_GESTORI_USERS](views/GET_GESTORI_USERS.md) - Utenti gestori
|
||||
- [GET_USERS_LIST](views/GET_USERS_LIST.md) - Lista utenti
|
||||
|
||||
Viste per pagamenti:
|
||||
|
||||
- [GET_EVENTI_DA_PAGARE_ENTRO_65GG](views/GET_EVENTI_DA_PAGARE_ENTRO_65GG.md) - Eventi da sollecitare
|
||||
|
||||
### [Stored Procedures](procedures/README.md) (11)
|
||||
|
||||
Business logic principale:
|
||||
|
||||
- [EVENTI_AGGIORNA_QTA_LISTA](procedures/EVENTI_AGGIORNA_QTA_LISTA.md) - Ricalcolo quantità lista prelievo
|
||||
- [EVENTI_AGGIORNA_TOT_OSPITI](procedures/EVENTI_AGGIORNA_TOT_OSPITI.md) - Aggiorna totale ospiti
|
||||
- [EVENTI_COPIA](procedures/EVENTI_COPIA.md) - Duplicazione evento
|
||||
- [EVENTI_RICALCOLA_ACCONTI](procedures/EVENTI_RICALCOLA_ACCONTI.md) - Ricalcolo acconti
|
||||
- [EVENTO_ELIMINA_PRELIEVI](procedures/EVENTO_ELIMINA_PRELIEVI.md) - Elimina prelievi
|
||||
- [LISTE_COPIA](procedures/LISTE_COPIA.md) - Copia liste tra eventi
|
||||
- [P_CANCEL_SAME_LOCATION_EVENTS](procedures/P_CANCEL_SAME_LOCATION_EVENTS.md) - Annulla eventi stessa location
|
||||
|
||||
Utility:
|
||||
|
||||
- [ROWSORT_TIPI](procedures/ROWSORT_TIPI.md) - Ordinamento tipi
|
||||
- [HTPPRN](procedures/HTPPRN.md) - Stampa HTTP
|
||||
- [SEND_DATA_TO_DROPBOX](procedures/SEND_DATA_TO_DROPBOX.md) - Export Dropbox
|
||||
- [XLOG](procedures/XLOG.md) - Logging
|
||||
|
||||
### [Funzioni](functions/README.md) (23)
|
||||
|
||||
Calcolo quantità e disponibilità:
|
||||
|
||||
- [F_GET_QTA_IMPEGNATA](functions/F_GET_QTA_IMPEGNATA.md) - Quantità impegnata
|
||||
- [F_GET_TOT_OSPITI](functions/F_GET_TOT_OSPITI.md) - Totale ospiti
|
||||
- [F_GET_OSPITI](functions/F_GET_OSPITI.md) - Dettaglio ospiti (pipelined)
|
||||
- [F_LIST_PRELIEVO_ADD_ARTICOLO](functions/F_LIST_PRELIEVO_ADD_ARTICOLO.md) - Aggiunta articolo
|
||||
|
||||
Calcolo costi:
|
||||
|
||||
- [F_GET_COSTO_ARTICOLO](functions/F_GET_COSTO_ARTICOLO.md) - Costo articolo a data
|
||||
|
||||
Validazioni:
|
||||
|
||||
- [F_EVENTO_SCADUTO](functions/F_EVENTO_SCADUTO.md) - Verifica scadenza
|
||||
- [F_MAX_NUMERO_EVENTI_RAGGIUNTO](functions/F_MAX_NUMERO_EVENTI_RAGGIUNTO.md) - Limite eventi
|
||||
- [F_MAX_NUM_EVENTI_CONFERMATI](functions/F_MAX_NUM_EVENTI_CONFERMATI.md) - Limite confermati
|
||||
- [F_CI_SONO_EVENTI_CONFERMATI](functions/F_CI_SONO_EVENTI_CONFERMATI.md) - Check confermati
|
||||
|
||||
Report:
|
||||
|
||||
- [F_REP_ALLESTIMENTI](functions/F_REP_ALLESTIMENTI.md) - Report allestimenti
|
||||
- [F_REP_CUCINA](functions/F_REP_CUCINA.md) - Report cucina
|
||||
- [F_GET_ANGOLO_ALLESTIMENTO](functions/F_GET_ANGOLO_ALLESTIMENTO.md) - Angolo allestimento
|
||||
- [F_GET_ANGOLO_ALLESTIMENTO_OB](functions/F_GET_ANGOLO_ALLESTIMENTO_OB.md) - Angolo open bar
|
||||
- [F_GET_TOVAGLIATO_ALLESTIMENTO](functions/F_GET_TOVAGLIATO_ALLESTIMENTO.md) - Tovagliato
|
||||
|
||||
Autorizzazioni:
|
||||
|
||||
- [F_USER_IN_ROLE](functions/F_USER_IN_ROLE.md) - Verifica ruolo utente
|
||||
- [F_USER_IN_ROLE_STR](functions/F_USER_IN_ROLE_STR.md) - Ruolo utente (stringa)
|
||||
|
||||
Utility:
|
||||
|
||||
- [F_DAY_TO_NAME](functions/F_DAY_TO_NAME.md) - Giorno in italiano
|
||||
- [STRING_TO_TABLE_ENUM](functions/STRING_TO_TABLE_ENUM.md) - Stringa a tabella
|
||||
- [GET_PARAM_VALUE](functions/GET_PARAM_VALUE.md) - Valore parametro
|
||||
- [SPLIT](functions/SPLIT.md) - Split stringa
|
||||
- [MY_INSTR](functions/MY_INSTR.md) - Instr custom
|
||||
- [CLOB2BLOB](functions/CLOB2BLOB.md) - Conversione CLOB
|
||||
- [EXTDATE_GET_ITA](functions/EXTDATE_GET_ITA.md) - Data in italiano
|
||||
|
||||
### [Packages](packages/README.md) (17)
|
||||
|
||||
Business:
|
||||
|
||||
- [MAIL_PKG](packages/MAIL_PKG.md) - Gestione invio email automatiche
|
||||
|
||||
Utility esterne:
|
||||
|
||||
- [UTL_BASE64](packages/UTL_BASE64.md) - Encoding Base64
|
||||
|
||||
JasperReports:
|
||||
|
||||
- [XLIB_JASPERREPORTS](packages/XLIB_JASPERREPORTS.md) - Integrazione JasperReports
|
||||
- [XLIB_JASPERREPORTS_IMG](packages/XLIB_JASPERREPORTS_IMG.md) - Immagini report
|
||||
|
||||
HTTP/Componenti:
|
||||
|
||||
- [XLIB_HTTP](packages/XLIB_HTTP.md) - Chiamate HTTP
|
||||
- [XLIB_COMPONENT](packages/XLIB_COMPONENT.md) - Componenti
|
||||
- [XLIB_LOG](packages/XLIB_LOG.md) - Logging
|
||||
|
||||
JSON (libreria PLJSON):
|
||||
|
||||
- [PLJSON_DYN](packages/PLJSON_DYN.md)
|
||||
- [PLJSON_EXT](packages/PLJSON_EXT.md)
|
||||
- [PLJSON_HELPER](packages/PLJSON_HELPER.md)
|
||||
- [PLJSON_ML](packages/PLJSON_ML.md)
|
||||
- [PLJSON_OBJECT_CACHE](packages/PLJSON_OBJECT_CACHE.md)
|
||||
- [PLJSON_PARSER](packages/PLJSON_PARSER.md)
|
||||
- [PLJSON_PRINTER](packages/PLJSON_PRINTER.md)
|
||||
- [PLJSON_UT](packages/PLJSON_UT.md)
|
||||
- [PLJSON_UTIL_PKG](packages/PLJSON_UTIL_PKG.md)
|
||||
- [PLJSON_XML](packages/PLJSON_XML.md)
|
||||
|
||||
### [Triggers](triggers/README.md) (19)
|
||||
|
||||
Generazione ID:
|
||||
|
||||
- [EVENTI_TRG](triggers/EVENTI_TRG.md) - ID eventi + inizializzazione
|
||||
- [EVENTI_AI_TRG](triggers/EVENTI_AI_TRG.md) - Creazione ospiti default
|
||||
- [EVENTI_DET_PREL_TRG](triggers/EVENTI_DET_PREL_TRG.md) - ID prelievi
|
||||
- [EVENTI_DET_RIS_TRG](triggers/EVENTI_DET_RIS_TRG.md) - ID risorse
|
||||
- [EVENTI_DET_DEGUST_TRG](triggers/EVENTI_DET_DEGUST_TRG.md) - ID degustazioni
|
||||
- [EVENTI_ACCONTI_TRG](triggers/EVENTI_ACCONTI_TRG.md) - ID acconti
|
||||
- [EVENTI_ALTRICOSTI_TRG](triggers/EVENTI_ALTRICOSTI_TRG.md) - ID altri costi
|
||||
- [EVENTI_ALLEG_TRG](triggers/EVENTI_ALLEG_TRG.md) - ID allegati
|
||||
- [CLIENTI_TRG](triggers/CLIENTI_TRG.md) - ID clienti
|
||||
- [LOCATION_TRG](triggers/LOCATION_TRG.md) - ID location
|
||||
- [RISORSE_TRG](triggers/RISORSE_TRG.md) - ID risorse
|
||||
- [ARTICOLI_DET_REGOLE_TRG](triggers/ARTICOLI_DET_REGOLE_TRG.md) - ID regole articoli
|
||||
- [TB_TIPI_PASTO_TRG](triggers/TB_TIPI_PASTO_TRG.md) - ID tipi pasto
|
||||
|
||||
Business logic:
|
||||
|
||||
- [EVENTI_DET_OSPITI_TRG_AI](triggers/EVENTI_DET_OSPITI_TRG_AI.md) - Aggiornamento ospiti
|
||||
- [EVENTI_DET_PREL_QTA_TOT_TRG](triggers/EVENTI_DET_PREL_QTA_TOT_TRG.md) - Calcolo quantità totale
|
||||
|
||||
Ordinamento:
|
||||
|
||||
- [ADD_COD_STEP](triggers/ADD_COD_STEP.md) - Ordine tipi materiale
|
||||
- [ON_DELETE_REORDER](triggers/ON_DELETE_REORDER.md) - Riordino dopo delete
|
||||
|
||||
Sistema:
|
||||
|
||||
- [BI_GL_SCHEMA_CHANGES](triggers/BI_GL_SCHEMA_CHANGES.md) - Log modifiche schema
|
||||
- [XLIB_LOGS_BI_TRG](triggers/XLIB_LOGS_BI_TRG.md) - Log applicazione
|
||||
|
||||
### [Sequences](sequences/README.md) (22)
|
||||
|
||||
Tutte le sequence del database.
|
||||
|
||||
### [Types](types/README.md) (10)
|
||||
|
||||
Tipi custom:
|
||||
|
||||
- [T_DET_OSPITI_ROW](types/T_DET_OSPITI_ROW.md) / [T_DET_OSPITI_TAB](types/T_DET_OSPITI_TAB.md) - Tipo per F_GET_OSPITI
|
||||
- [T_REP_ALLESTIMENTI_ROW](types/T_REP_ALLESTIMENTI_ROW.md) / [T_REP_ALLESTIMENTI_TAB](types/T_REP_ALLESTIMENTI_TAB.md) - Tipo per F_REP_ALLESTIMENTI
|
||||
- [T_REP_CUCINA_ROW](types/T_REP_CUCINA_ROW.md) / [T_REP_CUCINA_TAB](types/T_REP_CUCINA_TAB.md) - Tipo per F_REP_CUCINA
|
||||
- [STRING_LIST](types/STRING_LIST.md) - Lista stringhe
|
||||
- [ENUM_TABLE_OBJECT](types/ENUM_TABLE_OBJECT.md) / [ENUM_TABLE_TYPE](types/ENUM_TABLE_TYPE.md) - Tipi per STRING_TO_TABLE_ENUM
|
||||
- [XLIB_VC2_ARRAY_T](types/XLIB_VC2_ARRAY_T.md) - Array varchar2
|
||||
|
||||
---
|
||||
|
||||
## Schema ER Semplificato
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ CLIENTI │
|
||||
└──────┬──────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ LOCATION │◄────│ EVENTI │────►│TB_TIPI_EVENTO│
|
||||
└─────────────┘ └──────┬──────┘ └─────────────┘
|
||||
│
|
||||
┌─────────────────┼─────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│EVENTI_DET_OSPITI│ │ EVENTI_DET_PREL │ │ EVENTI_DET_RIS │
|
||||
└─────────────────┘ └────────┬────────┘ └────────┬────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ TB_TIPI_OSPITI │ │ ARTICOLI │ │ RISORSE │
|
||||
└─────────────────┘ └────────┬────────┘ └─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ TB_CODICI_CATEG │
|
||||
└────────┬────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ TB_TIPI_MAT │
|
||||
└─────────────────┘
|
||||
|
||||
┌─────────────────┬─────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│EVENTI_DET_DEGUST│ │ EVENTI_ACCONTI │ │EVENTI_ALTRICOSTI│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Workflow Stati Evento
|
||||
|
||||
```
|
||||
┌──────────────┐
|
||||
│ PREVENTIVO │ (100) - Bianco
|
||||
└──────┬───────┘
|
||||
│ Degustazione
|
||||
▼
|
||||
┌──────────────┐
|
||||
│SCHEDA EVENTO │ (200) - Celeste
|
||||
│(preparazione)│
|
||||
└──────┬───────┘
|
||||
│ Prima caparra
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ SCHEDA │ (300) - Giallo
|
||||
│ CONFERMATA │
|
||||
└──────┬───────┘
|
||||
│ Quasi confermato
|
||||
▼
|
||||
┌──────────────┐
|
||||
│SCHEDA QUASI │ (350) - Arancio
|
||||
│ CONFERMATA │
|
||||
└──────┬───────┘
|
||||
│ Conferma definitiva
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ CONFERMATO │ (400) - Verde
|
||||
└──────────────┘
|
||||
|
||||
│ Rifiuto/Scadenza
|
||||
▼
|
||||
┌──────────────┐
|
||||
│NON ACCETTATO/│ (900) - Viola
|
||||
│ SUPERATO │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
## Note per lo Sviluppo
|
||||
|
||||
1. **Packages PLJSON\_\***: Libreria esterna per parsing JSON, può essere sostituita con funzionalità native .NET
|
||||
|
||||
2. **Packages XLIB\_\***: Componenti per integrazione JasperReports, da valutare sostituzione con report .NET
|
||||
|
||||
3. **Trigger per ID**: In .NET usare Identity columns o GUID
|
||||
|
||||
4. **Calcolo quantità**: La logica in `EVENTI_AGGIORNA_QTA_LISTA` è critica e deve essere portata fedelmente
|
||||
|
||||
5. **Sistema acconti**: Le percentuali 30%-50%-20% sono hardcoded, valutare parametrizzazione
|
||||
392
docs/packages/MAIL_PKG.md
Normal file
392
docs/packages/MAIL_PKG.md
Normal file
@@ -0,0 +1,392 @@
|
||||
# MAIL_PKG
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
PACKAGE MAIL_PKG AS
|
||||
--==================================================================================
|
||||
-- SPECIFICA DEL PACKAGE
|
||||
-- Aggiunta delle nuove procedure per il reminder della seconda caparra.
|
||||
-- Ultima modifica: 26/07/2024
|
||||
--==================================================================================
|
||||
|
||||
-- Procedura generica per inviare email
|
||||
procedure send_custom_mail(p_recipients varchar2, p_subject varchar2, p_body varchar2);
|
||||
|
||||
-- Procedure esistenti
|
||||
PROCEDURE send_richiesta_riscontro_preventivo (
|
||||
p_style_id NUMBER DEFAULT 1,
|
||||
p_evento_id NUMBER
|
||||
);
|
||||
PROCEDURE send_richiesta_riscontro_preventivo_job;
|
||||
|
||||
PROCEDURE send_richiesta_riscontro_post_degustazione (
|
||||
p_style_id NUMBER DEFAULT 1,
|
||||
p_evento_id NUMBER
|
||||
);
|
||||
PROCEDURE send_richiesta_riscontro_post_degustazione_job;
|
||||
|
||||
-- ===============================================================================
|
||||
-- NUOVE PROCEDURE PER IL REMINDER DELLA SECONDA CAPARRA
|
||||
-- Data creazione: 26/07/2024
|
||||
-- ===============================================================================
|
||||
|
||||
/**
|
||||
* @descr Costruisce e invia la mail di sollecito per la seconda caparra per un dato evento.
|
||||
* @param p_style_id ID dello stile HTML da applicare alla mail.
|
||||
* @param p_evento_id ID dell'evento per cui inviare la notifica.
|
||||
*/
|
||||
PROCEDURE send_reminder_seconda_caparra (
|
||||
p_style_id NUMBER DEFAULT 1,
|
||||
p_evento_id NUMBER
|
||||
);
|
||||
|
||||
/**
|
||||
* @descr Job che seleziona gli eventi per cui inviare il sollecito della seconda caparra.
|
||||
* Il primo invio avviene 65 giorni prima dell'evento.
|
||||
* Gli invii successivi avvengono ogni 5 giorni fino alla data dell'evento,
|
||||
* se la seconda caparra non risulta ancora pagata.
|
||||
*/
|
||||
PROCEDURE send_reminder_seconda_caparra_job;
|
||||
|
||||
END MAIL_PKG;
|
||||
```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
PACKAGE BODY MAIL_PKG AS
|
||||
--==================================================================================
|
||||
-- BODY DEL PACKAGE
|
||||
-- Implementazione delle nuove procedure e mantenimento di quelle esistenti.
|
||||
-- Ultima modifica: 25/07/2024
|
||||
--==================================================================================
|
||||
|
||||
/**
|
||||
* @descr Procedura di utility generica per inviare una mail tramite APEX_MAIL.
|
||||
* @param p_recipients Lista di destinatari separati da virgola.
|
||||
* @param p_subject Oggetto della mail.
|
||||
* @param p_body Corpo della mail (può contenere HTML).
|
||||
*/
|
||||
procedure send_custom_mail(p_recipients varchar2, p_subject varchar2, p_body varchar2) AS
|
||||
BEGIN
|
||||
-- Se non ci sono destinatari, interrompe l'esecuzione.
|
||||
if trim(p_recipients) is null
|
||||
then
|
||||
return;
|
||||
end if;
|
||||
|
||||
-- Utilizza il package APEX_MAIL per comporre e inviare l'email.
|
||||
APEX_MAIL.SEND(
|
||||
p_to => p_recipients,
|
||||
p_from => 'noreply@apollinarecatering.it',
|
||||
p_bcc => 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',
|
||||
--p_bcc => 'monia@apollinarecatering.it, maria@apollinarecatering.it', -- Copia conoscenza nascosta
|
||||
p_subj => p_subject,
|
||||
p_body => p_body,
|
||||
p_body_html => p_body -- Il corpo viene inviato sia come testo che come HTML.
|
||||
);
|
||||
|
||||
-- Forza l'invio immediato delle mail presenti nella coda di APEX.
|
||||
APEX_MAIL.PUSH_QUEUE;
|
||||
END send_custom_mail;
|
||||
|
||||
/**
|
||||
* @descr Invia una mail di sollecito per avere un riscontro su un preventivo inviato per eventi in stato preventivo (100) o scheda confermata (200).
|
||||
* @param p_style_id ID dello stile HTML da usare per il corpo della mail.
|
||||
* @param p_evento_id ID dell'evento a cui la mail fa riferimento.
|
||||
*/
|
||||
PROCEDURE send_richiesta_riscontro_preventivo (
|
||||
p_style_id NUMBER DEFAULT 1,
|
||||
p_evento_id NUMBER
|
||||
) AS
|
||||
v_evento eventi%ROWTYPE;
|
||||
v_location location%ROWTYPE;
|
||||
BEGIN
|
||||
-- Imposta la lingua e il formato della data della sessione per garantire la corretta formattazione.
|
||||
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE="ITALIAN"';
|
||||
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT="DD-MON-YYYY"';
|
||||
|
||||
-- Recupera i dettagli dell'evento e della location.
|
||||
BEGIN
|
||||
-- Seleziona i dati dell'evento solo se le mail sono abilitate (mail_enabled > 0).
|
||||
SELECT e.* INTO v_evento
|
||||
FROM eventi e
|
||||
WHERE e.id = p_evento_id
|
||||
AND e.stato in (100, 200)
|
||||
AND e.mail_enabled > 0;
|
||||
|
||||
-- Seleziona i dati della location associata all'evento.
|
||||
SELECT l.* INTO v_location
|
||||
FROM location l
|
||||
WHERE l.id = v_evento.id_location;
|
||||
EXCEPTION
|
||||
-- Se l'evento non viene trovato (o ha le mail disabilitate), la procedura termina.
|
||||
WHEN NO_DATA_FOUND THEN RETURN;
|
||||
END;
|
||||
|
||||
-- Inizializza il corpo della mail e imposta lo stile HTML.
|
||||
CMN_MAIL_HTMLUTILS.mailbody := '';
|
||||
CMN_MAIL_HTMLUTILS.set_style(p_style_id);
|
||||
|
||||
-- Costruisce il corpo della mail paragrafo per paragrafo utilizzando il package di utility.
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('Gentilissimi,');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'in seguito all''invio della nostra proposta per il vostro evento, '||
|
||||
'desideriamo sapere se avete avuto modo di valutarla e se siete interessati ai nostri servizi.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'Saremmo lieti di incontrarvi per una degustazione, così da potervi presentare al meglio le nostre offerte. '||
|
||||
'Potete prenotare una delle date disponibili direttamente tramite il nostro sito: '||
|
||||
'<a href="https://www.apollinarecatering.it/degustazioni/">Degustazioni</a>.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'Per qualsiasi ulteriore informazione o chiarimento potete scriverci a '||
|
||||
'<a href="mailto:info@apollinarecatering.it">info@apollinarecatering.it</a>.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Si prega di non rispondere direttamente a questa email.</b>');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Ufficio Commerciale</b>');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('📞 +39 0743 45 449');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Apollinare Catering</b>');
|
||||
|
||||
-- Invia la mail usando APEX_MAIL, componendo un oggetto dinamico.
|
||||
APEX_MAIL.SEND(
|
||||
p_to => v_evento.cliente_email,
|
||||
p_from => 'noreply@apollinarecatering.it',
|
||||
p_bcc => 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',
|
||||
--p_bcc => 'monia@apollinarecatering.it, maria@apollinarecatering.it',
|
||||
p_subj => 'Apollinare – richiesta riscontro per evento del '||
|
||||
TO_CHAR(v_evento.data, 'DD/MM/YYYY')||' presso '||v_location.location,
|
||||
p_body => CMN_MAIL_HTMLUTILS.mailbody,
|
||||
p_body_html => CMN_MAIL_HTMLUTILS.mailbody
|
||||
);
|
||||
|
||||
-- Forza l'invio immediato dalla coda di APEX.
|
||||
APEX_MAIL.PUSH_QUEUE;
|
||||
END send_richiesta_riscontro_preventivo;
|
||||
|
||||
/**
|
||||
* @descr Invia una mail di sollecito dopo che il cliente ha partecipato a una degustazione.
|
||||
* @param p_style_id ID dello stile HTML da usare per il corpo della mail.
|
||||
* @param p_evento_id ID dell'evento a cui la mail fa riferimento.
|
||||
*/
|
||||
PROCEDURE send_richiesta_riscontro_post_degustazione (
|
||||
p_style_id NUMBER DEFAULT 1,
|
||||
p_evento_id NUMBER
|
||||
) AS
|
||||
v_evento eventi%ROWTYPE;
|
||||
v_location location%ROWTYPE;
|
||||
BEGIN
|
||||
-- Imposta la lingua e il formato della data della sessione.
|
||||
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE="ITALIAN"';
|
||||
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT="DD-MON-YYYY"';
|
||||
|
||||
-- Recupera i dettagli dell'evento e della location.
|
||||
BEGIN
|
||||
-- Seleziona i dati dell'evento solo se le mail sono abilitate.
|
||||
SELECT e.* INTO v_evento
|
||||
FROM eventi e
|
||||
WHERE e.id = p_evento_id
|
||||
AND e.stato in (200)
|
||||
AND e.mail_enabled > 0;
|
||||
|
||||
-- Seleziona i dati della location.
|
||||
SELECT l.* INTO v_location
|
||||
FROM location l
|
||||
WHERE l.id = v_evento.id_location;
|
||||
EXCEPTION
|
||||
-- Se non trova l'evento, esce dalla procedura.
|
||||
WHEN NO_DATA_FOUND THEN RETURN;
|
||||
END;
|
||||
|
||||
-- Inizializza il corpo della mail e imposta lo stile HTML.
|
||||
CMN_MAIL_HTMLUTILS.mailbody := '';
|
||||
CMN_MAIL_HTMLUTILS.set_style(p_style_id);
|
||||
|
||||
-- Costruisce il corpo della mail.
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('Gentilissimi,');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'in seguito alla degustazione effettuata per il vostro evento, '||
|
||||
'desideriamo sapere se la nostra proposta risponde alle vostre aspettative '||
|
||||
'e se intendete procedere con la conferma dei servizi.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'Per ogni ulteriore chiarimento siamo a vostra completa disposizione: '||
|
||||
'<a href="mailto:info@apollinarecatering.it">info@apollinarecatering.it</a>.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Si prega di non rispondere direttamente a questa email.</b>');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Ufficio Commerciale</b>');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('📞 +39 0743 45 449');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Apollinare Catering</b>');
|
||||
|
||||
-- Invia la mail, componendo un oggetto dinamico con data e location.
|
||||
APEX_MAIL.SEND(
|
||||
p_to => v_evento.cliente_email,
|
||||
p_from => 'noreply@apollinarecatering.it',
|
||||
p_bcc => 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',
|
||||
--p_bcc => 'monia@apollinarecatering.it, maria@apollinarecatering.it',
|
||||
p_subj => 'Apollinare – riscontro post-degustazione evento del '||
|
||||
TO_CHAR(v_evento.data, 'DD/MM/YYYY')||' presso '||v_location.location,
|
||||
p_body => CMN_MAIL_HTMLUTILS.mailbody,
|
||||
p_body_html => CMN_MAIL_HTMLUTILS.mailbody
|
||||
);
|
||||
|
||||
-- Forza l'invio immediato.
|
||||
APEX_MAIL.PUSH_QUEUE;
|
||||
END send_richiesta_riscontro_post_degustazione;
|
||||
|
||||
/**
|
||||
* @descr Procedura schedulabile (job) che invia solleciti per i preventivi non confermati.
|
||||
*/
|
||||
PROCEDURE send_richiesta_riscontro_preventivo_job AS
|
||||
BEGIN
|
||||
-- Itera su tutti gli eventi che soddisfano i criteri per il sollecito.
|
||||
FOR evt IN (
|
||||
SELECT e.*
|
||||
FROM eventi e
|
||||
WHERE e.stato in (100) -- Stato: Preventivo non confermato
|
||||
AND e.mail_enabled = 1 -- Mail abilitate
|
||||
AND TRUNC(e.data_doc) = TRUNC(SYSDATE) - 10 -- Sono passati 10 giorni dalla data del documento.
|
||||
)
|
||||
LOOP
|
||||
-- Per ogni evento trovato, chiama la procedura di invio mail.
|
||||
send_richiesta_riscontro_preventivo(
|
||||
p_style_id => 1,
|
||||
p_evento_id => evt.id
|
||||
);
|
||||
END LOOP;
|
||||
END send_richiesta_riscontro_preventivo_job;
|
||||
|
||||
/**
|
||||
* @descr Procedura schedulabile (job) che invia solleciti dopo una degustazione.
|
||||
*/
|
||||
PROCEDURE send_richiesta_riscontro_post_degustazione_job AS
|
||||
BEGIN
|
||||
-- Itera su tutti gli eventi che soddisfano i criteri per il sollecito post-degustazione.
|
||||
FOR evt IN (
|
||||
SELECT e.*
|
||||
FROM eventi e
|
||||
JOIN ( -- Sottoquery per trovare la data della prima degustazione per ogni evento.
|
||||
SELECT id_evento,
|
||||
MIN(TRUNC(data)) AS min_data
|
||||
FROM eventi_det_degust
|
||||
GROUP BY id_evento ) dm
|
||||
ON dm.id_evento = e.id
|
||||
WHERE e.stato = 200 -- Stato: Scheda evento in preparazione
|
||||
AND e.mail_enabled = 1 -- Mail abilitate
|
||||
AND dm.min_data = TRUNC(SYSDATE) - 15 -- Sono passati 15 giorni dalla prima degustazione.
|
||||
)
|
||||
LOOP
|
||||
-- Per ogni evento trovato, chiama la procedura di invio mail.
|
||||
send_richiesta_riscontro_post_degustazione(
|
||||
p_style_id => 1,
|
||||
p_evento_id => evt.id
|
||||
);
|
||||
END LOOP;
|
||||
END send_richiesta_riscontro_post_degustazione_job;
|
||||
|
||||
|
||||
-- ===============================================================================
|
||||
-- IMPLEMENTAZIONE NUOVE PROCEDURE
|
||||
-- Data creazione: 26/07/2024
|
||||
-- ===============================================================================
|
||||
|
||||
PROCEDURE send_reminder_seconda_caparra (
|
||||
p_style_id NUMBER DEFAULT 1,
|
||||
p_evento_id NUMBER
|
||||
) AS
|
||||
v_evento eventi%ROWTYPE;
|
||||
v_location location%ROWTYPE;
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE="ITALIAN"';
|
||||
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT="DD-MON-YYYY"';
|
||||
|
||||
-- Recupero i dati dell'evento e della location
|
||||
BEGIN
|
||||
SELECT e.* INTO v_evento
|
||||
FROM eventi e
|
||||
WHERE e.id = p_evento_id
|
||||
AND e.mail_enabled > 0;
|
||||
|
||||
SELECT l.* INTO v_location
|
||||
FROM location l
|
||||
WHERE l.id = v_evento.id_location;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
-- Se l'evento non esiste o le mail sono disabilitate, esco.
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
-- Costruzione del corpo della mail
|
||||
CMN_MAIL_HTMLUTILS.mailbody := '';
|
||||
CMN_MAIL_HTMLUTILS.set_style(p_style_id);
|
||||
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('Gentilissimi,');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'sperando che tutto proceda per il meglio, desideriamo cortesemente ricordarvi la scadenza relativa alla seconda tranche di pagamento per il vostro evento.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'Qualora non fosse ancora stato effettuato, vi invitiamo a procedere con il versamento della seconda caparra, previsto 60 giorni prima della data dell’evento, come da accordi e indicato nel preventivo.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph(
|
||||
'Rimaniamo a disposizione per qualsiasi chiarimento e vi ringraziamo sin da ora per la preziosa collaborazione.'
|
||||
);
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Ufficio Commerciale</b>');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('📞 +39 0743 45 449');
|
||||
CMN_MAIL_HTMLUTILS.create_paragraph('<b>Apollinare Catering</b>');
|
||||
|
||||
-- Invio della mail
|
||||
APEX_MAIL.SEND(
|
||||
--p_to => v_evento.cliente_email,
|
||||
p_to => 'amministrazione@apollinarecatering.it',
|
||||
p_from => 'noreply@apollinarecatering.it',
|
||||
p_bcc => 'monia@apollinarecatering.it, matrimonio@apollinarecatering.it',
|
||||
--p_bcc => 'monia@apollinarecatering.it, maria@apollinarecatering.it',
|
||||
p_subj => 'Apollinare – Promemoria pagamento per evento del '||
|
||||
TO_CHAR(v_evento.data, 'DD/MM/YYYY'),
|
||||
p_body => CMN_MAIL_HTMLUTILS.mailbody,
|
||||
p_body_html => CMN_MAIL_HTMLUTILS.mailbody
|
||||
);
|
||||
|
||||
-- Invio immediato dalla coda
|
||||
APEX_MAIL.PUSH_QUEUE;
|
||||
|
||||
END send_reminder_seconda_caparra;
|
||||
|
||||
|
||||
PROCEDURE send_reminder_seconda_caparra_job AS
|
||||
BEGIN
|
||||
-- Scorro tutti gli eventi che necessitano del reminder.
|
||||
-- La logica ora utilizza la vista GET_EVENTI_DA_PAGARE_ENTRO_65GG
|
||||
-- per identificare gli eventi che non hanno saldato la caparra.
|
||||
FOR evt IN (
|
||||
SELECT
|
||||
v.id,
|
||||
v.data -- Seleziono la data per il calcolo del MOD
|
||||
FROM
|
||||
GET_EVENTI_DA_PAGARE_ENTRO_65GG v
|
||||
JOIN
|
||||
eventi e ON v.id = e.id -- Join per recuperare il flag mail_enabled
|
||||
WHERE
|
||||
-- La vista già filtra per stato, importi e finestra di 65 giorni.
|
||||
-- Aggiungo solo le condizioni specifiche del job.
|
||||
|
||||
-- Le mail automatiche devono essere abilitate.
|
||||
e.mail_enabled = 1
|
||||
|
||||
-- La logica MOD assicura l'invio periodico ogni 5 giorni.
|
||||
AND MOD(65 - (TRUNC(v.data) - TRUNC(SYSDATE)), 5) = 0
|
||||
)
|
||||
LOOP
|
||||
-- Per ogni evento trovato, chiamo la procedura di invio mail.
|
||||
send_reminder_seconda_caparra(
|
||||
p_style_id => 1,
|
||||
p_evento_id => evt.id
|
||||
);
|
||||
END LOOP;
|
||||
END send_reminder_seconda_caparra_job;
|
||||
|
||||
END MAIL_PKG;```
|
||||
341
docs/packages/PLJSON_DYN.md
Normal file
341
docs/packages/PLJSON_DYN.md
Normal file
@@ -0,0 +1,341 @@
|
||||
# PLJSON_DYN
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_dyn authid current_user 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.
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
/* list with objects */
|
||||
function executeList(stmt varchar2, bindvar pljson default null, cur_num number default null, bindvardateformats pljson default null) return pljson_list;
|
||||
|
||||
/* object with lists */
|
||||
function executeObject(stmt varchar2, bindvar pljson default null, cur_num number default null) return pljson;
|
||||
|
||||
|
||||
/* 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;
|
||||
*/
|
||||
|
||||
/* --11g functions
|
||||
function executeList(stmt in out sys_refcursor) return json_list;
|
||||
function executeObject(stmt in out sys_refcursor) return json;
|
||||
*/
|
||||
end pljson_dyn;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```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;
|
||||
|
||||
-- 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;
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (cur_num is null) then l_status := dbms_sql.execute(l_cur); end if;
|
||||
|
||||
--loop through rows
|
||||
while ( dbms_sql.fetch_rows(l_cur) > 0 ) loop
|
||||
inner_obj := pljson(); --init for each row
|
||||
inner_obj.check_for_duplicate := 0;
|
||||
--loop through columns
|
||||
for i in 1..l_cnt loop
|
||||
case true
|
||||
--handling string types
|
||||
when l_dtbl(i).col_type in (1, 96) then -- varchar2
|
||||
dbms_sql.column_value(l_cur, i, l_val);
|
||||
if (l_val is null) then
|
||||
if (null_as_empty_string) then
|
||||
inner_obj.put(l_dtbl(i).col_name, ''); --treat as emptystring?
|
||||
else
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_null()); --null
|
||||
end if;
|
||||
else
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_string(l_val)); --null
|
||||
end if;
|
||||
--dbms_output.put_line(l_dtbl(i).col_name||' --> '||l_val||'varchar2' ||l_dtbl(i).col_type);
|
||||
--handling number types
|
||||
when l_dtbl(i).col_type = 2 then -- number
|
||||
dbms_sql.column_value(l_cur, i, l_val);
|
||||
conv := l_val;
|
||||
inner_obj.put(l_dtbl(i).col_name, conv);
|
||||
-- dbms_output.put_line(l_dtbl(i).col_name||' --> '||l_val||'number ' ||l_dtbl(i).col_type);
|
||||
when l_dtbl(i).col_type = 12 then -- date
|
||||
if (include_dates) then
|
||||
dbms_sql.column_value(l_cur, i, read_date);
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_ext.to_json_string(read_date));
|
||||
end if;
|
||||
--dbms_output.put_line(l_dtbl(i).col_name||' --> '||l_val||'date ' ||l_dtbl(i).col_type);
|
||||
when l_dtbl(i).col_type = 112 then --clob
|
||||
if (include_clobs) then
|
||||
dbms_sql.column_value(l_cur, i, read_clob);
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_string(read_clob));
|
||||
end if;
|
||||
when l_dtbl(i).col_type = 113 then --blob
|
||||
if (include_blobs) then
|
||||
dbms_sql.column_value(l_cur, i, read_blob);
|
||||
if (dbms_lob.getlength(read_blob) > 0) then
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_ext.encode(read_blob));
|
||||
else
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_null());
|
||||
end if;
|
||||
end if;
|
||||
/* E.I.Sarmas (github.com/dsnz) 2018-05-01 handling of pljson_varray in select */
|
||||
when l_dtbl(i).col_type = 109 and l_dtbl(i).col_type_name = 'PLJSON_VARRAY' then
|
||||
if (include_arrays) then
|
||||
dbms_sql.column_value(l_cur, i, read_varray);
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_list(read_varray));
|
||||
end if;
|
||||
/* E.I.Sarmas (github.com/dsnz) 2018-05-01 handling of pljson_narray in select */
|
||||
when l_dtbl(i).col_type = 109 and l_dtbl(i).col_type_name = 'PLJSON_NARRAY' then
|
||||
if (include_arrays) then
|
||||
dbms_sql.column_value(l_cur, i, read_narray);
|
||||
inner_obj.put(l_dtbl(i).col_name, pljson_list(read_narray));
|
||||
end if;
|
||||
|
||||
else null; --discard other types
|
||||
end case;
|
||||
end loop;
|
||||
inner_obj.check_for_duplicate := 1;
|
||||
outer_list.append(inner_obj);
|
||||
end loop;
|
||||
dbms_sql.close_cursor(l_cur);
|
||||
return outer_list;
|
||||
end executeList;
|
||||
|
||||
/* 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;
|
||||
|
||||
--build up name_list
|
||||
for i in 1..l_cnt loop
|
||||
case l_dtbl(i).col_type
|
||||
when 1 then inner_list_names.append(l_dtbl(i).col_name);
|
||||
when 96 then inner_list_names.append(l_dtbl(i).col_name);
|
||||
when 2 then inner_list_names.append(l_dtbl(i).col_name);
|
||||
when 12 then if (include_dates) then inner_list_names.append(l_dtbl(i).col_name); end if;
|
||||
when 112 then if (include_clobs) then inner_list_names.append(l_dtbl(i).col_name); end if;
|
||||
when 113 then if (include_blobs) then inner_list_names.append(l_dtbl(i).col_name); end if;
|
||||
else null;
|
||||
end case;
|
||||
end loop;
|
||||
|
||||
--loop through rows
|
||||
while ( dbms_sql.fetch_rows(l_cur) > 0 ) loop
|
||||
data_list := pljson_list();
|
||||
--loop through columns
|
||||
for i in 1..l_cnt loop
|
||||
case true
|
||||
--handling string types
|
||||
when l_dtbl(i).col_type in (1, 96) then -- varchar2
|
||||
dbms_sql.column_value(l_cur, i, l_val);
|
||||
if (l_val is null) then
|
||||
if (null_as_empty_string) then
|
||||
data_list.append(''); --treat as emptystring?
|
||||
else
|
||||
data_list.append(pljson_null()); --null
|
||||
end if;
|
||||
else
|
||||
data_list.append(pljson_string(l_val)); --null
|
||||
end if;
|
||||
--dbms_output.put_line(l_dtbl(i).col_name||' --> '||l_val||'varchar2' ||l_dtbl(i).col_type);
|
||||
--handling number types
|
||||
when l_dtbl(i).col_type = 2 then -- number
|
||||
dbms_sql.column_value(l_cur, i, l_val);
|
||||
conv := l_val;
|
||||
data_list.append(conv);
|
||||
-- dbms_output.put_line(l_dtbl(i).col_name||' --> '||l_val||'number ' ||l_dtbl(i).col_type);
|
||||
when l_dtbl(i).col_type = 12 then -- date
|
||||
if (include_dates) then
|
||||
dbms_sql.column_value(l_cur, i, read_date);
|
||||
data_list.append(pljson_ext.to_json_string(read_date));
|
||||
end if;
|
||||
--dbms_output.put_line(l_dtbl(i).col_name||' --> '||l_val||'date ' ||l_dtbl(i).col_type);
|
||||
when l_dtbl(i).col_type = 112 then --clob
|
||||
if (include_clobs) then
|
||||
dbms_sql.column_value(l_cur, i, read_clob);
|
||||
data_list.append(pljson_string(read_clob));
|
||||
end if;
|
||||
when l_dtbl(i).col_type = 113 then --blob
|
||||
if (include_blobs) then
|
||||
dbms_sql.column_value(l_cur, i, read_blob);
|
||||
if (dbms_lob.getlength(read_blob) > 0) then
|
||||
data_list.append(pljson_ext.encode(read_blob));
|
||||
else
|
||||
data_list.append(pljson_null());
|
||||
end if;
|
||||
end if;
|
||||
else null; --discard other types
|
||||
end case;
|
||||
end loop;
|
||||
inner_list_data.append(data_list);
|
||||
end loop;
|
||||
|
||||
outer_obj.put('names', inner_list_names);
|
||||
outer_obj.put('data', inner_list_data);
|
||||
dbms_sql.close_cursor(l_cur);
|
||||
return outer_obj;
|
||||
end executeObject;
|
||||
|
||||
end pljson_dyn;```
|
||||
1105
docs/packages/PLJSON_EXT.md
Normal file
1105
docs/packages/PLJSON_EXT.md
Normal file
File diff suppressed because it is too large
Load Diff
475
docs/packages/PLJSON_HELPER.md
Normal file
475
docs/packages/PLJSON_HELPER.md
Normal file
@@ -0,0 +1,475 @@
|
||||
# PLJSON_HELPER
|
||||
|
||||
## Package Specification
|
||||
|
||||
```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;
|
||||
|
||||
-- Join two lists
|
||||
-- json_helper.join(json_list('[1,2,3]'),json_list('[4,5,6]')) -> [1,2,3,4,5,6]
|
||||
function join(p_a_list pljson_list, p_b_list pljson_list) return pljson_list;
|
||||
|
||||
-- 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"]')) -> {"a":1,"f":6,"c":3}
|
||||
function keep(p_json pljson, p_keys pljson_list) return pljson;
|
||||
|
||||
-- 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"]')) -> {"b":2,"d":4,"e":5}
|
||||
function remove(p_json pljson, p_keys pljson_list) return pljson;
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
|
||||
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;
|
||||
|
||||
end pljson_helper;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_helper as
|
||||
|
||||
--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;
|
||||
|
||||
-- loop through p_b_json
|
||||
l_indx := p_b_json.json_data.first;
|
||||
loop
|
||||
exit when l_indx is null;
|
||||
l_jv := p_b_json.json_data(l_indx);
|
||||
if (l_jv.is_object) then
|
||||
--recursive
|
||||
l_recursive := l_json.get(l_jv.mapname);
|
||||
if (l_recursive is not null and l_recursive.is_object) then
|
||||
l_json.put(l_jv.mapname, merge(pljson(l_recursive), pljson(l_jv)));
|
||||
else
|
||||
l_json.put(l_jv.mapname, l_jv);
|
||||
end if;
|
||||
else
|
||||
l_json.put(l_jv.mapname, l_jv);
|
||||
end if;
|
||||
|
||||
--increment
|
||||
l_indx := p_b_json.json_data.next(l_indx);
|
||||
end loop;
|
||||
|
||||
return l_json;
|
||||
|
||||
end merge;
|
||||
|
||||
-- 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;
|
||||
|
||||
return l_json_list;
|
||||
|
||||
end join;
|
||||
|
||||
-- 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;
|
||||
|
||||
return l_json;
|
||||
end keep;
|
||||
|
||||
-- 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;
|
||||
|
||||
return l_json;
|
||||
end remove;
|
||||
|
||||
--equals functions
|
||||
|
||||
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;
|
||||
|
||||
if (not p_v1.is_number) then
|
||||
return false;
|
||||
end if;
|
||||
|
||||
return p_v2 = p_v1.get_number();
|
||||
end;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (not p_v1.is_number) then
|
||||
return false;
|
||||
end if;
|
||||
|
||||
return p_v2 = p_v1.get_double();
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
if (not p_v1.is_bool) then
|
||||
return false;
|
||||
end if;
|
||||
|
||||
return p_v2 = p_v1.get_bool();
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
if (not p_v1.is_string) then
|
||||
return false;
|
||||
end if;
|
||||
|
||||
return p_v2 = p_v1.get_string();
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
if (not p_v1.is_string) then
|
||||
return false;
|
||||
end if;
|
||||
|
||||
/*
|
||||
my_clob := empty_clob();
|
||||
dbms_lob.createtemporary(my_clob, true);
|
||||
p_v1.get_string(my_clob);
|
||||
*/
|
||||
my_clob := p_v1.get_clob();
|
||||
res := dbms_lob.compare(p_v2, my_clob) = 0;
|
||||
/*dbms_lob.freetemporary(my_clob);*/
|
||||
return res;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
if (p_v2.is_number) then return equals(p_v1, p_v2.get_number); end if;
|
||||
if (p_v2.is_bool) then return equals(p_v1, p_v2.get_bool); end if;
|
||||
if (p_v2.is_object) then return equals(p_v1, pljson(p_v2), exact); end if;
|
||||
if (p_v2.is_array) then return equals(p_v1, pljson_list(p_v2), exact); end if;
|
||||
if (p_v2.is_string) then
|
||||
if (treat(p_v2 as pljson_string).extended_str is null) then
|
||||
return equals(p_v1, p_v2.get_string);
|
||||
else
|
||||
declare
|
||||
my_clob clob; res boolean;
|
||||
begin
|
||||
/*
|
||||
my_clob := empty_clob();
|
||||
dbms_lob.createtemporary(my_clob, true);
|
||||
p_v2.get_string(my_clob);
|
||||
*/
|
||||
my_clob := p_v2.get_clob();
|
||||
res := equals(p_v1, my_clob);
|
||||
/*dbms_lob.freetemporary(my_clob);*/
|
||||
return res;
|
||||
end;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return false; --should never happen
|
||||
end;
|
||||
|
||||
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);
|
||||
|
||||
if (p_v2 is null) then
|
||||
return p_v1.is_null;
|
||||
end if;
|
||||
|
||||
if (not p_v1.is_array) then
|
||||
return false;
|
||||
end if;
|
||||
|
||||
-- dbms_output.put_line('labc2'||case when exact then 'X' else 'U' end);
|
||||
|
||||
cmp := pljson_list(p_v1);
|
||||
if (cmp.count != p_v2.count and exact) then return false; end if;
|
||||
|
||||
-- dbms_output.put_line('labc3'||case when exact then 'X' else 'U' end);
|
||||
|
||||
if (exact) then
|
||||
for i in 1 .. cmp.count loop
|
||||
res := equals(cmp.get(i), p_v2.get(i), exact);
|
||||
if (not res) then return res; end if;
|
||||
end loop;
|
||||
else
|
||||
-- dbms_output.put_line('labc4'||case when exact then 'X' else 'U' end);
|
||||
if (p_v2.count > cmp.count) then return false; end if;
|
||||
-- dbms_output.put_line('labc5'||case when exact then 'X' else 'U' end);
|
||||
|
||||
--match sublist here!
|
||||
for x in 0 .. (cmp.count-p_v2.count) loop
|
||||
-- dbms_output.put_line('labc7'||x);
|
||||
|
||||
for i in 1 .. p_v2.count loop
|
||||
res := equals(cmp.get(x+i), p_v2.get(i), exact);
|
||||
if (not res) then
|
||||
goto next_index;
|
||||
end if;
|
||||
end loop;
|
||||
return true;
|
||||
|
||||
<<next_index>>
|
||||
null;
|
||||
end loop;
|
||||
|
||||
-- dbms_output.put_line('labc7'||case when exact then 'X' else 'U' end);
|
||||
|
||||
return false; --no match
|
||||
|
||||
end if;
|
||||
|
||||
return res;
|
||||
end;
|
||||
|
||||
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');
|
||||
|
||||
if (p_v2 is null) then
|
||||
return p_v1.is_null;
|
||||
end if;
|
||||
|
||||
if (not p_v1.is_object) then
|
||||
return false;
|
||||
end if;
|
||||
|
||||
cmp := pljson(p_v1);
|
||||
|
||||
-- dbms_output.put_line('abc2');
|
||||
|
||||
if (cmp.count != p_v2.count and exact) then return false; end if;
|
||||
|
||||
-- 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);
|
||||
|
||||
if (v1.is_object and v2.is_object) then
|
||||
if (not equals(v1, v2, false)) then return false; end if;
|
||||
elsif (v1.is_array and v2.is_array) then
|
||||
if (not equals(v1, v2, false)) then return false; end if;
|
||||
else
|
||||
if (not equals(v1, v2, true)) then return false; end if;
|
||||
end if;
|
||||
end;
|
||||
|
||||
end if;
|
||||
end loop;
|
||||
end;
|
||||
|
||||
-- dbms_output.put_line('abc4');
|
||||
|
||||
return true;
|
||||
end;
|
||||
|
||||
function equals(p_v1 pljson, p_v2 pljson, exact boolean) return boolean as
|
||||
begin
|
||||
return equals(p_v1, p_v2, exact);
|
||||
end;
|
||||
|
||||
function equals(p_v1 pljson_list, p_v2 pljson_list, exact boolean) return boolean as
|
||||
begin
|
||||
return equals(p_v1, p_v2, exact);
|
||||
end;
|
||||
|
||||
--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;
|
||||
|
||||
v_values := p_v1.get_values();
|
||||
|
||||
for i in 1 .. v_values.count loop
|
||||
declare
|
||||
v_val pljson_element := v_values.get(i);
|
||||
begin
|
||||
if (v_val.is_object) then
|
||||
if (contains(pljson(v_val), p_v2, exact)) then return true; end if;
|
||||
end if;
|
||||
if (v_val.is_array) then
|
||||
if (contains(pljson_list(v_val), p_v2, exact)) then return true; end if;
|
||||
end if;
|
||||
|
||||
if (equals(v_val, p_v2, exact)) then return true; end if;
|
||||
end;
|
||||
|
||||
end loop;
|
||||
|
||||
return false;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
for i in 1 .. p_v1.count loop
|
||||
declare
|
||||
v_val pljson_element := p_v1.get(i);
|
||||
begin
|
||||
if (v_val.is_object) then
|
||||
if (contains(pljson(v_val), p_v2, exact)) then return true; end if;
|
||||
end if;
|
||||
if (v_val.is_array) then
|
||||
if (contains(pljson_list(v_val), p_v2, exact)) then return true; end if;
|
||||
end if;
|
||||
|
||||
if (equals(v_val, p_v2, exact)) then return true; end if;
|
||||
end;
|
||||
|
||||
end loop;
|
||||
|
||||
return false;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
end pljson_helper;```
|
||||
310
docs/packages/PLJSON_ML.md
Normal file
310
docs/packages/PLJSON_ML.md
Normal file
@@ -0,0 +1,310 @@
|
||||
# PLJSON_ML
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_ml 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.
|
||||
*/
|
||||
|
||||
/* This package contains extra methods to lookup types and
|
||||
an easy way of adding date values in json - without changing the structure */
|
||||
|
||||
jsonml_stylesheet xmltype := null;
|
||||
|
||||
function xml2json(xml in xmltype) return pljson_list;
|
||||
function xmlstr2json(xmlstr in varchar2) return pljson_list;
|
||||
|
||||
end pljson_ml;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_ml as
|
||||
function get_jsonml_stylesheet return xmltype;
|
||||
|
||||
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;
|
||||
|
||||
function xmlstr2json(xmlstr in varchar2) return pljson_list as
|
||||
begin
|
||||
return xml2json(xmltype(xmlstr));
|
||||
end xmlstr2json;
|
||||
|
||||
function get_jsonml_stylesheet return xmltype as
|
||||
begin
|
||||
if (jsonml_stylesheet is null) then
|
||||
jsonml_stylesheet := xmltype('<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
JsonML.xslt
|
||||
|
||||
Created: 2006-11-15-0551
|
||||
Modified: 2009-02-14-0927
|
||||
|
||||
Released under an open-source license:
|
||||
http://jsonml.org/License.htm
|
||||
|
||||
This transformation converts any XML document into JsonML.
|
||||
It omits processing-instructions and comment-nodes.
|
||||
|
||||
To enable comment-nodes to be emitted as JavaScript comments,
|
||||
uncomment the Comment() template.
|
||||
-->
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:output method="text"
|
||||
media-type="application/json"
|
||||
encoding="UTF-8"
|
||||
indent="no"
|
||||
omit-xml-declaration="yes" />
|
||||
|
||||
<!-- constants -->
|
||||
<xsl:variable name="XHTML"
|
||||
select="''http://www.w3.org/1999/xhtml''" />
|
||||
|
||||
<xsl:variable name="START_ELEM"
|
||||
select="''[''" />
|
||||
|
||||
<xsl:variable name="END_ELEM"
|
||||
select="'']''" />
|
||||
|
||||
<xsl:variable name="VALUE_DELIM"
|
||||
select="'',''" />
|
||||
|
||||
<xsl:variable name="START_ATTRIB"
|
||||
select="''{''" />
|
||||
|
||||
<xsl:variable name="END_ATTRIB"
|
||||
select="''}''" />
|
||||
|
||||
<xsl:variable name="NAME_DELIM"
|
||||
select="'':''" />
|
||||
|
||||
<xsl:variable name="STRING_DELIM"
|
||||
select="''"''" />
|
||||
|
||||
<xsl:variable name="START_COMMENT"
|
||||
select="''/*''" />
|
||||
|
||||
<xsl:variable name="END_COMMENT"
|
||||
select="''*/''" />
|
||||
|
||||
<!-- root-node -->
|
||||
<xsl:template match="/">
|
||||
<xsl:apply-templates select="*" />
|
||||
</xsl:template>
|
||||
|
||||
<!-- comments -->
|
||||
<xsl:template match="comment()">
|
||||
<!-- uncomment to support JSON comments -->
|
||||
<!--
|
||||
<xsl:value-of select="$START_COMMENT" />
|
||||
|
||||
<xsl:value-of select="."
|
||||
disable-output-escaping="yes" />
|
||||
|
||||
<xsl:value-of select="$END_COMMENT" />
|
||||
-->
|
||||
</xsl:template>
|
||||
|
||||
<!-- elements -->
|
||||
<xsl:template match="*">
|
||||
<xsl:value-of select="$START_ELEM" />
|
||||
|
||||
<!-- tag-name string -->
|
||||
<xsl:value-of select="$STRING_DELIM" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="namespace-uri()=$XHTML">
|
||||
<xsl:value-of select="local-name()" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="name()" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:value-of select="$STRING_DELIM" />
|
||||
|
||||
<!-- attribute object -->
|
||||
<xsl:if test="count(@*)>0">
|
||||
<xsl:value-of select="$VALUE_DELIM" />
|
||||
<xsl:value-of select="$START_ATTRIB" />
|
||||
<xsl:for-each select="@*">
|
||||
<xsl:if test="position()>1">
|
||||
<xsl:value-of select="$VALUE_DELIM" />
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="." />
|
||||
</xsl:for-each>
|
||||
<xsl:value-of select="$END_ATTRIB" />
|
||||
</xsl:if>
|
||||
|
||||
<!-- child elements and text-nodes -->
|
||||
<xsl:for-each select="*|text()">
|
||||
<xsl:value-of select="$VALUE_DELIM" />
|
||||
<xsl:apply-templates select="." />
|
||||
</xsl:for-each>
|
||||
|
||||
<xsl:value-of select="$END_ELEM" />
|
||||
</xsl:template>
|
||||
|
||||
<!-- text-nodes -->
|
||||
<xsl:template match="text()">
|
||||
<xsl:call-template name="escape-string">
|
||||
<xsl:with-param name="value"
|
||||
select="." />
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- attributes -->
|
||||
<xsl:template match="@*">
|
||||
<xsl:value-of select="$STRING_DELIM" />
|
||||
<xsl:choose>
|
||||
<xsl:when test="namespace-uri()=$XHTML">
|
||||
<xsl:value-of select="local-name()" />
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="name()" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:value-of select="$STRING_DELIM" />
|
||||
|
||||
<xsl:value-of select="$NAME_DELIM" />
|
||||
|
||||
<xsl:call-template name="escape-string">
|
||||
<xsl:with-param name="value"
|
||||
select="." />
|
||||
</xsl:call-template>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- escape-string: quotes and escapes -->
|
||||
<xsl:template name="escape-string">
|
||||
<xsl:param name="value" />
|
||||
|
||||
<xsl:value-of select="$STRING_DELIM" />
|
||||
|
||||
<xsl:if test="string-length($value)>0">
|
||||
<xsl:variable name="escaped-whacks">
|
||||
<!-- escape backslashes -->
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="value"
|
||||
select="$value" />
|
||||
<xsl:with-param name="find"
|
||||
select="''\''" />
|
||||
<xsl:with-param name="replace"
|
||||
select="''\\''" />
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="escaped-LF">
|
||||
<!-- escape line feeds -->
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="value"
|
||||
select="$escaped-whacks" />
|
||||
<xsl:with-param name="find"
|
||||
select="''
''" />
|
||||
<xsl:with-param name="replace"
|
||||
select="''\n''" />
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="escaped-CR">
|
||||
<!-- escape carriage returns -->
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="value"
|
||||
select="$escaped-LF" />
|
||||
<xsl:with-param name="find"
|
||||
select="''
''" />
|
||||
<xsl:with-param name="replace"
|
||||
select="''\r''" />
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="escaped-tabs">
|
||||
<!-- escape tabs -->
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="value"
|
||||
select="$escaped-CR" />
|
||||
<xsl:with-param name="find"
|
||||
select="''	''" />
|
||||
<xsl:with-param name="replace"
|
||||
select="''\t''" />
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<!-- escape quotes -->
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="value"
|
||||
select="$escaped-tabs" />
|
||||
<xsl:with-param name="find"
|
||||
select="''"''" />
|
||||
<xsl:with-param name="replace"
|
||||
select="''\"''" />
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:value-of select="$STRING_DELIM" />
|
||||
</xsl:template>
|
||||
|
||||
<!-- string-replace: replaces occurances of one string with another -->
|
||||
<xsl:template name="string-replace">
|
||||
<xsl:param name="value" />
|
||||
<xsl:param name="find" />
|
||||
<xsl:param name="replace" />
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($value,$find)">
|
||||
<!-- replace and call recursively on next -->
|
||||
<xsl:value-of select="substring-before($value,$find)"
|
||||
disable-output-escaping="yes" />
|
||||
<xsl:value-of select="$replace"
|
||||
disable-output-escaping="yes" />
|
||||
<xsl:call-template name="string-replace">
|
||||
<xsl:with-param name="value"
|
||||
select="substring-after($value,$find)" />
|
||||
<xsl:with-param name="find"
|
||||
select="$find" />
|
||||
<xsl:with-param name="replace"
|
||||
select="$replace" />
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<!-- no replacement necessary -->
|
||||
<xsl:value-of select="$value"
|
||||
disable-output-escaping="yes" />
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>');
|
||||
end if;
|
||||
return jsonml_stylesheet;
|
||||
end get_jsonml_stylesheet;
|
||||
|
||||
end pljson_ml;```
|
||||
171
docs/packages/PLJSON_OBJECT_CACHE.md
Normal file
171
docs/packages/PLJSON_OBJECT_CACHE.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# PLJSON_OBJECT_CACHE
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_object_cache as
|
||||
|
||||
/* E.I.Sarmas (github.com/dsnz) 2020-04-18 object cache to speed up internal operations */
|
||||
|
||||
/* !!! NOTE: this package is used internally by pljson and it's not part of the api !!! */
|
||||
|
||||
/* index by string of "id.path" or "path" */
|
||||
type pljson_element_tab is table of pljson_element index by varchar2(250);
|
||||
|
||||
last_id number := 0;
|
||||
pljson_element_cache pljson_element_tab;
|
||||
cache_reqs number := 0;
|
||||
cache_hits number := 0;
|
||||
cache_invalid_reqs number := 0;
|
||||
|
||||
type vset is table of varchar2(1) index by varchar2(250);
|
||||
names_set vset;
|
||||
|
||||
procedure set_names_set(names pljson_varray);
|
||||
function in_names_set(a_name varchar2) return boolean;
|
||||
|
||||
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;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_object_cache as
|
||||
|
||||
/* E.I.Sarmas (github.com/dsnz) 2020-04-18 object cache to speed up internal operations */
|
||||
|
||||
/* !!! NOTE: this package is used internally by pljson and it's not part of the api !!! */
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
procedure reset is
|
||||
begin
|
||||
last_id := 0;
|
||||
flush;
|
||||
end;
|
||||
|
||||
procedure flush is
|
||||
begin
|
||||
pljson_element_cache.delete;
|
||||
cache_reqs := 0;
|
||||
cache_hits := 0;
|
||||
cache_invalid_reqs := 0;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
function next_id return number is
|
||||
begin
|
||||
last_id := last_id + 1;
|
||||
return last_id;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
-- experimental, ignore
|
||||
-- to use with 'get_json_element'
|
||||
|
||||
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;
|
||||
|
||||
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;```
|
||||
986
docs/packages/PLJSON_PARSER.md
Normal file
986
docs/packages/PLJSON_PARSER.md
Normal file
@@ -0,0 +1,986 @@
|
||||
# PLJSON_PARSER
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_parser 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.
|
||||
*/
|
||||
|
||||
/** 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
|
||||
|
||||
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);
|
||||
|
||||
json_strict boolean not null := false;
|
||||
|
||||
ucs2_exception EXCEPTION;
|
||||
pragma exception_init(ucs2_exception, -22831);
|
||||
|
||||
function lengthcc(buf clob) return number;
|
||||
|
||||
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;
|
||||
|
||||
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>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;
|
||||
|
||||
end pljson_parser;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_parser as
|
||||
/*
|
||||
Copyright (c) 2009 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.
|
||||
*/
|
||||
|
||||
decimalpoint varchar2(1 char) := '.';
|
||||
|
||||
/* moved to package spec
|
||||
ucs2_exception EXCEPTION;
|
||||
pragma exception_init(ucs2_exception, -22831);
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
procedure update_decimalpoint as
|
||||
begin
|
||||
select substr(value, 1, 1)
|
||||
into decimalpoint
|
||||
from nls_session_parameters
|
||||
where parameter = 'NLS_NUMERIC_CHARACTERS';
|
||||
end update_decimalpoint;
|
||||
|
||||
/* 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 > s.len) then return null; end if;
|
||||
|
||||
--right offset?
|
||||
/* if (indx > 4000 + s.offset or indx < s.offset) then */
|
||||
/* fix for issue #37 */
|
||||
/* code before fix for issue #169
|
||||
if (indx > 4000 + s.offset or indx <= s.offset) then
|
||||
s.offset := indx - (indx mod 4000);
|
||||
-- addon fix for issue #37
|
||||
if s.offset = indx then
|
||||
s.offset := s.offset - 4000;
|
||||
end if;
|
||||
s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);
|
||||
end if;
|
||||
--read from s.src
|
||||
return substr(s.src, indx-s.offset, 1);
|
||||
*/
|
||||
|
||||
/* use of length, so works correctly for 4-byte unicode characters (issue #169) */
|
||||
/* lengthc does not work (issue #190) */
|
||||
if (indx > length(s.src) + s.offset_chars) then
|
||||
while (indx > length(s.src) + s.offset_chars) loop
|
||||
s.offset_chars := s.offset_chars + length(s.src);
|
||||
s.offset := s.offset + length2(s.src);
|
||||
/* exception check, so works correctly for 4-byte unicode characters (issue #169) */
|
||||
begin
|
||||
s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);
|
||||
exception
|
||||
when ucs2_exception then
|
||||
s.src := dbms_lob.substr(s.s_clob, 3999, s.offset+1);
|
||||
end;
|
||||
end loop;
|
||||
elsif (indx <= s.offset_chars) then
|
||||
s.offset_chars := 0;
|
||||
s.offset := 0;
|
||||
/* exception check, so works correctly for 4-byte unicode characters (issue #169) */
|
||||
begin
|
||||
s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);
|
||||
exception
|
||||
when ucs2_exception then
|
||||
s.src := dbms_lob.substr(s.s_clob, 3999, s.offset+1);
|
||||
end;
|
||||
while (indx > length(s.src) + s.offset_chars) loop
|
||||
s.offset_chars := s.offset_chars + length(s.src);
|
||||
s.offset := s.offset + length2(s.src);
|
||||
/* exception check, so works correctly for 4-byte unicode characters (issue #169) */
|
||||
begin
|
||||
s.src := dbms_lob.substr(s.s_clob, 4000, s.offset+1);
|
||||
exception
|
||||
when ucs2_exception then
|
||||
s.src := dbms_lob.substr(s.s_clob, 3999, s.offset+1);
|
||||
end;
|
||||
end loop;
|
||||
end if;
|
||||
--dbms_output.put_line('indx: ' || indx || ' offset: ' || s.offset || ' (chars: ' || s.offset_chars || ') src chars: ' || length(s.src));
|
||||
--read from s.src
|
||||
return substr(s.src, indx-s.offset_chars, 1);
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
procedure debug(text varchar2) as
|
||||
begin
|
||||
dbms_output.put_line(text);
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
procedure s_error(text varchar2, tok rToken) as
|
||||
begin
|
||||
raise_application_error(-20100, 'JSON Scanner exception @ line: '||tok.line||' column: '||tok.col||' - '||text);
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
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]([0-9])*
|
||||
if (buf = '0') then
|
||||
numbuf := numbuf || '0'; indx := indx + 1;
|
||||
buf := next_char(indx, jsrc);
|
||||
elsif (buf >= '1' and buf <= '9') then
|
||||
numbuf := numbuf || buf; indx := indx + 1;
|
||||
--read digits
|
||||
buf := next_char(indx, jsrc);
|
||||
while (buf >= '0' and buf <= '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 >= '0' and buf <= '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 >= '0' and buf <= '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;
|
||||
|
||||
tok.data := numbuf;
|
||||
return indx;
|
||||
end lexNumber;
|
||||
|
||||
-- [a-zA-Z]([a-zA-Z0-9])*
|
||||
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;
|
||||
<<retname>>
|
||||
--could check for reserved keywords here
|
||||
--debug(varbuf);
|
||||
tok.data := varbuf;
|
||||
return indx-1;
|
||||
end lexName;
|
||||
|
||||
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;
|
||||
|
||||
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 > 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;
|
||||
|
||||
if (buf is null) then
|
||||
s_error('string ending not found', tok);
|
||||
--debug('Premature string ending');
|
||||
end if;
|
||||
|
||||
--debug(varbuf);
|
||||
--dbms_output.put_line(varbuf);
|
||||
if (v_extended is not null) then
|
||||
updateClob(v_extended, unistr(varbuf));
|
||||
tok.data_overflow := v_extended;
|
||||
-- tok.data := dbms_lob.substr(v_extended, 1, 32767);
|
||||
/* may read less than "max_string_chars" characters but it's a sample so doesn't matter */
|
||||
dbms_lob.read(v_extended, max_string_chars, 1, tok.data);
|
||||
else
|
||||
tok.data := unistr(varbuf);
|
||||
end if;
|
||||
return indx;
|
||||
end lexString;
|
||||
|
||||
/* 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 <= 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;
|
||||
|
||||
when (buf = Chr(13)) then --Windows or Mac way
|
||||
lin_no := lin_no + 1;
|
||||
col_no := 0;
|
||||
if (jsrc.len >= indx+1) then -- better safe than sorry
|
||||
buf := next_char(indx+1, jsrc);
|
||||
if (buf = Chr(10)) then --\r\n
|
||||
indx := indx + 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when (buf = CHR(9)) then null; --tabbing
|
||||
when (buf in ('-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) then --number
|
||||
tokens(tok_indx) := mt('NUMBER', lin_no, col_no, null);
|
||||
indx := lexNumber(jsrc, tokens(tok_indx), indx)-1;
|
||||
col_no := col_no + length(tokens(tok_indx).data);
|
||||
tok_indx := tok_indx + 1;
|
||||
when buf = '"' then --string
|
||||
tokens(tok_indx) := mt('STRING', lin_no, col_no, null);
|
||||
indx := lexString(jsrc, tokens(tok_indx), indx, '"');
|
||||
col_no := col_no + length(tokens(tok_indx).data) + 1;
|
||||
tok_indx := tok_indx + 1;
|
||||
when buf = '''' and json_strict = false then --string
|
||||
tokens(tok_indx) := mt('STRING', lin_no, col_no, null);
|
||||
indx := lexString(jsrc, tokens(tok_indx), indx, '''');
|
||||
col_no := col_no + length(tokens(tok_indx).data) + 1; --hovsa her
|
||||
tok_indx := tok_indx + 1;
|
||||
when 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);
|
||||
if (tokens(tok_indx).data_overflow is not null) then
|
||||
/* use of lengthcc, so works correctly for 4-byte unicode characters (issue #169) */
|
||||
col_no := col_no + lengthcc(tokens(tok_indx).data_overflow) + 1; --dbms_lob.getlength(tokens(tok_indx).data_overflow) + 1;
|
||||
else
|
||||
col_no := col_no + length(tokens(tok_indx).data) + 1;
|
||||
end if;
|
||||
tok_indx := tok_indx + 1;
|
||||
when json_strict = false and buf||next_char(indx+1, jsrc) = '/*' then --strip comments
|
||||
declare
|
||||
saveindx number := indx;
|
||||
un_esc clob;
|
||||
begin
|
||||
indx := indx + 1;
|
||||
loop
|
||||
indx := indx + 1;
|
||||
buf := next_char(indx, jsrc)||next_char(indx+1, jsrc);
|
||||
exit when buf = '*/';
|
||||
exit when buf is null;
|
||||
end loop;
|
||||
|
||||
if (indx = saveindx+2) then
|
||||
--enter unescaped mode
|
||||
--dbms_output.put_line('Entering unescaped mode');
|
||||
un_esc := empty_clob();
|
||||
dbms_lob.createtemporary(un_esc, true);
|
||||
indx := indx + 1;
|
||||
loop
|
||||
indx := indx + 1;
|
||||
buf := next_char(indx, jsrc)||next_char(indx+1, jsrc)||next_char(indx+2, jsrc)||next_char(indx+3, jsrc);
|
||||
exit when buf = '/**/';
|
||||
if buf is null then
|
||||
s_error('Unexpected sequence /**/ to end unescaped data: '||buf, lin_no, col_no);
|
||||
end if;
|
||||
buf := next_char(indx, jsrc);
|
||||
/* use of length2, so works correctly for 4-byte unicode characters (issue #169) */
|
||||
dbms_lob.writeappend(un_esc, length2(buf), buf);
|
||||
end loop;
|
||||
tokens(tok_indx) := mt('ESTRING', lin_no, col_no, null);
|
||||
tokens(tok_indx).data_overflow := un_esc;
|
||||
/* use of lengthcc, so works correctly for 4-byte unicode characters (issue #169) */
|
||||
col_no := col_no + lengthcc(un_esc) + 1; --dbms_lob.getlength(un_esc) + 1; --note: line count won't work properly
|
||||
tok_indx := tok_indx + 1;
|
||||
indx := indx + 2;
|
||||
end if;
|
||||
|
||||
indx := indx + 1;
|
||||
end;
|
||||
when buf = ' ' then null; --space
|
||||
else
|
||||
s_error('Unexpected char: '||buf, lin_no, col_no);
|
||||
end case;
|
||||
|
||||
indx := indx + 1;
|
||||
end loop;
|
||||
|
||||
return tokens;
|
||||
end lexer;
|
||||
|
||||
/* SCANNER END */
|
||||
|
||||
/* 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;
|
||||
|
||||
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 > 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 > tokens.count) then p_error('] not found', tok); end if;
|
||||
tok := tokens(indx);
|
||||
if (tok.type_name = ',') then --advance
|
||||
indx := indx + 1;
|
||||
if (indx > 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;
|
||||
|
||||
end loop;
|
||||
ret_list.list_data := e_arr;
|
||||
return ret_list;
|
||||
end parseArr;
|
||||
|
||||
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;
|
||||
|
||||
indx := indx + 1;
|
||||
return mem;
|
||||
end parseMem;
|
||||
|
||||
/*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;*/
|
||||
|
||||
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;
|
||||
|
||||
obj pljson;
|
||||
tok rToken;
|
||||
mem_name varchar(4000);
|
||||
arr pljson_element_array := pljson_element_array();
|
||||
begin
|
||||
--what to expect?
|
||||
while (indx <= 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;
|
||||
|
||||
indx := indx + 1;
|
||||
if (indx > tokens.count) then p_error('Unexpected end of input', tok); end if;
|
||||
tok := tokens(indx);
|
||||
indx := indx + 1;
|
||||
if (indx > tokens.count) then p_error('Unexpected end of input', tok); end if;
|
||||
if (tok.type_name = ':') then
|
||||
--parse
|
||||
declare
|
||||
jmb pljson_element;
|
||||
x number;
|
||||
begin
|
||||
x := arr.count + 1;
|
||||
jmb := parseMem(tokens, indx, mem_name, x);
|
||||
arr.extend;
|
||||
arr(x) := jmb;
|
||||
end;
|
||||
else
|
||||
p_error('Expected '':''', tok);
|
||||
end if;
|
||||
--move indx forward if ',' is found
|
||||
if (indx > tokens.count) then p_error('Unexpected end of input', tok); end if;
|
||||
|
||||
tok := tokens(indx);
|
||||
if (tok.type_name = ',') then
|
||||
--debug('found ,');
|
||||
indx := indx + 1;
|
||||
tok := tokens(indx);
|
||||
if (tok.type_name = '}') then --premature exit
|
||||
p_error('Premature exit in json object', tok);
|
||||
end if;
|
||||
elsif (tok.type_name != '}') then
|
||||
p_error('A comma seperator is probably missing', tok);
|
||||
end if;
|
||||
when '}' then
|
||||
obj := pljson();
|
||||
obj.json_data := arr;
|
||||
return obj;
|
||||
else
|
||||
p_error('Expected string or }', tok);
|
||||
end case;
|
||||
end loop;
|
||||
|
||||
p_error('} not found', tokens(indx-1));
|
||||
|
||||
return obj;
|
||||
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
return obj;
|
||||
end parser;
|
||||
|
||||
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;
|
||||
|
||||
return obj;
|
||||
end parse_list;
|
||||
|
||||
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;
|
||||
|
||||
return obj;
|
||||
end parse_list;
|
||||
|
||||
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;
|
||||
|
||||
return obj;
|
||||
end parser;
|
||||
|
||||
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;
|
||||
|
||||
return obj.head();
|
||||
end parse_any;
|
||||
|
||||
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;
|
||||
|
||||
return obj.head();
|
||||
end parse_any;
|
||||
|
||||
/* 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;
|
||||
|
||||
validated.check_duplicate(false);
|
||||
indx := members.first;
|
||||
loop
|
||||
exit when indx is null;
|
||||
validated.put(indx, members(indx));
|
||||
indx := members.next(indx);
|
||||
end loop;
|
||||
if (nulljsonvalue is not null) then
|
||||
validated.put('', nulljsonvalue);
|
||||
end if;
|
||||
|
||||
validated.check_for_duplicate := obj.check_for_duplicate;
|
||||
|
||||
obj := validated;
|
||||
end;
|
||||
|
||||
function get_version return varchar2 as
|
||||
begin
|
||||
return 'PL/JSON 3.5.2';
|
||||
end get_version;
|
||||
|
||||
end pljson_parser;```
|
||||
727
docs/packages/PLJSON_PRINTER.md
Normal file
727
docs/packages/PLJSON_PRINTER.md
Normal file
@@ -0,0 +1,727 @@
|
||||
# PLJSON_PRINTER
|
||||
|
||||
## Package Specification
|
||||
|
||||
```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;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
end pljson_printer;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_printer as
|
||||
max_line_len number := 0;
|
||||
cur_line_len number := 0;
|
||||
|
||||
-- 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;
|
||||
|
||||
function llcheck(str in varchar2) return varchar2 as
|
||||
begin
|
||||
--dbms_output.put_line(cur_line_len || ' : ' || str);
|
||||
if (max_line_len > 0 and length(str)+cur_line_len > 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;
|
||||
|
||||
-- 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;
|
||||
|
||||
case ch
|
||||
when chr( 8) then result := '\b';
|
||||
when chr( 9) then result := '\t';
|
||||
when chr(10) then result := '\n';
|
||||
when chr(12) then result := '\f';
|
||||
when chr(13) then result := '\r';
|
||||
when chr(34) then result := '\"';
|
||||
when chr(47) then if (escape_solidus) then result := '\/'; end if;
|
||||
when chr(92) then result := '\\';
|
||||
/* WARNING: ascii() returns PLS_INTEGER and large unicode code points can be negative */
|
||||
else if (ascii(ch) >= 0 and ascii(ch) < 32) then
|
||||
result := '\u' || replace(substr(to_char(ascii(ch), 'XXXX'), 2, 4), ' ', '0');
|
||||
elsif (ascii_output) then
|
||||
result := replace(asciistr(ch), '\', '\u');
|
||||
end if;
|
||||
end case;
|
||||
return result;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
-- clear the cache if global parameters have been changed
|
||||
if char_map_escape_solidus <> escape_solidus or
|
||||
char_map_ascii_output <> ascii_output
|
||||
then
|
||||
char_map.delete;
|
||||
char_map_escape_solidus := escape_solidus;
|
||||
char_map_ascii_output := ascii_output;
|
||||
end if;
|
||||
|
||||
for i in 1 .. length(str) loop
|
||||
ch := substr(str, i, 1 ) ;
|
||||
|
||||
begin
|
||||
-- it this char has already been processed, I have cached its escaped value
|
||||
buf:=char_map(ch);
|
||||
exception when no_Data_found then
|
||||
-- otherwise, i convert the value and add it to the cache
|
||||
buf := escapeChar(ch);
|
||||
char_map(ch) := buf;
|
||||
end;
|
||||
|
||||
sb := sb || buf;
|
||||
end loop;
|
||||
return sb;
|
||||
end escapeString;
|
||||
|
||||
function newline(spaces boolean) return varchar2 as
|
||||
begin
|
||||
cur_line_len := 0;
|
||||
if (spaces) then return newline_char; else return ''; end if;
|
||||
end;
|
||||
|
||||
/* 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;
|
||||
|
||||
function getCommaSep(spaces boolean) return varchar2 as
|
||||
begin
|
||||
if (spaces) then return ', '; else return ','; end if;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
/* 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) > 5000 - length(buf_str)) then
|
||||
if (lengthb(str) > 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;
|
||||
|
||||
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;
|
||||
|
||||
procedure ppObj(obj pljson, indent number, buf in out nocopy clob, spaces boolean, buf_str in out nocopy varchar2);
|
||||
|
||||
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 <= 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 <= 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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 > 0) then
|
||||
dbms_lob.trim(buf, 0);
|
||||
-- dbms_lob.erase(buf, amount);
|
||||
end if;
|
||||
|
||||
max_line_len := line_length;
|
||||
cur_line_len := 0;
|
||||
ppObj(obj, 0, buf, spaces, buf_str);
|
||||
flush_clob(buf, buf_str);
|
||||
end;
|
||||
|
||||
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 > 0) then
|
||||
dbms_lob.trim(buf, 0);
|
||||
-- dbms_lob.erase(buf, amount);
|
||||
end if;
|
||||
|
||||
max_line_len := line_length;
|
||||
cur_line_len := 0;
|
||||
add_to_clob(buf, buf_str, llcheck('['));
|
||||
ppEA(obj, 0, buf, spaces, buf_str);
|
||||
add_to_clob(buf, buf_str, llcheck(']'));
|
||||
flush_clob(buf, buf_str);
|
||||
end;
|
||||
|
||||
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 > 0) then
|
||||
dbms_lob.trim(buf, 0);
|
||||
-- dbms_lob.erase(buf, amount);
|
||||
end if;
|
||||
|
||||
case json_part.typeval
|
||||
/* number */
|
||||
when 4 then
|
||||
numbuf := treat(json_part as pljson_number).number_toString();
|
||||
add_to_clob(buf, buf_str, numbuf);
|
||||
/* string */
|
||||
when 3 then
|
||||
ppString(treat(json_part as pljson_string), buf, buf_str);
|
||||
/* bool */
|
||||
when 5 then
|
||||
if (json_part.get_bool()) then
|
||||
add_to_clob(buf, buf_str, 'true');
|
||||
else
|
||||
add_to_clob(buf, buf_str, 'false');
|
||||
end if;
|
||||
/* null */
|
||||
when 6 then
|
||||
add_to_clob(buf, buf_str, 'null');
|
||||
/* array */
|
||||
when 2 then
|
||||
pretty_print_list(pljson_list(json_part), spaces, buf, line_length);
|
||||
return;
|
||||
/* object */
|
||||
when 1 then
|
||||
pretty_print(pljson(json_part), spaces, buf, line_length);
|
||||
return;
|
||||
else
|
||||
add_to_clob(buf, buf_str, 'unknown type:' || json_part.get_type);
|
||||
end case;
|
||||
flush_clob(buf, buf_str);
|
||||
end;
|
||||
|
||||
/* Clob method end here */
|
||||
|
||||
/* Varchar2 method start here */
|
||||
procedure add_buf (buf in out nocopy varchar2, str in varchar2) as
|
||||
begin
|
||||
if (lengthb(str)>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;
|
||||
|
||||
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 <= 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 <= 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;
|
||||
|
||||
procedure ppObj(obj pljson, indent number, buf in out nocopy varchar2, spaces boolean);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (indx = 0) then
|
||||
--emit from prev to end;
|
||||
amount := max_string_chars;
|
||||
--dbms_output.put_line(' mycloblen ' || dbms_lob.getlength(my_clob));
|
||||
loop
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
dbms_output.put_line(v_str);
|
||||
prev := prev+amount;
|
||||
exit when prev >= dbms_lob.getlength(my_clob);
|
||||
end loop;
|
||||
else
|
||||
amount := indx - prev;
|
||||
if (amount > max_string_chars) then
|
||||
amount := max_string_chars;
|
||||
--dbms_output.put_line(' mycloblen ' || dbms_lob.getlength(my_clob));
|
||||
loop
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
dbms_output.put_line(v_str);
|
||||
prev := prev+amount;
|
||||
amount := indx - prev;
|
||||
exit when prev >= indx - 1;
|
||||
if (amount > max_string_chars) then
|
||||
amount := max_string_chars;
|
||||
end if;
|
||||
end loop;
|
||||
prev := indx + size_of_nl;
|
||||
else
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
dbms_output.put_line(v_str);
|
||||
prev := indx + size_of_nl;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end loop;
|
||||
if (jsonp is not null) then dbms_output.put_line(')'); end if;
|
||||
|
||||
/* while (amount != 0) loop
|
||||
indx := dbms_lob.instr(my_clob, delim, prev+1);
|
||||
|
||||
-- dbms_output.put_line(prev || ' to ' || indx);
|
||||
if (indx = 0) then
|
||||
indx := dbms_lob.getlength(my_clob)+1;
|
||||
end if;
|
||||
if (indx-prev > 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;
|
||||
|
||||
/* 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);
|
||||
|
||||
--dbms_output.put_line(prev || ' to ' || indx);
|
||||
if (indx-prev > 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)
|
||||
if (indx = 0) then
|
||||
--dbms_output.put_line(dbms_lob.substr(my_clob, dbms_lob.getlength(my_clob)-prev+size_of_nl, prev));
|
||||
amount := dbms_lob.getlength(my_clob)-prev+size_of_nl;
|
||||
dbms_lob.read(my_clob, amount, prev, v_str);
|
||||
else
|
||||
--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);
|
||||
end if;
|
||||
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;
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
begin
|
||||
loop
|
||||
dbms_lob.read( my_clob, l_amt, l_off, l_str );
|
||||
|
||||
-- it is vital to use htp.PRN to avoid
|
||||
-- spurious line feeds getting added to your
|
||||
-- document
|
||||
htp.prn( l_str );
|
||||
l_off := l_off+l_amt;
|
||||
end loop;
|
||||
exception
|
||||
when no_data_found then NULL;
|
||||
end;
|
||||
|
||||
/*
|
||||
len := dbms_lob.getlength(my_clob);
|
||||
|
||||
while (pos < len) loop
|
||||
htp.prn(dbms_lob.substr(my_clob, amount, pos)); -- should I replace substr with dbms_lob.read?
|
||||
--dbms_output.put_line(dbms_lob.substr(my_clob, amount, pos));
|
||||
pos := pos + amount;
|
||||
end loop;
|
||||
*/
|
||||
if (jsonp is not null) then htp.prn(')'); end if;
|
||||
end;
|
||||
|
||||
end pljson_printer;```
|
||||
204
docs/packages/PLJSON_UT.md
Normal file
204
docs/packages/PLJSON_UT.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# PLJSON_UT
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_ut as
|
||||
|
||||
/*
|
||||
*
|
||||
* E.I.Sarmas (github.com/dsnz) 2017-07-22
|
||||
*
|
||||
* Simple unit test framework for pljson
|
||||
*
|
||||
*/
|
||||
|
||||
suite_id number;
|
||||
suite_name varchar2(100);
|
||||
file_name varchar2(100);
|
||||
pass_count number;
|
||||
fail_count number;
|
||||
total_count number;
|
||||
|
||||
case_name varchar2(100);
|
||||
case_pass number;
|
||||
case_fail number;
|
||||
case_total number;
|
||||
|
||||
INDENT_1 varchar2(10) := ' ';
|
||||
INDENT_2 varchar2(10) := ' ';
|
||||
|
||||
procedure testsuite(suite_name_ varchar2, file_name_ varchar2);
|
||||
procedure testcase(case_name_ varchar2);
|
||||
|
||||
procedure pass(test_name varchar2 := null);
|
||||
procedure fail(test_name varchar2 := null);
|
||||
|
||||
procedure assertTrue(b boolean, test_name varchar2 := null);
|
||||
procedure assertFalse(b boolean, test_name varchar2 := null);
|
||||
|
||||
procedure testsuite_report;
|
||||
|
||||
procedure startup;
|
||||
procedure shutdown;
|
||||
|
||||
end pljson_ut;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_ut as
|
||||
|
||||
/*
|
||||
*
|
||||
* E.I.Sarmas (github.com/dsnz) 2017-07-22
|
||||
*
|
||||
* Simple unit test framework for pljson
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
procedure assertTrue(b boolean, test_name varchar2 := null) is
|
||||
begin
|
||||
if (b) then
|
||||
pass(test_name);
|
||||
else
|
||||
fail(test_name);
|
||||
end if;
|
||||
end;
|
||||
|
||||
procedure assertFalse(b boolean, test_name varchar2 := null) is
|
||||
begin
|
||||
if (not b) then
|
||||
pass(test_name);
|
||||
else
|
||||
fail(test_name);
|
||||
end if;
|
||||
end;
|
||||
|
||||
procedure testsuite_report is
|
||||
begin
|
||||
dbms_output.put_line('');
|
||||
dbms_output.put_line(
|
||||
total_count || ' tests, '
|
||||
|| pass_count || ' passed, '
|
||||
|| fail_count || ' failed'
|
||||
);
|
||||
|
||||
execute immediate 'insert into pljson_testsuite values (:1, :2, :3, :4, :5, :6)'
|
||||
using suite_id, suite_name, file_name, pass_count, fail_count, total_count;
|
||||
end;
|
||||
|
||||
procedure startup is
|
||||
begin
|
||||
suite_id := 0;
|
||||
execute immediate 'truncate table pljson_testsuite';
|
||||
end;
|
||||
|
||||
procedure shutdown is
|
||||
begin
|
||||
commit;
|
||||
|
||||
dbms_output.put_line('');
|
||||
for rec in (
|
||||
select suite_id, suite_name, passed, failed, total, file_name
|
||||
from (
|
||||
select 3 s, suite_id,
|
||||
lpad(suite_name, 30) suite_name,
|
||||
to_char(passed, '999999') passed,
|
||||
to_char(failed, '999999') failed,
|
||||
to_char(total, '999999') total,
|
||||
lpad(file_name, 30) file_name
|
||||
from pljson_testsuite
|
||||
union
|
||||
select 1 s, 0 suite_id,
|
||||
lpad('SUITE_NAME', 30) suite_name,
|
||||
lpad('PASSED', 7) passed,
|
||||
lpad('FAILED', 7) failed,
|
||||
lpad('TOTAL', 7) total,
|
||||
lpad('FILE_NAME', 30) file_name
|
||||
from dual
|
||||
union
|
||||
select 5 s, 0,
|
||||
lpad('ALL TESTS', 30) suite_name,
|
||||
to_char(sum(passed), '999999') passed,
|
||||
to_char(sum(failed), '999999') failed,
|
||||
to_char(sum(total), '999999') total,
|
||||
lpad(' ', 30) file_name
|
||||
from pljson_testsuite
|
||||
union
|
||||
select 2 s, 0 suite_id,
|
||||
lpad('-', 30, '-') suite_name,
|
||||
lpad('-', 7, '-') passed,
|
||||
lpad('-', 7, '-') failed,
|
||||
lpad('-', 7, '-') total,
|
||||
lpad('-', 30, '-') file_name
|
||||
from dual
|
||||
union
|
||||
select 4 s, 0 suite_id,
|
||||
lpad('-', 30, '-') suite_name,
|
||||
lpad('-', 7, '-') passed,
|
||||
lpad('-', 7, '-') failed,
|
||||
lpad('-', 7, '-') total,
|
||||
lpad('-', 30, '-') file_name
|
||||
from dual
|
||||
order by s, suite_id
|
||||
)
|
||||
)
|
||||
loop
|
||||
dbms_output.put_line(
|
||||
rec.suite_name||' '||rec.passed||' '||rec.failed||' '||rec.total||' '||rec.file_name
|
||||
);
|
||||
end loop;
|
||||
end;
|
||||
|
||||
end pljson_ut;```
|
||||
370
docs/packages/PLJSON_UTIL_PKG.md
Normal file
370
docs/packages/PLJSON_UTIL_PKG.md
Normal file
@@ -0,0 +1,370 @@
|
||||
# PLJSON_UTIL_PKG
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_util_pkg authid current_user as
|
||||
|
||||
/*
|
||||
|
||||
Purpose: JSON utilities for PL/SQL
|
||||
see http://ora-00001.blogspot.com/
|
||||
|
||||
Remarks:
|
||||
|
||||
Who Date Description
|
||||
------ ---------- -------------------------------------
|
||||
MBR 30.01.2010 Created
|
||||
JKR 01.05.2010 Edited to fit in PL/JSON
|
||||
JKR 19.01.2011 Newest stylesheet + bugfix handling
|
||||
|
||||
*/
|
||||
|
||||
-- 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;
|
||||
|
||||
-- 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;
|
||||
|
||||
|
||||
end pljson_util_pkg;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```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);
|
||||
|
||||
/*
|
||||
|
||||
Purpose: JSON utilities for PL/SQL
|
||||
|
||||
Remarks:
|
||||
|
||||
Who Date Description
|
||||
------ ---------- -------------------------------------
|
||||
MBR 30.01.2010 Created
|
||||
|
||||
*/
|
||||
|
||||
function get_xml_to_json_stylesheet return varchar2 as
|
||||
stylesheet varchar2(32767);
|
||||
nls_numeric_characters varchar2(2);
|
||||
begin
|
||||
|
||||
/*
|
||||
|
||||
Purpose: return XSLT stylesheet for XML to JSON transformation
|
||||
|
||||
Remarks: see http://code.google.com/p/xml2json-xslt/
|
||||
|
||||
Who Date Description
|
||||
------ ---------- -------------------------------------
|
||||
MBR 30.01.2010 Created
|
||||
MBR 30.01.2010 Added fix for nulls
|
||||
|
||||
*/
|
||||
|
||||
stylesheet := q'^<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<!--
|
||||
Copyright (c) 2006,2008 Doeke Zanstra
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer. Redistributions in binary
|
||||
form must reproduce the above copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
|
||||
<xsl:output indent="no" omit-xml-declaration="yes" method="text" encoding="UTF-8" media-type="text/x-json"/>
|
||||
<xsl:strip-space elements="*"/>
|
||||
<!--contant-->
|
||||
<xsl:variable name="d">0123456789</xsl:variable>
|
||||
|
||||
<!-- ignore document text -->
|
||||
<xsl:template match="text()[preceding-sibling::node() or following-sibling::node()]"/>
|
||||
|
||||
<!-- string -->
|
||||
<xsl:template match="text()">
|
||||
<xsl:call-template name="escape-string">
|
||||
<xsl:with-param name="s" select="."/>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Main template for escaping strings; used by above template and for object-properties
|
||||
Responsibilities: placed quotes around string, and chain up to next filter, escape-bs-string -->
|
||||
<xsl:template name="escape-string">
|
||||
<xsl:param name="s"/>
|
||||
<xsl:text>"</xsl:text>
|
||||
<xsl:call-template name="escape-bs-string">
|
||||
<xsl:with-param name="s" select="$s"/>
|
||||
</xsl:call-template>
|
||||
<xsl:text>"</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Escape the backslash (\) before everything else. -->
|
||||
<xsl:template name="escape-bs-string">
|
||||
<xsl:param name="s"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($s,'\')">
|
||||
<xsl:call-template name="escape-quot-string">
|
||||
<xsl:with-param name="s" select="concat(substring-before($s,'\'),'\\')"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="escape-bs-string">
|
||||
<xsl:with-param name="s" select="substring-after($s,'\')"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="escape-quot-string">
|
||||
<xsl:with-param name="s" select="$s"/>
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Escape the double quote ("). -->
|
||||
<xsl:template name="escape-quot-string">
|
||||
<xsl:param name="s"/>
|
||||
<xsl:choose>
|
||||
<xsl:when test="contains($s,'"')">
|
||||
<xsl:call-template name="encode-string">
|
||||
<xsl:with-param name="s" select="concat(substring-before($s,'"'),'\"')"/>
|
||||
</xsl:call-template>
|
||||
<xsl:call-template name="escape-quot-string">
|
||||
<xsl:with-param name="s" select="substring-after($s,'"')"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="encode-string">
|
||||
<xsl:with-param name="s" select="$s"/>
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Replace tab, line feed and/or carriage return by its matching escape code. Can't escape backslash
|
||||
or double quote here, because they don't replace characters (� becomes \t), but they prefix
|
||||
characters (\ becomes \\). Besides, backslash should be seperate anyway, because it should be
|
||||
processed first. This function can't do that. -->
|
||||
<xsl:template name="encode-string">
|
||||
<xsl:param name="s"/>
|
||||
<xsl:choose>
|
||||
<!-- tab -->
|
||||
<xsl:when test="contains($s,'	')">
|
||||
<xsl:call-template name="encode-string">
|
||||
<xsl:with-param name="s" select="concat(substring-before($s,'	'),'\t',substring-after($s,'	'))"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<!-- line feed -->
|
||||
<xsl:when test="contains($s,'
')">
|
||||
<xsl:call-template name="encode-string">
|
||||
<xsl:with-param name="s" select="concat(substring-before($s,'
'),'\n',substring-after($s,'
'))"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<!-- carriage return -->
|
||||
<xsl:when test="contains($s,'
')">
|
||||
<xsl:call-template name="encode-string">
|
||||
<xsl:with-param name="s" select="concat(substring-before($s,'
'),'\r',substring-after($s,'
'))"/>
|
||||
</xsl:call-template>
|
||||
</xsl:when>
|
||||
<xsl:otherwise><xsl:value-of select="$s"/></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
<!-- number (no support for javascript mantissa) -->
|
||||
<xsl:template match="text()[not(
|
||||
(starts-with(., '0' ) and . != '0' and not(starts-with(., '0.' ))) or
|
||||
(starts-with(.,'-0' ) and . != '-0' and not(starts-with(.,'-0.' ))) or
|
||||
string(number(translate(., '{{nls_numeric_characters}}', '.,')))='NaN'
|
||||
)]">
|
||||
|
||||
<xsl:variable name="num_string" select="translate(., '{{nls_numeric_characters}}', '.,')"/>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="starts-with($num_string, '.')">
|
||||
<xsl:value-of select="concat('0', $num_string)"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:value-of select="$num_string"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<!-- boolean, case-insensitive -->
|
||||
<xsl:template match="text()[translate(.,'TRUE','true')='true']">true</xsl:template>
|
||||
<xsl:template match="text()[translate(.,'FALSE','false')='false']">false</xsl:template>
|
||||
|
||||
<!-- object -->
|
||||
<xsl:template match="*" name="base">
|
||||
<xsl:if test="not(preceding-sibling::*)">{</xsl:if>
|
||||
<xsl:call-template name="escape-string">
|
||||
<xsl:with-param name="s" select="name()"/>
|
||||
</xsl:call-template>
|
||||
<xsl:text>:</xsl:text>
|
||||
<!-- check type of node -->
|
||||
<xsl:choose>
|
||||
<!-- null nodes -->
|
||||
<xsl:when test="count(child::node())=0">null</xsl:when>
|
||||
<!-- other nodes -->
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates select="child::node()"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<!-- end of type check -->
|
||||
<xsl:if test="following-sibling::*">,</xsl:if>
|
||||
<xsl:if test="not(following-sibling::*)">}</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<!-- array -->
|
||||
<xsl:template match="*[count(../*[name(../*)=name(.)])=count(../*) and count(../*)>1]">
|
||||
<xsl:if test="not(preceding-sibling::*)">[</xsl:if>
|
||||
<xsl:choose>
|
||||
<xsl:when test="not(child::node())">
|
||||
<xsl:text>null</xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates select="child::node()"/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
<xsl:if test="following-sibling::*">,</xsl:if>
|
||||
<xsl:if test="not(following-sibling::*)">]</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<!-- convert root element to an anonymous container -->
|
||||
<xsl:template match="/">
|
||||
<xsl:apply-templates select="node()"/>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>^';
|
||||
|
||||
select value
|
||||
into nls_numeric_characters
|
||||
from nls_session_parameters
|
||||
where parameter = 'NLS_NUMERIC_CHARACTERS';
|
||||
|
||||
return replace(stylesheet, '{{nls_numeric_characters}}', nls_numeric_characters);
|
||||
|
||||
end get_xml_to_json_stylesheet;
|
||||
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
|
||||
Purpose: generate JSON from REF Cursor
|
||||
|
||||
Remarks:
|
||||
|
||||
Who Date Description
|
||||
------ ---------- -------------------------------------
|
||||
MBR 30.01.2010 Created
|
||||
JKR 01.05.2010 Edited to fit in PL/JSON
|
||||
|
||||
*/
|
||||
|
||||
l_ctx := dbms_xmlgen.newcontext (p_ref_cursor);
|
||||
|
||||
dbms_xmlgen.setnullhandling (l_ctx, dbms_xmlgen.empty_tag);
|
||||
|
||||
-- for pagination
|
||||
|
||||
if p_max_rows is not null then
|
||||
dbms_xmlgen.setmaxrows (l_ctx, p_max_rows);
|
||||
end if;
|
||||
|
||||
if p_skip_rows is not null then
|
||||
dbms_xmlgen.setskiprows (l_ctx, p_skip_rows);
|
||||
end if;
|
||||
|
||||
-- get the XML content
|
||||
l_xml := dbms_xmlgen.getxmltype (l_ctx, dbms_xmlgen.none);
|
||||
|
||||
l_num_rows := dbms_xmlgen.getnumrowsprocessed (l_ctx);
|
||||
|
||||
dbms_xmlgen.closecontext (l_ctx);
|
||||
|
||||
close p_ref_cursor;
|
||||
|
||||
if(l_num_rows = 0) then
|
||||
return pljson_list();
|
||||
end if;
|
||||
|
||||
--dbms_output.put_line(l_xml.getstringval);
|
||||
-- perform the XSL transformation
|
||||
SELECT l_xml.transform(l_xsl).getclobval()
|
||||
INTO l_returnvalue
|
||||
FROM DUAL;
|
||||
|
||||
--dbms_output.put_line(l_returnvalue);
|
||||
|
||||
if(l_num_rows > 1) then
|
||||
return pljson_list(pljson(l_returnvalue).get('ROWSET'));
|
||||
end if;
|
||||
|
||||
declare ret pljson_list := pljson_list();
|
||||
begin
|
||||
ret.append(
|
||||
pljson(
|
||||
pljson(l_returnvalue).get('ROWSET')
|
||||
).get('ROW')
|
||||
);
|
||||
return ret;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
end sql_to_json;
|
||||
|
||||
end pljson_util_pkg;```
|
||||
162
docs/packages/PLJSON_XML.md
Normal file
162
docs/packages/PLJSON_XML.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# PLJSON_XML
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
package pljson_xml 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
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;
|
||||
*/
|
||||
|
||||
function json_to_xml(obj pljson, tagname varchar2 default 'root') return xmltype;
|
||||
|
||||
end pljson_xml;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
package body pljson_xml as
|
||||
|
||||
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 '&' then buf := buf || '&';
|
||||
when '<' then buf := buf || '<';
|
||||
when '>' then buf := buf || '>';
|
||||
when '"' then buf := buf || '"';
|
||||
else buf := buf || ch;
|
||||
end case;
|
||||
end loop;
|
||||
return buf;
|
||||
end escapeStr;
|
||||
|
||||
/* 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) > 5000 - length(buf_str)) then
|
||||
if (lengthb(str) > 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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
v_keys pljson_list;
|
||||
v_value pljson_element;
|
||||
key_str varchar2(4000);
|
||||
begin
|
||||
if (obj.is_object()) then
|
||||
add_to_clob(xmlstr, xmlbuf, '<' || tagname || '>');
|
||||
v_obj := pljson(obj);
|
||||
|
||||
v_keys := v_obj.get_keys();
|
||||
for i in 1 .. v_keys.count loop
|
||||
v_value := v_obj.get(i);
|
||||
key_str := v_keys.get(i).get_string();
|
||||
|
||||
if (key_str = 'content') then
|
||||
if (v_value.is_array()) then
|
||||
declare
|
||||
v_l pljson_list := pljson_list(v_value);
|
||||
begin
|
||||
for j in 1 .. v_l.count loop
|
||||
if (j > 1) then add_to_clob(xmlstr, xmlbuf, chr(13)||chr(10)); end if;
|
||||
add_to_clob(xmlstr, xmlbuf, escapeStr(v_l.get(j).to_char()));
|
||||
end loop;
|
||||
end;
|
||||
else
|
||||
add_to_clob(xmlstr, xmlbuf, escapeStr(v_value.to_char()));
|
||||
end if;
|
||||
elsif (v_value.is_array()) then
|
||||
declare
|
||||
v_l pljson_list := pljson_list(v_value);
|
||||
begin
|
||||
for j in 1 .. v_l.count loop
|
||||
v_value := v_l.get(j);
|
||||
if (v_value.is_array()) then
|
||||
add_to_clob(xmlstr, xmlbuf, '<' || key_str || '>');
|
||||
add_to_clob(xmlstr, xmlbuf, escapeStr(v_value.to_char()));
|
||||
add_to_clob(xmlstr, xmlbuf, '</' || key_str || '>');
|
||||
else
|
||||
toString(v_value, key_str, xmlstr, xmlbuf);
|
||||
end if;
|
||||
end loop;
|
||||
end;
|
||||
elsif (v_value.is_null() or (v_value.is_string() and v_value.get_string() = '')) then
|
||||
add_to_clob(xmlstr, xmlbuf, '<' || key_str || '/>');
|
||||
else
|
||||
toString(v_value, key_str, xmlstr, xmlbuf);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
add_to_clob(xmlstr, xmlbuf, '</' || tagname || '>');
|
||||
elsif (obj.is_array()) then
|
||||
v_list := pljson_list(obj);
|
||||
for i in 1 .. v_list.count loop
|
||||
v_value := v_list.get(i);
|
||||
toString(v_value, nvl(tagname, 'array'), xmlstr, xmlbuf);
|
||||
end loop;
|
||||
else
|
||||
add_to_clob(xmlstr, xmlbuf, '<' || tagname || '>'||case when obj.value_of() is not null then escapeStr(obj.value_of()) end ||'</' || tagname || '>');
|
||||
end if;
|
||||
end toString;
|
||||
|
||||
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);
|
||||
|
||||
toString(obj, tagname, xmlstr, xmlbuf);
|
||||
|
||||
flush_clob(xmlstr, xmlbuf);
|
||||
returnValue := xmltype('<?xml version="1.0"?>'||xmlstr);
|
||||
dbms_lob.freetemporary(xmlstr);
|
||||
return returnValue;
|
||||
end;
|
||||
|
||||
end pljson_xml;```
|
||||
102
docs/packages/README.md
Normal file
102
docs/packages/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Packages Database
|
||||
|
||||
Questa cartella contiene la documentazione di tutti i 17 packages del database.
|
||||
|
||||
## Packages Business
|
||||
|
||||
| Package | Descrizione |
|
||||
|---------|-------------|
|
||||
| [MAIL_PKG](MAIL_PKG.md) | Gestione invio email automatiche (solleciti, reminder) |
|
||||
|
||||
## Packages Utility
|
||||
|
||||
| Package | Descrizione |
|
||||
|---------|-------------|
|
||||
| [UTL_BASE64](UTL_BASE64.md) | Encoding/decoding Base64 |
|
||||
|
||||
## Packages JasperReports (XLIB)
|
||||
|
||||
| Package | Descrizione |
|
||||
|---------|-------------|
|
||||
| [XLIB_JASPERREPORTS](XLIB_JASPERREPORTS.md) | Integrazione con JasperReports server |
|
||||
| [XLIB_JASPERREPORTS_IMG](XLIB_JASPERREPORTS_IMG.md) | Gestione immagini nei report |
|
||||
| [XLIB_HTTP](XLIB_HTTP.md) | Chiamate HTTP/REST |
|
||||
| [XLIB_COMPONENT](XLIB_COMPONENT.md) | Gestione componenti |
|
||||
| [XLIB_LOG](XLIB_LOG.md) | Sistema di logging |
|
||||
|
||||
## Packages JSON (PLJSON Library)
|
||||
|
||||
Libreria esterna per parsing e generazione JSON. In .NET può essere sostituita con `System.Text.Json` o `Newtonsoft.Json`.
|
||||
|
||||
| Package | Descrizione |
|
||||
|---------|-------------|
|
||||
| [PLJSON_DYN](PLJSON_DYN.md) | Query dinamiche JSON |
|
||||
| [PLJSON_EXT](PLJSON_EXT.md) | Estensioni JSON |
|
||||
| [PLJSON_HELPER](PLJSON_HELPER.md) | Helper functions |
|
||||
| [PLJSON_ML](PLJSON_ML.md) | Multi-line JSON |
|
||||
| [PLJSON_OBJECT_CACHE](PLJSON_OBJECT_CACHE.md) | Cache oggetti JSON |
|
||||
| [PLJSON_PARSER](PLJSON_PARSER.md) | Parser JSON |
|
||||
| [PLJSON_PRINTER](PLJSON_PRINTER.md) | Output JSON formattato |
|
||||
| [PLJSON_UT](PLJSON_UT.md) | Unit test JSON |
|
||||
| [PLJSON_UTIL_PKG](PLJSON_UTIL_PKG.md) | Utility JSON |
|
||||
| [PLJSON_XML](PLJSON_XML.md) | Conversione JSON ↔ XML |
|
||||
|
||||
## Dettaglio Package MAIL_PKG
|
||||
|
||||
### Procedures Disponibili
|
||||
|
||||
| Procedura | Descrizione |
|
||||
|-----------|-------------|
|
||||
| `send_custom_mail` | Invio email generica |
|
||||
| `send_richiesta_riscontro_preventivo` | Sollecito per preventivi in stato 100/200 |
|
||||
| `send_richiesta_riscontro_preventivo_job` | Job: 10 giorni dopo DATA_DOC |
|
||||
| `send_richiesta_riscontro_post_degustazione` | Sollecito post-degustazione |
|
||||
| `send_richiesta_riscontro_post_degustazione_job` | Job: 15 giorni dopo prima degustazione |
|
||||
| `send_reminder_seconda_caparra` | Reminder pagamento seconda caparra |
|
||||
| `send_reminder_seconda_caparra_job` | Job: ogni 5 giorni da 65gg prima evento |
|
||||
|
||||
### Configurazione Email
|
||||
|
||||
- **From**: `noreply@apollinarecatering.it`
|
||||
- **BCC**: `monia@apollinarecatering.it, matrimonio@apollinarecatering.it`
|
||||
- Usa `APEX_MAIL` per invio
|
||||
- Richiede `CMN_MAIL_HTMLUTILS` per costruzione body HTML
|
||||
|
||||
### Migrazione .NET
|
||||
|
||||
```csharp
|
||||
// Esempio implementazione con SendGrid o SMTP
|
||||
public interface IMailService
|
||||
{
|
||||
Task SendCustomMailAsync(string recipients, string subject, string body);
|
||||
Task SendRichiestaRiscontroPreventivo(int eventoId);
|
||||
Task SendReminderSecondaCaparra(int eventoId);
|
||||
}
|
||||
|
||||
// Jobs con Hangfire
|
||||
[RecurringJob("0 9 * * *")]
|
||||
public async Task SendReminderSecondaCaparraJob()
|
||||
{
|
||||
var eventi = await GetEventiDaPagareEntro65gg();
|
||||
foreach (var evento in eventi.Where(e => ShouldSendReminder(e)))
|
||||
{
|
||||
await _mailService.SendReminderSecondaCaparra(evento.Id);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Note per Migrazione
|
||||
|
||||
1. **MAIL_PKG**: Sostituire con servizio email .NET (SendGrid, SMTP, Azure Communication Services)
|
||||
|
||||
2. **PLJSON_***: Non necessari in .NET, usare `System.Text.Json`
|
||||
|
||||
3. **XLIB_JASPERREPORTS**: Valutare alternative:
|
||||
- SSRS (SQL Server Reporting Services)
|
||||
- DevExpress Reports
|
||||
- Telerik Reporting
|
||||
- QuestPDF / iTextSharp per PDF
|
||||
|
||||
4. **XLIB_HTTP**: Sostituire con `HttpClient`
|
||||
|
||||
5. **UTL_BASE64**: Usare `Convert.ToBase64String` / `Convert.FromBase64String`
|
||||
168
docs/packages/UTL_BASE64.md
Normal file
168
docs/packages/UTL_BASE64.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# UTL_BASE64
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
PACKAGE "UTL_BASE64" is
|
||||
function decode_base64(p_clob_in in clob) return blob;
|
||||
|
||||
function encode_base64(p_blob_in in blob) return clob;
|
||||
|
||||
FUNCTION encodeBlob2Base64(pBlobIn IN BLOB) RETURN BLOB;
|
||||
|
||||
FUNCTION decodeBase642Blob(pBlobIn IN BLOB) RETURN BLOB;
|
||||
|
||||
function base64encode(p_blob in blob) return clob;
|
||||
end;
|
||||
|
||||
```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
PACKAGE BODY "UTL_BASE64" is
|
||||
function decode_base64(p_clob_in in clob) return blob is
|
||||
v_blob blob;
|
||||
v_result blob;
|
||||
v_offset integer;
|
||||
v_buffer_size binary_integer := 48;
|
||||
v_buffer_varchar varchar2(48);
|
||||
v_buffer_raw raw(48);
|
||||
begin
|
||||
if p_clob_in is null then
|
||||
return null;
|
||||
end if;
|
||||
dbms_lob.createtemporary(v_blob, true);
|
||||
v_offset := 1;
|
||||
for i in 1 .. ceil(dbms_lob.getlength(p_clob_in) / v_buffer_size) loop
|
||||
dbms_lob.read(p_clob_in, v_buffer_size, v_offset, v_buffer_varchar);
|
||||
v_buffer_raw := utl_raw.cast_to_raw(v_buffer_varchar);
|
||||
v_buffer_raw := utl_encode.base64_decode(v_buffer_raw);
|
||||
dbms_lob.writeappend(v_blob, utl_raw.length(v_buffer_raw), v_buffer_raw);
|
||||
v_offset := v_offset + v_buffer_size;
|
||||
end loop;
|
||||
v_result := v_blob;
|
||||
dbms_lob.freetemporary(v_blob);
|
||||
return v_result;
|
||||
end decode_base64;
|
||||
|
||||
function encode_base64(p_blob_in in blob) return clob is
|
||||
v_clob clob;
|
||||
v_result clob;
|
||||
v_offset integer;
|
||||
v_chunk_size binary_integer := (48 / 4) * 3;
|
||||
v_buffer_varchar varchar2(48);
|
||||
v_buffer_raw raw(48);
|
||||
begin
|
||||
if p_blob_in is null then
|
||||
return null;
|
||||
end if;
|
||||
dbms_lob.createtemporary(v_clob, true);
|
||||
v_offset := 1;
|
||||
for i in 1 .. ceil(dbms_lob.getlength(p_blob_in) / v_chunk_size) loop
|
||||
dbms_lob.read(p_blob_in, v_chunk_size, v_offset, v_buffer_raw);
|
||||
v_buffer_raw := utl_encode.base64_encode(v_buffer_raw);
|
||||
v_buffer_varchar := utl_raw.cast_to_varchar2(v_buffer_raw);
|
||||
dbms_lob.writeappend(v_clob, length(v_buffer_varchar), v_buffer_varchar);
|
||||
v_offset := v_offset + v_chunk_size;
|
||||
end loop;
|
||||
v_result := v_clob;
|
||||
dbms_lob.freetemporary(v_clob);
|
||||
return v_result;
|
||||
end encode_base64;
|
||||
|
||||
FUNCTION encodeBlob2Base64(pBlobIn IN BLOB) RETURN BLOB IS
|
||||
vAmount NUMBER := 45;
|
||||
vBlobEnc BLOB := empty_blob();
|
||||
vBlobEncLen NUMBER := 0;
|
||||
vBlobInLen NUMBER := 0;
|
||||
vBuffer RAW(45);
|
||||
vOffset NUMBER := 1;
|
||||
BEGIN
|
||||
-- dbms_output.put_line('Start base64 encoding.');
|
||||
vBlobInLen := dbms_lob.getlength(pBlobIn);
|
||||
-- dbms_output.put_line('<BlobInLength>' || vBlobInLen);
|
||||
dbms_lob.createtemporary(vBlobEnc, TRUE);
|
||||
LOOP
|
||||
IF vOffset >= vBlobInLen THEN
|
||||
EXIT;
|
||||
END IF;
|
||||
dbms_lob.read(pBlobIn, vAmount, vOffset, vBuffer);
|
||||
BEGIN
|
||||
dbms_lob.append(vBlobEnc, utl_encode.base64_encode(vBuffer));
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
dbms_output.put_line('<vAmount>' || vAmount || '<vOffset>' || vOffset || '<vBuffer>' || vBuffer);
|
||||
dbms_output.put_line('ERROR IN append: ' || SQLERRM);
|
||||
RAISE;
|
||||
END;
|
||||
vOffset := vOffset + vAmount;
|
||||
END LOOP;
|
||||
vBlobEncLen := dbms_lob.getlength(vBlobEnc);
|
||||
-- dbms_output.put_line('<BlobEncLength>' || vBlobEncLen);
|
||||
-- dbms_output.put_line('Finshed base64 encoding.');
|
||||
RETURN vBlobEnc;
|
||||
END encodeBlob2Base64;
|
||||
|
||||
FUNCTION decodeBase642Blob(pBlobIn IN BLOB) RETURN BLOB IS
|
||||
vAmount NUMBER := 256;--32;
|
||||
vBlobDec BLOB := empty_blob();
|
||||
vBlobDecLen NUMBER := 0;
|
||||
vBlobInLen NUMBER := 0;
|
||||
vBuffer RAW(256);--32);
|
||||
vOffset NUMBER := 1;
|
||||
BEGIN
|
||||
-- dbms_output.put_line('Start base64 decoding.');
|
||||
vBlobInLen := dbms_lob.getlength(pBlobIn);
|
||||
-- dbms_output.put_line('<BlobInLength>' || vBlobInLen);
|
||||
dbms_lob.createtemporary(vBlobDec, TRUE);
|
||||
LOOP
|
||||
IF vOffset >= vBlobInLen THEN
|
||||
EXIT;
|
||||
END IF;
|
||||
dbms_lob.read(pBlobIn, vAmount, vOffset, vBuffer);
|
||||
BEGIN
|
||||
dbms_lob.append(vBlobDec, utl_encode.base64_decode(vBuffer));
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
dbms_output.put_line('<vAmount>' || vAmount || '<vOffset>' || vOffset || '<vBuffer>' || vBuffer);
|
||||
dbms_output.put_line('ERROR IN append: ' || SQLERRM);
|
||||
RAISE;
|
||||
END;
|
||||
vOffset := vOffset + vAmount;
|
||||
END LOOP;
|
||||
vBlobDecLen := dbms_lob.getlength(vBlobDec);
|
||||
-- dbms_output.put_line('<BlobDecLength>' || vBlobDecLen);
|
||||
-- dbms_output.put_line('Finshed base64 decoding.');
|
||||
RETURN vBlobDec;
|
||||
END decodeBase642Blob;
|
||||
|
||||
function base64encode(p_blob in blob)
|
||||
return clob
|
||||
is
|
||||
CRLF constant varchar2(2) := chr(13)||chr(10);
|
||||
l_clob clob;
|
||||
l_amount integer := 23826;
|
||||
l_offset integer := 1;
|
||||
l_raw raw(32767);
|
||||
l_buf varchar2(32767);
|
||||
l_len integer := dbms_lob.getlength(p_blob);
|
||||
begin
|
||||
|
||||
dbms_lob.createtemporary(l_clob, true, dbms_lob.call);
|
||||
|
||||
while l_offset <= l_len loop
|
||||
dbms_lob.read(p_blob, l_amount, l_offset, l_raw);
|
||||
l_offset := l_offset + l_amount;
|
||||
l_buf := utl_raw.cast_to_varchar2(utl_encode.base64_encode(l_raw));
|
||||
l_buf := replace(l_buf, CRLF);
|
||||
dbms_lob.writeappend(l_clob, length(l_buf), l_buf);
|
||||
end loop;
|
||||
|
||||
return l_clob;
|
||||
|
||||
end base64encode;
|
||||
|
||||
end;
|
||||
|
||||
```
|
||||
265
docs/packages/XLIB_COMPONENT.md
Normal file
265
docs/packages/XLIB_COMPONENT.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# XLIB_COMPONENT
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
PACKAGE "XLIB_COMPONENT"
|
||||
AS
|
||||
/*=========================================================================
|
||||
$Id: xlib_component.pks 57 2013-05-13 07:09:51Z dietmar.aust $
|
||||
|
||||
Purpose :
|
||||
|
||||
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
|
||||
|
||||
$LastChangedDate: 2013-05-13 09:09:51 +0200 (Mon, 13 May 2013) $
|
||||
$LastChangedBy: dietmar.aust $
|
||||
|
||||
Date Author Comment
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
06.01.2010 D. Aust Initial creation
|
||||
|
||||
=========================================================================*/
|
||||
|
||||
-- how many digits does the version key have?
|
||||
-- 3 => e.g. 1.0.0
|
||||
-- 4 => e.g. 1.0.0.0
|
||||
c_num_version_components CONSTANT NUMBER := 6;
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
PROCEDURE delete_component (p_name IN xlib_components.comp_name%TYPE);
|
||||
|
||||
/*****
|
||||
utility functions
|
||||
****/
|
||||
FUNCTION get_version (p_name IN xlib_components.comp_name%TYPE)
|
||||
RETURN xlib_components.comp_version%TYPE;
|
||||
|
||||
FUNCTION make_version_string (p_version IN VARCHAR2)
|
||||
RETURN VARCHAR2;
|
||||
|
||||
PROCEDURE verify_required_component (
|
||||
p_comp_name IN VARCHAR2,
|
||||
p_comp_version_min IN VARCHAR2
|
||||
);
|
||||
END xlib_component;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```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;
|
||||
|
||||
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
|
||||
|
||||
)
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
IF SQL%ROWCOUNT = 0
|
||||
THEN
|
||||
raise_application_error (-20006,
|
||||
'component ' || p_name || ' not found'
|
||||
);
|
||||
END IF;
|
||||
END;
|
||||
|
||||
PROCEDURE delete_component (p_name IN xlib_components.comp_name%TYPE)
|
||||
IS
|
||||
BEGIN
|
||||
-- delete component
|
||||
DELETE FROM xlib_components
|
||||
WHERE comp_name = p_name;
|
||||
|
||||
IF SQL%ROWCOUNT = 0
|
||||
THEN
|
||||
raise_application_error (-20001,
|
||||
'Component ' || p_name || ' not found'
|
||||
);
|
||||
END IF;
|
||||
END;
|
||||
|
||||
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;
|
||||
|
||||
LOOP
|
||||
l_sep_index := INSTR (l_string, p_sep, l_index);
|
||||
EXIT WHEN l_sep_index = 0;
|
||||
l_tab (l_tab.COUNT) :=
|
||||
SUBSTR (l_string, l_index, l_sep_index - l_index);
|
||||
l_index := l_sep_index + 1;
|
||||
END LOOP;
|
||||
|
||||
RETURN l_tab;
|
||||
END;
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
RETURN l_version;
|
||||
END;
|
||||
|
||||
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, ' ') > 0
|
||||
THEN
|
||||
raise_application_error (-20002, 'wrong version format');
|
||||
END IF;
|
||||
|
||||
l_tab := split_string (p_version, '.');
|
||||
|
||||
FOR i IN 0 .. l_tab.COUNT - 1
|
||||
LOOP
|
||||
l_num := TO_NUMBER (l_tab (i));
|
||||
END LOOP;
|
||||
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;
|
||||
|
||||
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 => p_version);
|
||||
l_tab := split_string (p_version, '.');
|
||||
|
||||
FOR i IN 1 .. c_num_version_components
|
||||
LOOP
|
||||
IF l_tab.EXISTS (i - 1)
|
||||
THEN
|
||||
l_comp :=
|
||||
TO_CHAR (TO_NUMBER (NVL (l_tab (i - 1), '0')), 'FM0000');
|
||||
ELSE
|
||||
l_comp := '0000';
|
||||
END IF;
|
||||
|
||||
IF l_str IS NULL
|
||||
THEN
|
||||
l_str := l_comp;
|
||||
ELSE
|
||||
l_str := l_str || '.' || l_comp;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
RETURN l_str;
|
||||
END;
|
||||
|
||||
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 => p_comp_name);
|
||||
|
||||
IF make_version_string (l_current_version)
|
||||
>= make_version_string (p_comp_version_min)
|
||||
THEN
|
||||
NULL; -- ok
|
||||
ELSE
|
||||
raise_application_error
|
||||
(-20020,
|
||||
'this upgrade requires '||p_comp_name||' in version '
|
||||
|| p_comp_version_min
|
||||
|| ' or higher, not version '
|
||||
|| l_current_version
|
||||
);
|
||||
END IF;
|
||||
END;
|
||||
END xlib_component;```
|
||||
477
docs/packages/XLIB_HTTP.md
Normal file
477
docs/packages/XLIB_HTTP.md
Normal file
@@ -0,0 +1,477 @@
|
||||
# XLIB_HTTP
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
PACKAGE "XLIB_HTTP"
|
||||
AS
|
||||
/*=========================================================================
|
||||
|
||||
Purpose : Make http callouts
|
||||
|
||||
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
|
||||
|
||||
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()
|
||||
|
||||
=========================================================================*/
|
||||
|
||||
c_success CONSTANT CHAR (1) := '1';
|
||||
c_fail CONSTANT CHAR (1) := '0';
|
||||
|
||||
-- version of this package
|
||||
version_c constant varchar2(20 char) := '2.6.2';
|
||||
|
||||
TYPE vc_arr_t IS TABLE OF VARCHAR2 (32767) INDEX BY BINARY_INTEGER;
|
||||
g_empty_vc_arr vc_arr_t;
|
||||
|
||||
/* 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
|
||||
);
|
||||
|
||||
/* Procedure: retrieve_blob_from_url
|
||||
|
||||
Multiplies two integers.
|
||||
|
||||
Parameters:
|
||||
|
||||
p_url - url to be called
|
||||
|
||||
o_blob - output: the resulting out blob
|
||||
o_mime_type - output: the resulting out mime type from the call
|
||||
|
||||
Returns:
|
||||
|
||||
The two integers multiplied together.
|
||||
o_blob - the resulting out blob
|
||||
|
||||
See Also:
|
||||
|
||||
<escape_form_data>
|
||||
*/
|
||||
PROCEDURE retrieve_blob_from_url (
|
||||
p_url VARCHAR2,
|
||||
o_blob OUT BLOB,
|
||||
o_mime_type OUT VARCHAR2
|
||||
);
|
||||
|
||||
/*
|
||||
Function: escape_form_data
|
||||
Here is some describing text ...
|
||||
|
||||
--- SQL
|
||||
declare
|
||||
l_i number;
|
||||
begin
|
||||
null;
|
||||
|
||||
Select count(*)
|
||||
into l_count
|
||||
from dual;
|
||||
end;
|
||||
---
|
||||
|
||||
|
||||
Parameters:
|
||||
s - string to be escaped
|
||||
|
||||
Returns:
|
||||
the escaped data
|
||||
*/
|
||||
FUNCTION escape_form_data (s VARCHAR2)
|
||||
RETURN VARCHAR2;
|
||||
|
||||
/*
|
||||
Function: check_get_request
|
||||
|
||||
Parameters:
|
||||
p_url the url to be called
|
||||
|
||||
Returns:
|
||||
Returns c_fail or c_success
|
||||
|
||||
*/
|
||||
FUNCTION check_get_request (p_url VARCHAR2)
|
||||
RETURN CHAR;
|
||||
|
||||
/*
|
||||
Function: check_acl
|
||||
|
||||
Parameters:
|
||||
p_url the url to be called
|
||||
|
||||
Returns:
|
||||
Returns c_fail or c_success
|
||||
*/
|
||||
FUNCTION check_acl (p_url VARCHAR2)
|
||||
RETURN CHAR;
|
||||
END;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
PACKAGE BODY "XLIB_HTTP"
|
||||
AS
|
||||
/*=========================================================================
|
||||
|
||||
Purpose : Make http callouts
|
||||
|
||||
License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de)
|
||||
Licensed under a BSD style license (license.txt)
|
||||
https://github.com/daust/JasperReportsIntegration
|
||||
|
||||
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()
|
||||
|
||||
=========================================================================*/
|
||||
|
||||
m_module VARCHAR2 (50) := 'XLIB_HTTP';
|
||||
|
||||
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();
|
||||
|
||||
-- Initialize the BLOB.
|
||||
DBMS_LOB.createtemporary (l_blob, FALSE);
|
||||
|
||||
l_http_request := UTL_HTTP.begin_request (url => p_url,
|
||||
method => 'GET',
|
||||
http_version => utl_http.http_version_1_0);
|
||||
|
||||
utl_http.set_header (l_http_request, 'Connection', 'Keep-Alive');
|
||||
|
||||
-- pass additional headers to the target service
|
||||
for i in 1..p_header_name_arr.count loop
|
||||
xlog(l_proc, 'pass additional headers to target service: '|| p_header_name_arr(i) ||': '||p_header_value_arr(i));
|
||||
utl_http.set_header(l_http_request, p_header_name_arr(i), p_header_value_arr(i));
|
||||
end loop;
|
||||
|
||||
-- get response from target service
|
||||
l_http_response := UTL_HTTP.get_response (l_http_request);
|
||||
|
||||
FOR i IN 1 .. UTL_HTTP.get_header_count (l_http_response)
|
||||
LOOP
|
||||
UTL_HTTP.get_header (l_http_response,
|
||||
i,
|
||||
l_header_name,
|
||||
l_header_value
|
||||
);
|
||||
-- store header value in arr
|
||||
l_header_name_arr (i) := l_header_name;
|
||||
l_header_value_arr (i) := l_header_value;
|
||||
|
||||
IF LOWER (l_header_name) = 'content-type'
|
||||
THEN
|
||||
l_mime_type := l_header_value;
|
||||
xlog(l_proc, 'content-type from server: ' || l_mime_type);
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
-- override mime type
|
||||
IF p_mime_type_override IS NOT NULL
|
||||
THEN
|
||||
l_mime_type := p_mime_type_override;
|
||||
END IF;
|
||||
|
||||
-- Copy the response into the BLOB.
|
||||
BEGIN
|
||||
LOOP
|
||||
UTL_HTTP.read_raw (l_http_response, l_raw, l_buffer_size);
|
||||
DBMS_LOB.writeappend (l_blob, UTL_RAW.LENGTH (l_raw), l_raw);
|
||||
END LOOP;
|
||||
EXCEPTION
|
||||
WHEN UTL_HTTP.end_of_body
|
||||
THEN
|
||||
UTL_HTTP.end_response (l_http_response);
|
||||
END;
|
||||
|
||||
xlog(l_proc, 'set content-type: ' || l_mime_type);
|
||||
OWA_UTIL.mime_header (ccontent_type => l_mime_type,
|
||||
bclose_header => FALSE,
|
||||
ccharset => p_charset
|
||||
);
|
||||
|
||||
FOR i IN 1 .. l_header_name_arr.COUNT
|
||||
LOOP
|
||||
IF UPPER (l_header_name_arr (i)) IN
|
||||
('CONTENT-LENGTH', 'CONTENT-TYPE', 'MIME-TYPE', 'TRANSFER-ENCODING',
|
||||
'STRICT-TRANSPORT-SECURITY', 'CACHE-CONTROL', 'PRAGMA', 'EXPIRES')
|
||||
THEN
|
||||
--xlog (l_proc, 'skip header ' || l_header_name_arr (i));
|
||||
null;
|
||||
ELSE
|
||||
if upper(l_header_name_arr(i)) = 'SET-COOKIE' and l_header_value_arr (i) like 'JSESSIONID%' then
|
||||
xlog(l_proc , 'JSESSION_ID found !!!:'||l_header_value_arr (i));
|
||||
--extract path
|
||||
l_jsession := regexp_substr(l_header_value_arr (i), 'JSESSIONID=(.*);[ ]*Path',1, 1,'i',1);
|
||||
l_path := regexp_substr(l_header_value_arr (i), ';[ ]*Path=(.*)',1, 1,'i',1);
|
||||
|
||||
xlog(l_proc, 'xx:full:'||l_header_value_arr (i)|| '; xx:session:'||l_jsession || '; xx:path:'||l_path);
|
||||
else
|
||||
l_header_value := l_header_value_arr (i);
|
||||
end if;
|
||||
xlog (l_proc,
|
||||
'set header:'
|
||||
|| l_header_name_arr (i)
|
||||
|| ': '
|
||||
|| l_header_value
|
||||
);
|
||||
HTP.p (l_header_name_arr (i) || ': ' || l_header_value);
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
-- JSESSION Cookies ausgeben
|
||||
-- if using tunnel, then the cookie is JRI_JSESSIONID
|
||||
-- if not using tunnel, then cookie is JSESSIONID directly
|
||||
--
|
||||
if xlib_jasperreports.get_use_images_no_tunnel=false then
|
||||
l_msg := 'Set-Cookie: ' || xlib_jasperreports.m_jri_cookie_name_c || '=' || l_jsession;
|
||||
xlog (l_proc, 'set header:' || l_msg );
|
||||
HTP.p (l_msg);
|
||||
l_msg := 'Set-Cookie: ' || xlib_jasperreports.m_jri_path_cookie_name_c || '=' || l_path;
|
||||
xlog (l_proc, 'set header:' || l_msg );
|
||||
HTP.p (l_msg);
|
||||
else
|
||||
l_msg := 'Set-Cookie: JSESSIONID=' || l_jsession;
|
||||
if xlib_jasperreports.get_cookie_path_no_tunnel is not null then
|
||||
l_msg := l_msg || '; Path=' || xlib_jasperreports.get_cookie_path_no_tunnel;
|
||||
end if;
|
||||
xlog (l_proc, 'set header:' || l_msg );
|
||||
HTP.p (l_msg);
|
||||
end if;
|
||||
|
||||
-- set content length
|
||||
HTP.p ('Content-length: ' || DBMS_LOB.getlength (l_blob));
|
||||
OWA_UTIL.http_header_close;
|
||||
WPG_DOCLOAD.download_file (l_blob);
|
||||
-- Relase the resources associated with the temporary LOB.
|
||||
DBMS_LOB.freetemporary (l_blob);
|
||||
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;
|
||||
|
||||
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 => p_url,
|
||||
method => 'GET',
|
||||
http_version => utl_http.http_version_1_0);
|
||||
|
||||
l_http_response := UTL_HTTP.get_response (l_http_request);
|
||||
|
||||
FOR i IN 1 .. UTL_HTTP.get_header_count (l_http_response)
|
||||
LOOP
|
||||
UTL_HTTP.get_header (l_http_response,
|
||||
i,
|
||||
l_header_name,
|
||||
l_header_value
|
||||
);
|
||||
|
||||
IF LOWER (l_header_name) = 'content-type'
|
||||
THEN
|
||||
o_mime_type := l_header_value;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
-- Copy the response into the BLOB.
|
||||
BEGIN
|
||||
LOOP
|
||||
UTL_HTTP.read_raw (l_http_response, l_raw, 32767);
|
||||
DBMS_LOB.writeappend (o_blob, UTL_RAW.LENGTH (l_raw), l_raw);
|
||||
END LOOP;
|
||||
EXCEPTION
|
||||
WHEN UTL_HTTP.end_of_body
|
||||
THEN
|
||||
UTL_HTTP.end_response (l_http_response);
|
||||
END;
|
||||
-- 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;
|
||||
|
||||
FUNCTION escape_form_data (s VARCHAR2)
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
l_s VARCHAR2 (500 CHAR);
|
||||
|
||||
FUNCTION r (s VARCHAR2, c VARCHAR2)
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
BEGIN
|
||||
RETURN REPLACE (s, c, '%' || TRIM (TO_CHAR (ASCII (c), 'XX')));
|
||||
END;
|
||||
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)); -- &
|
||||
l_s := r (l_s, chr(228)); -- <20><><EFBFBD>
|
||||
l_s := r (l_s, chr(196)); -- <20><>
|
||||
l_s := r (l_s, chr(246)); -- <20><>
|
||||
l_s := r (l_s, chr(214)); -- <20><>
|
||||
l_s := r (l_s, chr(252)); -- <20><>
|
||||
l_s := r (l_s, chr(220)); -- <20><><EFBFBD>
|
||||
l_s := r (l_s, chr(223)); -- <20><><EFBFBD>
|
||||
RETURN l_s;
|
||||
END;
|
||||
|
||||
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;
|
||||
|
||||
SELECT HTTPURITYPE (p_url).getclob ()
|
||||
INTO l_clob
|
||||
FROM DUAL;
|
||||
|
||||
/*SELECT c_success
|
||||
INTO l_ret
|
||||
FROM DUAL
|
||||
WHERE EXISTS (SELECT HTTPURITYPE (p_url).getclob ()
|
||||
FROM DUAL);
|
||||
*/
|
||||
RETURN c_success;
|
||||
EXCEPTION
|
||||
WHEN OTHERS
|
||||
THEN
|
||||
RETURN c_fail;
|
||||
END;
|
||||
|
||||
FUNCTION check_acl (p_url VARCHAR2)
|
||||
RETURN CHAR
|
||||
IS
|
||||
l_clob CLOB;
|
||||
BEGIN
|
||||
IF p_url IS NULL
|
||||
THEN
|
||||
RETURN c_fail;
|
||||
END IF;
|
||||
|
||||
SELECT HTTPURITYPE (p_url).getclob ()
|
||||
INTO l_clob
|
||||
FROM DUAL;
|
||||
|
||||
/*SELECT c_success
|
||||
INTO l_ret
|
||||
FROM DUAL
|
||||
WHERE EXISTS (SELECT HTTPURITYPE (p_url).getclob ()
|
||||
FROM DUAL);
|
||||
*/
|
||||
RETURN c_success;
|
||||
EXCEPTION
|
||||
WHEN OTHERS
|
||||
THEN
|
||||
-- acl problem
|
||||
if sqlcode=24247 then
|
||||
RETURN c_fail;
|
||||
else
|
||||
-- no acl problem
|
||||
return c_success;
|
||||
end if;
|
||||
END;
|
||||
END;```
|
||||
721
docs/packages/XLIB_JASPERREPORTS.md
Normal file
721
docs/packages/XLIB_JASPERREPORTS.md
Normal file
@@ -0,0 +1,721 @@
|
||||
# XLIB_JASPERREPORTS
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
PACKAGE "XLIB_JASPERREPORTS"
|
||||
AS
|
||||
/*=========================================================================
|
||||
Purpose :
|
||||
|
||||
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
|
||||
|
||||
$LastChangedDate: 2018-09-30 09:00:44 +0200 (So, 30 Sep 2018) $
|
||||
$LastChangedBy: dietmar.aust $
|
||||
|
||||
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
|
||||
|
||||
=========================================================================*/
|
||||
|
||||
-- version of this package
|
||||
version_c constant varchar2(20 char) := '2.6.2';
|
||||
|
||||
-- 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';
|
||||
|
||||
-- images uri
|
||||
--c_images_uri_tunnel constant varchar2(100 char)
|
||||
-- := 'xlib_jasperreports_img.get_image?p_url=#REPORT_URL#&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&p_flow_id=#APP_ID#&p_flow_step_id=0&p_instance=#APP_SESSION#&x01=#IMAGE_NAME#';
|
||||
c_images_uri_no_tunnel constant varchar2(500 char) := '#J2EE_CONTEXT_PATH#/report_image?image=#IMAGE_NAME#';
|
||||
|
||||
-- exceptions
|
||||
report_url_not_defined EXCEPTION;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- sets the url for the report server for all requests in the
|
||||
-- current session
|
||||
----------------------------------------------------------------------------
|
||||
PROCEDURE set_report_url (p_report_url IN VARCHAR2);
|
||||
|
||||
FUNCTION get_report_url
|
||||
RETURN VARCHAR2;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- set the image uri for html reports only!
|
||||
----------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
FUNCTION get_images_uri
|
||||
return varchar2;
|
||||
FUNCTION get_cookie_path_no_tunnel
|
||||
RETURN VARCHAR2;
|
||||
|
||||
|
||||
/** make a callout with utl_http to the j2ee container running the
|
||||
* JasperReportsIntegration web application
|
||||
* => 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&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 - <report name>
|
||||
*
|
||||
*/
|
||||
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
|
||||
);
|
||||
|
||||
/* tunnels images for html reports */
|
||||
procedure show_image(p_image_name IN VARCHAR2);
|
||||
|
||||
|
||||
/** 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&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 - <report name>
|
||||
*
|
||||
*/
|
||||
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
|
||||
);
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- get default configuration
|
||||
----------------------------------------------------------------------------
|
||||
FUNCTION get_default_configuration
|
||||
return xlib_jasperreports_conf%rowtype;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- set default configuration
|
||||
----------------------------------------------------------------------------
|
||||
PROCEDURE set_default_configuration(p_conf in out xlib_jasperreports_conf%rowtype);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
END;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
PACKAGE BODY "XLIB_JASPERREPORTS"
|
||||
AS
|
||||
/*=========================================================================
|
||||
Purpose :
|
||||
|
||||
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
|
||||
|
||||
$LastChangedDate: 2018-09-30 09:00:44 +0200 (So, 30 Sep 2018) $
|
||||
$LastChangedBy: dietmar.aust $
|
||||
|
||||
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
|
||||
|
||||
=========================================================================*/
|
||||
|
||||
|
||||
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;
|
||||
|
||||
-- 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;
|
||||
|
||||
procedure setup_configuration_defaults
|
||||
is
|
||||
l_conf xlib_jasperreports_conf%rowtype;
|
||||
l_timeout PLS_INTEGER;
|
||||
begin
|
||||
l_conf := get_default_configuration();
|
||||
|
||||
-- override report url if not defined
|
||||
if m_report_url is null then
|
||||
m_report_url := l_conf.conf_protocol || '://'||l_conf.conf_server||':'||l_conf.conf_port||'/'||l_conf.conf_context_path||'/report';
|
||||
xlog(p_module => m_module, p_msg => 'Override report url from defaults: '|| m_report_url, p_type=> 'DEBUG');
|
||||
end if;
|
||||
|
||||
-- set wallet path and pwd
|
||||
-- will ALWAYS override the settings, will ignore previous calls to set_wallet
|
||||
-- at least we check whether the config table has an entry for the wallet or not.
|
||||
-- thus it could work relying on the wallet set by APEX through the internal workspace! :)
|
||||
if lower(m_report_url) like 'https%' and l_conf.conf_wallet_path is not null then
|
||||
utl_http.set_wallet(l_conf.conf_wallet_path, l_conf.conf_wallet_pwd);
|
||||
xlog(p_module => m_module, p_msg => 'Override wallet location/pwd from defaults', p_type=> 'DEBUG');
|
||||
end if;
|
||||
|
||||
-- override http transfer timeout it not defined
|
||||
utl_http.get_transfer_timeout( timeout => l_timeout );
|
||||
--xlog(p_module => m_module, p_msg => 'Current setting of transfer_timeout: '||l_timeout, p_type=> 'DEBUG');
|
||||
if (l_timeout is null or l_timeout=60 /*60 is the default*/) then
|
||||
utl_http.set_transfer_timeout(l_conf.conf_http_transfer_timeout);
|
||||
xlog(p_module => m_module, p_msg => 'Override http transfer timeout ('||l_timeout||'s) from defaults: '|| l_conf.conf_http_transfer_timeout ||'s', p_type=> 'DEBUG');
|
||||
end if;
|
||||
|
||||
end;
|
||||
|
||||
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 => l_name_arr, vals => l_vals_arr, num_vals => l_vals_ret);
|
||||
|
||||
xlog (l_proc, '#num of cookies: ' || l_vals_ret);
|
||||
|
||||
FOR i IN 1 .. l_name_arr.COUNT
|
||||
LOOP
|
||||
xlog (l_proc, i || ':' || l_name_arr (i) || '=' || l_vals_arr (i));
|
||||
END LOOP;
|
||||
|
||||
xlog (l_proc, 'end');
|
||||
END;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- sets the url for the report server for all requests in the
|
||||
-- current session
|
||||
----------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
FUNCTION get_report_url
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
BEGIN
|
||||
RETURN m_report_url;
|
||||
END;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- sets the images_uri only for http reports!
|
||||
----------------------------------------------------------------------------
|
||||
PROCEDURE set_images_uri (p_images_uri IN VARCHAR2)
|
||||
IS
|
||||
BEGIN
|
||||
m_images_uri := p_images_uri;
|
||||
END;
|
||||
|
||||
/* use the images from the application server when both /ords and /jri are
|
||||
installed on the same application server
|
||||
|
||||
the p_server_uri parameter is rarely used, only when they are not run on the same application server
|
||||
and the uri differs. But that comes with a lot of CORS and other cookie issues.
|
||||
*/
|
||||
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;
|
||||
|
||||
-- the placeholders #J2EE_CONTEXT_PATH# and #IMAGE_NAME# will be replaced
|
||||
-- inside the J2EE application with the current values of the deployment
|
||||
set_images_uri( p_images_uri => p_server_uri || '#J2EE_CONTEXT_PATH#/report_image?image=#IMAGE_NAME#');
|
||||
end;
|
||||
|
||||
function get_use_images_no_tunnel return boolean
|
||||
is
|
||||
begin
|
||||
return m_use_images_no_tunnel;
|
||||
end;
|
||||
|
||||
FUNCTION get_cookie_path_no_tunnel
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
BEGIN
|
||||
RETURN m_cookie_path_no_tunnel;
|
||||
END;
|
||||
|
||||
|
||||
FUNCTION get_images_uri
|
||||
RETURN VARCHAR2
|
||||
IS
|
||||
BEGIN
|
||||
RETURN m_images_uri;
|
||||
END;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
c_images_uri_tunnel
|
||||
:='xlib_jasperreports_img.get_image?p_url=#REPORT_URL#&p_image=';
|
||||
*/
|
||||
|
||||
--l_uri := replace(l_uri, '#REPORT_URL#', APEX_UTIL.URL_ENCODE(m_report_url));
|
||||
--l_uri := replace(l_uri, '#REPORT_URL#', m_report_url);
|
||||
|
||||
-- c_images_uri_tunnel constant varchar2(100 char) := 'wwv_flow.show?p_request=APPLICATION_PROCESS%3DJRI_SHOW_IMAGE&p_flow_id=#APP_ID#&p_flow_step_id=0&p_instance=#APP_SESSION#&x01=#IMG_NAME#';
|
||||
l_uri := c_images_uri_tunnel;
|
||||
l_uri := REPLACE (l_uri, '#APP_ID#', v ('APP_ID'));
|
||||
l_uri := REPLACE (l_uri, '#APP_SESSION#', v ('APP_SESSION'));
|
||||
|
||||
xlog ('compute tunnel', l_uri);
|
||||
|
||||
RETURN l_uri;
|
||||
END;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- displays an image for html reports
|
||||
----------------------------------------------------------------------------
|
||||
PROCEDURE show_image (p_image_name IN VARCHAR2)
|
||||
IS
|
||||
l_proc VARCHAR2 (100) := m_module || '.show_image';
|
||||
l_url VARCHAR2 (32767);
|
||||
|
||||
l_header_name_arr xlib_http.vc_arr_t;
|
||||
l_header_value_arr xlib_http.vc_arr_t;
|
||||
|
||||
PROCEDURE get_headers_to_pass2j2ee (p_header_name_arr OUT xlib_http.vc_arr_t,
|
||||
p_header_value_arr OUT xlib_http.vc_arr_t)
|
||||
IS
|
||||
l_proc VARCHAR2 (100) := m_module || '.get_headers_to_pass2j2ee';
|
||||
jsession_cookie OWA_COOKIE.cookie;
|
||||
jsession_path_cookie OWA_COOKIE.cookie;
|
||||
BEGIN
|
||||
jsession_cookie := OWA_COOKIE.get (name => m_jri_cookie_name_c);
|
||||
jsession_path_cookie := OWA_COOKIE.get (name => m_jri_path_cookie_name_c);
|
||||
|
||||
xlog (l_proc, 'show jsession_id and path: ');
|
||||
xlog (l_proc, jsession_cookie.vals (1));
|
||||
xlog (l_proc, jsession_path_cookie.vals (1));
|
||||
|
||||
|
||||
p_header_name_arr (p_header_name_arr.COUNT + 1) := 'Cookie';
|
||||
p_header_value_arr (p_header_value_arr.COUNT + 1) :=
|
||||
'JSESSIONID=' || jsession_cookie.vals (1) || ';Path=' || jsession_path_cookie.vals (1);
|
||||
--xlog(l_proc, 'end');
|
||||
EXCEPTION
|
||||
WHEN OTHERS
|
||||
THEN
|
||||
xlog (l_proc, DBMS_UTILITY.format_error_backtrace, 'ERROR');
|
||||
END;
|
||||
BEGIN
|
||||
xlog (l_proc, 'start: ### SHOW IMAGE: ' || p_image_name);
|
||||
dump_all_cookies;
|
||||
|
||||
-- pick up defaults from table xlib_jasperreports_conf
|
||||
setup_configuration_defaults();
|
||||
|
||||
-------------------------------------------------------
|
||||
-- assert valid values for the input variables
|
||||
-------------------------------------------------------
|
||||
IF m_report_url IS NULL
|
||||
THEN
|
||||
RAISE report_url_not_defined;
|
||||
END IF;
|
||||
|
||||
-------------------------------------------------------
|
||||
-- construct URL
|
||||
-------------------------------------------------------
|
||||
-- _image?image=img_0_0_15&uuid=b41eb881-7ca5-4919-bd8f-5afa8d10b398
|
||||
l_url := m_report_url || '_image';
|
||||
l_url := l_url || '?image=' || p_image_name;
|
||||
l_url := l_url || '&JSESSIONID=' || OWA_COOKIE.get (name => m_jri_cookie_name_c).vals (1);
|
||||
|
||||
-------------------------------------------------------
|
||||
-- determine cookies for calling the j2ee server
|
||||
-- JSESSIONID needs to be passed, the path needs to
|
||||
-- be modified for the j2ee server context
|
||||
-------------------------------------------------------
|
||||
get_headers_to_pass2j2ee (p_header_name_arr => l_header_name_arr, p_header_value_arr => l_header_value_arr);
|
||||
|
||||
-------------------------------------------------------
|
||||
-- call J2EE server
|
||||
-------------------------------------------------------
|
||||
xlib_http.
|
||||
display_url_raw (p_url => l_url, p_header_name_arr => l_header_name_arr, p_header_value_arr => l_header_value_arr);
|
||||
END;
|
||||
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- make a callout with utl_http to the j2ee container running the
|
||||
-- JasperReportsIntegration webapp
|
||||
-- => return the results
|
||||
----------------------------------------------------------------------------
|
||||
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();
|
||||
|
||||
-------------------------------------------------------
|
||||
-- assert valid values for the input variables
|
||||
-------------------------------------------------------
|
||||
IF m_report_url IS NULL
|
||||
THEN
|
||||
xlog(p_module => m_module, p_msg => 'The report url is empty', p_type=> 'ERROR');
|
||||
|
||||
RAISE report_url_not_defined;
|
||||
END IF;
|
||||
|
||||
-------------------------------------------------------
|
||||
-- construct URL
|
||||
-------------------------------------------------------
|
||||
l_url := m_report_url;
|
||||
l_url := l_url || '?_repName=' || p_rep_name;
|
||||
l_url := l_url || '&_repFormat=' || p_rep_format;
|
||||
l_url := l_url || '&_dataSource=' || p_data_source;
|
||||
l_url := l_url || '&_outFilename=' || p_out_filename;
|
||||
l_url := l_url || '&_repLocale=' || p_rep_locale;
|
||||
l_url := l_url || '&_repEncoding=' || p_rep_encoding;
|
||||
l_url := l_url || '&_repTimeZone=' || APEX_UTIL.URL_ENCODE (p_rep_time_zone);
|
||||
|
||||
-- per default use the tunnel through the database
|
||||
IF m_images_uri IS NULL OR m_images_uri = c_images_uri_tunnel
|
||||
THEN
|
||||
-- tunnel through database
|
||||
l_url := l_url || '&_imagesURI=' || APEX_UTIL.URL_ENCODE (compute_images_uri_tunnel);
|
||||
ELSE
|
||||
-- use parameter, mostly for direct access to servlet
|
||||
l_url := l_url || '&_imagesURI=' || APEX_UTIL.URL_ENCODE (m_images_uri);
|
||||
END IF;
|
||||
|
||||
-- direct printing
|
||||
l_url := l_url || '&_printIsEnabled=' || bool2string (p_print_is_enabled);
|
||||
l_url := l_url || '&_printPrinterName=' || p_print_printer_name;
|
||||
l_url := l_url || '&_printPrinterTray=' || p_print_media;
|
||||
l_url := l_url || '&_printCopies=' || p_print_copies;
|
||||
l_url := l_url || '&_printDuplex=' || bool2string (p_print_duplex);
|
||||
l_url := l_url || '&_printCollate=' || bool2string (p_print_collate);
|
||||
l_url := l_url || '&_printJobName=' || p_print_job_name;
|
||||
|
||||
-- save file on server
|
||||
l_url := l_url || '&_saveIsEnabled=' || bool2string (p_save_is_enabled);
|
||||
l_url := l_url || '&_saveFileName=' || p_save_filename;
|
||||
|
||||
|
||||
/*
|
||||
Each additional parameter needs to be escaped using utl_url.escape()
|
||||
utl_url.escape(
|
||||
url => p_additional_params,
|
||||
escape_reserved_chars => true,
|
||||
url_charset => 'UTF-8'
|
||||
);
|
||||
*/
|
||||
|
||||
-- additional report parameter passed?
|
||||
IF (p_additional_params IS NOT NULL)
|
||||
THEN
|
||||
-- l_url := l_url || '&' || p_additional_params;
|
||||
l_url := l_url || '&' || utl_url.escape(
|
||||
url => p_additional_params,
|
||||
escape_reserved_chars => false,
|
||||
url_charset => 'UTF-8'
|
||||
);
|
||||
END IF;
|
||||
|
||||
-------------------------------------------------------
|
||||
-- call J2EE server
|
||||
-------------------------------------------------------
|
||||
xlib_http.display_url_raw (p_url => l_url);
|
||||
END;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- run the report and return the result as a blob
|
||||
----------------------------------------------------------------------------
|
||||
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();
|
||||
|
||||
-------------------------------------------------------
|
||||
-- assert valid values for the input variables
|
||||
-------------------------------------------------------
|
||||
IF m_report_url IS NULL
|
||||
THEN
|
||||
RAISE report_url_not_defined;
|
||||
END IF;
|
||||
|
||||
-------------------------------------------------------
|
||||
-- construct URL
|
||||
-------------------------------------------------------
|
||||
l_url := m_report_url;
|
||||
l_url := l_url || '?_repName=' || p_rep_name;
|
||||
l_url := l_url || '&_repFormat=' || p_rep_format;
|
||||
l_url := l_url || '&_dataSource=' || p_data_source;
|
||||
l_url := l_url || '&_repLocale=' || p_rep_locale;
|
||||
l_url := l_url || '&_repEncoding=' || p_rep_encoding;
|
||||
l_url := l_url || '&_repTimeZone=' || APEX_UTIL.URL_ENCODE (p_rep_time_zone);
|
||||
|
||||
-- per default use the tunnel through the database
|
||||
IF m_images_uri IS NULL OR m_images_uri = c_images_uri_tunnel
|
||||
THEN
|
||||
-- tunnel through database
|
||||
l_url := l_url || '&_imagesURI=' || APEX_UTIL.URL_ENCODE (compute_images_uri_tunnel);
|
||||
ELSE
|
||||
-- use parameter, mostly for direct access to servlet
|
||||
l_url := l_url || '&_imagesURI=' || APEX_UTIL.URL_ENCODE (m_images_uri);
|
||||
END IF;
|
||||
|
||||
-- direct printing
|
||||
l_url := l_url || '&_printIsEnabled=' || bool2string (p_print_is_enabled);
|
||||
l_url := l_url || '&_printPrinterName=' || p_print_printer_name;
|
||||
l_url := l_url || '&_printPrinterTray=' || p_print_media;
|
||||
l_url := l_url || '&_printCopies=' || p_print_copies;
|
||||
l_url := l_url || '&_printDuplex=' || bool2string (p_print_duplex);
|
||||
l_url := l_url || '&_printCollate=' || bool2string (p_print_collate);
|
||||
l_url := l_url || '&_printJobName=' || p_print_job_name;
|
||||
|
||||
-- save file on server
|
||||
l_url := l_url || '&_saveIsEnabled=' || bool2string (p_save_is_enabled);
|
||||
l_url := l_url || '&_saveFileName=' || p_save_filename;
|
||||
|
||||
-- additional report parameter passed?
|
||||
IF (p_additional_params IS NOT NULL)
|
||||
THEN
|
||||
-- l_url := l_url || '&' || p_additional_params;
|
||||
l_url := l_url || '&' || utl_url.escape(
|
||||
url => p_additional_params,
|
||||
escape_reserved_chars => false,
|
||||
url_charset => 'UTF-8'
|
||||
);
|
||||
END IF;
|
||||
|
||||
-------------------------------------------------------
|
||||
-- call Tomcat
|
||||
-------------------------------------------------------
|
||||
xlib_http.retrieve_blob_from_url (p_url => l_url, o_blob => p_out_blob, o_mime_type => p_out_mime_type);
|
||||
END;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- get default configuration
|
||||
----------------------------------------------------------------------------
|
||||
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';
|
||||
|
||||
RETURN l_conf;
|
||||
END;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- set default configuration
|
||||
----------------------------------------------------------------------------
|
||||
PROCEDURE set_default_configuration (p_conf IN OUT xlib_jasperreports_conf%ROWTYPE)
|
||||
IS
|
||||
BEGIN
|
||||
p_conf.conf_id := 'MAIN';
|
||||
|
||||
UPDATE xlib_jasperreports_conf
|
||||
SET row = p_conf
|
||||
WHERE conf_id = p_conf.conf_id;
|
||||
END;
|
||||
|
||||
|
||||
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;```
|
||||
63
docs/packages/XLIB_JASPERREPORTS_IMG.md
Normal file
63
docs/packages/XLIB_JASPERREPORTS_IMG.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# XLIB_JASPERREPORTS_IMG
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
PACKAGE XLIB_JASPERREPORTS_IMG AS
|
||||
/*
|
||||
$Id: xlib_jasperreports_img.pks 71 2017-10-15 16:25:51Z dietmar.aust $
|
||||
*/
|
||||
----------------------------------------------------------------------------
|
||||
-- get_image: retrieves a report image from the server
|
||||
----------------------------------------------------------------------------
|
||||
PROCEDURE get_image (p_url in varchar2, p_image IN VARCHAR2);
|
||||
|
||||
procedure test;
|
||||
|
||||
|
||||
END XLIB_JASPERREPORTS_IMG;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```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;
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- get_image: retrieves a report image from the server
|
||||
----------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
-------------------------------------------------------
|
||||
-- construct URL
|
||||
-------------------------------------------------------
|
||||
l_url := p_url;
|
||||
-- use image servlet
|
||||
l_url := l_url || '_image?image=' || p_image;
|
||||
-- use images directory /report_tmp/
|
||||
--l_url := l_url || '_tmp/' || p_image;
|
||||
|
||||
-------------------------------------------------------
|
||||
-- call J2EE server
|
||||
-------------------------------------------------------
|
||||
xlog(l_proc, l_url);
|
||||
xlib_http.display_url_raw (p_url => l_url);
|
||||
|
||||
end;
|
||||
|
||||
procedure test
|
||||
is
|
||||
begin
|
||||
htp.p('test');
|
||||
end;
|
||||
|
||||
|
||||
END XLIB_JASPERREPORTS_IMG;```
|
||||
58
docs/packages/XLIB_LOG.md
Normal file
58
docs/packages/XLIB_LOG.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# XLIB_LOG
|
||||
|
||||
## Package Specification
|
||||
|
||||
```sql
|
||||
PACKAGE "XLIB_LOG"
|
||||
IS
|
||||
/*=========================================================================
|
||||
|
||||
Purpose : Application Logging
|
||||
|
||||
License : Copyright (c) 2010 Dietmar Aust (opal-consulting.de)
|
||||
Licensed under a BSD style license (license.txt)
|
||||
https://github.com/daust/JasperReportsIntegration
|
||||
|
||||
Date Author Comment
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
06.01.2010 D. Aust Initial creation
|
||||
13.05.2012 D. Aust insert fails when created_by user value too large
|
||||
|
||||
=========================================================================*/
|
||||
|
||||
PROCEDURE m (
|
||||
p_module IN VARCHAR2,
|
||||
p_msg IN VARCHAR2,
|
||||
p_type IN VARCHAR2 DEFAULT 'DEBUG',
|
||||
p_level PLS_INTEGER DEFAULT 15
|
||||
);
|
||||
END;```
|
||||
|
||||
## Package Body
|
||||
|
||||
```sql
|
||||
PACKAGE BODY "XLIB_LOG"
|
||||
IS
|
||||
|
||||
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;```
|
||||
419
docs/procedures/EVENTI_AGGIORNA_QTA_LISTA.md
Normal file
419
docs/procedures/EVENTI_AGGIORNA_QTA_LISTA.md
Normal file
@@ -0,0 +1,419 @@
|
||||
# EVENTI_AGGIORNA_QTA_LISTA
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
PROCEDURE "EVENTI_AGGIORNA_QTA_LISTA" (
|
||||
p_id_evento NUMBER
|
||||
) AS
|
||||
-- ricalcola tutte le qta della lista
|
||||
|
||||
v_cod_art VARCHAR2(10);
|
||||
v_coeff_a NUMBER;
|
||||
v_coeff_s NUMBER;
|
||||
v_coeff_b NUMBER;
|
||||
v_ospiti NUMBER;
|
||||
v_qta_a NUMBER;
|
||||
v_qta_s NUMBER;
|
||||
v_qta_b NUMBER;
|
||||
v_qta_std_a NUMBER;
|
||||
v_qta_std_s NUMBER;
|
||||
v_qta_std_b NUMBER;
|
||||
v_count_tov NUMBER;
|
||||
v_count_tov_buf NUMBER;
|
||||
v_qta_giac NUMBER;
|
||||
v_qta_imp NUMBER;
|
||||
v_data_evt DATE;
|
||||
v_qta_man VARCHAR2(100);
|
||||
BEGIN
|
||||
|
||||
-- Daniele Viti
|
||||
-- Scorre tutti gli articoli dell'evento
|
||||
---------
|
||||
FOR c IN (
|
||||
SELECT DISTINCT
|
||||
cod_articolo
|
||||
FROM
|
||||
eventi_det_prel
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
) LOOP
|
||||
BEGIN
|
||||
|
||||
--default su qta:
|
||||
|
||||
--verifica qta standard
|
||||
SELECT
|
||||
nvl(qta_std_a, 0),
|
||||
nvl(qta_std_s, 0),
|
||||
nvl(qta_std_b, 0)
|
||||
INTO
|
||||
v_qta_std_a,
|
||||
v_qta_std_s,
|
||||
v_qta_std_b
|
||||
FROM
|
||||
articoli
|
||||
WHERE
|
||||
cod_articolo = c.cod_articolo;
|
||||
|
||||
IF v_qta_std_a > 0 OR v_qta_std_s > 0 OR v_qta_std_b > 0 THEN
|
||||
UPDATE eventi_det_prel
|
||||
SET
|
||||
qta_ape = v_qta_std_a,
|
||||
qta_sedu = v_qta_std_s,
|
||||
qta_bufdol = v_qta_std_b,
|
||||
qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND cod_articolo = c.cod_articolo;
|
||||
|
||||
COMMIT;
|
||||
CONTINUE; -- se esistono le qta standard aggiorna e passa il giro successivo!
|
||||
|
||||
END IF;
|
||||
|
||||
SELECT
|
||||
cod_relativo
|
||||
INTO v_cod_art
|
||||
FROM
|
||||
articoli
|
||||
WHERE
|
||||
cod_articolo = c.cod_articolo;
|
||||
|
||||
IF v_cod_art IS NULL THEN
|
||||
--Articolo Relativo assente
|
||||
|
||||
--verifica se cod_articolo è di tipo TOVAGLE O CARAFFE etc...
|
||||
SELECT
|
||||
COUNT(*)
|
||||
INTO v_count_tov
|
||||
FROM
|
||||
articoli a
|
||||
JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ
|
||||
JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo
|
||||
WHERE
|
||||
( c.cod_tipo IN ( 'CA-CARAFFE' )
|
||||
-- or c.COD_CATEG in ('TOV-BUFF','TOV-SED')
|
||||
OR c.cod_categ IN ( 'TOV-SED' ) )
|
||||
AND a.cod_articolo = c.cod_articolo;
|
||||
|
||||
--verifica se cod_articolo è di tipo TOVAGLE BUFFET
|
||||
SELECT
|
||||
COUNT(*)
|
||||
INTO v_count_tov_buf
|
||||
FROM
|
||||
articoli a
|
||||
JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ
|
||||
JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo
|
||||
WHERE
|
||||
c.cod_categ IN ( 'TOV-BUFF' )
|
||||
AND a.cod_articolo = c.cod_articolo; -- 'CM-DANI'
|
||||
|
||||
IF v_count_tov > 0 THEN
|
||||
--c.COD_ARTICOLO è di tipo TOVAGLE O CARAFFE etc...
|
||||
|
||||
-- reperisco le qta tot inserita per i tavoli
|
||||
SELECT
|
||||
nvl(SUM(qta_ape),
|
||||
0),
|
||||
nvl(SUM(qta_sedu),
|
||||
0),
|
||||
nvl(SUM(qta_bufdol),
|
||||
0)
|
||||
INTO
|
||||
v_qta_a,
|
||||
v_qta_s,
|
||||
v_qta_b
|
||||
FROM
|
||||
eventi_det_prel e
|
||||
JOIN articoli a ON e.cod_articolo = a.cod_articolo
|
||||
JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ
|
||||
JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND c.cod_tipo IN ( 'TA' );
|
||||
|
||||
--recupero il coefficente dell'atricolo (tovagliato o caraffe) e lo moltiplico x la qta tavoli
|
||||
SELECT
|
||||
nvl(coeff_a, 0),
|
||||
nvl(coeff_s, 0),
|
||||
nvl(coeff_b, 0)
|
||||
INTO
|
||||
v_coeff_a,
|
||||
v_coeff_s,
|
||||
v_coeff_b
|
||||
FROM
|
||||
articoli
|
||||
WHERE
|
||||
cod_articolo = c.cod_articolo;
|
||||
|
||||
UPDATE eventi_det_prel
|
||||
SET
|
||||
qta_ape = v_qta_a * v_coeff_a,
|
||||
qta_sedu = v_qta_s * v_coeff_s,
|
||||
qta_bufdol = v_qta_b * v_coeff_b,
|
||||
qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND cod_articolo = c.cod_articolo;
|
||||
|
||||
COMMIT;
|
||||
ELSIF v_count_tov_buf > 0 THEN
|
||||
--c.COD_ARTICOLO è di tipo TOVAGLE BUFFET
|
||||
|
||||
-- reperisco le qta tot inserita per gli angoli buffet
|
||||
SELECT
|
||||
nvl(SUM(qta_ape),
|
||||
0),
|
||||
nvl(SUM(qta_sedu),
|
||||
0),
|
||||
nvl(SUM(qta_bufdol),
|
||||
0)
|
||||
INTO
|
||||
v_qta_a,
|
||||
v_qta_s,
|
||||
v_qta_b
|
||||
FROM
|
||||
eventi_det_prel e
|
||||
JOIN articoli a ON e.cod_articolo = a.cod_articolo
|
||||
JOIN tb_codici_categ c ON a.cod_categ = c.cod_categ
|
||||
JOIN tb_tipi_mat t ON c.cod_tipo = t.cod_tipo
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND c.cod_tipo IN ( 'AN' );
|
||||
|
||||
--recupero il coefficente dell'atricolo (tovagliato buffet) e lo moltiplico x la qta angoli
|
||||
SELECT
|
||||
nvl(coeff_a, 0),
|
||||
nvl(coeff_s, 0),
|
||||
nvl(coeff_b, 0)
|
||||
INTO
|
||||
v_coeff_a,
|
||||
v_coeff_s,
|
||||
v_coeff_b
|
||||
FROM
|
||||
articoli
|
||||
WHERE
|
||||
cod_articolo = c.cod_articolo;
|
||||
|
||||
UPDATE eventi_det_prel
|
||||
SET
|
||||
qta_ape = v_qta_a * v_coeff_a,
|
||||
qta_sedu = v_qta_s * v_coeff_s,
|
||||
qta_bufdol = v_qta_b * v_coeff_b,
|
||||
qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND cod_articolo = c.cod_articolo;
|
||||
|
||||
COMMIT;
|
||||
ELSE
|
||||
BEGIN
|
||||
v_cod_art := c.cod_articolo;
|
||||
SELECT
|
||||
nvl(coeff_a, 0),
|
||||
nvl(coeff_s, 0),
|
||||
nvl(coeff_b, 0)
|
||||
INTO
|
||||
v_coeff_a,
|
||||
v_coeff_s,
|
||||
v_coeff_b
|
||||
FROM
|
||||
articoli
|
||||
WHERE
|
||||
cod_articolo = v_cod_art;
|
||||
|
||||
SELECT
|
||||
nvl(tot_ospiti, 0)
|
||||
INTO v_ospiti
|
||||
FROM
|
||||
eventi
|
||||
WHERE
|
||||
id = p_id_evento;
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
raise_application_error(-20001, 'Errore: Coefficenti/Num Ospiti NON TROVATI - '
|
||||
|| sqlcode
|
||||
|| ' - '
|
||||
|| substr(sqlerrm, 1, 64));
|
||||
END;
|
||||
|
||||
UPDATE eventi_det_prel
|
||||
SET
|
||||
qta_ape = trunc(v_coeff_a * v_ospiti),
|
||||
qta_sedu = trunc(v_coeff_s * v_ospiti),
|
||||
qta_bufdol = trunc(v_coeff_b * v_ospiti),
|
||||
qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND cod_articolo = c.cod_articolo;
|
||||
|
||||
COMMIT;
|
||||
END IF;
|
||||
|
||||
ELSE
|
||||
-- cod relativo valorizzato
|
||||
BEGIN
|
||||
-- reperisco le qta inserite per il cod_relativo nella lista
|
||||
SELECT
|
||||
nvl(qta_ape, 0),
|
||||
nvl(qta_sedu, 0),
|
||||
nvl(qta_bufdol, 0)
|
||||
INTO
|
||||
v_qta_a,
|
||||
v_qta_s,
|
||||
v_qta_b
|
||||
FROM
|
||||
eventi_det_prel
|
||||
WHERE
|
||||
cod_articolo = v_cod_art
|
||||
AND id_evento = p_id_evento;
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
CONTINUE;
|
||||
-- Disattivato temporaneamente per evitare spam
|
||||
--RAISE_APPLICATION_ERROR(-20000, 'Errore: Qta NON TROVATA !!! - v_cod_art: ' || v_cod_art || ' - ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64));
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
-- reperisco i coefficenti
|
||||
SELECT
|
||||
nvl(coeff_a, 0),
|
||||
nvl(coeff_s, 0),
|
||||
nvl(coeff_b, 0)
|
||||
INTO
|
||||
v_coeff_a,
|
||||
v_coeff_s,
|
||||
v_coeff_b
|
||||
FROM
|
||||
articoli
|
||||
WHERE
|
||||
cod_articolo = c.cod_articolo;
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
raise_application_error(-20001, 'Errore: Qta/Coefficenti del codice relativo NON TROVATI - '
|
||||
|| sqlcode
|
||||
|| ' - '
|
||||
|| substr(sqlerrm, 1, 64));
|
||||
END;
|
||||
|
||||
UPDATE eventi_det_prel
|
||||
SET
|
||||
qta_ape = trunc(v_coeff_a * v_qta_a),
|
||||
qta_sedu = trunc(v_coeff_s * v_qta_s),
|
||||
qta_bufdol = trunc(v_coeff_b * v_qta_b),
|
||||
qta = qta_ape + qta_sedu + qta_bufdol + qta_man_ape + qta_man_sedu + qta_man_bufdol
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND cod_articolo = c.cod_articolo;
|
||||
|
||||
COMMIT;
|
||||
END IF;
|
||||
|
||||
-- NOTE SE SUPERO LA QTA DISPONBILE !!!
|
||||
BEGIN
|
||||
SELECT
|
||||
data
|
||||
INTO v_data_evt
|
||||
FROM
|
||||
eventi
|
||||
WHERE
|
||||
id = p_id_evento;
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
raise_application_error(-20001, 'v_data_evento - '
|
||||
|| v_data_evt
|
||||
|| ' - '
|
||||
|| sqlcode
|
||||
|| ' - '
|
||||
|| substr(sqlerrm, 1, 64));
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
SELECT
|
||||
qta_giac
|
||||
INTO v_qta_giac
|
||||
FROM
|
||||
articoli
|
||||
WHERE
|
||||
cod_articolo = c.cod_articolo;
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
raise_application_error(-20001, 'v_qta_giac - '
|
||||
|| v_qta_giac
|
||||
|| ' - '
|
||||
|| sqlcode
|
||||
|| ' - '
|
||||
|| substr(sqlerrm, 1, 64));
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
SELECT
|
||||
nvl(f_get_qta_impegnata(c.cod_articolo, v_data_evt),
|
||||
0)
|
||||
INTO v_qta_imp
|
||||
FROM
|
||||
dual;
|
||||
|
||||
EXCEPTION
|
||||
WHEN no_data_found THEN
|
||||
raise_application_error(-20001, 'v_qta_imp - '
|
||||
|| v_qta_imp
|
||||
|| ' - '
|
||||
|| v_cod_art
|
||||
|| ', '
|
||||
|| v_data_evt
|
||||
|| ' - '
|
||||
|| sqlcode
|
||||
|| ' - '
|
||||
|| substr(sqlerrm, 1, 64));
|
||||
END;
|
||||
|
||||
--RAISE_APPLICATION_ERROR(-20000, 'v_qta_giac - ' || v_qta_giac || ' - ' || SQLCODE || ' - ' || SUBSTR(SQLERRM, 1 , 64));
|
||||
dbms_output.put_line('CodArt: '
|
||||
|| c.cod_articolo
|
||||
|| '; Qta Imp: '
|
||||
|| v_qta_imp
|
||||
|| '; Qta Giac: '
|
||||
|| v_qta_giac);
|
||||
--NOTA: a differenza del trigger "BEFORE INSERT ON EVENTI_DET_PREL",
|
||||
-- in questo caso la qta_imp è già comprensiva della qta ricalcolata
|
||||
IF v_qta_imp > v_qta_giac THEN
|
||||
v_qta_man := v_qta_imp - v_qta_giac;
|
||||
--:NEW.NOTE := 'QTA TOT NON Disponibile, mancano: ' || to_char(v_qta_man);
|
||||
UPDATE eventi_det_prel
|
||||
SET
|
||||
note = 'QTA TOT NON Disponibile, mancano: ' || to_char(v_qta_man)
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND cod_articolo = c.cod_articolo;
|
||||
|
||||
COMMIT;
|
||||
ELSE
|
||||
UPDATE eventi_det_prel
|
||||
SET
|
||||
note = NULL
|
||||
WHERE
|
||||
id_evento = p_id_evento
|
||||
AND cod_articolo = c.cod_articolo
|
||||
AND note LIKE '%QTA TOT NON Disponibile%';
|
||||
|
||||
COMMIT;
|
||||
END IF;
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
raise_application_error(-20001, 'Errore: '
|
||||
|| sqlcode
|
||||
|| ' - '
|
||||
|| substr(sqlerrm, 1, 64));
|
||||
END;
|
||||
END LOOP;
|
||||
|
||||
RETURN;
|
||||
END eventi_aggiorna_qta_lista;```
|
||||
45
docs/procedures/EVENTI_AGGIORNA_TOT_OSPITI.md
Normal file
45
docs/procedures/EVENTI_AGGIORNA_TOT_OSPITI.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# EVENTI_AGGIORNA_TOT_OSPITI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
PROCEDURE "EVENTI_AGGIORNA_TOT_OSPITI" (
|
||||
p_id_evento IN NUMBER DEFAULT 0
|
||||
) AS
|
||||
--aggiorna la qta toto ospiti
|
||||
--job aggiorna_tot_ospiti
|
||||
|
||||
CURSOR c_eventi IS
|
||||
SELECT
|
||||
id
|
||||
FROM
|
||||
eventi
|
||||
WHERE
|
||||
id = p_id_evento;
|
||||
|
||||
v_tot_ospiti NUMBER;
|
||||
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;
|
||||
|
||||
COMMIT;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
raise_application_error(-20000, 'Errore nel calcolo del totale ospiti: '
|
||||
|| sqlcode
|
||||
|| ' - '
|
||||
|| sqlerrm);
|
||||
END;
|
||||
|
||||
-- end loop;
|
||||
|
||||
END eventi_aggiorna_tot_ospiti;```
|
||||
214
docs/procedures/EVENTI_COPIA.md
Normal file
214
docs/procedures/EVENTI_COPIA.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# EVENTI_COPIA
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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;
|
||||
|
||||
r_evento.id := NULL;
|
||||
r_evento.is_template := 0;
|
||||
IF nuova_versione = 1 THEN
|
||||
r_evento.id_evt_padre := id_evento_old;
|
||||
r_evento.vers_number := nvl(r_evento.vers_number, 0) + 1; -- aggiorno il numero versione
|
||||
ELSE
|
||||
r_evento.id_evt_padre := NULL;
|
||||
r_evento.vers_number := 0;
|
||||
END IF;
|
||||
|
||||
-- Copio l'evento facendo creare il nuovo id dal trigger
|
||||
INSERT INTO eventi VALUES r_evento RETURNING id INTO v_new_evt_id;
|
||||
|
||||
IF nuova_versione = 1 THEN
|
||||
-- Aggiorno il vecchio evento col nuovo id
|
||||
UPDATE eventi
|
||||
SET
|
||||
id_evt_figlio = v_new_evt_id
|
||||
WHERE
|
||||
id = id_evento_old;
|
||||
|
||||
END IF;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Aggiungo i figli alla nuova versione
|
||||
-- Degustazioni
|
||||
INSERT INTO eventi_det_degust (
|
||||
id_evento,
|
||||
data,
|
||||
ora,
|
||||
nome,
|
||||
telefono,
|
||||
email,
|
||||
location,
|
||||
n_persone,
|
||||
menu,
|
||||
n_paganti,
|
||||
note,
|
||||
n_degustazione,
|
||||
consumata,
|
||||
costo_degustazione
|
||||
)
|
||||
SELECT
|
||||
v_new_evt_id,
|
||||
data,
|
||||
ora,
|
||||
nome,
|
||||
telefono,
|
||||
email,
|
||||
location,
|
||||
n_persone,
|
||||
menu,
|
||||
n_paganti,
|
||||
note,
|
||||
n_degustazione,
|
||||
consumata,
|
||||
costo_degustazione
|
||||
FROM
|
||||
eventi_det_degust
|
||||
WHERE
|
||||
id_evento = id_evento_old;
|
||||
|
||||
-- Ospiti
|
||||
-- Devo fare una update... DIO TRIGGER
|
||||
FOR c IN (
|
||||
SELECT
|
||||
id_evento,
|
||||
cod_tipo_ospite,
|
||||
numero,
|
||||
note
|
||||
FROM
|
||||
eventi_det_ospiti
|
||||
WHERE
|
||||
id_evento = id_evento_old
|
||||
) LOOP
|
||||
UPDATE eventi_det_ospiti
|
||||
SET
|
||||
numero = c.numero,
|
||||
note = c.note
|
||||
WHERE
|
||||
id_evento = v_new_evt_id
|
||||
AND cod_tipo_ospite = c.cod_tipo_ospite;
|
||||
|
||||
END LOOP;
|
||||
-- insert into eventi_det_ospiti (ID_EVENTO, COD_TIPO_OSPITE, NUMERO, NOTE)
|
||||
-- select v_new_evt_id, COD_TIPO_OSPITE, NUMERO, NOTE
|
||||
-- from eventi_det_ospiti
|
||||
-- where id_evento = ID_EVENTO_OLD;
|
||||
|
||||
-- Prelievi
|
||||
/* COME DA RICHIESTA DEL 01/2024 NON COPIO LA LISTA PRELIEVO NELLA NUOVA VERSIONE */
|
||||
/* RIATTIVO NUOVAMENTE LA COPIA IL 12/02/2024 */
|
||||
INSERT INTO eventi_det_prel (
|
||||
id_evento,
|
||||
cod_articolo,
|
||||
qta,
|
||||
note,
|
||||
qta_ape,
|
||||
qta_sedu,
|
||||
qta_bufdol,
|
||||
qta_man_ape,
|
||||
qta_man_sedu,
|
||||
qta_man_bufdol,
|
||||
costo_articolo
|
||||
)
|
||||
SELECT
|
||||
v_new_evt_id,
|
||||
cod_articolo,
|
||||
qta,
|
||||
note,
|
||||
qta_ape,
|
||||
qta_sedu,
|
||||
qta_bufdol,
|
||||
qta_man_ape,
|
||||
qta_man_sedu,
|
||||
qta_man_bufdol,
|
||||
costo_articolo
|
||||
FROM
|
||||
eventi_det_prel
|
||||
WHERE
|
||||
id_evento = id_evento_old;
|
||||
|
||||
-- Risorse
|
||||
INSERT INTO eventi_det_ris (
|
||||
id_evento,
|
||||
id_risorsa,
|
||||
ore_lav,
|
||||
costo,
|
||||
note
|
||||
)
|
||||
SELECT
|
||||
v_new_evt_id,
|
||||
id_risorsa,
|
||||
ore_lav,
|
||||
costo,
|
||||
note
|
||||
FROM
|
||||
eventi_det_ris
|
||||
WHERE
|
||||
id_evento = id_evento_old;
|
||||
|
||||
-- Costi
|
||||
INSERT INTO eventi_acconti (
|
||||
data,
|
||||
acconto,
|
||||
id_evento,
|
||||
a_conferma,
|
||||
ordine,
|
||||
descrizione
|
||||
)
|
||||
SELECT
|
||||
data,
|
||||
acconto,
|
||||
v_new_evt_id,
|
||||
a_conferma,
|
||||
ordine,
|
||||
descrizione
|
||||
FROM
|
||||
eventi_acconti
|
||||
WHERE
|
||||
id_evento = id_evento_old;
|
||||
|
||||
-- Altri Costi
|
||||
INSERT INTO eventi_altricosti (
|
||||
id_evento,
|
||||
descrizione,
|
||||
costo,
|
||||
quantity
|
||||
)
|
||||
SELECT
|
||||
v_new_evt_id,
|
||||
descrizione,
|
||||
costo,
|
||||
quantity
|
||||
FROM
|
||||
eventi_altricosti
|
||||
WHERE
|
||||
id_evento = id_evento_old;
|
||||
|
||||
-- Carico il nuovo id nella pagina
|
||||
id_evento_new := v_new_evt_id;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
DELETE FROM eventi
|
||||
WHERE
|
||||
id = v_new_evt_id;
|
||||
|
||||
COMMIT;
|
||||
raise_application_error(-20001, sqlcode
|
||||
|| ' - '
|
||||
|| sqlerrm);
|
||||
END eventi_copia;```
|
||||
205
docs/procedures/EVENTI_RICALCOLA_ACCONTI.md
Normal file
205
docs/procedures/EVENTI_RICALCOLA_ACCONTI.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# EVENTI_RICALCOLA_ACCONTI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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
|
||||
|
||||
select count(*)
|
||||
into v_cnt
|
||||
from eventi_acconti
|
||||
where id_evento = p_event_id
|
||||
and "DATA" is not null;
|
||||
/*
|
||||
if v_cnt > 0 then
|
||||
raise_application_error(-20001, 'Impossibile ricalcolare gli acconti per un evento già 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;
|
||||
|
||||
if v_cnt > 0 then
|
||||
v_calc_only_saldo := 1;
|
||||
end if;
|
||||
|
||||
select sum(costo_ivato)
|
||||
into v_totale_tipi
|
||||
from get_costo_tipi_evt
|
||||
where id_evento = p_event_id;
|
||||
|
||||
select sum(costo)
|
||||
into v_totale_degus
|
||||
from get_costo_degus_evt
|
||||
where id_evento = p_event_id;
|
||||
|
||||
select sum(costo)
|
||||
into v_totale_ris
|
||||
from get_costo_ris_evt
|
||||
where id_evento = p_event_id;
|
||||
|
||||
select sum(costo+costo*0.10)
|
||||
into v_totale_ospiti
|
||||
from get_costo_ospiti_evt
|
||||
where id_evento = p_event_id;
|
||||
|
||||
select sum((costo * quantity)+(case when costo > 0 then costo * quantity * 0.10 else 0 end))
|
||||
into v_totale_altricosti
|
||||
from eventi_altricosti
|
||||
where id_evento = p_event_id;
|
||||
|
||||
v_totale_evento :=
|
||||
nvl(v_totale_tipi, 0) -
|
||||
nvl(v_totale_degus, 0) +
|
||||
nvl(v_totale_ris, 0) +
|
||||
nvl(v_totale_ospiti, 0) +
|
||||
nvl(v_totale_altricosti, 0);
|
||||
|
||||
if v_calc_only_saldo = 0 then
|
||||
-- Se nessun acconto è stato pagato allora ricalcola tutti gli acconti
|
||||
delete
|
||||
from eventi_acconti
|
||||
where id_evento = p_event_id
|
||||
and ordine in (10, 20, 30);
|
||||
|
||||
insert into eventi_acconti
|
||||
(DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)
|
||||
values
|
||||
('PRIMA CAPARRA (art.7 punto A del contratto) a conferma evento nella cifra di euro:',
|
||||
v_totale_evento * v_prima_perc, p_event_id, 1, 10);
|
||||
|
||||
insert into eventi_acconti
|
||||
(DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)
|
||||
values
|
||||
('SECONDA CAPARRA (art. 7 punto B - circa 60 giorni prima dell''evento) nella cifra di euro:',
|
||||
v_totale_evento * v_seconda_perc, p_event_id, 0, 20);
|
||||
|
||||
insert into eventi_acconti
|
||||
(DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)
|
||||
values
|
||||
('SALDO A RICEVIMENTO CONSUNTIVO (art.7 punto c del contratto) 5 giorni prima dell''evento',
|
||||
v_totale_evento * v_terza_perc, p_event_id, 0, 30);
|
||||
|
||||
else
|
||||
-- Controllo se gli acconti sono stato pagati e in caso ricalcolo soltanto i saldi
|
||||
begin
|
||||
select acconto
|
||||
into v_primo_acconto
|
||||
from eventi_acconti
|
||||
where id_evento = p_event_id
|
||||
and ORDINE = 10
|
||||
and data is not null; -- Il primo acconto è stato pagato
|
||||
exception when no_data_found then
|
||||
v_primo_acconto := 0;
|
||||
end;
|
||||
|
||||
begin
|
||||
select acconto
|
||||
into v_secondo_acconto
|
||||
from eventi_acconti
|
||||
where id_evento = p_event_id
|
||||
and ORDINE = 20
|
||||
and data is not null; -- Il secondo acconto è stato pagato
|
||||
exception when no_data_found then
|
||||
v_secondo_acconto := 0;
|
||||
end;
|
||||
|
||||
begin
|
||||
select acconto
|
||||
into v_terzo_acconto
|
||||
from eventi_acconti
|
||||
where id_evento = p_event_id
|
||||
and ORDINE = 30
|
||||
and data is not null; -- Il terzo acconto è stato pagato
|
||||
exception when no_data_found then
|
||||
v_terzo_acconto := 0;
|
||||
end;
|
||||
|
||||
-- Se non hanno pagato il primo acconto lo calcolo in automatico
|
||||
if v_primo_acconto = 0 then
|
||||
v_primo_acconto := v_totale_evento * v_prima_perc;
|
||||
end if;
|
||||
|
||||
-- Ricalcolo la percentuale del secondo acconto in base al primo se non è stato pagato
|
||||
if v_secondo_acconto = 0 then
|
||||
v_secondo_acconto := (v_totale_evento - v_primo_acconto) * (v_seconda_perc/(v_seconda_perc + v_terza_perc));
|
||||
end if;
|
||||
|
||||
-- Calcolo il terzo acconto come la rimanenza tra il totale e il primo + secondo se non è stato pagato
|
||||
if v_terzo_acconto = 0 then
|
||||
v_terzo_acconto := v_totale_evento - (v_primo_acconto + v_secondo_acconto);
|
||||
end if;
|
||||
|
||||
-- Controllo se i totali acconti superano il totale dell'evento
|
||||
if v_primo_acconto > v_totale_evento then
|
||||
raise_application_error(-20001, 'Attenzione! Il primo acconto supera il costo totale del''evento');
|
||||
end if;
|
||||
|
||||
if v_primo_acconto + v_secondo_acconto > v_totale_evento then
|
||||
raise_application_error(-20001, 'Attenzione! Il primo e il secondo acconto superano il costo totale del''evento');
|
||||
end if;
|
||||
|
||||
if v_primo_acconto + v_secondo_acconto + v_terzo_acconto > v_totale_evento then
|
||||
raise_application_error(-20001, 'Attenzione! Gli acconti superano il costo totale del''evento');
|
||||
end if;
|
||||
|
||||
-- Se gli acconti successivi sono validi allora li aggiorno, se l'acconto precendente salda tutto li elimino
|
||||
if v_secondo_acconto > 0 then
|
||||
update eventi_acconti
|
||||
set ACCONTO = v_secondo_acconto
|
||||
where id_evento = p_event_id
|
||||
and ordine = 20;
|
||||
|
||||
if SQL%ROWCOUNT = 0 then
|
||||
insert into eventi_acconti
|
||||
(DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)
|
||||
values
|
||||
('SECONDA CAPARRA (art. 7 punto B - circa 60 giorni prima dell''evento) nella cifra di euro:',
|
||||
v_secondo_acconto, p_event_id, 0, 20);
|
||||
end if;
|
||||
else
|
||||
delete
|
||||
from eventi_acconti
|
||||
where id_evento = p_event_id
|
||||
and ordine = 20;
|
||||
end if;
|
||||
|
||||
if v_terzo_acconto > 0 then
|
||||
update eventi_acconti
|
||||
set ACCONTO = v_terzo_acconto
|
||||
where id_evento = p_event_id
|
||||
and ordine = 30;
|
||||
|
||||
if SQL%ROWCOUNT = 0 then
|
||||
insert into eventi_acconti
|
||||
(DESCRIZIONE, ACCONTO, ID_EVENTO, A_CONFERMA, ORDINE)
|
||||
values
|
||||
('SALDO A RICEVIMENTO CONSUNTIVO (art.7 punto c del contratto) ', v_terzo_acconto, p_event_id, 0, 30);
|
||||
end if;
|
||||
else
|
||||
delete
|
||||
from eventi_acconti
|
||||
where id_evento = p_event_id
|
||||
and ordine = 30;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end;```
|
||||
12
docs/procedures/EVENTO_ELIMINA_PRELIEVI.md
Normal file
12
docs/procedures/EVENTO_ELIMINA_PRELIEVI.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# EVENTO_ELIMINA_PRELIEVI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
PROCEDURE EVENTO_ELIMINA_PRELIEVI
|
||||
(
|
||||
P_ID_EVENTO IN NUMBER
|
||||
) AS
|
||||
BEGIN
|
||||
NULL;
|
||||
END EVENTO_ELIMINA_PRELIEVI;```
|
||||
22
docs/procedures/HTPPRN.md
Normal file
22
docs/procedures/HTPPRN.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# HTPPRN
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
PROCEDURE "HTPPRN" (pclob in out nocopy clob) is
|
||||
v_excel varchar2(32000);
|
||||
v_clob clob := pclob;
|
||||
begin
|
||||
while length(v_clob) > 0 loop begin
|
||||
if length(v_clob) > 32000 then v_excel:= substr(v_clob,1,32000);
|
||||
htp.prn(v_excel);
|
||||
v_clob:= substr(v_clob,length(v_excel)+1);
|
||||
else
|
||||
v_excel := v_clob;
|
||||
htp.prn(v_excel);
|
||||
v_clob:=''; v_excel := ''; end if;
|
||||
end;
|
||||
end loop;
|
||||
end;
|
||||
|
||||
```
|
||||
308
docs/procedures/LISTE_COPIA.md
Normal file
308
docs/procedures/LISTE_COPIA.md
Normal file
@@ -0,0 +1,308 @@
|
||||
# LISTE_COPIA
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```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;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Degustazioni (Tastings)
|
||||
----------------------------------------------------------------------------
|
||||
IF copia_degustazioni > 0 THEN
|
||||
FOR rec IN (
|
||||
SELECT
|
||||
id,
|
||||
data,
|
||||
ora,
|
||||
nome,
|
||||
telefono,
|
||||
email,
|
||||
location,
|
||||
n_persone,
|
||||
menu,
|
||||
n_paganti,
|
||||
note,
|
||||
n_degustazione,
|
||||
consumata,
|
||||
costo_degustazione
|
||||
FROM eventi_det_degust
|
||||
WHERE id_evento = id_evento_from
|
||||
) LOOP
|
||||
-- Try to update using the unique key (assumed here as n_degustazione)
|
||||
UPDATE eventi_det_degust
|
||||
SET
|
||||
data = rec.data,
|
||||
ora = rec.ora,
|
||||
nome = rec.nome,
|
||||
telefono = rec.telefono,
|
||||
email = rec.email,
|
||||
location = rec.location,
|
||||
n_persone = rec.n_persone,
|
||||
menu = rec.menu,
|
||||
n_paganti = rec.n_paganti,
|
||||
note = rec.note,
|
||||
consumata = rec.consumata,
|
||||
costo_degustazione = rec.costo_degustazione
|
||||
WHERE id_evento = id_evento_to
|
||||
AND id = rec.id;
|
||||
|
||||
IF SQL%ROWCOUNT = 0 THEN
|
||||
INSERT INTO eventi_det_degust (
|
||||
id_evento,
|
||||
data,
|
||||
ora,
|
||||
nome,
|
||||
telefono,
|
||||
email,
|
||||
location,
|
||||
n_persone,
|
||||
menu,
|
||||
n_paganti,
|
||||
note,
|
||||
n_degustazione,
|
||||
consumata,
|
||||
costo_degustazione
|
||||
)
|
||||
VALUES (
|
||||
id_evento_to,
|
||||
rec.data,
|
||||
rec.ora,
|
||||
rec.nome,
|
||||
rec.telefono,
|
||||
rec.email,
|
||||
rec.location,
|
||||
rec.n_persone,
|
||||
rec.menu,
|
||||
rec.n_paganti,
|
||||
rec.note,
|
||||
rec.n_degustazione,
|
||||
rec.consumata,
|
||||
rec.costo_degustazione
|
||||
);
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Ospiti (Guests)
|
||||
----------------------------------------------------------------------------
|
||||
FOR rec IN (
|
||||
SELECT
|
||||
cod_tipo_ospite,
|
||||
numero,
|
||||
note
|
||||
FROM eventi_det_ospiti
|
||||
WHERE id_evento = id_evento_from
|
||||
) LOOP
|
||||
UPDATE eventi_det_ospiti
|
||||
SET
|
||||
numero = rec.numero,
|
||||
note = rec.note
|
||||
WHERE id_evento = id_evento_to
|
||||
AND cod_tipo_ospite = rec.cod_tipo_ospite;
|
||||
|
||||
IF SQL%ROWCOUNT = 0 THEN
|
||||
INSERT INTO eventi_det_ospiti (
|
||||
id_evento,
|
||||
cod_tipo_ospite,
|
||||
numero,
|
||||
note
|
||||
)
|
||||
VALUES (
|
||||
id_evento_to,
|
||||
rec.cod_tipo_ospite,
|
||||
rec.numero,
|
||||
rec.note
|
||||
);
|
||||
END IF;
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Prelievi (Sampling): inserisce solo i record mancanti
|
||||
----------------------------------------------------------------------------
|
||||
IF copia_prelievi > 0 THEN
|
||||
MERGE INTO eventi_det_prel dest
|
||||
USING (
|
||||
SELECT
|
||||
cod_articolo,
|
||||
qta,
|
||||
note,
|
||||
qta_ape,
|
||||
qta_sedu,
|
||||
qta_bufdol,
|
||||
qta_man_ape,
|
||||
qta_man_sedu,
|
||||
qta_man_bufdol,
|
||||
costo_articolo
|
||||
FROM eventi_det_prel
|
||||
WHERE id_evento = id_evento_from
|
||||
) src
|
||||
ON (
|
||||
dest.id_evento = id_evento_to
|
||||
AND dest.cod_articolo = src.cod_articolo
|
||||
)
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (
|
||||
id_evento,
|
||||
cod_articolo,
|
||||
qta,
|
||||
note,
|
||||
qta_ape,
|
||||
qta_sedu,
|
||||
qta_bufdol,
|
||||
qta_man_ape,
|
||||
qta_man_sedu,
|
||||
qta_man_bufdol,
|
||||
costo_articolo
|
||||
)
|
||||
VALUES (
|
||||
id_evento_to,
|
||||
src.cod_articolo,
|
||||
src.qta,
|
||||
src.note,
|
||||
src.qta_ape,
|
||||
src.qta_sedu,
|
||||
src.qta_bufdol,
|
||||
src.qta_man_ape,
|
||||
src.qta_man_sedu,
|
||||
src.qta_man_bufdol,
|
||||
src.costo_articolo
|
||||
);
|
||||
END IF;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Risorse (Resources)
|
||||
----------------------------------------------------------------------------
|
||||
IF copia_risorse > 0 THEN
|
||||
FOR rec IN (
|
||||
SELECT
|
||||
id,
|
||||
id_risorsa,
|
||||
ore_lav,
|
||||
costo,
|
||||
note
|
||||
FROM eventi_det_ris
|
||||
WHERE id_evento = id_evento_from
|
||||
) LOOP
|
||||
UPDATE eventi_det_ris
|
||||
SET
|
||||
ore_lav = rec.ore_lav,
|
||||
costo = rec.costo,
|
||||
note = rec.note
|
||||
WHERE id_evento = id_evento_to
|
||||
AND id = rec.id;
|
||||
|
||||
IF SQL%ROWCOUNT = 0 THEN
|
||||
INSERT INTO eventi_det_ris (
|
||||
id_evento,
|
||||
id_risorsa,
|
||||
ore_lav,
|
||||
costo,
|
||||
note
|
||||
)
|
||||
VALUES (
|
||||
id_evento_to,
|
||||
rec.id_risorsa,
|
||||
rec.ore_lav,
|
||||
rec.costo,
|
||||
rec.note
|
||||
);
|
||||
END IF;
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Acconti (Payments)
|
||||
----------------------------------------------------------------------------
|
||||
IF copia_acconti > 0 THEN
|
||||
FOR rec IN (
|
||||
SELECT
|
||||
id,
|
||||
data,
|
||||
acconto,
|
||||
a_conferma,
|
||||
ordine,
|
||||
descrizione
|
||||
FROM eventi_acconti
|
||||
WHERE id_evento = id_evento_from
|
||||
) LOOP
|
||||
UPDATE eventi_acconti
|
||||
SET
|
||||
data = rec.data,
|
||||
acconto = rec.acconto,
|
||||
a_conferma = rec.a_conferma,
|
||||
descrizione = rec.descrizione
|
||||
WHERE id_evento = id_evento_to
|
||||
AND id = rec.id;
|
||||
|
||||
IF SQL%ROWCOUNT = 0 THEN
|
||||
INSERT INTO eventi_acconti (
|
||||
data,
|
||||
acconto,
|
||||
id_evento,
|
||||
a_conferma,
|
||||
ordine,
|
||||
descrizione
|
||||
)
|
||||
VALUES (
|
||||
rec.data,
|
||||
rec.acconto,
|
||||
id_evento_to,
|
||||
rec.a_conferma,
|
||||
rec.ordine,
|
||||
rec.descrizione
|
||||
);
|
||||
END IF;
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
-- Altri Costi (Other Costs)
|
||||
----------------------------------------------------------------------------
|
||||
IF copia_altricosti > 0 THEN
|
||||
FOR rec IN (
|
||||
SELECT
|
||||
id,
|
||||
descrizione,
|
||||
costo,
|
||||
quantity
|
||||
FROM eventi_altricosti
|
||||
WHERE id_evento = id_evento_from
|
||||
) LOOP
|
||||
UPDATE eventi_altricosti
|
||||
SET
|
||||
costo = rec.costo,
|
||||
quantity = rec.quantity
|
||||
WHERE id_evento = id_evento_to
|
||||
AND id = rec.id;
|
||||
|
||||
IF SQL%ROWCOUNT = 0 THEN
|
||||
INSERT INTO eventi_altricosti (
|
||||
id_evento,
|
||||
descrizione,
|
||||
costo,
|
||||
quantity
|
||||
)
|
||||
VALUES (
|
||||
id_evento_to,
|
||||
rec.descrizione,
|
||||
rec.costo,
|
||||
rec.quantity
|
||||
);
|
||||
END IF;
|
||||
END LOOP;
|
||||
END IF;
|
||||
END liste_copia;```
|
||||
41
docs/procedures/P_CANCEL_SAME_LOCATION_EVENTS.md
Normal file
41
docs/procedures/P_CANCEL_SAME_LOCATION_EVENTS.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# P_CANCEL_SAME_LOCATION_EVENTS
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
PROCEDURE "P_CANCEL_SAME_LOCATION_EVENTS" (p_good_event_id number) as
|
||||
-- ---------------------------
|
||||
-- Autore: Daniele Viti
|
||||
-- Data: 17/01/2020
|
||||
-- Descrizione: Controlla che ci siano più eventi con la stessa locazione e data di quello in esame e li annulla
|
||||
-- ---------------------------
|
||||
v_date date;
|
||||
v_idloc number;
|
||||
begin
|
||||
|
||||
begin
|
||||
-- Seleziono la data e la location per confrontarle dopo
|
||||
select data, id_location
|
||||
into v_date, v_idloc
|
||||
from eventi
|
||||
where id = p_good_event_id;
|
||||
exception when no_data_found then
|
||||
raise_application_error(-20001, 'Impossibile trovare l''evento da confermare');
|
||||
end;
|
||||
|
||||
for c in (
|
||||
select *
|
||||
from eventi
|
||||
where data = v_date
|
||||
and id_location = v_idloc
|
||||
and id != p_good_event_id
|
||||
) loop
|
||||
-- Imposta l'evento come obsoleto (annullato)
|
||||
UPDATE EVENTI
|
||||
SET
|
||||
FLG_SUPERATO = 1,
|
||||
STATO = 900
|
||||
WHERE ID = c.id;
|
||||
end loop;
|
||||
|
||||
end;```
|
||||
90
docs/procedures/README.md
Normal file
90
docs/procedures/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Stored Procedures
|
||||
|
||||
Questa cartella contiene la documentazione di tutte le 11 stored procedures del database.
|
||||
|
||||
## Procedures Business Logic
|
||||
|
||||
| Procedura | Descrizione |
|
||||
|-----------|-------------|
|
||||
| [EVENTI_AGGIORNA_QTA_LISTA](EVENTI_AGGIORNA_QTA_LISTA.md) | Ricalcola tutte le quantità della lista prelievo |
|
||||
| [EVENTI_AGGIORNA_TOT_OSPITI](EVENTI_AGGIORNA_TOT_OSPITI.md) | Aggiorna il totale ospiti in testata evento |
|
||||
| [EVENTI_COPIA](EVENTI_COPIA.md) | Duplica un evento con tutti i dettagli |
|
||||
| [EVENTI_RICALCOLA_ACCONTI](EVENTI_RICALCOLA_ACCONTI.md) | Ricalcola gli importi degli acconti |
|
||||
| [EVENTO_ELIMINA_PRELIEVI](EVENTO_ELIMINA_PRELIEVI.md) | Elimina i prelievi di un evento |
|
||||
| [LISTE_COPIA](LISTE_COPIA.md) | Copia selettiva di liste tra due eventi |
|
||||
| [P_CANCEL_SAME_LOCATION_EVENTS](P_CANCEL_SAME_LOCATION_EVENTS.md) | Annulla eventi nella stessa location/data |
|
||||
|
||||
## Procedures Utility
|
||||
|
||||
| Procedura | Descrizione |
|
||||
|-----------|-------------|
|
||||
| [ROWSORT_TIPI](ROWSORT_TIPI.md) | Riordina i tipi materiale |
|
||||
| [HTPPRN](HTPPRN.md) | Output HTTP per APEX |
|
||||
| [SEND_DATA_TO_DROPBOX](SEND_DATA_TO_DROPBOX.md) | Export dati verso Dropbox |
|
||||
| [XLOG](XLOG.md) | Procedura di logging |
|
||||
|
||||
## Dettaglio Procedures Critiche
|
||||
|
||||
### EVENTI_AGGIORNA_QTA_LISTA
|
||||
|
||||
**Parametri:**
|
||||
- `p_id_evento NUMBER` - ID dell'evento
|
||||
|
||||
**Logica:**
|
||||
1. Cicla su tutti gli articoli nella lista prelievo
|
||||
2. Per ogni articolo determina il metodo di calcolo:
|
||||
- **Quantità Standard**: Se `QTA_STD_A/S/B` sono valorizzate
|
||||
- **Tovagliato/Caraffe**: Moltiplica per quantità tavoli/angoli
|
||||
- **Codice Relativo**: Moltiplica per quantità articolo di riferimento
|
||||
- **Standard**: Moltiplica coefficienti per totale ospiti
|
||||
3. Verifica disponibilità rispetto alla giacenza
|
||||
4. Aggiorna note con warning se quantità insufficiente
|
||||
|
||||
### EVENTI_COPIA
|
||||
|
||||
**Parametri:**
|
||||
- `id_evento_old NUMBER` - ID evento da copiare
|
||||
- `nuova_versione NUMBER DEFAULT 0` - 1 per creare nuova versione
|
||||
- `id_evento_new OUT NUMBER` - ID nuovo evento creato
|
||||
|
||||
**Logica:**
|
||||
1. Copia testata evento
|
||||
2. Se nuova versione: imposta `ID_EVT_PADRE`, incrementa `VERS_NUMBER`
|
||||
3. Aggiorna evento vecchio con `ID_EVT_FIGLIO`
|
||||
4. Copia tutte le tabelle dettaglio:
|
||||
- `EVENTI_DET_DEGUST`
|
||||
- `EVENTI_DET_OSPITI` (via UPDATE, non INSERT)
|
||||
- `EVENTI_DET_PREL`
|
||||
- `EVENTI_DET_RIS`
|
||||
- `EVENTI_ACCONTI`
|
||||
- `EVENTI_ALTRICOSTI`
|
||||
5. In caso di errore: elimina evento creato e solleva eccezione
|
||||
|
||||
### EVENTI_RICALCOLA_ACCONTI
|
||||
|
||||
**Parametri:**
|
||||
- `p_event_id NUMBER` - ID evento
|
||||
|
||||
**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 ≤ totale evento
|
||||
|
||||
### LISTE_COPIA
|
||||
|
||||
**Parametri:**
|
||||
- `id_evento_from NUMBER` - Evento sorgente
|
||||
- `id_evento_to NUMBER` - Evento destinazione
|
||||
- `copia_degustazioni NUMBER DEFAULT 0`
|
||||
- `copia_prelievi NUMBER DEFAULT 0`
|
||||
- `copia_risorse NUMBER DEFAULT 0`
|
||||
- `copia_acconti NUMBER DEFAULT 0`
|
||||
- `copia_altricosti NUMBER DEFAULT 0`
|
||||
|
||||
**Logica:**
|
||||
Per ogni flag > 0 esegue un MERGE (UPDATE se esiste, INSERT altrimenti).
|
||||
145
docs/procedures/ROWSORT_TIPI.md
Normal file
145
docs/procedures/ROWSORT_TIPI.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# ROWSORT_TIPI
|
||||
|
||||
## Codice Sorgente
|
||||
|
||||
```sql
|
||||
PROCEDURE "ROWSORT_TIPI" (
|
||||
p_direc_cod IN VARCHAR2,
|
||||
o_return OUT CLOB
|
||||
) AS
|
||||
|
||||
v_direc VARCHAR2(4);
|
||||
v_cod_tipo VARCHAR2(10);
|
||||
v_cod_step NUMBER;
|
||||
v_cod_step_new NUMBER;
|
||||
v_return CLOB;
|
||||
BEGIN
|
||||
|
||||
-- Separo i valori in entrata su p_direc_cod 'direc_cod' in un array ( Es: 'desc_AN' => [ 'desc', 'AN' ] )
|
||||
---- Seleziono la direzione (asc o desc)
|
||||
SELECT
|
||||
upper(result)
|
||||
INTO v_direc
|
||||
FROM
|
||||
TABLE ( string_to_table_enum(p_string => p_direc_cod, v_level => 0, p_separator => '_') )
|
||||
WHERE
|
||||
id = 1;
|
||||
|
||||
---- Seleziono l'cod_tipo della riga da spostare
|
||||
|
||||
SELECT
|
||||
upper(result)
|
||||
INTO v_cod_tipo
|
||||
FROM
|
||||
TABLE ( string_to_table_enum(p_string => p_direc_cod, v_level => 0, p_separator => '_') )
|
||||
WHERE
|
||||
id = 2;
|
||||
|
||||
IF v_direc = 'ASC' THEN
|
||||
|
||||
-- Seleziono i numeri di riga
|
||||
SELECT
|
||||
cod_step,
|
||||
cod_step - 1
|
||||
INTO
|
||||
v_cod_step,
|
||||
v_cod_step_new
|
||||
FROM
|
||||
tb_tipi_mat
|
||||
WHERE
|
||||
upper(TRIM(cod_tipo)) = upper(TRIM(v_cod_tipo));
|
||||
|
||||
-- Libero i numeri di riga richiesti
|
||||
-- diminuendo il numero di riga di un valore inutilizzato (Es: 0.5)
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = cod_step - 0.5
|
||||
WHERE
|
||||
cod_tipo = v_cod_tipo;
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = cod_step - 0.5
|
||||
WHERE
|
||||
cod_step = v_cod_step_new;
|
||||
|
||||
-- Sposto la riga precedente al posto di quella selezionata (Es: row 1 diventerà row 2)
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = v_cod_step
|
||||
WHERE
|
||||
cod_step = v_cod_step_new - 0.5;
|
||||
|
||||
-- Sposto la riga selezionata al nuovo posto
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = v_cod_step_new
|
||||
WHERE
|
||||
cod_tipo = v_cod_tipo;
|
||||
|
||||
v_return := 'cod_tipo: '
|
||||
|| v_cod_tipo
|
||||
|| ' - From Row '
|
||||
|| v_cod_step
|
||||
|| ' - To Row '
|
||||
|| v_cod_step_new;
|
||||
|
||||
ELSIF v_direc = 'DESC' THEN
|
||||
|
||||
-- Seleziono i numeri di riga
|
||||
SELECT
|
||||
cod_step,
|
||||
cod_step + 1
|
||||
INTO
|
||||
v_cod_step,
|
||||
v_cod_step_new
|
||||
FROM
|
||||
tb_tipi_mat
|
||||
WHERE
|
||||
upper(TRIM(cod_tipo)) = upper(TRIM(v_cod_tipo));
|
||||
|
||||
-- Libero i numeri di riga richiesti
|
||||
-- diminuendo il numero di riga di un valore inutilizzato (Es: 0.5)
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = cod_step + 0.5
|
||||
WHERE
|
||||
cod_tipo = v_cod_tipo;
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = cod_step + 0.5
|
||||
WHERE
|
||||
cod_step = v_cod_step_new;
|
||||
|
||||
-- Sposto la riga precedente al posto di quella selezionata (Es: row 1 diventerà row 2)
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = v_cod_step
|
||||
WHERE
|
||||
cod_step = v_cod_step_new + 0.5;
|
||||
|
||||
-- Sposto la riga selezionata al nuovo posto
|
||||
|
||||
UPDATE tb_tipi_mat
|
||||
SET
|
||||
cod_step = v_cod_step_new
|
||||
WHERE
|
||||
cod_tipo = v_cod_tipo;
|
||||
|
||||
v_return := 'cod_tipo: '
|
||||
|| v_cod_tipo
|
||||
|| ' - From row. '
|
||||
|| v_cod_step
|
||||
|| ' - To row: '
|
||||
|| v_cod_step_new;
|
||||
|
||||
END IF;
|
||||
|
||||
o_return := v_return;
|
||||
END;```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user