- fix zona provinciale
- email abilitazione circuito: invio email ad admin - admin che abilita la fiducia cliccando sul bottone
This commit is contained in:
401
emails/RISO/circuit_chiedi_facilitatori_di_entrare/it/html.pug
Executable file
401
emails/RISO/circuit_chiedi_facilitatori_di_entrare/it/html.pug
Executable file
@@ -0,0 +1,401 @@
|
|||||||
|
doctype html
|
||||||
|
html(lang="it")
|
||||||
|
head
|
||||||
|
meta(charset="UTF-8")
|
||||||
|
meta(name="viewport" content="width=device-width, initial-scale=1.0")
|
||||||
|
style(type="text/css").
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-logo {
|
||||||
|
width: 120px;
|
||||||
|
height: auto;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
background: linear-gradient(135deg, #7cb342 0%, #558b2f 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 40px 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header .subtitle {
|
||||||
|
margin: 8px 0 0 0;
|
||||||
|
font-size: 17px;
|
||||||
|
opacity: 0.95;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-icon {
|
||||||
|
font-size: 56px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 32px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-text {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-card {
|
||||||
|
background: linear-gradient(135deg, #e3f2fd 0%, #f0f7ff 100%);
|
||||||
|
border: 2px solid #2196f3;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px;
|
||||||
|
margin: 20px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-card h3 {
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #2196f3;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-card .member-name {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-card .member-detail {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #555;
|
||||||
|
margin: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-card .member-detail strong {
|
||||||
|
color: #2196f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.territory-badge {
|
||||||
|
background: linear-gradient(135deg, #4caf50 0%, #388e3c 100%);
|
||||||
|
color: white;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 8px 20px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-box {
|
||||||
|
background: #e1f5fe;
|
||||||
|
border-left: 4px solid #2196f3;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 24px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-box p {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section {
|
||||||
|
text-align: center;
|
||||||
|
margin: 32px 0;
|
||||||
|
padding: 24px 0;
|
||||||
|
border-top: 2px solid #e0e0e0;
|
||||||
|
border-bottom: 2px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 18px 56px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: white;
|
||||||
|
background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
|
||||||
|
border-radius: 50px;
|
||||||
|
text-decoration: none;
|
||||||
|
box-shadow: 0 6px 20px rgba(33, 150, 243, 0.4);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box {
|
||||||
|
background: #e8f5e9;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box p {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
color: #2e7d32;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsibility-box {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsibility-box h3 {
|
||||||
|
font-size: 17px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsibility-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsibility-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
min-width: 24px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsibility-text {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #555;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-footer {
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
background: #f8f9fa;
|
||||||
|
color: #777;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-footer p {
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(to right, transparent, #e0e0e0, transparent);
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
body {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header {
|
||||||
|
padding: 24px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-header h1 {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-body {
|
||||||
|
padding: 20px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.request-card .member-name {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.territory-badge {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 6px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-box p {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
padding: 16px 40px;
|
||||||
|
font-size: 18px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsibility-item {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
.email-container
|
||||||
|
//- Header
|
||||||
|
.email-header
|
||||||
|
img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp)
|
||||||
|
h1 🎯 Richiesta Abilitazione #{nomeTerritorio}
|
||||||
|
p.subtitle Nuovo membro in attesa di attivazione
|
||||||
|
|
||||||
|
//- Body
|
||||||
|
.email-body
|
||||||
|
//- Intro
|
||||||
|
.intro-text
|
||||||
|
| Ciao <strong>#{nomeFacilitatore}</strong>,<br>
|
||||||
|
| un nuovo membro richiede l'abilitazione alla fiducia al Circuito RIS del tuo territorio!
|
||||||
|
|
||||||
|
//- Card richiesta
|
||||||
|
.request-card
|
||||||
|
h3 👤 Richiesta Ingresso Circuito
|
||||||
|
.member-name #{usernameMembro}
|
||||||
|
if nomeMembro
|
||||||
|
if cognomeMembro
|
||||||
|
.member-detail
|
||||||
|
strong Nome:
|
||||||
|
| #{nomeMembro} #{cognomeMembro}
|
||||||
|
else
|
||||||
|
.member-detail
|
||||||
|
strong Nome:
|
||||||
|
| #{nomeMembro}
|
||||||
|
if emailMembro
|
||||||
|
.member-detail
|
||||||
|
strong Email:
|
||||||
|
| #{emailMembro}
|
||||||
|
if telegramMembro
|
||||||
|
.member-detail
|
||||||
|
strong Telegram:
|
||||||
|
a(href=`https://t.me/${telegramMembro}` target="_blank" style="color: #2196f3; text-decoration: none;") @#{telegramMembro}
|
||||||
|
if comuneResidenza
|
||||||
|
.member-detail
|
||||||
|
strong Comune:
|
||||||
|
| #{comuneResidenza} (#{provinciaResidenza})
|
||||||
|
|
||||||
|
.territory-badge 📍 #{nomeTerritorio}
|
||||||
|
|
||||||
|
if usernameInvitante
|
||||||
|
.divider(style="margin: 20px auto; width: 80%;")
|
||||||
|
h3(style="font-size: 14px; text-transform: uppercase; color: #2196f3; margin-bottom: 12px;") 👥 Invitato da
|
||||||
|
.member-detail
|
||||||
|
strong Invitante:
|
||||||
|
| #{usernameInvitante}
|
||||||
|
if nomeInvitante
|
||||||
|
if cognomeInvitante
|
||||||
|
.member-detail
|
||||||
|
strong Nome:
|
||||||
|
| #{nomeInvitante} #{cognomeInvitante}
|
||||||
|
else
|
||||||
|
.member-detail
|
||||||
|
strong Nome:
|
||||||
|
| #{nomeInvitante}
|
||||||
|
if telegramInvitante
|
||||||
|
.member-detail
|
||||||
|
strong Telegram:
|
||||||
|
a(href=`https://t.me/${telegramInvitante}` target="_blank" style="color: #2196f3; text-decoration: none;") @#{telegramInvitante}
|
||||||
|
|
||||||
|
//- CTA principale
|
||||||
|
.cta-section
|
||||||
|
a.cta-button(href=linkAbilitazione target="_blank")
|
||||||
|
span.button-icon ✓
|
||||||
|
| Abilita fiducia
|
||||||
|
|
||||||
|
.divider(style="margin: 24px 0;")
|
||||||
|
p(style="font-size: 16px; color: #666; margin-bottom: 16px;") Visualizza i profili
|
||||||
|
.button-group(style="display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;")
|
||||||
|
a.secondary-button(href=linkProfiloMembro target="_blank" style="display: inline-block; padding: 12px 24px; font-size: 16px; font-weight: 600; color: #2196f3; background: white; border: 2px solid #2196f3; border-radius: 25px; text-decoration: none; transition: all 0.3s ease;")
|
||||||
|
span(style="margin-right: 6px;") 👤
|
||||||
|
| Profilo Membro
|
||||||
|
if linkProfiloInvitante
|
||||||
|
a.secondary-button(href=linkProfiloInvitante target="_blank" style="display: inline-block; padding: 12px 24px; font-size: 16px; font-weight: 600; color: #7cb342; background: white; border: 2px solid #7cb342; border-radius: 25px; text-decoration: none; transition: all 0.3s ease;")
|
||||||
|
span(style="margin-right: 6px;") 👥
|
||||||
|
| Profilo Invitante
|
||||||
|
|
||||||
|
//- Responsabilità
|
||||||
|
.responsibility-box
|
||||||
|
h3 📋 Compiti del Facilitatore RISO
|
||||||
|
.responsibility-item
|
||||||
|
span.responsibility-icon 🔍
|
||||||
|
span.responsibility-text
|
||||||
|
strong Verifica:
|
||||||
|
| Contatta il membro, se non lo conosci, oppure il suo invitante: #{usernameInvitante}
|
||||||
|
.responsibility-item
|
||||||
|
span.responsibility-icon 🌍
|
||||||
|
span.responsibility-text
|
||||||
|
strong Territorio:
|
||||||
|
| Assicurati che il membro appartenga effettivamente al territorio di competenza
|
||||||
|
.responsibility-item
|
||||||
|
span.responsibility-icon 👥
|
||||||
|
span.responsibility-text
|
||||||
|
strong Integrazione:
|
||||||
|
| Supporta il nuovo membro nell'attivazione e utilizzo del Circuito RIS locale
|
||||||
|
|
||||||
|
//- Info box
|
||||||
|
.info-box
|
||||||
|
p
|
||||||
|
| ✓ Dopo l'abilitazione, #{usernameMembro} potrà accedere al Circuito RIS di #{nomeTerritorio}
|
||||||
|
p
|
||||||
|
| ✓ Il membro riceverà una notifica automatica dell'avvenuta attivazione
|
||||||
|
|
||||||
|
//- Footer
|
||||||
|
.email-footer
|
||||||
|
.divider
|
||||||
|
p Hai ricevuto questa email in qualità di Facilitatore RISO per #{nomeTerritorio}
|
||||||
|
p(style="margin-top: 12px; font-size: 12px;")
|
||||||
|
| #{new Date().getFullYear()} #{nomeapp}
|
||||||
1
emails/RISO/circuit_chiedi_facilitatori_di_entrare/it/subject.pug
Executable file
1
emails/RISO/circuit_chiedi_facilitatori_di_entrare/it/subject.pug
Executable file
@@ -0,0 +1 @@
|
|||||||
|
=`Richiesta ingresso di ${usernameMembro} - ${nomeMembro} ${cognomeMembro} su ${nomeTerritorio} in ${nomeapp}`
|
||||||
@@ -294,7 +294,7 @@ html(lang="it")
|
|||||||
.email-container
|
.email-container
|
||||||
//- Header
|
//- Header
|
||||||
.email-header
|
.email-header
|
||||||
img.header-logo(src=baseurl+'/images/logo.png' alt='RISO - Rete Italiana Scambio Orizzontale')
|
img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp)
|
||||||
h1 🔔 Richiesta di Ammissione
|
h1 🔔 Richiesta di Ammissione
|
||||||
p.subtitle Nuovo membro in attesa
|
p.subtitle Nuovo membro in attesa
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ html(lang="it")
|
|||||||
span.responsibility-icon 🛡️
|
span.responsibility-icon 🛡️
|
||||||
span.responsibility-text
|
span.responsibility-text
|
||||||
strong Fiducia:
|
strong Fiducia:
|
||||||
| L'ammissione si basa sulla fiducia reciproca nella comunità RISO
|
| L'ammissione si basa sulla fiducia reciproca nella comunità #{nomeapp}
|
||||||
.responsibility-item
|
.responsibility-item
|
||||||
span.responsibility-icon 👥
|
span.responsibility-icon 👥
|
||||||
span.responsibility-text
|
span.responsibility-text
|
||||||
@@ -355,8 +355,6 @@ html(lang="it")
|
|||||||
.info-box
|
.info-box
|
||||||
p
|
p
|
||||||
| ✓ Dopo l'ammissione, #{usernameInvitato} potrà completare il profilo
|
| ✓ Dopo l'ammissione, #{usernameInvitato} potrà completare il profilo
|
||||||
p
|
|
||||||
| ✓ Il facilitatore locale valuterà l'abilitazione all'uso dei RIS
|
|
||||||
|
|
||||||
//- Warning box
|
//- Warning box
|
||||||
.warning-box
|
.warning-box
|
||||||
@@ -369,6 +367,4 @@ html(lang="it")
|
|||||||
.divider
|
.divider
|
||||||
p Hai ricevuto questa email perché #{usernameInvitato} ha indicato te come invitante su #{nomeapp}
|
p Hai ricevuto questa email perché #{usernameInvitato} ha indicato te come invitante su #{nomeapp}
|
||||||
p(style="margin-top: 12px; font-size: 12px;")
|
p(style="margin-top: 12px; font-size: 12px;")
|
||||||
| #{new Date().getFullYear()} #{nomeapp} - Rete Italiana Scambi Orizzontali
|
| #{new Date().getFullYear()} #{nomeapp}
|
||||||
p(style="margin-top: 12px; font-size: 12px;")
|
|
||||||
| 🍚 Comunità · Fiducia · Scambi Solidali · Sostenibilità
|
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ html(lang="it")
|
|||||||
.step-number 1
|
.step-number 1
|
||||||
.step-content
|
.step-content
|
||||||
h3 ✅ Completa il tuo profilo
|
h3 ✅ Completa il tuo profilo
|
||||||
p Collega il tuo profilo a Telegram, inserisci la tua Provincia ed accedi ai Circuiti Territoriali per poter iniziare ad usare i RIS. Un profilo completo aiuta gli altri membri a conoscerti meglio!
|
p Collega il tuo profilo a Telegram ed accedi ai Circuiti Territoriali per poter iniziare ad usare i RIS. Un profilo completo aiuta gli altri membri a conoscerti meglio!
|
||||||
|
|
||||||
.step-item
|
.step-item
|
||||||
.step-number 2
|
.step-number 2
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
=`🎉 Il tuo invito è stato accettato su RISO da ${name ? ', ' + name : username} !`
|
=`🎉 Il tuo invito è stato accettato su RISO da ${name ? name : username} !`
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
=`🎉 Il tuo invito è stato accettato su ${nomeapp} da ${name ? ', ' + name : username} !`
|
=`🎉 Il tuo invito è stato accettato su ${nomeapp} da ${name ? name : username} !`
|
||||||
|
|||||||
@@ -1030,8 +1030,10 @@ CircuitSchema.statics.getCircuitByCircuitId = async function (circuitId) {
|
|||||||
return await Circuit.findOne({ _id: circuitId });
|
return await Circuit.findOne({ _id: circuitId });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// getListAdminsByCircuitPath - ritorna oggetti interi + USER_ADMIN_CIRCUITS
|
||||||
|
// getListAdminsByCircuitPath - ritorna oggetti interi senza duplicati
|
||||||
CircuitSchema.statics.getListAdminsByCircuitPath = async function (idapp, circuitPath) {
|
CircuitSchema.statics.getListAdminsByCircuitPath = async function (idapp, circuitPath) {
|
||||||
let arr = await Circuit.findOne(
|
let circuit = await Circuit.findOne(
|
||||||
{
|
{
|
||||||
idapp,
|
idapp,
|
||||||
path: circuitPath,
|
path: circuitPath,
|
||||||
@@ -1040,9 +1042,22 @@ CircuitSchema.statics.getListAdminsByCircuitPath = async function (idapp, circui
|
|||||||
{ admins: 1 }
|
{ admins: 1 }
|
||||||
).lean();
|
).lean();
|
||||||
|
|
||||||
let myarr = arr && arr.admins ? arr.admins : [];
|
let adminObjects = circuit && circuit.admins ? circuit.admins : [];
|
||||||
|
|
||||||
return [...myarr, ...shared_consts.USER_ADMIN_CIRCUITS];
|
// Aggiungi USER_ADMIN_CIRCUITS come oggetti
|
||||||
|
let systemAdmins = shared_consts.USER_ADMIN_CIRCUITS.map(username => ({
|
||||||
|
username,
|
||||||
|
date: null,
|
||||||
|
_id: null
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Unisci e rimuovi duplicati per username
|
||||||
|
let allAdmins = [...adminObjects, ...systemAdmins];
|
||||||
|
let uniqueAdmins = allAdmins.filter((admin, index, self) =>
|
||||||
|
index === self.findIndex(a => a.username === admin.username)
|
||||||
|
);
|
||||||
|
|
||||||
|
return uniqueAdmins;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Imposta a tutti i Conti Collettivi, i seguenti minimi e massimi
|
// Imposta a tutti i Conti Collettivi, i seguenti minimi e massimi
|
||||||
@@ -1177,7 +1192,7 @@ CircuitSchema.statics.createCircuitIfNotExist = async function (req, idapp, prov
|
|||||||
date_created: new Date(),
|
date_created: new Date(),
|
||||||
admins: admins.map((username) => ({ username })),
|
admins: admins.map((username) => ({ username })),
|
||||||
askManagerToEnter: false,
|
askManagerToEnter: false,
|
||||||
sendEmailAfterAskingToEnter: false,
|
sendEmailAfterAskingToEnter: true,
|
||||||
circuitoIndipendente: false,
|
circuitoIndipendente: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -465,6 +465,7 @@ const UserSchema = new mongoose.Schema({
|
|||||||
_id: false,
|
_id: false,
|
||||||
circuitname: { type: String },
|
circuitname: { type: String },
|
||||||
date: { type: Date },
|
date: { type: Date },
|
||||||
|
token: { type: String },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
last_circuitpath: {
|
last_circuitpath: {
|
||||||
@@ -2489,25 +2490,38 @@ UserSchema.statics.addCircuitToUser = async function (idapp, usernameOrig, circu
|
|||||||
} else {
|
} else {
|
||||||
// prima di aggiungerlo controlla se esiste già !
|
// prima di aggiungerlo controlla se esiste già !
|
||||||
|
|
||||||
let update = {
|
const token = tools.getTokenRandom();
|
||||||
$addToSet: {
|
|
||||||
// Utilizziamo $addToSet invece di $push per garantire che l'elemento venga aggiunto solo se non esiste già
|
let update = null;
|
||||||
'profile.mycircuits': {
|
|
||||||
$each: [
|
const updateparams = {
|
||||||
{
|
$set: {
|
||||||
circuitname,
|
'profile.mycircuits.$[elem].date': new Date(),
|
||||||
date: new Date(),
|
'profile.mycircuits.$[elem].token': token,
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
ris = await User.updateOne(
|
let ris = await User.updateOne(
|
||||||
{ idapp, username: usernameOrig, 'profile.mycircuits': { $not: { $elemMatch: { circuitname } } } },
|
{ idapp, username: usernameOrig, 'profile.mycircuits.circuitname': circuitname },
|
||||||
update
|
updateparams,
|
||||||
|
{ arrayFilters: [{ 'elem.circuitname': circuitname }] }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Se non ha modificato nulla (nModified === 0), significa che non esiste, quindi lo aggiungiamo
|
||||||
|
if (ris.modifiedCount === 0) {
|
||||||
|
const insertUpdate = {
|
||||||
|
$push: {
|
||||||
|
'profile.mycircuits': {
|
||||||
|
circuitname,
|
||||||
|
date: new Date(),
|
||||||
|
token,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
ris = await User.updateOne({ idapp, username: usernameOrig }, insertUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
if (confido) {
|
if (confido) {
|
||||||
// Elimina la richiesta:
|
// Elimina la richiesta:
|
||||||
update = { $pull: { req_users: { username: { $in: [usernameOrig] } } } };
|
update = { $pull: { req_users: { username: { $in: [usernameOrig] } } } };
|
||||||
@@ -2525,6 +2539,24 @@ UserSchema.statics.addCircuitToUser = async function (idapp, usernameOrig, circu
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Rimuovo il Gruppo per Tutti gli Utenti
|
// Rimuovo il Gruppo per Tutti gli Utenti
|
||||||
|
UserSchema.statics.getCircuitByTokenAndUsername = async function (idapp, username, token) {
|
||||||
|
try {
|
||||||
|
const user = await User.findOne({
|
||||||
|
idapp,
|
||||||
|
username,
|
||||||
|
'profile.mycircuits.token': token,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Il circuito sarà in: circuit?.profile?.mycircuits?.[0]
|
||||||
|
const foundCircuit = user?.profile?.mycircuits?.[0];
|
||||||
|
if (foundCircuit) {
|
||||||
|
return { circuitname: foundCircuit.circuitname, user };
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return { circuitname: '', user: null };
|
||||||
|
}
|
||||||
|
return { circuitname: '', user: null };
|
||||||
|
};
|
||||||
UserSchema.statics.removeAllUsersFromMyGroups = async function (idapp, groupnameDest) {
|
UserSchema.statics.removeAllUsersFromMyGroups = async function (idapp, groupnameDest) {
|
||||||
return await User.updateMany({ idapp }, { $pull: { 'profile.mygroups': { groupname: { $in: [groupnameDest] } } } });
|
return await User.updateMany({ idapp }, { $pull: { 'profile.mygroups': { groupname: { $in: [groupnameDest] } } } });
|
||||||
};
|
};
|
||||||
@@ -2630,7 +2662,7 @@ UserSchema.statics.setFriendsCmd = async function (req, idapp, usernameOrig, use
|
|||||||
);
|
);
|
||||||
msgDest = i18n.__({ phrase: '✅ Sei stato Ammesso correttamente da %s!', locale: lang }, usernameOrig);
|
msgDest = i18n.__({ phrase: '✅ Sei stato Ammesso correttamente da %s!', locale: lang }, usernameOrig);
|
||||||
msgAdmin = i18n.__(
|
msgAdmin = i18n.__(
|
||||||
{ phrase: '✅ %s è stato Ammesso correttamente (da %s)!', locale: userDest.lang },
|
{ phrase: '✅ %s è stato Ammesso/a correttamente (da %s) tramite Email!', locale: userDest.lang },
|
||||||
userDest.username,
|
userDest.username,
|
||||||
usernameOrig
|
usernameOrig
|
||||||
);
|
);
|
||||||
@@ -6912,6 +6944,25 @@ UserSchema.statics.createNewSubRecord = async function (idapp, req) {
|
|||||||
return rec;
|
return rec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Nel tuo User schema, aggiungi questo metodo statico:
|
||||||
|
|
||||||
|
UserSchema.statics.getTokenByUsernameAndCircuitName = async function (idapp, username, circuitname) {
|
||||||
|
const User = this;
|
||||||
|
|
||||||
|
const user = await User.findOne(
|
||||||
|
{
|
||||||
|
idapp,
|
||||||
|
username,
|
||||||
|
'profile.mycircuits.circuitname': circuitname,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'profile.mycircuits.$': 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return user?.profile?.mycircuits?.[0]?.token || null;
|
||||||
|
};
|
||||||
|
|
||||||
const User = mongoose.model('User', UserSchema);
|
const User = mongoose.model('User', UserSchema);
|
||||||
|
|
||||||
class Hero {
|
class Hero {
|
||||||
|
|||||||
@@ -1,575 +0,0 @@
|
|||||||
/**
|
|
||||||
* Classe per gestire l'invio di notifiche via Email e Telegram
|
|
||||||
* per gli eventi della piattaforma RISO
|
|
||||||
*/
|
|
||||||
|
|
||||||
class InvioNotifiche {
|
|
||||||
/**
|
|
||||||
* @param {Object} config - Configurazione per l'invio notifiche
|
|
||||||
* @param {Object} config.emailService - Servizio per invio email (es. nodemailer)
|
|
||||||
* @param {Object} config.telegramBot - Istanza del bot Telegram
|
|
||||||
* @param {String} config.adminTelegramId - ID Telegram dell'amministratore
|
|
||||||
* @param {String} config.adminEmail - Email dell'amministratore
|
|
||||||
* @param {String} config.baseUrl - URL base dell'applicazione
|
|
||||||
* @param {String} config.nomeApp - Nome dell'applicazione
|
|
||||||
* @param {Object} config.emailTemplates - Path ai template email PUG
|
|
||||||
*/
|
|
||||||
constructor(config) {
|
|
||||||
this.emailService = config.emailService;
|
|
||||||
this.telegramBot = config.telegramBot;
|
|
||||||
this.adminTelegramId = config.adminTelegramId;
|
|
||||||
this.adminEmail = config.adminEmail;
|
|
||||||
this.baseUrl = config.baseUrl;
|
|
||||||
this.nomeApp = config.nomeApp || 'RISO';
|
|
||||||
this.emailTemplates = config.emailTemplates || {};
|
|
||||||
|
|
||||||
// Logger (puoi sostituirlo con Winston o altro)
|
|
||||||
this.logger = config.logger || console;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// METODI PRIVATI - Invio Base
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invia una email
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
async _inviaEmail(destinatario, oggetto, htmlContent, templatePath = null, templateData = null) {
|
|
||||||
try {
|
|
||||||
let html = htmlContent;
|
|
||||||
|
|
||||||
// Se è specificato un template PUG, renderizzalo
|
|
||||||
if (templatePath && templateData) {
|
|
||||||
const pug = require('pug');
|
|
||||||
html = pug.renderFile(templatePath, templateData);
|
|
||||||
}
|
|
||||||
|
|
||||||
const emailOptions = {
|
|
||||||
from: `${this.nomeApp} <noreply@riso.app>`,
|
|
||||||
to: destinatario,
|
|
||||||
subject: oggetto,
|
|
||||||
html: html,
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await this.emailService.sendMail(emailOptions);
|
|
||||||
|
|
||||||
this.logger.info(`Email inviata a ${destinatario}: ${oggetto}`);
|
|
||||||
return { success: true, messageId: result.messageId };
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error(`Errore invio email a ${destinatario}:`, error);
|
|
||||||
return { success: false, error: error.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invia un messaggio Telegram
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
async _inviaTelegram(telegramId, messaggio, opzioni = {}) {
|
|
||||||
try {
|
|
||||||
if (!telegramId || telegramId === 0) {
|
|
||||||
this.logger.warn(`Telegram ID non valido: ${telegramId}`);
|
|
||||||
return { success: false, error: 'Telegram ID non valido' };
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
parse_mode: 'HTML',
|
|
||||||
disable_web_page_preview: false,
|
|
||||||
...opzioni,
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await this.telegramBot.sendMessage(telegramId, messaggio, defaultOptions);
|
|
||||||
|
|
||||||
this.logger.info(`Messaggio Telegram inviato a ${telegramId}`);
|
|
||||||
return { success: true, messageId: result.message_id };
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error(`Errore invio Telegram a ${telegramId}:`, error);
|
|
||||||
return { success: false, error: error.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invia notifica sia via email che Telegram
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
async _inviaNotificaDoppia(destinatario, opzioniEmail, opzioniTelegram) {
|
|
||||||
const risultati = {
|
|
||||||
email: null,
|
|
||||||
telegram: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invia email
|
|
||||||
if (destinatario.email) {
|
|
||||||
risultati.email = await this._inviaEmail(
|
|
||||||
destinatario.email,
|
|
||||||
opzioniEmail.oggetto,
|
|
||||||
opzioniEmail.html,
|
|
||||||
opzioniEmail.templatePath,
|
|
||||||
opzioniEmail.templateData
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invia Telegram
|
|
||||||
if (destinatario.telegramId && destinatario.telegramId !== 0) {
|
|
||||||
risultati.telegram = await this._inviaTelegram(
|
|
||||||
destinatario.telegramId,
|
|
||||||
opzioniTelegram.messaggio,
|
|
||||||
opzioniTelegram.opzioni
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return risultati;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invia copia all'amministratore
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
async _inviaCopiaCopiaAdmin(oggetto, messaggio) {
|
|
||||||
const risultati = {
|
|
||||||
email: null,
|
|
||||||
telegram: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Email admin
|
|
||||||
if (this.adminEmail) {
|
|
||||||
risultati.email = await this._inviaEmail(this.adminEmail, `[ADMIN] ${oggetto}`, messaggio);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Telegram admin
|
|
||||||
if (this.adminTelegramId) {
|
|
||||||
risultati.telegram = await this._inviaTelegram(this.adminTelegramId, `🔔 <b>NOTIFICA ADMIN</b>\n\n${messaggio}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return risultati;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// EVENTO 1: REGISTRAZIONE UTENTE
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gestisce le notifiche dopo la registrazione
|
|
||||||
* @param {Object} utente - Dati dell'utente registrato
|
|
||||||
* @param {String} tokenVerifica - Token per verifica email
|
|
||||||
*/
|
|
||||||
async notificaRegistrazione(utente, tokenVerifica) {
|
|
||||||
try {
|
|
||||||
this.logger.info(`Notifica registrazione per utente: ${utente.username}`);
|
|
||||||
|
|
||||||
// Se l'email è già verificata, salta la verifica e vai direttamente alla richiesta ammissione
|
|
||||||
if (utente.verified_email === true) {
|
|
||||||
this.logger.info(`Email già verificata per ${utente.username}, salto verifica email`);
|
|
||||||
|
|
||||||
// Invia direttamente la richiesta di ammissione all'invitante
|
|
||||||
await this.notificaRichiestaAmmissione(utente);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: 'Email già verificata, richiesta ammissione inviata',
|
|
||||||
emailVerificaInviata: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Email non verificata: invia email di verifica
|
|
||||||
const linkVerifica = `${this.baseUrl}/verifica-email/${tokenVerifica}`;
|
|
||||||
|
|
||||||
const templateData = {
|
|
||||||
name: utente.name,
|
|
||||||
username: utente.username,
|
|
||||||
emailto: utente.email,
|
|
||||||
nomeapp: this.nomeApp,
|
|
||||||
baseurl: this.baseUrl,
|
|
||||||
linkVerifica: linkVerifica,
|
|
||||||
};
|
|
||||||
|
|
||||||
const risultato = await this._inviaEmail(
|
|
||||||
utente.email,
|
|
||||||
`Verifica il tuo indirizzo email - ${this.nomeApp}`,
|
|
||||||
null,
|
|
||||||
this.emailTemplates.verificaEmail,
|
|
||||||
templateData
|
|
||||||
);
|
|
||||||
|
|
||||||
// Notifica admin della nuova registrazione
|
|
||||||
const messaggioAdmin = `
|
|
||||||
📝 <b>Nuova Registrazione</b>
|
|
||||||
|
|
||||||
👤 <b>Username:</b> ${utente.username}
|
|
||||||
📧 <b>Email:</b> ${utente.email}
|
|
||||||
${utente.name ? `🏷️ <b>Nome:</b> ${utente.name}` : ''}
|
|
||||||
✅ <b>Email verificata:</b> ${utente.verified_email ? 'Sì' : 'No'}
|
|
||||||
📅 <b>Data:</b> ${new Date().toLocaleString('it-IT')}
|
|
||||||
|
|
||||||
${utente.verified_email ? "✓ Richiesta ammissione inviata all'invitante" : '⏳ In attesa verifica email'}
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
await this._inviaCopiaCopiaAdmin('Nuova Registrazione', messaggioAdmin);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: 'Email di verifica inviata',
|
|
||||||
emailVerificaInviata: true,
|
|
||||||
risultato,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Errore in notificaRegistrazione:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// EVENTO 2: EMAIL VERIFICATA
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifica l'invitante che l'utente ha verificato l'email
|
|
||||||
* @param {Object} utente - Dati dell'utente che ha verificato l'email
|
|
||||||
*/
|
|
||||||
async notificaRichiestaAmmissione(utente) {
|
|
||||||
try {
|
|
||||||
this.logger.info(`Notifica richiesta ammissione per utente: ${utente.username}`);
|
|
||||||
|
|
||||||
// Recupera dati invitante (assumendo che tu abbia un metodo per recuperarlo)
|
|
||||||
const invitante = await this._getInvitante(utente.invitante_id);
|
|
||||||
|
|
||||||
if (!invitante) {
|
|
||||||
throw new Error(`Invitante non trovato per utente ${utente.username}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dati per email invitante
|
|
||||||
const templateDataInvitante = {
|
|
||||||
nomeInvitante: invitante.name || invitante.username,
|
|
||||||
nomeUtente: utente.name || utente.username,
|
|
||||||
usernameUtente: utente.username,
|
|
||||||
emailUtente: utente.email,
|
|
||||||
nomeapp: this.nomeApp,
|
|
||||||
baseurl: this.baseUrl,
|
|
||||||
linkAmmetti: `${this.baseUrl}/admin/ammetti-utente/${utente.id}`,
|
|
||||||
dataRegistrazione: new Date(utente.created_at).toLocaleDateString('it-IT'),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Messaggio Telegram per invitante
|
|
||||||
const messaggioTelegramInvitante = `
|
|
||||||
🎉 <b>Nuovo Utente da Ammettere!</b>
|
|
||||||
|
|
||||||
Ciao ${invitante.name || invitante.username}!
|
|
||||||
|
|
||||||
L'utente che hai invitato ha completato la registrazione:
|
|
||||||
|
|
||||||
👤 <b>Nome:</b> ${utente.name || 'Non specificato'}
|
|
||||||
🔑 <b>Username:</b> ${utente.username}
|
|
||||||
📧 <b>Email:</b> ${utente.email}
|
|
||||||
📅 <b>Registrato il:</b> ${new Date(utente.created_at).toLocaleDateString('it-IT')}
|
|
||||||
|
|
||||||
✅ <b>Azione richiesta:</b> Accedi alla piattaforma per ammettere questo utente alla comunità RISO.
|
|
||||||
|
|
||||||
<a href="${this.baseUrl}/admin/ammetti-utente/${utente.id}">👉 Clicca qui per ammettere</a>
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
// Invia notifica all'invitante
|
|
||||||
const risultatiInvitante = await this._inviaNotificaDoppia(
|
|
||||||
{
|
|
||||||
email: invitante.email,
|
|
||||||
telegramId: invitante.teleg_id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oggetto: `Nuovo utente da ammettere: ${utente.username}`,
|
|
||||||
templatePath: this.emailTemplates.richiestaAmmissione,
|
|
||||||
templateData: templateDataInvitante,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
messaggio: messaggioTelegramInvitante,
|
|
||||||
opzioni: {
|
|
||||||
reply_markup: {
|
|
||||||
inline_keyboard: [
|
|
||||||
[{ text: '✅ Ammetti Utente', url: `${this.baseUrl}/admin/ammetti-utente/${utente.id}` }],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Notifica admin
|
|
||||||
const messaggioAdmin = `
|
|
||||||
✅ <b>Email Verificata - Richiesta Ammissione</b>
|
|
||||||
|
|
||||||
👤 <b>Utente:</b> ${utente.username} (${utente.email})
|
|
||||||
👥 <b>Invitante:</b> ${invitante.username} (${invitante.email})
|
|
||||||
📅 <b>Data verifica:</b> ${new Date().toLocaleString('it-IT')}
|
|
||||||
|
|
||||||
📧 Notifica inviata all'invitante
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
await this._inviaCopiaCopiaAdmin('Richiesta Ammissione', messaggioAdmin);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: 'Notifica richiesta ammissione inviata',
|
|
||||||
risultatiInvitante,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Errore in notificaRichiestaAmmissione:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// EVENTO 3: UTENTE AMMESSO
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invia email di benvenuto all'utente ammesso
|
|
||||||
* @param {Object} utente - Dati dell'utente ammesso
|
|
||||||
*/
|
|
||||||
async notificaUtenteAmmesso(utente) {
|
|
||||||
try {
|
|
||||||
this.logger.info(`Notifica utente ammesso: ${utente.username}`);
|
|
||||||
|
|
||||||
// Dati per email benvenuto
|
|
||||||
const templateData = {
|
|
||||||
name: utente.name,
|
|
||||||
username: utente.username,
|
|
||||||
emailto: utente.email,
|
|
||||||
nomeapp: this.nomeApp,
|
|
||||||
baseurl: this.baseUrl,
|
|
||||||
strlinksito: this.baseUrl,
|
|
||||||
forgetpwd: `${this.baseUrl}/reset-password`,
|
|
||||||
verified_email: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invia email di benvenuto (template già esistente)
|
|
||||||
const risultatoEmail = await this._inviaEmail(
|
|
||||||
utente.email,
|
|
||||||
`💚 Benvenuto nella comunità ${this.nomeApp}!`,
|
|
||||||
null,
|
|
||||||
this.emailTemplates.benvenuto,
|
|
||||||
templateData
|
|
||||||
);
|
|
||||||
|
|
||||||
// Messaggio Telegram all'utente (se ha già Telegram collegato)
|
|
||||||
if (utente.teleg_id && utente.teleg_id !== 0) {
|
|
||||||
const messaggioTelegramUtente = `
|
|
||||||
🎉 <b>Benvenuto nella comunità RISO!</b>
|
|
||||||
|
|
||||||
Ciao ${utente.name || utente.username}!
|
|
||||||
|
|
||||||
Sei stato ammesso nella rete RISO! 🌱
|
|
||||||
|
|
||||||
Ora puoi:
|
|
||||||
✅ Completare il tuo profilo
|
|
||||||
📢 Pubblicare i tuoi primi annunci
|
|
||||||
🔍 Esplorare beni e servizi nella tua comunità
|
|
||||||
💬 Unirti al gruppo territoriale
|
|
||||||
|
|
||||||
<a href="${this.baseUrl}">👉 Accedi ora alla piattaforma</a>
|
|
||||||
|
|
||||||
Costruiamo insieme un'economia più umana e solidale! 💚
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
await this._inviaTelegram(utente.teleg_id, messaggioTelegramUtente, {
|
|
||||||
reply_markup: {
|
|
||||||
inline_keyboard: [[{ text: '🚀 Vai alla Piattaforma', url: this.baseUrl }]],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notifica admin
|
|
||||||
const messaggioAdmin = `
|
|
||||||
✅ <b>Utente Ammesso</b>
|
|
||||||
|
|
||||||
👤 <b>Username:</b> ${utente.username}
|
|
||||||
📧 <b>Email:</b> ${utente.email}
|
|
||||||
${utente.name ? `🏷️ <b>Nome:</b> ${utente.name}` : ''}
|
|
||||||
📅 <b>Ammesso il:</b> ${new Date().toLocaleString('it-IT')}
|
|
||||||
|
|
||||||
📧 Email di benvenuto inviata
|
|
||||||
${utente.teleg_id && utente.teleg_id !== 0 ? '📱 Notifica Telegram inviata' : '⏳ Telegram non ancora collegato'}
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
await this._inviaCopiaCopiaAdmin('Utente Ammesso', messaggioAdmin);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: 'Notifica utente ammesso inviata',
|
|
||||||
risultatoEmail,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Errore in notificaUtenteAmmesso:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// EVENTO 4: PROFILO COMPLETATO + TELEGRAM VERIFICATO
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifica l'invitante che l'utente ha completato il profilo e verificato Telegram
|
|
||||||
* @param {Object} utente - Dati dell'utente che ha completato il profilo
|
|
||||||
*/
|
|
||||||
async notificaProfiloCompletato(utente) {
|
|
||||||
try {
|
|
||||||
this.logger.info(`Notifica profilo completato per utente: ${utente.username}`);
|
|
||||||
|
|
||||||
// Verifica che il profilo sia effettivamente completo e Telegram verificato
|
|
||||||
if (!utente.teleg_id || utente.teleg_id === 0) {
|
|
||||||
this.logger.warn(`Telegram non verificato per ${utente.username}`);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: 'Telegram non ancora verificato',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recupera invitante
|
|
||||||
const invitante = await this._getInvitante(utente.invitante_id);
|
|
||||||
|
|
||||||
if (!invitante) {
|
|
||||||
throw new Error(`Invitante non trovato per utente ${utente.username}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dati per email invitante
|
|
||||||
const templateDataInvitante = {
|
|
||||||
nomeInvitante: invitante.name || invitante.username,
|
|
||||||
nomeUtente: utente.name || utente.username,
|
|
||||||
usernameUtente: utente.username,
|
|
||||||
nomeapp: this.nomeApp,
|
|
||||||
baseurl: this.baseUrl,
|
|
||||||
linkProfilo: `${this.baseUrl}/utenti/${utente.username}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Messaggio Telegram per invitante
|
|
||||||
const messaggioTelegramInvitante = `
|
|
||||||
🎊 <b>Profilo Completato!</b>
|
|
||||||
|
|
||||||
Ciao ${invitante.name || invitante.username}!
|
|
||||||
|
|
||||||
L'utente che hai invitato ha completato il suo profilo ed è ora attivo su RISO:
|
|
||||||
|
|
||||||
👤 <b>Nome:</b> ${utente.name || utente.username}
|
|
||||||
🔑 <b>Username:</b> @${utente.username}
|
|
||||||
✅ <b>Telegram:</b> Verificato
|
|
||||||
📱 <b>Profilo:</b> Completato
|
|
||||||
|
|
||||||
L'utente è ora un membro attivo della comunità e può iniziare a pubblicare annunci!
|
|
||||||
|
|
||||||
<a href="${this.baseUrl}/utenti/${utente.username}">👉 Visualizza profilo</a>
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
// Invia notifica all'invitante
|
|
||||||
const risultatiInvitante = await this._inviaNotificaDoppia(
|
|
||||||
{
|
|
||||||
email: invitante.email,
|
|
||||||
telegramId: invitante.teleg_id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oggetto: `${utente.username} ha completato il profilo su ${this.nomeApp}!`,
|
|
||||||
templatePath: this.emailTemplates.profiloCompletato,
|
|
||||||
templateData: templateDataInvitante,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
messaggio: messaggioTelegramInvitante,
|
|
||||||
opzioni: {
|
|
||||||
reply_markup: {
|
|
||||||
inline_keyboard: [[{ text: '👤 Visualizza Profilo', url: `${this.baseUrl}/utenti/${utente.username}` }]],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Notifica admin
|
|
||||||
const messaggioAdmin = `
|
|
||||||
✅ <b>Profilo Completato</b>
|
|
||||||
|
|
||||||
👤 <b>Utente:</b> ${utente.username}
|
|
||||||
📧 <b>Email:</b> ${utente.email}
|
|
||||||
📱 <b>Telegram:</b> Verificato (ID: ${utente.teleg_id})
|
|
||||||
👥 <b>Invitante:</b> ${invitante.username}
|
|
||||||
📅 <b>Data:</b> ${new Date().toLocaleString('it-IT')}
|
|
||||||
|
|
||||||
✅ L'utente è ora completamente attivo sulla piattaforma
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
await this._inviaCopiaCopiaAdmin('Profilo Completato', messaggioAdmin);
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: 'Notifica profilo completato inviata',
|
|
||||||
risultatiInvitante,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Errore in notificaProfiloCompletato:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// METODI HELPER
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recupera i dati dell'invitante (da implementare con il tuo DB)
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
async _getInvitante(invitanteId) {
|
|
||||||
// TODO: Implementa il recupero dell'invitante dal database
|
|
||||||
// Esempio con MongoDB:
|
|
||||||
// return await User.findById(invitanteId);
|
|
||||||
|
|
||||||
// Esempio con MySQL/PostgreSQL:
|
|
||||||
// return await db.query('SELECT * FROM users WHERE id = ?', [invitanteId]);
|
|
||||||
|
|
||||||
throw new Error('Metodo _getInvitante non implementato. Implementalo con il tuo database.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifica se il profilo utente è completo
|
|
||||||
* @param {Object} utente
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
isProfiloCompleto(utente) {
|
|
||||||
// Definisci i criteri per considerare un profilo completo
|
|
||||||
return !!(
|
|
||||||
(utente.name && utente.email && utente.teleg_id && utente.teleg_id !== 0)
|
|
||||||
// Aggiungi altri campi necessari
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Metodo principale per orchestrare le notifiche basate sugli eventi
|
|
||||||
* @param {String} evento - Tipo di evento
|
|
||||||
* @param {Object} dati - Dati dell'evento
|
|
||||||
*/
|
|
||||||
async gestisciEvento(evento, dati) {
|
|
||||||
try {
|
|
||||||
switch (evento) {
|
|
||||||
case 'REGISTRAZIONE':
|
|
||||||
return await this.notificaRegistrazione(dati.utente, dati.tokenVerifica);
|
|
||||||
|
|
||||||
case 'EMAIL_VERIFICATA':
|
|
||||||
return await this.notificaRichiestaAmmissione(dati.utente);
|
|
||||||
|
|
||||||
case 'UTENTE_AMMESSO':
|
|
||||||
return await this.notificaUtenteAmmesso(dati.utente);
|
|
||||||
|
|
||||||
case 'PROFILO_COMPLETATO':
|
|
||||||
// Verifica che Telegram sia effettivamente verificato
|
|
||||||
if (dati.utente.teleg_id && dati.utente.teleg_id !== 0) {
|
|
||||||
return await this.notificaProfiloCompletato(dati.utente);
|
|
||||||
} else {
|
|
||||||
this.logger.warn(`Profilo completato ma Telegram non verificato per ${dati.utente.username}`);
|
|
||||||
return { success: false, message: 'Telegram non verificato' };
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error(`Evento non riconosciuto: ${evento}`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error(`Errore gestione evento ${evento}:`, error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = InvioNotifiche;
|
|
||||||
@@ -1,541 +0,0 @@
|
|||||||
/**
|
|
||||||
* TEST UNITARI PER LA CLASSE InvioNotifiche
|
|
||||||
*
|
|
||||||
* Framework: Jest
|
|
||||||
* Installazione: npm install --save-dev jest
|
|
||||||
* Esecuzione: npm test
|
|
||||||
*/
|
|
||||||
|
|
||||||
const InvioNotifiche = require('./InvioNotifiche');
|
|
||||||
|
|
||||||
// Mock dei servizi esterni
|
|
||||||
const mockEmailService = {
|
|
||||||
sendMail: jest.fn().mockResolvedValue({ messageId: 'mock-email-id' })
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockTelegramBot = {
|
|
||||||
sendMessage: jest.fn().mockResolvedValue({ message_id: 123 })
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockLogger = {
|
|
||||||
info: jest.fn(),
|
|
||||||
warn: jest.fn(),
|
|
||||||
error: jest.fn()
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('InvioNotifiche', () => {
|
|
||||||
let notifiche;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
// Reset dei mock prima di ogni test
|
|
||||||
jest.clearAllMocks();
|
|
||||||
|
|
||||||
// Inizializza classe con mock
|
|
||||||
notifiche = new InvioNotifiche({
|
|
||||||
emailService: mockEmailService,
|
|
||||||
telegramBot: mockTelegramBot,
|
|
||||||
adminTelegramId: '999999999',
|
|
||||||
adminEmail: 'paolo@riso.app',
|
|
||||||
baseUrl: 'https://riso.app',
|
|
||||||
nomeApp: 'RISO',
|
|
||||||
emailTemplates: {
|
|
||||||
verificaEmail: './templates/verifica.pug',
|
|
||||||
richiestaAmmissione: './templates/ammissione.pug',
|
|
||||||
benvenuto: './templates/benvenuto.pug',
|
|
||||||
profiloCompletato: './templates/profilo.pug'
|
|
||||||
},
|
|
||||||
logger: mockLogger
|
|
||||||
});
|
|
||||||
|
|
||||||
// Mock del metodo _getInvitante
|
|
||||||
notifiche._getInvitante = jest.fn().mockResolvedValue({
|
|
||||||
id: 5,
|
|
||||||
username: 'invitante',
|
|
||||||
email: 'invitante@example.com',
|
|
||||||
name: 'Marco Invitante',
|
|
||||||
teleg_id: 111111111
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: notificaRegistrazione
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('notificaRegistrazione', () => {
|
|
||||||
|
|
||||||
test('Invia email di verifica quando verified_email = false', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
verified_email: false,
|
|
||||||
invitante_id: 5
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await notifiche.notificaRegistrazione(utente, 'token123');
|
|
||||||
|
|
||||||
// Verifica che l'email sia stata inviata
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalledTimes(2); // utente + admin
|
|
||||||
expect(result.emailVerificaInviata).toBe(true);
|
|
||||||
expect(result.success).toBe(true);
|
|
||||||
|
|
||||||
// Verifica logging
|
|
||||||
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
||||||
expect.stringContaining('Notifica registrazione')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Salta verifica email quando verified_email = true', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
verified_email: true,
|
|
||||||
invitante_id: 5
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await notifiche.notificaRegistrazione(utente, null);
|
|
||||||
|
|
||||||
// Verifica che NON sia stata inviata email di verifica
|
|
||||||
expect(result.emailVerificaInviata).toBe(false);
|
|
||||||
expect(result.success).toBe(true);
|
|
||||||
|
|
||||||
// Verifica che sia stata chiamata notificaRichiestaAmmissione
|
|
||||||
expect(notifiche._getInvitante).toHaveBeenCalledWith(5);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Gestisce errori correttamente', async () => {
|
|
||||||
mockEmailService.sendMail.mockRejectedValueOnce(new Error('SMTP Error'));
|
|
||||||
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
verified_email: false,
|
|
||||||
invitante_id: 5
|
|
||||||
};
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
notifiche.notificaRegistrazione(utente, 'token123')
|
|
||||||
).rejects.toThrow();
|
|
||||||
|
|
||||||
expect(mockLogger.error).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: notificaRichiestaAmmissione
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('notificaRichiestaAmmissione', () => {
|
|
||||||
|
|
||||||
test('Invia notifica email e telegram all\'invitante', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
invitante_id: 5,
|
|
||||||
created_at: new Date()
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await notifiche.notificaRichiestaAmmissione(utente);
|
|
||||||
|
|
||||||
// Verifica chiamate
|
|
||||||
expect(notifiche._getInvitante).toHaveBeenCalledWith(5);
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalled();
|
|
||||||
expect(mockTelegramBot.sendMessage).toHaveBeenCalled();
|
|
||||||
expect(result.success).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Gestisce invitante non trovato', async () => {
|
|
||||||
notifiche._getInvitante.mockResolvedValueOnce(null);
|
|
||||||
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
invitante_id: 999
|
|
||||||
};
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
notifiche.notificaRichiestaAmmissione(utente)
|
|
||||||
).rejects.toThrow('Invitante non trovato');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Invia notifica anche se Telegram fallisce', async () => {
|
|
||||||
mockTelegramBot.sendMessage.mockRejectedValueOnce(new Error('Telegram Error'));
|
|
||||||
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
invitante_id: 5,
|
|
||||||
created_at: new Date()
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await notifiche.notificaRichiestaAmmissione(utente);
|
|
||||||
|
|
||||||
// Email dovrebbe essere comunque inviata
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalled();
|
|
||||||
expect(mockLogger.error).toHaveBeenCalledWith(
|
|
||||||
expect.stringContaining('Errore invio Telegram'),
|
|
||||||
expect.any(Error)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: notificaUtenteAmmesso
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('notificaUtenteAmmesso', () => {
|
|
||||||
|
|
||||||
test('Invia email di benvenuto all\'utente', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
teleg_id: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await notifiche.notificaUtenteAmmesso(utente);
|
|
||||||
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalled();
|
|
||||||
expect(result.success).toBe(true);
|
|
||||||
|
|
||||||
// Verifica oggetto email
|
|
||||||
const emailCall = mockEmailService.sendMail.mock.calls[0][0];
|
|
||||||
expect(emailCall.subject).toContain('Benvenuto');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Invia anche Telegram se utente ha teleg_id', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
teleg_id: 123456789
|
|
||||||
};
|
|
||||||
|
|
||||||
await notifiche.notificaUtenteAmmesso(utente);
|
|
||||||
|
|
||||||
expect(mockTelegramBot.sendMessage).toHaveBeenCalledWith(
|
|
||||||
123456789,
|
|
||||||
expect.stringContaining('Benvenuto'),
|
|
||||||
expect.any(Object)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Salta Telegram se teleg_id = 0', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
teleg_id: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
await notifiche.notificaUtenteAmmesso(utente);
|
|
||||||
|
|
||||||
// Solo email, no Telegram
|
|
||||||
expect(mockTelegramBot.sendMessage).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: notificaProfiloCompletato
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('notificaProfiloCompletato', () => {
|
|
||||||
|
|
||||||
test('Invia notifica se Telegram è verificato', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
teleg_id: 123456789,
|
|
||||||
invitante_id: 5
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await notifiche.notificaProfiloCompletato(utente);
|
|
||||||
|
|
||||||
expect(notifiche._getInvitante).toHaveBeenCalledWith(5);
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalled();
|
|
||||||
expect(mockTelegramBot.sendMessage).toHaveBeenCalled();
|
|
||||||
expect(result.success).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Non invia se Telegram non verificato', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
teleg_id: 0,
|
|
||||||
invitante_id: 5
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await notifiche.notificaProfiloCompletato(utente);
|
|
||||||
|
|
||||||
expect(result.success).toBe(false);
|
|
||||||
expect(result.message).toContain('Telegram non ancora verificato');
|
|
||||||
expect(mockEmailService.sendMail).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: gestisciEvento
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('gestisciEvento', () => {
|
|
||||||
|
|
||||||
test('Gestisce evento REGISTRAZIONE', async () => {
|
|
||||||
const spy = jest.spyOn(notifiche, 'notificaRegistrazione');
|
|
||||||
|
|
||||||
await notifiche.gestisciEvento('REGISTRAZIONE', {
|
|
||||||
utente: { username: 'test' },
|
|
||||||
tokenVerifica: 'token123'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Gestisce evento EMAIL_VERIFICATA', async () => {
|
|
||||||
const spy = jest.spyOn(notifiche, 'notificaRichiestaAmmissione');
|
|
||||||
|
|
||||||
await notifiche.gestisciEvento('EMAIL_VERIFICATA', {
|
|
||||||
utente: { username: 'test', invitante_id: 5 }
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Gestisce evento UTENTE_AMMESSO', async () => {
|
|
||||||
const spy = jest.spyOn(notifiche, 'notificaUtenteAmmesso');
|
|
||||||
|
|
||||||
await notifiche.gestisciEvento('UTENTE_AMMESSO', {
|
|
||||||
utente: { username: 'test' }
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Gestisce evento PROFILO_COMPLETATO solo se Telegram verificato', async () => {
|
|
||||||
const spy = jest.spyOn(notifiche, 'notificaProfiloCompletato');
|
|
||||||
|
|
||||||
// Con Telegram verificato
|
|
||||||
await notifiche.gestisciEvento('PROFILO_COMPLETATO', {
|
|
||||||
utente: { username: 'test', teleg_id: 123, invitante_id: 5 }
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
|
|
||||||
spy.mockClear();
|
|
||||||
|
|
||||||
// Senza Telegram
|
|
||||||
const result = await notifiche.gestisciEvento('PROFILO_COMPLETATO', {
|
|
||||||
utente: { username: 'test', teleg_id: 0 }
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(spy).not.toHaveBeenCalled();
|
|
||||||
expect(result.success).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Lancia errore per evento non riconosciuto', async () => {
|
|
||||||
await expect(
|
|
||||||
notifiche.gestisciEvento('EVENTO_INESISTENTE', {})
|
|
||||||
).rejects.toThrow('Evento non riconosciuto');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: isProfiloCompleto
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('isProfiloCompleto', () => {
|
|
||||||
|
|
||||||
test('Ritorna true se profilo completo', () => {
|
|
||||||
const utente = {
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
teleg_id: 123456789
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(notifiche.isProfiloCompleto(utente)).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Ritorna false se manca name', () => {
|
|
||||||
const utente = {
|
|
||||||
email: 'mario@example.com',
|
|
||||||
teleg_id: 123456789
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(notifiche.isProfiloCompleto(utente)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Ritorna false se manca email', () => {
|
|
||||||
const utente = {
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
teleg_id: 123456789
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(notifiche.isProfiloCompleto(utente)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Ritorna false se Telegram non verificato', () => {
|
|
||||||
const utente = {
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
teleg_id: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(notifiche.isProfiloCompleto(utente)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: Metodi Privati
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('Metodi privati', () => {
|
|
||||||
|
|
||||||
test('_inviaEmail invia email correttamente', async () => {
|
|
||||||
const result = await notifiche._inviaEmail(
|
|
||||||
'test@example.com',
|
|
||||||
'Test Subject',
|
|
||||||
'<p>Test HTML</p>'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.success).toBe(true);
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
to: 'test@example.com',
|
|
||||||
subject: 'Test Subject',
|
|
||||||
html: '<p>Test HTML</p>'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_inviaTelegram invia messaggio correttamente', async () => {
|
|
||||||
const result = await notifiche._inviaTelegram(
|
|
||||||
123456789,
|
|
||||||
'Test message'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.success).toBe(true);
|
|
||||||
expect(mockTelegramBot.sendMessage).toHaveBeenCalledWith(
|
|
||||||
123456789,
|
|
||||||
'Test message',
|
|
||||||
expect.any(Object)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_inviaTelegram gestisce ID non valido', async () => {
|
|
||||||
const result = await notifiche._inviaTelegram(0, 'Test');
|
|
||||||
|
|
||||||
expect(result.success).toBe(false);
|
|
||||||
expect(result.error).toContain('non valido');
|
|
||||||
expect(mockLogger.warn).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('_inviaCopiaCopiaAdmin invia a email e telegram admin', async () => {
|
|
||||||
await notifiche._inviaCopiaCopiaAdmin('Test', 'Message');
|
|
||||||
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
to: 'admin@riso.app',
|
|
||||||
subject: '[ADMIN] Test'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(mockTelegramBot.sendMessage).toHaveBeenCalledWith(
|
|
||||||
'999999999',
|
|
||||||
expect.stringContaining('NOTIFICA ADMIN'),
|
|
||||||
expect.any(Object)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// TEST: Integrazione
|
|
||||||
// ============================================
|
|
||||||
|
|
||||||
describe('Test di Integrazione', () => {
|
|
||||||
let notifiche;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
notifiche = new InvioNotifiche({
|
|
||||||
emailService: mockEmailService,
|
|
||||||
telegramBot: mockTelegramBot,
|
|
||||||
adminTelegramId: '999999999',
|
|
||||||
adminEmail: 'admin@riso.app',
|
|
||||||
baseUrl: 'https://riso.app',
|
|
||||||
nomeApp: 'RISO',
|
|
||||||
emailTemplates: {},
|
|
||||||
logger: mockLogger
|
|
||||||
});
|
|
||||||
|
|
||||||
notifiche._getInvitante = jest.fn().mockResolvedValue({
|
|
||||||
id: 5,
|
|
||||||
username: 'invitante',
|
|
||||||
email: 'invitante@example.com',
|
|
||||||
teleg_id: 111111111
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Flusso completo: Registrazione → Verifica → Ammissione → Profilo', async () => {
|
|
||||||
const utente = {
|
|
||||||
id: 1,
|
|
||||||
username: 'mario.rossi',
|
|
||||||
email: 'mario@example.com',
|
|
||||||
name: 'Mario Rossi',
|
|
||||||
verified_email: false,
|
|
||||||
invitante_id: 5,
|
|
||||||
teleg_id: 0,
|
|
||||||
created_at: new Date()
|
|
||||||
};
|
|
||||||
|
|
||||||
// 1. Registrazione
|
|
||||||
await notifiche.notificaRegistrazione(utente, 'token123');
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalled();
|
|
||||||
|
|
||||||
// 2. Verifica email
|
|
||||||
utente.verified_email = true;
|
|
||||||
await notifiche.notificaRichiestaAmmissione(utente);
|
|
||||||
expect(notifiche._getInvitante).toHaveBeenCalled();
|
|
||||||
|
|
||||||
// 3. Ammissione
|
|
||||||
await notifiche.notificaUtenteAmmesso(utente);
|
|
||||||
expect(mockEmailService.sendMail).toHaveBeenCalled();
|
|
||||||
|
|
||||||
// 4. Profilo completato
|
|
||||||
utente.teleg_id = 123456789;
|
|
||||||
await notifiche.notificaProfiloCompletato(utente);
|
|
||||||
expect(mockTelegramBot.sendMessage).toHaveBeenCalled();
|
|
||||||
|
|
||||||
// Verifica che tutte le notifiche admin siano state inviate
|
|
||||||
const adminCalls = mockEmailService.sendMail.mock.calls.filter(
|
|
||||||
call => call[0].subject.includes('[ADMIN]')
|
|
||||||
);
|
|
||||||
expect(adminCalls.length).toBeGreaterThan(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Configurazione package.json per Jest
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"test": "jest",
|
|
||||||
"test:watch": "jest --watch",
|
|
||||||
"test:coverage": "jest --coverage"
|
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"testEnvironment": "node",
|
|
||||||
"coveragePathIgnorePatterns": ["/node_modules/"],
|
|
||||||
"testMatch": ["**/__tests__/**/*.js", "**/?(*.)+(spec|test).js"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -143,9 +143,9 @@ router.post('/ammetti', (req, res) => {
|
|||||||
} else {
|
} else {
|
||||||
const lang = user.lang;
|
const lang = user.lang;
|
||||||
console.log('user', user);
|
console.log('user', user);
|
||||||
user.verified_by_aportador = false;
|
// user.verified_by_aportador = false;
|
||||||
if (user.verified_by_aportador) {
|
if (user.verified_by_aportador) {
|
||||||
res.send({
|
return res.send({
|
||||||
code: server_constants.RIS_CODE_GIA_AMMESSO,
|
code: server_constants.RIS_CODE_GIA_AMMESSO,
|
||||||
msg: 'Il membro ' + user.username + ' è stato già Ammesso!',
|
msg: 'Il membro ' + user.username + ' è stato già Ammesso!',
|
||||||
});
|
});
|
||||||
@@ -180,7 +180,7 @@ router.post('/ammetti', (req, res) => {
|
|||||||
|
|
||||||
// user.token_da_ammettere = 'OK';
|
// user.token_da_ammettere = 'OK';
|
||||||
user.save().then(() => {
|
user.save().then(() => {
|
||||||
res.send({
|
return res.send({
|
||||||
code: server_constants.RIS_CODE_AMMESSO,
|
code: server_constants.RIS_CODE_AMMESSO,
|
||||||
msg: 'Ottimo! Hai ammesso ' + user.username + '!',
|
msg: 'Ottimo! Hai ammesso ' + user.username + '!',
|
||||||
//msg: tools.getres__('Ottimo! Hai ammesso', res) + ' ' + user.username + '!',
|
//msg: tools.getres__('Ottimo! Hai ammesso', res) + ' ' + user.username + '!',
|
||||||
@@ -199,6 +199,68 @@ router.post('/ammetti', (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/abcirc', async (req, res) => {
|
||||||
|
const body = _.pick(req.body, ['idapp', 'token', 'username', 'username_action', 'cmd', 'groupname']);
|
||||||
|
const idapp = body.idapp;
|
||||||
|
const token = body.token;
|
||||||
|
const username = body.username;
|
||||||
|
const groupname = body.groupname;
|
||||||
|
const username_action = body.username_action;
|
||||||
|
const cmd = body.cmd;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Cerco il token se è ancora da ammettere
|
||||||
|
|
||||||
|
await User.getCircuitByTokenAndUsername(idapp, username, token)
|
||||||
|
.then(async (ris) => {
|
||||||
|
const { circuitname, user } = ris;
|
||||||
|
if (!user) {
|
||||||
|
return res.status(404).send();
|
||||||
|
} else {
|
||||||
|
const lang = user.lang;
|
||||||
|
// console.log('user', user);
|
||||||
|
|
||||||
|
let nomeCircuito = circuitname;
|
||||||
|
let giaabilitato = false;
|
||||||
|
|
||||||
|
let ret = null;
|
||||||
|
|
||||||
|
// user.verified_by_aportador = false;
|
||||||
|
if (giaabilitato) {
|
||||||
|
res.send({
|
||||||
|
code: server_constants.RIS_CODE_GIA_AMMESSO,
|
||||||
|
msg: 'Il membro ' + user.username + ' è stato già Abilitato!',
|
||||||
|
circuitName: nomeCircuito,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ret = await User.setCircuitCmd(user.idapp, username, nomeCircuito, cmd, 0, username_action, {
|
||||||
|
groupname,
|
||||||
|
});
|
||||||
|
return res.send({
|
||||||
|
code: server_constants.RIS_CODE_AMMESSO,
|
||||||
|
msg: 'Ottimo! Hai abilitato ' + user.username + ' al circuito ' + nomeCircuito + '!',
|
||||||
|
circuitName: nomeCircuito,
|
||||||
|
//msg: tools.getres__('Ottimo! Hai ammesso', res) + ' ' + user.username + '!',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.send({
|
||||||
|
code: server_constants.RIS_CODE_GIA_AMMESSO,
|
||||||
|
msg: 'L\'utente è già stato abilitato al circuito ' + nomeCircuito + '!',
|
||||||
|
circuitName: nomeCircuito,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log('Errore Abilitazione Circuito:', e.message);
|
||||||
|
res.status(400).send();
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Errore: ', e);
|
||||||
|
res.status(400).send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.post(process.env.LINKVERIF_REG, (req, res) => {
|
router.post(process.env.LINKVERIF_REG, (req, res) => {
|
||||||
const body = _.pick(req.body, ['idapp', 'idlink']);
|
const body = _.pick(req.body, ['idapp', 'idlink']);
|
||||||
const idapp = body.idapp;
|
const idapp = body.idapp;
|
||||||
@@ -1597,7 +1659,9 @@ router.patch('/chval', authenticate, async (req, res) => {
|
|||||||
|
|
||||||
profileData = await User.updateProvinceUserByComune(idapp, id, idcomune);
|
profileData = await User.updateProvinceUserByComune(idapp, id, idcomune);
|
||||||
|
|
||||||
provincia = profileData['profile.resid_province'];
|
provincia = profileData.profile.resid_province;
|
||||||
|
} else {
|
||||||
|
provincia = rec.profile.resid_province;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (provincia) {
|
if (provincia) {
|
||||||
|
|||||||
@@ -505,9 +505,16 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
|
getLinkAbilitaCircuito: function (idapp, user, data) {
|
||||||
|
if (data.token_circuito_da_ammettere) {
|
||||||
|
const strlink = tools.getHostByIdApp(idapp) + `/abcirc/${data.cmd}/${data.token_circuito_da_ammettere}/${user.username}`;
|
||||||
|
return strlink;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
|
||||||
getPathEmail(idapp, email_template) {
|
getPathEmail(idapp, email_template) {
|
||||||
const RISO_TEMPLATES = ['reg_notifica_all_invitante', 'reg_email_benvenuto_ammesso', 'reg_chiedi_ammettere_all_invitante'];
|
const RISO_TEMPLATES = ['reg_notifica_all_invitante', 'reg_email_benvenuto_ammesso', 'reg_chiedi_ammettere_all_invitante', 'circuit_chiedi_facilitatori_di_entrare'];
|
||||||
|
|
||||||
if (idapp === '13') {
|
if (idapp === '13') {
|
||||||
if (RISO_TEMPLATES.includes(email_template)) {
|
if (RISO_TEMPLATES.includes(email_template)) {
|
||||||
@@ -667,6 +674,53 @@ module.exports = {
|
|||||||
console.error('Err sendEmail_Utente_Ammesso', e);
|
console.error('Err sendEmail_Utente_Ammesso', e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
sendEmail_Richiesta_Al_Facilitatore_Di_FarEntrare_AlCircuito: async function (lang, emailto, user, userInvitante, idapp, dati) {
|
||||||
|
try {
|
||||||
|
// dati.circuitId
|
||||||
|
// dati.groupname
|
||||||
|
dati.cmd = shared_consts.CallFunz.RICHIESTA_FIDO;
|
||||||
|
|
||||||
|
const linkAbilitazione = this.getLinkAbilitaCircuito(idapp, user, dati);
|
||||||
|
|
||||||
|
let mylocalsconf = {
|
||||||
|
idapp,
|
||||||
|
dataemail: await this.getdataemail(idapp),
|
||||||
|
baseurl: tools.getHostByIdApp(idapp),
|
||||||
|
locale: lang,
|
||||||
|
usernameInvitante: user.aportador_solidario,
|
||||||
|
nomeInvitante: userInvitante.name,
|
||||||
|
cognomeInvitante: userInvitante.surname,
|
||||||
|
nomeapp: tools.getNomeAppByIdApp(idapp),
|
||||||
|
strlinksito: tools.getHostByIdApp(idapp),
|
||||||
|
//strlinkreg: this.getlinkReg(idapp, idreg),
|
||||||
|
emailto: emailto,
|
||||||
|
usernameMembro: user.username,
|
||||||
|
nomeMembro: user.name,
|
||||||
|
cognomeMembro: user.surname,
|
||||||
|
emailMembro: user.email,
|
||||||
|
nomeFacilitatore: dati.nomeFacilitatore,
|
||||||
|
nomeTerritorio: dati.nomeTerritorio,
|
||||||
|
comuneResidenza: user.profile.resid_str_comune,
|
||||||
|
provinciaResidenza: user.profile.resid_province,
|
||||||
|
user,
|
||||||
|
linkAbilitazione: linkAbilitazione,
|
||||||
|
linkProfiloMembro: tools.getLinkUserProfile(idapp, user.username),
|
||||||
|
linkProfiloInvitante: tools.getLinkUserProfile(idapp, user.aportador_solidario),
|
||||||
|
telegramMembro: user.profile?.username_telegram,
|
||||||
|
telegramInvitante: userInvitante.profile?.username_telegram,
|
||||||
|
};
|
||||||
|
|
||||||
|
const quale_email_inviare = this.getPathEmail(idapp, 'circuit_chiedi_facilitatori_di_entrare') + '/' + lang;
|
||||||
|
|
||||||
|
const ris = await this.sendEmail_base(quale_email_inviare, emailto, mylocalsconf, '');
|
||||||
|
|
||||||
|
// await telegrambot.notifyToTelegram(telegrambot.phase.AMMETTI_UTENTE, mylocalsconf);
|
||||||
|
|
||||||
|
return ris;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Err sendEmail_Richiesta_Al_Facilitatore_Di_FarEntrare_AlCircuito', e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
sendEmail_IscrizioneConacreis: async function (lang, emailto, iscritto, idapp) {
|
sendEmail_IscrizioneConacreis: async function (lang, emailto, iscritto, idapp) {
|
||||||
// console.log('idapp', idapp, tools.getNomeAppByIdApp(idapp));
|
// console.log('idapp', idapp, tools.getNomeAppByIdApp(idapp));
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ const txt = {
|
|||||||
MSG_ACCEPT_NEWENTRY_INGROUP: '❇️👥 🧍♂️ Accetta Ingresso nel GRUPPO %s:',
|
MSG_ACCEPT_NEWENTRY_INGROUP: '❇️👥 🧍♂️ Accetta Ingresso nel GRUPPO %s:',
|
||||||
MSG_FRIENDS_NOT_ACCEPTED_CONFIRMED: '🚫 Hai rifiutato la richiesta di Amicizia di %s !',
|
MSG_FRIENDS_NOT_ACCEPTED_CONFIRMED: '🚫 Hai rifiutato la richiesta di Amicizia di %s !',
|
||||||
MSG_HANDSHAKE_NOT_ACCEPTED_CONFIRMED: '🚫 Hai rifiutato la richiesta di Stretta di mano di %s !',
|
MSG_HANDSHAKE_NOT_ACCEPTED_CONFIRMED: '🚫 Hai rifiutato la richiesta di Stretta di mano di %s !',
|
||||||
MSG_APORTADOR_CONFIRMED: '✅ %s è stato Ammesso correttamente (da %s)!',
|
MSG_APORTADOR_CONFIRMED: '✅ %s è stato Ammesso correttamente (da %s) tramite Telegram!',
|
||||||
MSG_APORTADOR_DEST_CONFIRMED:
|
MSG_APORTADOR_DEST_CONFIRMED:
|
||||||
'✅ La tua registrazione a %s è stata accettata da %s!\n' + 'Vai sulla App oppure clicca qui per entrare\n👉🏻 %s',
|
'✅ La tua registrazione a %s è stata accettata da %s!\n' + 'Vai sulla App oppure clicca qui per entrare\n👉🏻 %s',
|
||||||
MSG_GROUP_CONFIRMED: '✅ Sei stato Aggiunto sul Gruppo %s!',
|
MSG_GROUP_CONFIRMED: '✅ Sei stato Aggiunto sul Gruppo %s!',
|
||||||
@@ -838,6 +838,8 @@ const MyTelegramBot = {
|
|||||||
groupname = ''
|
groupname = ''
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
const sendemail = require('../sendemail');
|
||||||
|
|
||||||
const cl = getclTelegByidapp(idapp);
|
const cl = getclTelegByidapp(idapp);
|
||||||
if (!cl) return false;
|
if (!cl) return false;
|
||||||
|
|
||||||
@@ -1000,6 +1002,7 @@ const MyTelegramBot = {
|
|||||||
groupid + tools.SEP + groupname,
|
groupid + tools.SEP + groupname,
|
||||||
},*/
|
},*/
|
||||||
]);
|
]);
|
||||||
|
|
||||||
send_notif = true;
|
send_notif = true;
|
||||||
} else {
|
} else {
|
||||||
msg_notifpush = i18n.__({ phrase: 'CIRCUIT_ACCEPT_NEWENTRY', locale: langdest }, myuser.username, name);
|
msg_notifpush = i18n.__({ phrase: 'CIRCUIT_ACCEPT_NEWENTRY', locale: langdest }, myuser.username, name);
|
||||||
@@ -1032,6 +1035,37 @@ const MyTelegramBot = {
|
|||||||
]);
|
]);
|
||||||
send_notif = true;
|
send_notif = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mycircuit = await Circuit.getCircuitByCircuitId(circuitId);
|
||||||
|
// Invia Email ai facilitatori
|
||||||
|
// const usersmanagers = await Circuit.getListAdminsByCircuitPath(myuser.idapp, mycircuit.path);
|
||||||
|
|
||||||
|
// Ottiene il token relativo all'Utente e a quel circuito
|
||||||
|
const token = await User.getTokenByUsernameAndCircuitName(myuser.idapp, myuser.username, mycircuit.name);
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
const data = {
|
||||||
|
token_circuito_da_ammettere: token,
|
||||||
|
nomeTerritorio: mycircuit.name,
|
||||||
|
};
|
||||||
|
// if (usersmanagers) {
|
||||||
|
// for (const recadminCirc of usersmanagers) {
|
||||||
|
data.nomeFacilitatore = userrecDest.username;
|
||||||
|
|
||||||
|
const myusercompleto = await User.getUserByUsername(myuser.idapp, myuser.username);
|
||||||
|
const userInvitante = await User.getUserByUsername(myuser.idapp, myusercompleto.aportador_solidario);
|
||||||
|
|
||||||
|
await sendemail.sendEmail_Richiesta_Al_Facilitatore_Di_FarEntrare_AlCircuito(
|
||||||
|
myuser.lang,
|
||||||
|
userrecDest.email,
|
||||||
|
myusercompleto,
|
||||||
|
userInvitante,
|
||||||
|
idapp,
|
||||||
|
data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
} else if (myfunc === shared_consts.CallFunz.RICHIESTA_CIRCUIT) {
|
} else if (myfunc === shared_consts.CallFunz.RICHIESTA_CIRCUIT) {
|
||||||
if (groupname) {
|
if (groupname) {
|
||||||
msg_notifpush = i18n.__({ phrase: 'CIRCUIT_ACCEPT_NEWENTRY_BYGROUP_CIRC', locale: langdest }, groupname);
|
msg_notifpush = i18n.__({ phrase: 'CIRCUIT_ACCEPT_NEWENTRY_BYGROUP_CIRC', locale: langdest }, groupname);
|
||||||
@@ -4574,7 +4608,7 @@ if (true) {
|
|||||||
userDest,
|
userDest,
|
||||||
null,
|
null,
|
||||||
user.idapp,
|
user.idapp,
|
||||||
null,
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
await local_sendMsgTelegram(user.idapp, data.username, msgOrig);
|
await local_sendMsgTelegram(user.idapp, data.username, msgOrig);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user