
La gestione corretta e precisa degli appuntamenti con i clienti è fondamentale per qualsiasi tipo di attività o business.
Non è quindi un caso che molte delle applicazioni di mercato, come i CRM o le applicazioni di Field Services, abbiano al proprio interno strumenti di gestione degli appuntamenti.
Usando la soluzione giusta è possibile avere ben più di un’agenda: un vero e proprio strumento di organizzazione personale e del proprio team.
In questo articolo desidero spiegarti come creare una applicazione per gestire gli appuntamenti in Oracle APEX, da integrare, magari, con qualche altra soluzione APEX che hai già realizzato.
Buona lettura!
IN QUESTO ARTICOLO
Prima di Iniziare
Nel seguito dell’articolo introdurrò l’utilizzo del componente Calendar e ti spiegherò come configurarlo e personalizzarlo.
Per fare pratica, ti consiglio di installare anche l’applicazione Sample Calendar, disponibile tra le Sample Apps di APEX o da questo link.

Infine ti invito a vedere una applicazione di esempio che ho creato collegandoti al link seguente:
Step 1: Crea una Applicazione
Per costruire questa applicazione utilizzerò 3 tabelle.
- CUSTOMER: è il cliente per il quale dobbiamo pianificare un appuntamento
- EMPLOYEE: è la persona che si occuperà di assistere il cliente
- APPOINTMENT: è l’appuntamento vero e proprio
Quindi, prima di tutto, andrò a creare questi oggetti nel database.
- Accedo ad Oracle APEX e vado in SQL Workshop > Utilities > Quick SQL
- Inserisco lo script seguente
app04_employee
id /pk
first_name vc50
last_name vc50
app04_customer
id /pk
first_name vc50
last_name vc50
app04_appointment
id /pk
employee /fk app04_employee
customer /fk app04_customer
booking_status vc150
start_time date
end_time date
notes vc500
- Premo Generate SQL per generare automaticamente gli script necessari per creare le tre tabelle nel database.

- Clicco Save SQL Script e successivamente Review and Run

- Premo Run per completare l’operazione

Alla fine di questa procedura vedo che APEX restituisce questo messaggio di conferma.

Bene: non ci sono errori! Posso andare avanti.
In questo caso, non volendo modificare una applicazione già esistente, posso crearne una nuova direttamente da qui.
- Clicco sul bottone Create App

- Clicco su Create Application per avviare il wizard di creazione: questa opzione è molto utile perché automatizza alcuni passaggi.

- Assegno un nome all’applicazione e personalizzo il suo aspetto iniziale.
- Una volta fatto premo Create Application
Ecco che in pochi minuti ho a disposizione una applicazione di gestione degli appuntamenti già funzionante.

Da qui posso inserire e modificare i dipendenti, i clienti e ovviamente gli appuntamenti.
Nel seguito del tutorial ci concentreremo principalmente su come implementare la gestione del calendario degli appuntamenti.
Quindi, per prima cosa, provo a creare un nuovo appuntamento.
Step 2: Configura la Form Appuntamento
- Dal menù principale seleziono la voce Appointment per andare alla pagina di gestione degli appuntamenti
- Premo Create per fissare un nuovo appuntamento

- Questa è la form che mi si presenta davanti:

Ci sono due campi, Employee e Customer, che servono per inserire rispettivamente il cliente e il dipendente che ha in carico l’appuntamento.
C’è, inoltre, il campo Booking Status (Stato Prenotazione) che però in questo momento è un semplice campo di testo.
Infine ci sono i campi Start Time e End Time che ahimè, non permettono di specificare l’orario.
Vediamo insieme come migliorare questa form.
- Dall’ APP Builder seleziono la Form Page Appointment

- Seleziono la Form e vado alle sue proprietà

- Modifico il titolo della form in Dettagli Appuntamento

Booking Status
- Seleziono il Page Item PX_BOOKING_STATUS

- Modifico l’Item Type a Select List

- Vado in List of Values > Type e seleziono l’opzione Static Value

- Apro la maschera di configurazione della lista valori

- Configuro le seguenti opzioni (in realtà sarebbe meglio configurare la LOV come Shared Component ma non voglio complicartela troppo…):
- Display Value: Nuovo; Return Value: NEW
- Display Value: Confermato; Return Value: CONFIRMED
- Display Value: Annullato; Return Value: CANCELLED

- Disattivo le opzioni Display Extra Values e Display Null Value

- Infine, imposto il valore di default NEW

In questo caso ho usato un campo di tipo Select List ma, in effetti, penso sia più carino utilizzare una Page Item di tipo Radio Group.
Si configura più o meno nello stesso modo con l’unica differenza che posso impostare il numero di colonne (Number of Columns) affinché le opzioni vegano visualizzate in orizzontale.

Ecco il risultato

Start Time e End Time
- Seleziono i Page Items PX_START_TIME e PX_END_TIME

- Per prima cosa li rendo obbligatori, attivando l’opzione Value Required

- Dopodiché seleziono un formato dato appropriato che mi permetta di specificare anche un orario.

- Per ciascuno dei due Page Items, vado in Settings ed attivo l’opzione Show Time

Infine, inserisco una regola di validazione che mi impedisca di inserire una Data Inizio successiva alla Data Fine.
Per comodità decido di inserire la Regola di Validazione sul Page Item PX_END_DATE (ma avrei potuto usare anche PX_START_DATE).
- Seleziono il Page Item e con il pulsante destro clicco su Create Validation

Seleziono la Validation Rule che ho appena creato e vado a configurare le sue proprietà
- Name: Start Time < End Time
- Type: Expression
- Language: PL/SQL
- PL/SQL Expression: :p7_start_time < :p7_end_time
- Error Message: “Inserisci una Data Fine successiva alla Data Inizio”

Dopo aver applicato qualche altro raffinamento grafico, ecco finalmente la mia form per inserire un appuntamento.
Decisamente più bella, non credi?

Ecco cosa succede se provo a salvare un appuntamento senza specificare le date:

Allo stesso tempo non posso inserire una Data Inizio successiva alla Data Fine

Step 3: Configura il Calendario
Arrivato a questo punto ho già ottenuto un ottimo risultato, tuttavia credo di poter fare di meglio.
Infatti, mi rendo subito conto che gestire un’agenda usando un semplice report non è certo il massimo.

Come fare?
Posso utilizzare il componente Calendar che, come vedremo tra poco, mi permette di gestire gli appuntamenti in modo molto più funzionale.
Per praticità costruirò il calendario nell’Home Page.
- Accedi all’APP Builder e seleziono l’Home Page
- Aggiungo una nuova Page Region di nome Appointments

Seleziono la Page Region Appointment e vado a configurarne le proprietà:
- Title: Appointments
- Type: Calendar

- Configuro l’Origine Dati di tipo SQL Query ed inserisco la seguente query SQL
select ID,
EMPLOYEE,
CUSTOMER,
BOOKING_STATUS,
START_TIME,
END_TIME,
NOTES,
(case when BOOKING_STATUS = 'NEW' then 'apex-cal-orange'
when BOOKING_STATUS = 'CONFIRMED' then 'apex-cal-green'
when BOOKING_STATUS = 'CANCELLED' then 'apex-cal-gray'
else null
end) css_style,
(to_char(START_TIME,'HH24:MI')||'-'||to_char(END_TIME,'HH24:MI')||'<br>'|| (select apex_escape.html(first_name) ||' '||apex_escape.html(last_name) from app04_customer where id = customer)||'<br>'||apex_escape.html(notes)) display_value,
(select apex_escape.html(first_name) ||' '||apex_escape.html(last_name) from app04_employee where id = employee) employee_name
from APP04_APPOINTMENT

Prima di andare avanti ti faccio notare che nella query ho aggiunto un paio di colonne speciali
- css_style: restituisce una classe CSS diversa in funzione dello stato dell’appuntamento (nuovo, confermato oppure annullato)
- display_value: una stringa HTML che concatena ora di inizio e fine dell’appuntamento, il nome del cliente e le note
Tra poco vedremo a cosa servono.
- Prima di completare la configurazione di base, vado nella sezione Security e disattivo l’opzione Escape Special Characters. Questa operazione in generale va fatta con un certa attenzione, soprattutto quando la colonna del report deve visualizzare un campo di testo editato da un utente (è per questo motivo che ho usato la funzione apex_escape.html).

Ora posso completare la configurazione del calendario.
- Clicco su Attributes e nella sezione Settings configuro le seguenti opzioni:
- Display Column: DISPLAY_VALUE (è la colonna che abbiamo creato poco fa)
- Start Date Column: START_TIME
- End Date Column: END_TIME
- Primary Key Column: ID
- Show Time: Yes

- Sempre sotto Settings, posso configurare le opzioni di navigazione del calendario che preferiamo.

Questo è il risultato:

Come puoi vedere, grazie a questo utilissimo componente posso visualizzare tutti gli appuntamenti che ho fissato direttamente nel calendario.
Inoltre, in funzione delle opzioni di navigazione che ho abilitato, posso vedere tutto il mese, la settimana oppure puoi i soli appuntamenti della giornata.

Altra cosa interessante: posso colorare gli appuntamenti come preferisco, ad esempio in funzione dello stato:
- Arancione: appuntamento nuovo da confermare
- Verde: appuntamento confermato
- Grigio: appuntamento annullato
Per colorare gli appuntamenti devo:
- definire una colonna nell’Origine Dati che deve restituire come valore una classe CSS valida (è la colonna CSS_STYLE che ti ho fatto creare prima)
- mappare la colonna nella proprietà CSS Class della Page Region

Drag & Drop
Oltre a quello già visto, il componente Calendar supporta nativamente il Drag & Drop.
Per configurare il Drag & Drop devo:
- Andare in Settings e attivare l’opzione Drag and Drop
- Devo inserire lo script PL-SQL che deve essere eseguito da APEX per aggiornare la Data di Inizio e Fine di un appuntamento:
begin
update APP04_APPOINTMENT
set start_time = to_date(:APEX$NEW_START_DATE, 'YYYYMMDDHH24MISS'),
end_time = to_date(:APEX$NEW_END_DATE, 'YYYYMMDDHH24MISS')
where id = :APEX$PK_VALUE;
end;

Create Link e View / Edit Link
Configurando le opzioni Create Link e View / Edit Link posso modificare o creare gli appuntamenti direttamente dal Calendario senza dover usare il Report.

- Create Link
- Page: la Form Page Appuntamento che abbiamo configurato nella pima parte di questo tutorial
- Parametri: ho valorizzato la Data Inizio e Data Fine con i valori recuperati direttamente dal calendario

- View / Edit Link
- Page: la Form Page Appuntamento che abbiamo configurato nella pima parte di questo tutorial
- Parametri: ho valorizzato la Data Inizio e Data Fine con i valori recuperati direttamente dal calendario e l’ID dell’appuntamento

Step 4: Configurazioni Avanzate
Arrivati a questo punto potrei ritenermi soddisfatto perché la mia agenda digitale è completa e funzionante, il tutto scrivendo pochissimo codice PL-SQL.
Tuttavia, mi piace sperimentare e decido di personalizzarne ulteriormente sia l’aspetto che il funzionamento.
Vediamo con qualche esempio concreto cosa posso fare.
Filtri Interattivi
La prima cosa che ho fatto è stato creare dei filtri che mi permettessero di trovare rapidamente gli appuntamenti di mio interesse.
Per comodità ho modificato il layout dell’home page
- Seleziono il nodo principale dell’home page

- Vado in Appearance e seleziono il Page Template chiamato Left Side Column

- Creo una nuova Page Region di nome Filters e la posiziono nella sezione Left Column
- Aggiungo il Page Item PX_CUSTOMER di tipo Popup LOV

- Per configurare la lista valori utilizzo la LOV che APEX ha generato automaticamente quando ho creato l’applicazione tramite wizard.

- Creo una Dynamic Action di tipo Change e la collego al Page Item PX_CUSTOMER

- Opzioni della Dynamic Actions
- Event: Change
- Selection Type: Item(s)
- Item(s): PX_CUSTOMER

- Creo una Action di tipo Refresh per aggiornare il calendario

- Seleziono in calendario e seleziono nell’opzione Page Items di Submit il campo PX_CUSTOMER

- Modifico la query del calendario in questo modo
select ID,
EMPLOYEE,
CUSTOMER,
BOOKING_STATUS,
START_TIME,
END_TIME,
NOTES,
(case when BOOKING_STATUS = 'NEW' then 'apex-cal-orange'
when BOOKING_STATUS = 'CONFIRMED' then 'apex-cal-green'
when BOOKING_STATUS = 'CANCELLED' then 'apex-cal-gray'
else null
end) css_style,
(to_char(START_TIME,'HH24:MI')||'-'||to_char(END_TIME,'HH24:MI')||'<br>'|| (select apex_escape.html(first_name) ||' '||apex_escape.html(last_name) from app04_customer where id = customer)||'<br>'||apex_escape.html(notes)) display_value,
(select apex_escape.html(first_name) ||' '||apex_escape.html(last_name) from app04_employee where id = employee) employee_name
from APP04_APPOINTMENT
where (:P1_CUSTOMER is null or CUSTOMER=:P1_CUSTOMER)
Come risultato avrò la possibilità di filtrare velocemente gli appuntamenti per Cliente. Ovviamente posso replicare la stessa procedura per implementare altri filtri.

Opzioni di Configurazione Avanzata (JavaScript)
Oltre alle opzioni disponibili, è possibile personalizzare ulteriormente l’aspetto del calendario usando specifiche istruzioni JavaScript.
Per gestire questo tipo di configurazione avanzata di questo componente è necessario specificare le opzioni in questo modo:
- Dall’APP Builder seleziono il Calendario e vado in Attributes
- Inserisco uno speciale codice JavaScript in Advanced > JavaScript Initialization Code

Ad esempio, posso cambiare il titolo del calendario inserendo questa istruzione
function ( pOptions) {
pOptions.titleFormat = function( pDate ) { return "Appuntamenti" };
return pOptions;
}

Oppure, possio visualizzare la data con il mese nel formato letterale esteso
function ( pOptions) {
pOptions.titleFormat = { day: 'numeric', month: 'long', year: 'numeric' };
return pOptions;
}

All’interno dello stesso script posso combinare più istruzioni.
Ad esempio, se oltre a personalizzare il formato del titolo volessi mostrare i numeri delle settimane andrò ad inserire questo script:
function ( pOptions) {
pOptions.titleFormat = { day: 'numeric', month: 'long', year: 'numeric' };
pOptions.weekNumbers = true;
return pOptions;
}

Ora vedremo insieme alcune delle opzioni che ho trovato più utili e che puoi utilizzare anche tu.
Tieni a mente che ne esistono molte di più e, se lo desideri, puoi vedere l’elenco completo direttamente sulla pagina di documentazione di fullcalendar.io, il componente Open Source che è stato integrato all’interno di APEX.
function ( pOptions) {
pOptions.titleFormat = { day: 'numeric', month: 'long', year: 'numeric' };
pOptions.weekNumbers = true;
return pOptions;
}
Dimensioni del Calendario
Una delle cose che ho notato (e che non mi piace molto..) è che sugli schermi più piccoli l’altezza del calendario, che viene ridimensionata automaticamente, è decisamente bassa.

Posso modificare l’altezza del calendario usando questa opzione:
function ( pOptions) {
pOptions.height = "800px";
return pOptions;
}

Se non voglio fissare un’altezza specifica, posso usare l’opzione “auto”.
function ( pOptions) {
pOptions.height = "auto";
return pOptions;
}
Modifica Min-Time e Max-Time
Se vuoi limitare l’inserimento di appuntamenti a specifiche fasce orarie puoi usare la seguente opzione.
function ( pOptions) {
pOptions.slotMinTime = "07:00:00"; // hide slots before minTime
pOptions.slotMaxTime = "21:00:00"; // hide slots after maxTime
return pOptions;
}

Grazie all’opzione slotDuration puoi personalizzare la durata dello slot base. Ad esempio 15 minuti:
function ( pOptions) {
pOptions.slotMinTime = "07:00:00"; // hide slots before minTime
pOptions.slotMaxTime = "21:00:00"; // hide slots after maxTime
pOptions.slotDuration = "00:15:00"; // custom slot duration
return pOptions;
}

Puoi legare questi parametri di configurazione a dei Page Items APEX.
Ecco un esempio:
function (pOptions) {
var startTime = apex.item("PX_START_TIME").getValue();
var endTime = apex.item("PX_END_TIME").getValue();
var slotDuration = apex.item("PX_SLOT_DURATION").getValue();
pOptions.slotMinTime = startTime;
pOptions.slotMaxTime = endTime;
pOptions.slotDuration = slotDuration;
return pOptions;
}
Nascondi i Giorni della Settimana
Oracle APEX ti consente di nascondere nel calendario le giornate relative al fine settimana tramite l’opzione Show Weekend.

Nel caso in cui questa opzione non sia attiva il risultato è questo:

Questa si rivela particolarmente utile nella maggior parte dei casi, tuttavia potresti voler avere un controllo più fine su quali giorni della settimana nascondere o mostrare (magari tu sei una persona che fa pausa il lunedì).
Ci viene in aiuto l’opzione hiddenDays che va usata in questo modo:
function (pOptions) {
pOptions.hiddenDays = [ 0,1,2 ]
return pOptions;
}
I numeri che vedi sono i giorni della settimana dove 0 è domenica, 1 è lunedì, 2 è martedì e così via..

Vista di Default
Grazie all’opzione Calendar Views and Navigation puoi decidere quali Viste (Views) l’utente può utilizzare, tuttavia non puoi specificare quale deve essere quella di default che sarà sempre la prima attivata.

Grazie all’opzione initialView puoi specificare qual è la vista di default, ad esempio la vista Week
function (pOptions) {
pOptions.initialView = "timeGridWeek";
return pOptions;
}
Queste sono le viste che puoi utilizzare: dayGridMonth, dayGridWeek, timeGridDay, listWeek.
Controlli Interattivi via Dynamic Actions
L’ultima cosa che desidero spiegarti è che puoi integrare il calendario con le Azioni Dinamiche APEX (Dynamic Action) di Oracle APEX.
Puoi implementare la navigazione avanti e indietro, piuttosto che la selezione di una vista specifica, come ho fatto in questa applicazione.

Come esercizio, proveremo ad implementare una funzionalità “Vai alla Data”.
- Accedo all’APP Builder e seleziono la Page Region Appointments
- Se non è stato fatto precedentemente, vado ad inserire nel campo Static ID un identificativo (es: calendar)

- creo un nuovo Page Item di tipo Date Picker e di nome PX_GO_TO_DATE

- Seleziona come Format Mask l’opzione YYYY-MM-DD

- Crea una nuova Dynamic Action sul campo PX_GO_TO_DATE con queste caratteristiche
- Name: Change Date
- Event: Change
- Selection Type: Item(s)
- Item(s): PX_GO_TO_DATE
- Type: JavaScript Expression
- JavaScript Expression: inserisci la seguente espressione
$v("P1_GO_TO_DATE").match(/\d\d\d\d\-\d\d\-\d\d/) != null

- Aggiungo una Action True con queste caratteristiche
- Action: Execute JavaScript Code
- Code: inserisco lo script seguente
apex.region("calendar").widget().data("fullCalendar").gotoDate($v("P1_GO_TO_DATE"))

- Aggiungo una Action False con queste caratteristiche:

Il risultato finale sarà che dopo aver scelto una data nel campo Go To Date il calendario si sposterà alla data selezionata.

Conclusioni
Bene, siamo arrivati alla fine di questo tutorial.
Abbiamo visto come creare una applicazione per la gestione degli appuntamenti che puoi utilizzare in tantissimi contesti.
Spero con tutto il cuore che tu lo abbia trovato interessante.
Un abbraccio,
Daniele
Ciao, sto imparando ad usare APEX e volevo ringraziarti per gli ottimi spunti che trovo in questo spazio e la tua gentilezza.
Un caro saluto Francesca
ciao Francesca
grazie a te per l’apprezzamento!
Daniele
Molto interessante e utile !
Grazie mille Franca!
Grazie Daniele, grazie alle tue guide sto imparando a usare Oracle APEX rapidamente.
Una domanda, è possibile configurare un orario di inizio e fine di default in modo che quando si crea un appuntamento cliccando sulla data vengano proposti questi orari?
Grazie