# 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: '||
'Degustazioni.'
);
CMN_MAIL_HTMLUTILS.create_paragraph(
'Per qualsiasi ulteriore informazione o chiarimento potete scriverci a '||
'info@apollinarecatering.it.'
);
CMN_MAIL_HTMLUTILS.create_paragraph('Si prega di non rispondere direttamente a questa email.');
CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');
CMN_MAIL_HTMLUTILS.create_paragraph('Ufficio Commerciale');
CMN_MAIL_HTMLUTILS.create_paragraph('📞 +39 0743 45 449');
CMN_MAIL_HTMLUTILS.create_paragraph('Apollinare Catering');
-- 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: '||
'info@apollinarecatering.it.'
);
CMN_MAIL_HTMLUTILS.create_paragraph('Si prega di non rispondere direttamente a questa email.');
CMN_MAIL_HTMLUTILS.create_paragraph('Cordiali saluti,');
CMN_MAIL_HTMLUTILS.create_paragraph('Ufficio Commerciale');
CMN_MAIL_HTMLUTILS.create_paragraph('📞 +39 0743 45 449');
CMN_MAIL_HTMLUTILS.create_paragraph('Apollinare Catering');
-- 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('Ufficio Commerciale');
CMN_MAIL_HTMLUTILS.create_paragraph('📞 +39 0743 45 449');
CMN_MAIL_HTMLUTILS.create_paragraph('Apollinare Catering');
-- 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;```