Compare commits
10 Commits
c46d23cb83
...
b8dcd7f5e0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8dcd7f5e0 | ||
|
|
b35c99c8fb | ||
|
|
086e4ab8ba | ||
|
|
139d3fe241 | ||
|
|
6fe3ed7c8b | ||
|
|
81ae2df8ef | ||
|
|
997a7b8b98 | ||
|
|
331a5451b2 | ||
|
|
514c2488cc | ||
|
|
33e51bac0e |
@@ -30,8 +30,9 @@ SECRK=iUUb38v23jjDFaosWj92axkBOXCQ
|
||||
TOKEN_LIFE=30d
|
||||
REFRESH_TOKEN_LIFE=30d
|
||||
AUTH_NEW_SITES=B234HDSAOJ734ndcsdKWNV
|
||||
DOMAINS=[{"hostname":"riso.app","port":"3006"},{"hostname":"freeplanet.app","port":"3000"},{"hostname":"nuovomondo.app","port":"3032"},{"hostname":"germogliamo.app","port":"3042"}]
|
||||
DOMAINS_ALLOWED=["riso.app","comunitanuovomondo.app","nuovomondo.app","kolibrilab.it","artenergetica.org","freeplanet.app","www.freeplanet.app","freeplanet.app:3000","freeplanet.app:3001","www.freeplanet.app:3000","www.freeplanet.app:3001"]
|
||||
DOMAINS=[{"hostname":"riso.app","port":"3006"},{"hostname":"freeplanet.app","port":"3000"},{"hostname":"nuovomondo.app","port":"3032"}]
|
||||
DOMAINS_NEW=[{"hostname":"riso.app","port":"3006"},{"hostname":"freeplanet.app","port":"3000"},{"hostname":"nuovomondo.app","port":"3032"},{"hostname":"germogliamo.app","port":"3042"}]
|
||||
DOMAINS_ALLOWED=["riso.app","germogliamo.app","comunitanuovomondo.app","nuovomondo.app","kolibrilab.it","artenergetica.org","freeplanet.app","www.freeplanet.app","freeplanet.app:3000","freeplanet.app:3001","www.freeplanet.app:3000","www.freeplanet.app:3001"]
|
||||
#DOMAINS=[{"hostname":"abitaregliiblei.it","port":"3021"},{"hostname":"riso.app","port":"3005"}]
|
||||
SCRIPTS_DIR=admin_scripts
|
||||
CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}]
|
||||
|
||||
@@ -164,6 +164,7 @@ db.users.insertMany([
|
||||
"stepTutorial": 0,
|
||||
"noNameSurname": false,
|
||||
"noCircuit": false,
|
||||
"noComune": false,
|
||||
"noCircIta": false,
|
||||
"insert_circuito_ita": false,
|
||||
"noFoto": false,
|
||||
@@ -282,6 +283,7 @@ db.users.insertMany([
|
||||
"stepTutorial": 0,
|
||||
"noNameSurname": false,
|
||||
"noCircuit": false,
|
||||
"noComune": false,
|
||||
"noCircIta": false,
|
||||
"insert_circuito_ita": false,
|
||||
"noFoto": false,
|
||||
|
||||
492
emails/RISO/circuit_abilitato_al_fido_membro/it/html.pug
Executable file
492
emails/RISO/circuit_abilitato_al_fido_membro/it/html.pug
Executable file
@@ -0,0 +1,492 @@
|
||||
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;
|
||||
}
|
||||
|
||||
.email-body {
|
||||
padding: 32px 24px;
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.congrats-card {
|
||||
background: linear-gradient(135deg, #e8f5e9 0%, #f1f8f4 100%);
|
||||
border: 2px solid #7cb342;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.congrats-card .congrats-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.congrats-card h3 {
|
||||
font-size: 22px;
|
||||
color: #558b2f;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.congrats-card .territory-name {
|
||||
font-size: 20px;
|
||||
color: #7cb342;
|
||||
font-weight: 600;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
background: #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-section h3 {
|
||||
font-size: 18px;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.info-section p {
|
||||
font-size: 15px;
|
||||
color: #555;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.info-section ul {
|
||||
margin: 12px 0;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.info-section li {
|
||||
font-size: 15px;
|
||||
color: #555;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.highlight-box {
|
||||
background: linear-gradient(135deg, #fff8dc 0%, #fef9f3 100%);
|
||||
border-left: 4px solid #f0ad4e;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.highlight-box h4 {
|
||||
font-size: 17px;
|
||||
color: #f0ad4e;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.highlight-box p {
|
||||
font-size: 15px;
|
||||
color: #555;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.example-box {
|
||||
background: #e3f2fd;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.example-box h4 {
|
||||
font-size: 16px;
|
||||
color: #1976d2;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.example-box .transaction {
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
margin: 8px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.example-box .benefit {
|
||||
background: #c8e6c9;
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
margin-top: 12px;
|
||||
font-size: 14px;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.steps-box {
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.steps-box h4 {
|
||||
font-size: 17px;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 16px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16px;
|
||||
padding: 12px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
color: #7cb342;
|
||||
min-width: 40px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.step-content h5 {
|
||||
font-size: 16px;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 6px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.step-content p {
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.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, #7cb342 0%, #558b2f 100%);
|
||||
border-radius: 50px;
|
||||
text-decoration: none;
|
||||
box-shadow: 0 6px 20px rgba(124, 179, 66, 0.4);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.button-icon {
|
||||
font-size: 20px;
|
||||
margin-right: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.community-box {
|
||||
background: linear-gradient(135deg, #e8f5e9 0%, #f1f8f4 100%);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.community-box h4 {
|
||||
font-size: 17px;
|
||||
color: #558b2f;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.community-box p {
|
||||
font-size: 15px;
|
||||
color: #555;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.community-box a {
|
||||
color: #2196f3;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.email-body {
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
.congrats-card .congrats-icon {
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.congrats-card h3 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.cta-button {
|
||||
padding: 16px 40px;
|
||||
font-size: 18px;
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
body
|
||||
.email-container
|
||||
//- Header
|
||||
.email-header
|
||||
img.header-logo(src=baseurl+'/images/logo.png' alt=nomeapp)
|
||||
h1 🎉 Benvenuto nel #{nomeTerritorio}!
|
||||
p.subtitle Sei stato abilitato con successo
|
||||
|
||||
//- Body
|
||||
.email-body
|
||||
//- Intro
|
||||
.intro-text
|
||||
| Ciao <strong>#{usernameMembro}</strong>,<br>
|
||||
| complimenti! Sei stato abilitato al Circuito RIS del tuo territorio da #{usernameInvitante}.
|
||||
|
||||
if linkProfiloAdmin
|
||||
.divider(style="margin: 16px 0;")
|
||||
p(style="text-align: center; margin: 16px 0;")
|
||||
a.profile-button(href=linkProfiloAdmin target="_blank" style="display: inline-block; padding: 10px 24px; font-size: 15px; font-weight: 600; color: #7cb342; background: white; border: 2px solid #7cb342; border-radius: 20px; text-decoration: none; transition: all 0.3s ease;")
|
||||
span(style="margin-right: 6px;") 👤
|
||||
| Profilo #{usernameInvitante}
|
||||
|
||||
//- Congratulazioni
|
||||
.congrats-card
|
||||
.congrats-icon ✅
|
||||
h3 Abilitazione Completata
|
||||
p(style="font-size: 15px; color: #555; margin-top: 8px;")
|
||||
| Ora puoi utilizzare i RIS per i tuoi scambi nella comunità
|
||||
.territory-name 📍 #{nomeTerritorio}
|
||||
|
||||
//- Info comunità
|
||||
.community-box
|
||||
h4 💬 Unisciti alla Comunità Territoriale
|
||||
p
|
||||
| Entra nel gruppo Telegram di <strong>#{nomeTerritorio}</strong> per interagire con i partecipanti, rimanere aggiornato su eventi, mercatini e opportunità di scambio nella tua zona, e per poter inserire, anche tu, annunci di offro/cerco.
|
||||
|
||||
if linkTelegramTerritorio
|
||||
a.telegram-button(href=linkTelegramTerritorio target="_blank" style="display: inline-block; margin-top: 16px; padding: 14px 32px; font-size: 17px; font-weight: 600; color: white; background: linear-gradient(135deg, #0088cc 0%, #006699 100%); border-radius: 25px; text-decoration: none; box-shadow: 0 4px 12px rgba(0, 136, 204, 0.3); transition: all 0.3s ease;")
|
||||
span(style="font-size: 20px; margin-right: 8px; vertical-align: middle;") ✈️
|
||||
| Unisciti al gruppo Telegram
|
||||
|
||||
//- Cos'è RIS
|
||||
.info-section
|
||||
h3
|
||||
span 💰
|
||||
| Cosa sono i RIS?
|
||||
p
|
||||
| <strong>RIS</strong> (Rete Italiana Scambio) è un sistema di <strong>credito comunitario</strong> basato sulla fiducia reciproca. Non sono soldi tradizionali, ma un'unità di misura che rappresenta il valore degli scambi all'interno della comunità RISO.
|
||||
p
|
||||
| <strong>Parità con l'Euro:</strong> 1 RIS = 1 Euro (solo come riferimento di valore, non come convertibilità)
|
||||
|
||||
//- Come funziona la fiducia
|
||||
.highlight-box
|
||||
h4 🤝 Come Funziona la "Fiducia Concessa"
|
||||
p
|
||||
| <strong>Parti da 0 RIS</strong> - Non devi avere un "saldo positivo" per iniziare a scambiare!
|
||||
p
|
||||
| <strong>Quando ricevi</strong> un bene o servizio pagando in RIS → il tuo saldo <strong>diventa positivo</strong>
|
||||
p
|
||||
| <strong>Quando offri</strong> un bene o servizio ricevendo RIS → il tuo saldo <strong>diventa negativo</strong>
|
||||
p(style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #f0ad4e;")
|
||||
| 💡 <strong>Il saldo negativo non è un debito!</strong> È la fiducia che la comunità ti concede. Significa che hai ricevuto prima di aver dato, e la comunità si fida che restituirai nel tempo.
|
||||
|
||||
//- Esempio pratico
|
||||
.example-box
|
||||
h4 📖 Esempio Pratico
|
||||
.transaction
|
||||
| <strong>Situazione:</strong> Sei un grafico e vuoi comprare 100€ di verdure da un produttore locale
|
||||
.transaction
|
||||
| <strong>Transazione mista:</strong>
|
||||
| <br>• Paghi <strong>80€ in Euro</strong>
|
||||
| <br>• Paghi <strong>20 RIS</strong> (20% in RIS)
|
||||
| <br><br>🔻 Il tuo saldo RIS passa da 0 a <strong>-20 RIS</strong>
|
||||
.benefit
|
||||
| <strong>✓ Beneficio:</strong> Hai ridotto del 20% l'uso degli Euro, sostenendo il produttore locale e rafforzando la comunità! Puoi iniziare con percentuali basse (5-10%) e aumentare man mano che acquisisci fiducia.
|
||||
|
||||
//- Come riequilibrare
|
||||
.info-section
|
||||
h3
|
||||
span ⚖️
|
||||
| Come Riequilibrare il Saldo
|
||||
p
|
||||
| Per riportare il tuo saldo verso lo zero (o in positivo), puoi:
|
||||
ul
|
||||
li <strong>Offrire beni o servizi</strong> ricevendo RIS in cambio
|
||||
li <strong>Vendere prodotti</strong> accettando pagamenti parziali o totali in RIS
|
||||
li <strong>Mettere annunci</strong> sulla piattaforma specificando che accetti RIS
|
||||
li <strong>Partecipare ai mercatini</strong> locali della comunità RISO
|
||||
|
||||
//- Primi passi
|
||||
.steps-box
|
||||
h4 🚀 I Tuoi Primi Passi
|
||||
.step-item
|
||||
.step-number 1
|
||||
.step-content
|
||||
h5 Esplora la Piattaforma
|
||||
p Familiarizza con gli annunci, i membri e le funzionalità del Circuito RIS
|
||||
.step-item
|
||||
.step-number 2
|
||||
.step-content
|
||||
h5 Crea il Tuo Primo Annuncio
|
||||
p Pubblica cosa offri o cosa cerchi, specificando se accetti pagamenti in RIS
|
||||
.step-item
|
||||
.step-number 3
|
||||
.step-content
|
||||
h5 Inizia con Piccole Transazioni
|
||||
p Comincia con percentuali basse di RIS (5-10%) per prendere confidenza e vedi cosa succede. Più siamo aperti noi e più l'Universo ci aiuta e sostiene e ci dona quello di cui abbiamo bisogno.
|
||||
.step-item
|
||||
.step-number 4
|
||||
.step-content
|
||||
h5 Partecipa alla Comunità
|
||||
p Unisciti agli incontri locali e ai mercatini per conoscere altri membri. Se non ci sono membri che propongono incontri, puoi proporti anche tu!
|
||||
|
||||
//- CTA
|
||||
.cta-section
|
||||
.cta-title Inizia Subito a Usare i RIS!
|
||||
a.cta-button(href=strlinksito target="_blank")
|
||||
span.button-icon 🌾
|
||||
| Vai alla Piattaforma
|
||||
|
||||
//- Supporto
|
||||
.info-section
|
||||
h3
|
||||
span ❓
|
||||
| Hai Domande?
|
||||
p
|
||||
| Se hai dubbi sul funzionamento dei RIS o sulla piattaforma, non esitare a:
|
||||
ul
|
||||
li Contattare il facilitatore del tuo territorio
|
||||
li Chiedere nel gruppo Telegram locale
|
||||
li Partecipare agli incontri di comunità
|
||||
|
||||
//- Footer
|
||||
.email-footer
|
||||
.divider
|
||||
p Benvenuto nella Rete Italiana Scambio orizzontale - #{nomeTerritorio}
|
||||
p(style="margin-top: 12px; font-size: 12px;")
|
||||
| #{new Date().getFullYear()} #{nomeapp}
|
||||
1
emails/RISO/circuit_abilitato_al_fido_membro/it/subject.pug
Executable file
1
emails/RISO/circuit_abilitato_al_fido_membro/it/subject.pug
Executable file
@@ -0,0 +1 @@
|
||||
=`Richiesta ingresso di ${usernameMembro} - ${nomeMembro} ${cognomeMembro} su ${nomeTerritorio} in ${nomeapp}`
|
||||
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
|
||||
//- 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
|
||||
p.subtitle Nuovo membro in attesa
|
||||
|
||||
@@ -317,6 +317,10 @@ html(lang="it")
|
||||
.member-detail
|
||||
strong Email:
|
||||
| #{emailInvitato}
|
||||
if userprofile && userprofile.profile.resid_str_comune && userprofile.profile.resid_province
|
||||
.member-detail
|
||||
strong Comune Residenza:
|
||||
| #{userprofile.profile.resid_str_comune} (#{userprofile.profile.resid_province})
|
||||
|
||||
//- Domanda di conferma
|
||||
.question-box
|
||||
@@ -340,7 +344,7 @@ html(lang="it")
|
||||
span.responsibility-icon 🛡️
|
||||
span.responsibility-text
|
||||
strong Fiducia:
|
||||
| L'ammissione si basa sulla fiducia reciproca nella comunità RISO
|
||||
| L'ammissione si basa sulla fiducia reciproca nella comunità #{nomeapp}
|
||||
.responsibility-item
|
||||
span.responsibility-icon 👥
|
||||
span.responsibility-text
|
||||
@@ -351,8 +355,6 @@ html(lang="it")
|
||||
.info-box
|
||||
p
|
||||
| ✓ Dopo l'ammissione, #{usernameInvitato} potrà completare il profilo
|
||||
p
|
||||
| ✓ Il facilitatore locale valuterà l'abilitazione all'uso dei RIS
|
||||
|
||||
//- Warning box
|
||||
.warning-box
|
||||
@@ -365,6 +367,4 @@ html(lang="it")
|
||||
.divider
|
||||
p Hai ricevuto questa email perché #{usernameInvitato} ha indicato te come invitante su #{nomeapp}
|
||||
p(style="margin-top: 12px; font-size: 12px;")
|
||||
| #{new Date().getFullYear()} #{nomeapp} - Rete Italiana Scambi Orizzontali
|
||||
p(style="margin-top: 12px; font-size: 12px;")
|
||||
| 🍚 Comunità · Fiducia · Scambi Solidali · Sostenibilità
|
||||
| #{new Date().getFullYear()} #{nomeapp}
|
||||
|
||||
@@ -448,7 +448,7 @@ html(lang="it")
|
||||
.step-number 1
|
||||
.step-content
|
||||
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-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} !`
|
||||
|
||||
@@ -158,6 +158,12 @@ html(lang="it")
|
||||
.info-value
|
||||
| #{user.profile.intcode_cell || ''} #{user.profile.cell || ''}
|
||||
|
||||
if user && user.profile && (user.profile.resid_str_comune && user.profile.resid_province)
|
||||
.info-row
|
||||
.info-label Comune di Residenza:
|
||||
.info-value
|
||||
| #{user.profile.resid_str_comune || ''} (#{user.profile.resid_province || ''})
|
||||
|
||||
if user && user.profile && user.profile.nationality
|
||||
.info-row
|
||||
.info-label Nazionalità:
|
||||
|
||||
@@ -317,6 +317,10 @@ html(lang="it")
|
||||
.member-detail
|
||||
strong Email:
|
||||
| #{emailInvitato}
|
||||
if userprofile && userprofile.profile.resid_str_comune && userprofile.profile.resid_province
|
||||
.member-detail
|
||||
strong Comune Residenza:
|
||||
| #{userprofile.profile.resid_str_comune} (#{userprofile.profile.resid_province})
|
||||
|
||||
//- Domanda di conferma
|
||||
.question-box
|
||||
|
||||
@@ -1 +1 @@
|
||||
=`🎉 Il tuo invito è stato accettato su ${nomeapp} da ${name ? ', ' + name : username} !`
|
||||
=`🎉 Il tuo invito è stato accettato su ${nomeapp} da ${name ? name : username} !`
|
||||
|
||||
@@ -514,4 +514,9 @@ Dom 23/11 ORE 01:10: [<b>Circuito RIS Italia</b>]: Inviate Monete da perseo9 a s
|
||||
|
||||
Saldi:
|
||||
perseo9: -19.00 RIS]
|
||||
surya1977: 141.95 RIS]
|
||||
surya1977: 141.95 RIS]
|
||||
Gio 04/12 ORE 18:55: [<b>Circuito RIS Bologna</b>]: Inviate Monete da SurTest a ElenaEspx 0.1 RIS [causale: ]
|
||||
|
||||
Saldi:
|
||||
SurTest: 0.00 RIS]
|
||||
ElenaEspx: 38.05 RIS]
|
||||
@@ -71,12 +71,12 @@
|
||||
"CIRCUIT_REMOVED_ADMIN_YOU": "%s ti è stato rimosso l'incarico di Amministratore del %s da parte di %s",
|
||||
"RICHIESTA_BLOCCO_CIRCUIT": "Richiesta di bloccare il %s da parte di %s",
|
||||
"CIRCUIT_ELIMINATO": "Il %s è stato eliminato da parte di %s",
|
||||
"FIDO_IMPOSTATO_ADMINS_CIRCUIT": "✅ l'utente %s è stato abilitato alla Fiducia (%s RIS) sul '%s' (da parte di %s)",
|
||||
"FIDO_IMPOSTATO_ADMINS_CIRCUIT": "✅ Nuovo membro abilitato al Circuito RIS\n\n👤 Membro: %s\n🤝 Fiducia Concessa: %s RIS\n📍 Circuito: %s\n👨💼 Abilitato da: %s\n\nIl nuovo membro può ora utilizzare i RIS per gli scambi nel territorio.",
|
||||
"FIDO_IMPOSTATO_ADMINS_CIRCUIT_MYGROUP": "✅ il Conto di Gruppo %s è stato abilitato alla Fiducia fino a -%s sul '%s' (da parte di %s)",
|
||||
"ACCETTATO_NOTIFICA_ADMINS_CIRCUIT": "✅ l'utente %s è stato accettato a far parte del '%s' (da parte di %s)",
|
||||
"ACCETTATO_NOTIFICA_ADMINS_CIRCUIT_MYGROUP": "✅ il Conto di Gruppo %s è stato accettato a far parte del '%s' (da parte di %s)",
|
||||
"CIRCUIT_ACCEPTED": "✅ Sei stato accettato da %s a far parte del %s.\nApri la APP e clicca in alto a destra sull'icona delle monete, oppure clicca qui: %s",
|
||||
"FIDO_IMPOSTATO": "✅ Ti è stata attivata la possibilità di utilizzare la Fiducia Concessa fino a %s RIS da %s sul '%s'.",
|
||||
"FIDO_IMPOSTATO": "🎉 Complimenti! Sei stato abilitato al Circuito RIS di %s\n\n✅ Abilitazione completata da %s\n\n💰 Cosa significa?\nOra puoi utilizzare i RIS (credito comunitario) per i tuoi scambi nel territorio.\n\n🤝 Fiducia Concessa: %s RIS\nPuoi ricevere beni/servizi pagando in RIS anche partendo da saldo zero. Il saldo negativo non è un debito, ma la fiducia che la comunità ti concede!\n\n📱 Prossimi passi:\n• Esplora la piattaforma e crea annunci\n• Inizia con piccole transazioni (5-10%% in RIS)\n• Partecipa agli incontri e mercatini locali\n• Unisciti al gruppo Telegram territoriale\n\n💡 Ricorda: 1 RIS = 1 Euro (come riferimento di valore)\n\nBenvenuto nella comunità RISO! 🍚💚",
|
||||
"CIRCUIT_ACCEPTED_YOU": "✅ Hai accettato %s a far parte del '%s'",
|
||||
"CIRCUIT_REFUSED": "❌ Ti è stato rifiutato l'accesso da %s a far parte del '%s'. Se pensi sia un'errore, contatta l'amministratore del Circuito.",
|
||||
"CIRCUIT_REMOVED": "❌ l'utente %s è stato rimosso del %s (da parte di %s)",
|
||||
|
||||
@@ -56,6 +56,9 @@ const AccountSchema = new Schema({
|
||||
fidoConcesso: {
|
||||
type: Number,
|
||||
},
|
||||
username_admin_abilitante: {
|
||||
type: String,
|
||||
},
|
||||
qta_maxConcessa: {
|
||||
type: Number,
|
||||
},
|
||||
@@ -318,6 +321,7 @@ AccountSchema.statics.getAccountByUsernameAndCircuitId = async function (
|
||||
saldo: 0,
|
||||
saldo_pend: 0,
|
||||
fidoConcesso: 0,
|
||||
username_admin_abilitante: '',
|
||||
qta_maxConcessa: 0,
|
||||
totTransato: 0,
|
||||
numtransactions: 0,
|
||||
@@ -643,9 +647,10 @@ AccountSchema.statics.SetMinMaxPersonali = async function (idapp, fidoConcesso,
|
||||
}
|
||||
};
|
||||
|
||||
AccountSchema.statics.updateFido = async function (idapp, username, groupname, circuitId, fido) {
|
||||
AccountSchema.statics.updateFido = async function (idapp, username, groupname, circuitId, fido, username_action) {
|
||||
let paramstoupdate = {
|
||||
fidoConcesso: fido,
|
||||
username_admin_abilitante: username_action,
|
||||
};
|
||||
let risult = null;
|
||||
if (groupname) risult = await Account.updateOne({ idapp, circuitId, groupname }, { $set: paramstoupdate });
|
||||
|
||||
88
src/models/bacheca.js
Executable file
88
src/models/bacheca.js
Executable file
@@ -0,0 +1,88 @@
|
||||
const mongoose = require('mongoose').set('debug', false)
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
mongoose.Promise = global.Promise;
|
||||
mongoose.level = "F";
|
||||
|
||||
const tools = require('../tools/general');
|
||||
|
||||
const { ObjectId } = require('mongodb');
|
||||
|
||||
// Resolving error Unknown modifier: $pushAll
|
||||
mongoose.plugin(schema => {
|
||||
schema.options.usePushEach = true
|
||||
});
|
||||
|
||||
const BachecaSchema = new Schema({
|
||||
_id: {
|
||||
type: Number,
|
||||
},
|
||||
descr: {
|
||||
type: String,
|
||||
},
|
||||
idSectorBacheca: [{
|
||||
type: Number
|
||||
}],
|
||||
icon: {
|
||||
type: String,
|
||||
},
|
||||
img: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
|
||||
BachecaSchema.statics.findAllIdApp = async function (idapp) {
|
||||
const Bacheca = this;
|
||||
|
||||
const query = [
|
||||
{ $sort: { descr: 1 } }
|
||||
];
|
||||
|
||||
const res = await Bacheca
|
||||
.aggregate(query)
|
||||
.then((arrrec) => {
|
||||
return arrrec
|
||||
})
|
||||
|
||||
return res;
|
||||
|
||||
};
|
||||
|
||||
BachecaSchema.pre('save', async function (next) {
|
||||
if (this.isNew) {
|
||||
const myrec = await Bacheca.findOne().limit(1).sort({_id:-1});
|
||||
if (!!myrec) {
|
||||
if (myrec._doc._id === 0)
|
||||
this._id = 1;
|
||||
else
|
||||
this._id = myrec._doc._id + 1;
|
||||
|
||||
} else {
|
||||
this._id = 1;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
|
||||
BachecaSchema.statics.getFieldsForSearch = function () {
|
||||
return [{ field: 'label', type: tools.FieldType.string },
|
||||
{ field: 'descr', type: tools.FieldType.string }]
|
||||
};
|
||||
|
||||
BachecaSchema.statics.executeQueryTable = function (idapp, params) {
|
||||
params.fieldsearch = this.getFieldsForSearch();
|
||||
return tools.executeQueryTable(this, 0, params);
|
||||
};
|
||||
|
||||
|
||||
const Bacheca = mongoose.model('Bacheca', BachecaSchema);
|
||||
|
||||
Bacheca.createIndexes()
|
||||
.then(() => { })
|
||||
.catch((err) => { throw err; });
|
||||
|
||||
|
||||
module.exports = { Bacheca };
|
||||
@@ -166,6 +166,7 @@ const CircuitSchema = new Schema({
|
||||
},
|
||||
date_created: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
date_updated: {
|
||||
type: Date,
|
||||
@@ -174,6 +175,7 @@ const CircuitSchema = new Schema({
|
||||
{
|
||||
username: { type: String },
|
||||
date: { type: Date },
|
||||
enable_to_receive_email: { type: Boolean },
|
||||
},
|
||||
],
|
||||
photos: [
|
||||
@@ -1030,8 +1032,10 @@ CircuitSchema.statics.getCircuitByCircuitId = async function (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) {
|
||||
let arr = await Circuit.findOne(
|
||||
let circuit = await Circuit.findOne(
|
||||
{
|
||||
idapp,
|
||||
path: circuitPath,
|
||||
@@ -1040,9 +1044,22 @@ CircuitSchema.statics.getListAdminsByCircuitPath = async function (idapp, circui
|
||||
{ admins: 1 }
|
||||
).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
|
||||
@@ -1177,7 +1194,7 @@ CircuitSchema.statics.createCircuitIfNotExist = async function (req, idapp, prov
|
||||
date_created: new Date(),
|
||||
admins: admins.map((username) => ({ username })),
|
||||
askManagerToEnter: false,
|
||||
sendEmailAfterAskingToEnter: false,
|
||||
sendEmailAfterAskingToEnter: true,
|
||||
circuitoIndipendente: false,
|
||||
});
|
||||
|
||||
@@ -1316,7 +1333,7 @@ CircuitSchema.statics.SetDefMinMaxCollettivi = async function (idapp, valmin, va
|
||||
}
|
||||
};
|
||||
|
||||
CircuitSchema.statics.setFido = async function (idapp, username, circuitName, groupname) {
|
||||
CircuitSchema.statics.setFido = async function (idapp, username, circuitName, groupname, username_action) {
|
||||
try {
|
||||
mycircuit = await Circuit.findOne({ idapp, name: circuitName }).lean();
|
||||
if (mycircuit) {
|
||||
@@ -1369,9 +1386,9 @@ CircuitSchema.statics.setFido = async function (idapp, username, circuitName, gr
|
||||
variato = await Account.updateQtaMax(idapp, username, groupname, circuitId, qtamax);
|
||||
}
|
||||
|
||||
const ris = await Account.updateFido(idapp, username, groupname, circuitId, fido);
|
||||
const ris = await Account.updateFido(idapp, username, groupname, circuitId, fido, username_action);
|
||||
if (ris) {
|
||||
return { qta_maxConcessa: qtamax, fidoConcesso: fido, changed: variato || (ris && ris.modifiedCount > 0) };
|
||||
return { qta_maxConcessa: qtamax, fidoConcesso: fido, username_admin_abilitante: username_action, changed: variato || (ris && ris.modifiedCount > 0) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1867,6 +1884,15 @@ CircuitSchema.statics.getCircuitoItalia = async function (idapp) {
|
||||
return circuit;
|
||||
};
|
||||
|
||||
CircuitSchema.statics.isEnableToReceiveEmailByExtraRec = async function (idapp, recnotif) {
|
||||
let ricevo = true;
|
||||
if (recnotif.tag === 'setfido') {
|
||||
// Controllo se l'utente ha scelto di ricevere l'email
|
||||
}
|
||||
|
||||
return ricevo;
|
||||
};
|
||||
|
||||
const Circuit = mongoose.model('Circuit', CircuitSchema);
|
||||
|
||||
Circuit.createIndexes()
|
||||
|
||||
@@ -19,6 +19,12 @@ const ContribtypeSchema = new Schema({
|
||||
label: {
|
||||
type: String,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
},
|
||||
showprice: {
|
||||
type: Boolean,
|
||||
}
|
||||
|
||||
@@ -33,13 +33,24 @@ const MyBachecaSchema = new Schema({
|
||||
},
|
||||
userId: { type: Schema.Types.ObjectId, ref: 'User' },
|
||||
groupname: { type: String },
|
||||
idSector: {
|
||||
idSectorBacheca: {
|
||||
type: Number,
|
||||
},
|
||||
idSkill: {
|
||||
},
|
||||
idBacheca: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
// ------------------
|
||||
idSector: { // VECCHIO
|
||||
type: Number,
|
||||
},
|
||||
|
||||
idSkill: { // VECCHIO
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
|
||||
// ------------------
|
||||
idStatusSkill: [
|
||||
{
|
||||
type: Number,
|
||||
@@ -123,6 +134,7 @@ const MyBachecaSchema = new Schema({
|
||||
},
|
||||
date_created: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
date_updated: {
|
||||
type: Date,
|
||||
@@ -233,8 +245,8 @@ MyBachecaSchema.statics.getMyRecById = function (idapp, id) {
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: 'skills',
|
||||
localField: 'idSkill',
|
||||
from: 'bachecas',
|
||||
localField: 'idBacheca',
|
||||
foreignField: '_id',
|
||||
as: 'recSkill',
|
||||
},
|
||||
@@ -256,10 +268,10 @@ MyBachecaSchema.statics.getMyRecById = function (idapp, id) {
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: 'sectors',
|
||||
localField: 'idSector',
|
||||
from: 'sectorbachecas',
|
||||
localField: 'idSectorBacheca',
|
||||
foreignField: '_id',
|
||||
as: 'sector',
|
||||
as: 'sectorBacheca',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -267,7 +279,7 @@ MyBachecaSchema.statics.getMyRecById = function (idapp, id) {
|
||||
newRoot: {
|
||||
$mergeObjects: [
|
||||
{
|
||||
$arrayElemAt: ['$sector', 0],
|
||||
$arrayElemAt: ['$sectorBacheca', 0],
|
||||
},
|
||||
'$$ROOT',
|
||||
],
|
||||
|
||||
@@ -16,7 +16,7 @@ const { ObjectId } = require('mongodb');
|
||||
const tableModel = shared_consts.TABLES_MYGOODS;
|
||||
|
||||
// Resolving error Unknown modifier: $pushAll
|
||||
mongoose.plugin(schema => {
|
||||
mongoose.plugin((schema) => {
|
||||
schema.options.usePushEach = true;
|
||||
});
|
||||
|
||||
@@ -41,18 +41,21 @@ const MyGoodSchema = new Schema({
|
||||
idShipping: [
|
||||
{
|
||||
type: Number,
|
||||
}],
|
||||
},
|
||||
],
|
||||
|
||||
idContribType: [
|
||||
{
|
||||
type: String,
|
||||
}],
|
||||
},
|
||||
],
|
||||
idCity: [
|
||||
{
|
||||
type: Number,
|
||||
}],
|
||||
},
|
||||
],
|
||||
pub_to_share: {
|
||||
type: Number, // PUB_TO_SHARE_ALL, PUB_TO_SHARE_ONLY_TABLE_FOLLOW
|
||||
type: Number, // PUB_TO_SHARE_ALL, PUB_TO_SHARE_ONLY_TABLE_FOLLOW
|
||||
},
|
||||
numLevel: {
|
||||
type: Number,
|
||||
@@ -61,9 +64,11 @@ const MyGoodSchema = new Schema({
|
||||
adType: {
|
||||
type: Number,
|
||||
},
|
||||
otherfilters: [{
|
||||
type: Number,
|
||||
}],
|
||||
otherfilters: [
|
||||
{
|
||||
type: Number,
|
||||
},
|
||||
],
|
||||
photos: [
|
||||
{
|
||||
imagefile: {
|
||||
@@ -75,7 +80,8 @@ const MyGoodSchema = new Schema({
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
}],
|
||||
},
|
||||
],
|
||||
note: {
|
||||
type: String,
|
||||
default: '',
|
||||
@@ -89,19 +95,19 @@ const MyGoodSchema = new Schema({
|
||||
},
|
||||
date_created: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
date_updated: {
|
||||
type: Date,
|
||||
},
|
||||
},
|
||||
},
|
||||
...Reaction.getFieldsForReactions(),
|
||||
...tools.getFieldsForAnnunci()
|
||||
...tools.getFieldsForAnnunci(),
|
||||
});
|
||||
|
||||
MyGoodSchema.pre('save', async function (next) {
|
||||
if (this.isNew) {
|
||||
if (!this.date_created)
|
||||
this.date_created = new Date();
|
||||
if (!this.date_created) this.date_created = new Date();
|
||||
}
|
||||
|
||||
next();
|
||||
@@ -110,15 +116,11 @@ MyGoodSchema.pre('save', async function (next) {
|
||||
MyGoodSchema.statics.findAllIdApp = async function (idapp) {
|
||||
const MyGood = this;
|
||||
|
||||
const query = [
|
||||
{ $match: { idapp } },
|
||||
{ $sort: { descr: 1 } },
|
||||
];
|
||||
const query = [{ $match: { idapp } }, { $sort: { descr: 1 } }];
|
||||
|
||||
return await MyGood.aggregate(query).then((arrrec) => {
|
||||
return arrrec;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
MyGoodSchema.statics.getFieldsForSearch = function () {
|
||||
@@ -134,7 +136,6 @@ MyGoodSchema.statics.getFieldsLastForSearch = function () {
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
MyGoodSchema.statics.executeQueryTable = function (idapp, params, user) {
|
||||
params.fieldsearch = this.getFieldsForSearch();
|
||||
params.fieldsearch_last = this.getFieldsLastForSearch();
|
||||
@@ -159,44 +160,40 @@ MyGoodSchema.statics.getMyRecById = function (idapp, idGood) {
|
||||
const MyGood = this;
|
||||
|
||||
let myparsid = {
|
||||
'_id': idGood,
|
||||
_id: idGood,
|
||||
idapp,
|
||||
};
|
||||
|
||||
let query = [
|
||||
{
|
||||
'$match':
|
||||
myparsid,
|
||||
$match: myparsid,
|
||||
},
|
||||
{
|
||||
'$sort': {
|
||||
'desc': 1,
|
||||
$sort: {
|
||||
desc: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
'$addFields': {
|
||||
'myId1': {
|
||||
'$toObjectId': '$userId',
|
||||
$addFields: {
|
||||
myId1: {
|
||||
$toObjectId: '$userId',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
'$lookup': {
|
||||
'from': 'users',
|
||||
'localField': 'myId1',
|
||||
'foreignField': '_id',
|
||||
'as': 'user',
|
||||
$lookup: {
|
||||
from: 'users',
|
||||
localField: 'myId1',
|
||||
foreignField: '_id',
|
||||
as: 'user',
|
||||
},
|
||||
},
|
||||
{
|
||||
'$replaceRoot': {
|
||||
'newRoot': {
|
||||
'$mergeObjects': [
|
||||
$replaceRoot: {
|
||||
newRoot: {
|
||||
$mergeObjects: [
|
||||
{
|
||||
'$arrayElemAt': [
|
||||
'$user',
|
||||
0,
|
||||
],
|
||||
$arrayElemAt: ['$user', 0],
|
||||
},
|
||||
'$$ROOT',
|
||||
],
|
||||
@@ -207,22 +204,19 @@ MyGoodSchema.statics.getMyRecById = function (idapp, idGood) {
|
||||
$project: shared_consts.getProjectForAll({}, tableModel),
|
||||
},
|
||||
{
|
||||
'$lookup': {
|
||||
'from': 'goods',
|
||||
'localField': 'idGood',
|
||||
'foreignField': '_id',
|
||||
'as': 'recGood',
|
||||
$lookup: {
|
||||
from: 'goods',
|
||||
localField: 'idGood',
|
||||
foreignField: '_id',
|
||||
as: 'recGood',
|
||||
},
|
||||
},
|
||||
{
|
||||
'$replaceRoot': {
|
||||
'newRoot': {
|
||||
'$mergeObjects': [
|
||||
$replaceRoot: {
|
||||
newRoot: {
|
||||
$mergeObjects: [
|
||||
{
|
||||
'$arrayElemAt': [
|
||||
'$recGood',
|
||||
0,
|
||||
],
|
||||
$arrayElemAt: ['$recGood', 0],
|
||||
},
|
||||
'$$ROOT',
|
||||
],
|
||||
@@ -233,23 +227,19 @@ MyGoodSchema.statics.getMyRecById = function (idapp, idGood) {
|
||||
$project: shared_consts.getProjectForAll({}, tableModel),
|
||||
},
|
||||
{
|
||||
'$lookup': {
|
||||
'from': 'sectorgoods',
|
||||
'localField': 'idSectorGood',
|
||||
// 'localField': 'recGood.idSectorGood',
|
||||
'foreignField': '_id',
|
||||
'as': 'sectorGood',
|
||||
$lookup: {
|
||||
from: 'sectorgoods',
|
||||
localField: 'idSectorGood',
|
||||
foreignField: '_id',
|
||||
as: 'sectorGood',
|
||||
},
|
||||
},
|
||||
{
|
||||
'$replaceRoot': {
|
||||
'newRoot': {
|
||||
'$mergeObjects': [
|
||||
$replaceRoot: {
|
||||
newRoot: {
|
||||
$mergeObjects: [
|
||||
{
|
||||
'$arrayElemAt': [
|
||||
'$sectorgood',
|
||||
0,
|
||||
],
|
||||
$arrayElemAt: ['$sectorgood', 0],
|
||||
},
|
||||
'$$ROOT',
|
||||
],
|
||||
@@ -258,10 +248,10 @@ MyGoodSchema.statics.getMyRecById = function (idapp, idGood) {
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
'from': 'mygroups',
|
||||
'localField': 'groupname',
|
||||
'foreignField': 'groupname',
|
||||
'as': 'mygrp',
|
||||
from: 'mygroups',
|
||||
localField: 'groupname',
|
||||
foreignField: 'groupname',
|
||||
as: 'mygrp',
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -274,22 +264,19 @@ MyGoodSchema.statics.getMyRecById = function (idapp, idGood) {
|
||||
$project: shared_consts.getProjectForAll({}, tableModel),
|
||||
},
|
||||
{
|
||||
'$lookup': {
|
||||
'from': 'subgoods',
|
||||
'localField': 'idShipping',
|
||||
'foreignField': '_id',
|
||||
'as': 'MyGood',
|
||||
$lookup: {
|
||||
from: 'subgoods',
|
||||
localField: 'idShipping',
|
||||
foreignField: '_id',
|
||||
as: 'MyGood',
|
||||
},
|
||||
},
|
||||
{
|
||||
'$replaceRoot': {
|
||||
'newRoot': {
|
||||
'$mergeObjects': [
|
||||
$replaceRoot: {
|
||||
newRoot: {
|
||||
$mergeObjects: [
|
||||
{
|
||||
'$arrayElemAt': [
|
||||
'$MyGood',
|
||||
0,
|
||||
],
|
||||
$arrayElemAt: ['$MyGood', 0],
|
||||
},
|
||||
'$$ROOT',
|
||||
],
|
||||
@@ -300,22 +287,19 @@ MyGoodSchema.statics.getMyRecById = function (idapp, idGood) {
|
||||
$project: shared_consts.getProjectForAll({}, tableModel),
|
||||
},
|
||||
{
|
||||
'$lookup': {
|
||||
'from': 'cities',
|
||||
'localField': 'idCity',
|
||||
'foreignField': '_id',
|
||||
'as': 'mycities',
|
||||
$lookup: {
|
||||
from: 'cities',
|
||||
localField: 'idCity',
|
||||
foreignField: '_id',
|
||||
as: 'mycities',
|
||||
},
|
||||
},
|
||||
{
|
||||
'$replaceRoot': {
|
||||
'newRoot': {
|
||||
'$mergeObjects': [
|
||||
$replaceRoot: {
|
||||
newRoot: {
|
||||
$mergeObjects: [
|
||||
{
|
||||
'$arrayElemAt': [
|
||||
'$mycities',
|
||||
0,
|
||||
],
|
||||
$arrayElemAt: ['$mycities', 0],
|
||||
},
|
||||
'$$ROOT',
|
||||
],
|
||||
@@ -344,32 +328,30 @@ MyGoodSchema.statics.getCompleteRecord = function (idapp, id) {
|
||||
const MyGood = this;
|
||||
|
||||
return MyGood.getMyRecById(idapp, id);
|
||||
|
||||
};
|
||||
|
||||
MyGoodSchema.statics.getProject = function () {
|
||||
let proj = {
|
||||
'recGood': 1,
|
||||
'sectorGood': 1,
|
||||
'idSectorGood': 1,
|
||||
'idGood': 1,
|
||||
'idShipping': 1,
|
||||
'idStatusGood': 1,
|
||||
recGood: 1,
|
||||
sectorGood: 1,
|
||||
idSectorGood: 1,
|
||||
idGood: 1,
|
||||
idShipping: 1,
|
||||
idStatusGood: 1,
|
||||
//**ADDFIELD_MYGOOD
|
||||
|
||||
};
|
||||
|
||||
const proj_add = shared_consts.getProjectForAll()
|
||||
const proj_add = shared_consts.getProjectForAll();
|
||||
|
||||
return Object.assign({}, proj, proj_add);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const MyGood = mongoose.model('MyGood', MyGoodSchema);
|
||||
|
||||
MyGood.createIndexes()
|
||||
.then(() => { })
|
||||
.catch((err) => { throw err; });
|
||||
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
module.exports = { MyGood };
|
||||
|
||||
@@ -96,6 +96,7 @@ const MyGroupSchema = new Schema({
|
||||
},
|
||||
date_created: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
date_updated: {
|
||||
type: Date,
|
||||
|
||||
@@ -96,6 +96,7 @@ const MyHospSchema = new Schema({
|
||||
},
|
||||
date_created: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
date_updated: {
|
||||
type: Date,
|
||||
@@ -359,7 +360,7 @@ MyHospSchema.statics.SettaAdTypeOffro_In_Hosps = async function () {
|
||||
}
|
||||
};
|
||||
|
||||
MyHospSchema.statics.getProject = function () {
|
||||
/*MyHospSchema.statics.getProject = function () {
|
||||
let proj = {
|
||||
visibile: 1,
|
||||
typeHosp: 1,
|
||||
@@ -378,7 +379,7 @@ MyHospSchema.statics.getProject = function () {
|
||||
return Object.assign({}, proj, proj_add);
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
const MyHosp = mongoose.model('MyHosp', MyHospSchema);
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ const MySkillSchema = new Schema(
|
||||
},
|
||||
date_created: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
date_updated: {
|
||||
type: Date,
|
||||
@@ -347,7 +348,7 @@ MySkillSchema.statics.getMyRecById = function (idapp, idSkill) {
|
||||
});
|
||||
};
|
||||
|
||||
MySkillSchema.statics.getProject = function (proj_add2) {
|
||||
/*MySkillSchema.statics.getProject = function (proj_add2) {
|
||||
let proj = {
|
||||
recSkill: 1,
|
||||
sector: 1,
|
||||
@@ -364,6 +365,7 @@ MySkillSchema.statics.getProject = function (proj_add2) {
|
||||
return Object.assign({}, proj, proj_add);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
MySkillSchema.statics.getCompleteRecord = function (idapp, id) {
|
||||
const MySkill = this;
|
||||
|
||||
88
src/models/sectorbacheca.js
Executable file
88
src/models/sectorbacheca.js
Executable file
@@ -0,0 +1,88 @@
|
||||
const mongoose = require('mongoose').set('debug', false)
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
mongoose.Promise = global.Promise;
|
||||
mongoose.level = "F";
|
||||
|
||||
const tools = require('../tools/general');
|
||||
|
||||
const { ObjectId } = require('mongodb');
|
||||
|
||||
// Resolving error Unknown modifier: $pushAll
|
||||
mongoose.plugin(schema => {
|
||||
schema.options.usePushEach = true
|
||||
});
|
||||
|
||||
const SectorBachecaSchema = new Schema({
|
||||
_id: {
|
||||
type: Number,
|
||||
},
|
||||
descr: {
|
||||
type: String,
|
||||
},
|
||||
idSectorBacheca: {
|
||||
type: Number
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
},
|
||||
img: {
|
||||
type: String,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
},
|
||||
theme: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
|
||||
SectorBachecaSchema.pre('save', async function (next) {
|
||||
if (this.isNew) {
|
||||
const myrec = await SectorBacheca.findOne().limit(1).sort({_id:-1});
|
||||
if (!!myrec) {
|
||||
if (myrec._doc._id === 0)
|
||||
this._id = 1;
|
||||
else
|
||||
this._id = myrec._doc._id + 1;
|
||||
} else {
|
||||
this._id = 1;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
SectorBachecaSchema.statics.findAllIdApp = async function (idapp) {
|
||||
const SectorBacheca = this;
|
||||
|
||||
const query = [
|
||||
{ $sort: { descr: 1 } }
|
||||
];
|
||||
|
||||
return await SectorBacheca
|
||||
.aggregate(query)
|
||||
.then((arrrec) => {
|
||||
return arrrec
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
SectorBachecaSchema.statics.getFieldsForSearch = function () {
|
||||
return [{ field: 'descr', type: tools.FieldType.string }]
|
||||
};
|
||||
|
||||
SectorBachecaSchema.statics.executeQueryTable = function (idapp, params) {
|
||||
params.fieldsearch = this.getFieldsForSearch();
|
||||
return tools.executeQueryTable(this, 0, params);
|
||||
};
|
||||
|
||||
|
||||
const SectorBacheca = mongoose.model('SectorBacheca', SectorBachecaSchema);
|
||||
|
||||
SectorBacheca.createIndexes()
|
||||
.then(() => { })
|
||||
.catch((err) => { throw err; });
|
||||
|
||||
|
||||
module.exports = { SectorBacheca };
|
||||
@@ -505,6 +505,7 @@ sendNotifSchema.statics.getDescrAndLinkByRecNotif = async function (recnotif, us
|
||||
recnotif.paramsObj.circuitnameDest,
|
||||
username_action
|
||||
);
|
||||
tag = 'setfido_admin_group';
|
||||
} else {
|
||||
newdescr = i18n.__(
|
||||
'FIDO_IMPOSTATO_ADMINS_CIRCUIT',
|
||||
@@ -513,18 +514,20 @@ sendNotifSchema.statics.getDescrAndLinkByRecNotif = async function (recnotif, us
|
||||
recnotif.paramsObj.circuitnameDest,
|
||||
username_action
|
||||
);
|
||||
tag = 'setfido_admin';
|
||||
}
|
||||
|
||||
recnotif.openUrl = '/my/' + sender;
|
||||
} else {
|
||||
newdescr = i18n.__(
|
||||
'FIDO_IMPOSTATO',
|
||||
recnotif.paramsObj.circuitnameDest,
|
||||
recnotif.paramsObj.extrarec.username_admin_abilitante,
|
||||
-recnotif.paramsObj.extrarec.fidoConcesso,
|
||||
username_action,
|
||||
recnotif.paramsObj.circuitnameDest
|
||||
);
|
||||
tag = 'setfido';
|
||||
}
|
||||
tag = 'setfido';
|
||||
|
||||
} else if (recnotif.typeid === shared_consts.TypeNotifs.ID_CIRCUIT_ACCEPTED) {
|
||||
if (recnotif.paramsObj.isAdmin) {
|
||||
if (recnotif.extrarec.groupname) {
|
||||
@@ -971,7 +974,7 @@ sendNotifSchema.statics.findAllNotifCoinsAllIdAndIdApp = function (idapp) {
|
||||
});
|
||||
};
|
||||
|
||||
sendNotifSchema.statics.saveAndSendNotif = async function (myrecnotif, req, res, user) {
|
||||
sendNotifSchema.statics.saveAndSendNotif = async function (myrecnotif, req, res, user, paramsObj) {
|
||||
const SendNotif = this;
|
||||
|
||||
let idapp = req.body.idapp;
|
||||
@@ -1003,7 +1006,8 @@ sendNotifSchema.statics.saveAndSendNotif = async function (myrecnotif, req, res,
|
||||
res,
|
||||
idapp,
|
||||
user ? user : req.user,
|
||||
myrecread
|
||||
myrecread,
|
||||
paramsObj
|
||||
);
|
||||
else return false;
|
||||
}
|
||||
@@ -1018,7 +1022,8 @@ sendNotifSchema.statics.saveAndSendNotif = async function (myrecnotif, req, res,
|
||||
res,
|
||||
idapp,
|
||||
user ? user : req.user,
|
||||
myrecout
|
||||
myrecout,
|
||||
paramsObj
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1312,7 +1317,7 @@ sendNotifSchema.statics.createNewNotifToSingleUser = async function (req, res, p
|
||||
|
||||
myrecnotif = this.getExtraParam(myrecnotif, paramsObj);
|
||||
|
||||
return await SendNotif.sendToSingleUserDest(myrecnotif, req, res, onlysave);
|
||||
return await SendNotif.sendToSingleUserDest(myrecnotif, req, res, onlysave, paramsObj);
|
||||
} catch (e) {
|
||||
console.error('createNewNotification', e);
|
||||
return null;
|
||||
@@ -1378,6 +1383,8 @@ sendNotifSchema.statics.getNotificationRecipients = async function (myrecnotifpa
|
||||
|
||||
if (myrecnotifpass.tablerec === shared_consts.TABLES_MYGOODS) {
|
||||
idSector = myrectableorig.idSectorGood;
|
||||
} else if (myrecnotifpass.tablerec === shared_consts.TABLES_MYBACHECAS) {
|
||||
idSector = myrectableorig.idSectorBacheca;
|
||||
} else {
|
||||
idSector = myrectableorig.idSector;
|
||||
}
|
||||
@@ -1547,7 +1554,7 @@ sendNotifSchema.statics.sendToTheDestinations = async function (myrecnotifpass,
|
||||
}
|
||||
};
|
||||
|
||||
sendNotifSchema.statics.sendToSingleUserDest = async function (myrecnotif, req, res, onlysave) {
|
||||
sendNotifSchema.statics.sendToSingleUserDest = async function (myrecnotif, req, res, onlysave, paramsObj) {
|
||||
const SendNotif = this;
|
||||
|
||||
try {
|
||||
@@ -1559,9 +1566,9 @@ sendNotifSchema.statics.sendToSingleUserDest = async function (myrecnotif, req,
|
||||
: myrecnotif.dest;
|
||||
|
||||
if (onlysave) {
|
||||
return await SendNotif.saveNotif(myrecnotif, req);
|
||||
return await SendNotif.saveNotif(myrecnotif, req, paramsObj);
|
||||
} else {
|
||||
return await SendNotif.saveAndSendNotif(myrecnotif, req, res, null);
|
||||
return await SendNotif.saveAndSendNotif(myrecnotif, req, res, null, paramsObj);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('sendToSingleUserDest', e);
|
||||
|
||||
1177
src/models/user.js
1177
src/models/user.js
File diff suppressed because it is too large
Load Diff
163
src/models/version.js
Executable file
163
src/models/version.js
Executable file
@@ -0,0 +1,163 @@
|
||||
const mongoose = require('mongoose').set('debug', false);
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
mongoose.Promise = global.Promise;
|
||||
mongoose.level = 'F';
|
||||
|
||||
const tools = require('../tools/general');
|
||||
|
||||
const { ObjectId } = require('mongodb');
|
||||
|
||||
const LASTVERSION = 'lastversion';
|
||||
|
||||
// Resolving error Unknown modifier: $pushAll
|
||||
mongoose.plugin((schema) => {
|
||||
schema.options.usePushEach = true;
|
||||
});
|
||||
|
||||
const VersionSchema = new Schema({
|
||||
descr: {
|
||||
type: String,
|
||||
},
|
||||
idapp: {
|
||||
type: String,
|
||||
},
|
||||
executed: {
|
||||
type: Boolean,
|
||||
},
|
||||
table: {
|
||||
type: String,
|
||||
},
|
||||
version: {
|
||||
type: Number,
|
||||
},
|
||||
date_created: {
|
||||
type: Date,
|
||||
},
|
||||
});
|
||||
|
||||
VersionSchema.statics.isJobExecuted = async function (idapp, descr) {
|
||||
const Version = this;
|
||||
|
||||
try {
|
||||
const myrec = await Version.findOne({ idapp, descr });
|
||||
return myrec.executed;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
VersionSchema.statics.setJobExecuted = async function (idapp, descr) {
|
||||
const Version = this;
|
||||
|
||||
try {
|
||||
const myrec = await Version.findOneAndUpdate(
|
||||
{ idapp, descr },
|
||||
{
|
||||
$setOnInsert: { idapp, descr },
|
||||
$set: { executed: true },
|
||||
},
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
|
||||
if (!myrec) {
|
||||
throw new Error(`Error setting job as executed for idapp ${idapp} and descr ${descr}`);
|
||||
}
|
||||
|
||||
return myrec.executed;
|
||||
} catch (e) {
|
||||
console.error(`Error in setJobExecuted: ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
VersionSchema.statics.findAllIdApp = async function (idapp) {
|
||||
const Version = this;
|
||||
|
||||
const query = [{ $sort: { descr: 1 } }];
|
||||
|
||||
const res = await Version.aggregate(query).then((arrrec) => {
|
||||
return arrrec;
|
||||
});
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
VersionSchema.statics.getLastVersionRun = async function (idapp) {
|
||||
const Version = this;
|
||||
|
||||
try {
|
||||
const myrec = await Version.findOne({ idapp, table: '', descr: LASTVERSION });
|
||||
return myrec ? myrec.version : 0;
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
VersionSchema.statics.setLastVersionRun = async function (idapp, version) {
|
||||
const Version = this;
|
||||
|
||||
try {
|
||||
const myrec = await Version.findOneAndUpdate(
|
||||
{ idapp, table: '', descr: LASTVERSION },
|
||||
{
|
||||
$setOnInsert: { idapp, table: '', descr: LASTVERSION },
|
||||
$set: { version },
|
||||
},
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
|
||||
return !!myrec;
|
||||
} catch (e) {
|
||||
console.error(`Error in setLastVersionTable: ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
VersionSchema.statics.isTableVersionUpdated = async function (idapp, table) {
|
||||
const Version = this;
|
||||
|
||||
const lastversion = await Version.getLastVersionRun(idapp);
|
||||
|
||||
try {
|
||||
const myrec = await Version.findOne({ idapp, table });
|
||||
return myrec.version === lastversion;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
VersionSchema.statics.updateTableVersion = async function (idapp, table, version) {
|
||||
const Version = this;
|
||||
|
||||
try {
|
||||
const myrec = await Version.findOneAndUpdate(
|
||||
{ idapp, table },
|
||||
{
|
||||
$setOnInsert: { idapp, table },
|
||||
$set: { version },
|
||||
},
|
||||
{ new: true, upsert: true }
|
||||
);
|
||||
|
||||
return !!myrec;
|
||||
} catch (e) {
|
||||
console.error(`Error in updateTableVersion: ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const Version = mongoose.model('Version', VersionSchema);
|
||||
|
||||
Version.createIndexes()
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
module.exports = { Version };
|
||||
@@ -199,6 +199,10 @@ class CronMod {
|
||||
ris = await User.setVerifiedByAportadorToALL();
|
||||
} else if (mydata.dbop === 'RewriteContribType') {
|
||||
ris = populate.rewriteTable('contribtypes');
|
||||
} else if (mydata.dbop === 'RewriteCategESubCateg') {
|
||||
const migration = require('../populate/migration-categories');
|
||||
|
||||
ris = await migration.aggiornaCategorieESottoCategorie()
|
||||
} else if (mydata.dbop === 'ReplaceUsername') {
|
||||
if (User.isAdmin(req.user.perm)) {
|
||||
ris = globalTables.replaceUsername(req.body.idapp, mydata.search_username, mydata.replace_username);
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -1,82 +1,82 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
{ _id: 1, idSectorGood: [1], descr: 'Abbigliamento donna', icon: 'fas fa-tshirt', color: 'pink' },
|
||||
{ _id: 2, idSectorGood: [1], descr: 'Abbigliamento uomo', icon: 'fas fa-tshirt', color: 'blue' },
|
||||
{ _id: 3, idSectorGood: [1], descr: 'Accessori', icon: 'fas fa-glasses', color: 'purple' },
|
||||
{ _id: 4, idSectorGood: [1], descr: 'Scarpe donna', icon: 'fas fa-shoe-prints', color: 'pink' },
|
||||
{ _id: 5, idSectorGood: [1], descr: 'Scarpe uomo', icon: 'fas fa-shoe-prints', color: 'blue' },
|
||||
{ _id: 6, idSectorGood: [2], descr: 'Bagno', icon: 'fas fa-bath', color: 'teal' },
|
||||
{ _id: 7, idSectorGood: [2], descr: 'Camera', icon: 'fas fa-bed', color: 'indigo' },
|
||||
{ _id: 8, idSectorGood: [2], descr: 'Complementi d\'arredo', icon: 'fas fa-couch', color: 'brown' },
|
||||
{ _id: 9, idSectorGood: [2], descr: 'Cucina', icon: 'fas fa-utensils', color: 'orange' },
|
||||
{ _id: 10, idSectorGood: [2], descr: 'Esterno', icon: 'fas fa-tree', color: 'green' },
|
||||
{ _id: 11, idSectorGood: [2], descr: 'Soggiorno', icon: 'fas fa-tv', color: 'grey' },
|
||||
{ _id: 12, idSectorGood: [3], descr: 'Altri veicoli', icon: 'fas fa-car', color: 'black' },
|
||||
{ _id: 13, idSectorGood: [3], descr: 'Auto', icon: 'fas fa-car', color: 'red' },
|
||||
{ _id: 14, idSectorGood: [3], descr: 'Moto', icon: 'fas fa-motorcycle', color: 'black' },
|
||||
{ _id: 15, idSectorGood: [3], descr: 'Camper', icon: 'fas fa-caravan', color: 'orange' },
|
||||
{ _id: 16, idSectorGood: [3], descr: 'Van (furgoni camperizzati)', icon: 'fas fa-truck', color: 'blue' },
|
||||
{ _id: 17, idSectorGood: [4], descr: 'Bigiotteria', icon: 'fas fa-gem', color: 'gold' },
|
||||
{ _id: 18, idSectorGood: [4], descr: 'Lavoretti', icon: 'fas fa-paint-brush', color: 'yellow' },
|
||||
{ _id: 19, idSectorGood: [4], descr: 'Altro', icon: 'fas fa-question', color: 'grey' },
|
||||
{ _id: 20, idSectorGood: [5], descr: 'Accessori bellezza', icon: 'fas fa-spa', color: 'pink' },
|
||||
{ _id: 21, idSectorGood: [5], descr: 'Creme e detergenti', icon: 'fas fa-pump-soap', color: 'teal' },
|
||||
{ _id: 22, idSectorGood: [5], descr: 'Trucchi e profumi', icon: 'fas fa-palette', color: 'purple' },
|
||||
{ _id: 23, idSectorGood: [6], descr: 'Giocattoli e giochi di società', icon: 'fas fa-dice', color: 'yellow' },
|
||||
{ _id: 24, idSectorGood: [6], descr: 'Igiene e pannolini', icon: 'fas fa-baby', color: 'pink' },
|
||||
{ _id: 25, idSectorGood: [6], descr: 'Lettini e culle', icon: 'fas fa-baby-carriage', color: 'blue' },
|
||||
{ _id: 26, idSectorGood: [6], descr: 'Passeggini & co', icon: 'fas fa-baby-carriage', color: 'green' },
|
||||
{ _id: 27, idSectorGood: [6], descr: 'Vestiti e scarpe', icon: 'fas fa-socks', color: 'purple' },
|
||||
{ _id: 28, idSectorGood: [7], descr: 'Bere', icon: 'fas fa-glass-cheers', color: 'red' },
|
||||
{ _id: 29, idSectorGood: [7], descr: 'Mangiare', icon: 'fas fa-utensils', color: 'orange' },
|
||||
{ _id: 30, idSectorGood: [8], descr: 'Antiquariato', icon: 'fas fa-history', color: 'brown' },
|
||||
{ _id: 31, idSectorGood: [8], descr: 'Collezionismo', icon: 'fas fa-coins', color: 'gold' },
|
||||
{ _id: 32, idSectorGood: [9], descr: 'Cellulari e accessori', icon: 'fas fa-mobile-alt', color: 'blue' },
|
||||
{ _id: 33, idSectorGood: [9], descr: 'Computer e software', icon: 'fas fa-laptop', color: 'grey' },
|
||||
{ _id: 34, idSectorGood: [9], descr: 'Elettrodomestici', icon: 'fas fa-blender', color: 'green' },
|
||||
{ _id: 35, idSectorGood: [9], descr: 'Fotografia', icon: 'fas fa-camera', color: 'black' },
|
||||
{ _id: 36, idSectorGood: [9], descr: 'Videogiochi e console', icon: 'fas fa-gamepad', color: 'purple' },
|
||||
{ _id: 37, idSectorGood: [10], descr: 'Console', icon: 'fas fa-gamepad', color: 'black' },
|
||||
{ _id: 38, idSectorGood: [10], descr: 'Giochi di società', icon: 'fas fa-dice', color: 'yellow' },
|
||||
{ _id: 39, idSectorGood: [10], descr: 'PC games', icon: 'fas fa-desktop', color: 'blue' },
|
||||
{ _id: 40, idSectorGood: [11], descr: 'Attrezzatura', icon: 'fas fa-tools', color: 'grey' },
|
||||
{ _id: 41, idSectorGood: [11], descr: 'Materiali', icon: 'fas fa-box-open', color: 'brown' },
|
||||
{ _id: 42, idSectorGood: [11], descr: 'Prodotti', icon: 'fas fa-box', color: 'green' },
|
||||
{ _id: 43, idSectorGood: [11], descr: 'Strumentazione', icon: 'fas fa-toolbox', color: 'blue' },
|
||||
{ _id: 44, idSectorGood: [12], descr: ' riviste e fumetti', icon: 'fas fa-book-open', color: 'red' },
|
||||
{ _id: 45, idSectorGood: [13], descr: 'CD e vinili', icon: 'fas fa-compact-disc', color: 'black' },
|
||||
{ _id: 46, idSectorGood: [13], descr: 'Film e DVD', icon: 'fas fa-film', color: 'blue' },
|
||||
{ _id: 47, idSectorGood: [13], descr: 'Strumenti musicali', icon: 'fas fa-guitar', color: 'brown' },
|
||||
{ _id: 48, idSectorGood: [14], descr: 'Arredamento', icon: 'fas fa-couch', color: 'brown' },
|
||||
{ _id: 49, idSectorGood: [14], descr: 'Attrezzature e accessori', icon: 'fas fa-tools', color: 'grey' },
|
||||
{ _id: 50, idSectorGood: [14], descr: 'Cancelleria e cartucce', icon: 'fas fa-print', color: 'blue' },
|
||||
{ _id: 51, idSectorGood: [15], descr: 'Abbigliamento', icon: 'fas fa-tshirt', color: 'purple' },
|
||||
{ _id: 52, idSectorGood: [15], descr: 'Attrezzature e accessori Sport', icon: 'fas fa-football-ball', color: 'green' },
|
||||
{ _id: 53, idSectorGood: [15], descr: 'Bici e accessori', icon: 'fas fa-bicycle', color: 'blue' },
|
||||
{ _id: 54, idSectorGood: [17], descr: 'Edilizia', icon: 'fas fa-hard-hat', color: 'orange' },
|
||||
{ _id: 55, idSectorGood: [17], descr: 'Modellismo', icon: 'fas fa-puzzle-piece', color: 'yellow' },
|
||||
{ _id: 56, idSectorGood: [17], descr: 'Cucito', icon: 'fas fa-cut', color: 'pink' },
|
||||
{ _id: 57, idSectorGood: [17], descr: 'Pulizia', icon: 'fas fa-broom', color: 'green' },
|
||||
{ _id: 58, idSectorGood: [17], descr: 'Per Imbiancare', icon: 'fas fa-paint-roller', color: 'white' },
|
||||
{ _id: 59, idSectorGood: [17], descr: 'Giardinaggio', icon: 'fas fa-seedling', color: 'green' },
|
||||
{ _id: 60, idSectorGood: [17], descr: 'Falegnameria', icon: 'fas fa-hammer', color: 'brown' },
|
||||
{ _id: 61, idSectorGood: [7], descr: 'Pane', icon: 'fas fa-bread-slice', color: 'brown' },
|
||||
{ _id: 62, idSectorGood: [7], descr: 'Pasta', icon: 'fas fa-utensils', color: 'yellow' },
|
||||
{ _id: 63, idSectorGood: [7], descr: 'Formaggi', icon: 'fas fa-cheese', color: 'yellow' },
|
||||
{ _id: 64, idSectorGood: [7], descr: 'Olio', icon: 'fas fa-oil-can', color: 'green' },
|
||||
{ _id: 65, idSectorGood: [7], descr: 'Fervida', icon: 'fas fa-fire', color: 'red' },
|
||||
{ _id: 66, idSectorGood: [7], descr: 'Fermentati', icon: 'fas fa-beer', color: 'brown' },
|
||||
{ _id: 67, idSectorGood: [7], descr: 'Marmellate', icon: 'fas fa-jar', color: 'orange' },
|
||||
{ _id: 68, idSectorGood: [7], descr: 'Salse', icon: 'fas fa-mortar-pestle', color: 'red' },
|
||||
{ _id: 69, idSectorGood: [20], descr: 'Cereali', icon: 'fas fa-wheat', color: 'yellow' },
|
||||
{ _id: 70, idSectorGood: [20], descr: 'Frutta', icon: 'fas fa-apple-alt', color: 'red' },
|
||||
{ _id: 71, idSectorGood: [20], descr: 'Ortaggi', icon: 'fas fa-carrot', color: 'orange' },
|
||||
{ _id: 72, idSectorGood: [20], descr: 'Zootecnia', icon: 'fas fa-paw', color: 'brown' },
|
||||
{ _id: 73, idSectorGood: [20], descr: 'Biologica', icon: 'fas fa-leaf', color: 'green' },
|
||||
{ _id: 74, idSectorGood: [20], descr: 'Permacultura', icon: 'fas fa-recycle', color: 'green' },
|
||||
{ _id: 75, idSectorGood: [20], descr: 'Sinergico', icon: 'fas fa-handshake', color: 'green' },
|
||||
{ _id: 76, idSectorGood: [20], descr: 'Tradizionale', icon: 'fas fa-tractor', color: 'brown' },
|
||||
{ _id: 77, idSectorGood: [20], descr: 'Viticoltura', icon: 'fas fa-wine-glass-alt', color: 'purple' },
|
||||
{ _id: 78, idSectorGood: [20], descr: 'Acquacoltura', icon: 'fas fa-fish', color: 'blue' },
|
||||
{ _id: 1, idSectorGood: [1], descr: 'Abbigliamento donna', icon: 'fas fa-tshirt' },
|
||||
{ _id: 2, idSectorGood: [1], descr: 'Abbigliamento uomo', icon: 'fas fa-tshirt' },
|
||||
{ _id: 3, idSectorGood: [1], descr: 'Accessori', icon: 'fas fa-glasses' },
|
||||
{ _id: 4, idSectorGood: [1], descr: 'Scarpe donna', icon: 'fas fa-shoe-prints' },
|
||||
{ _id: 5, idSectorGood: [1], descr: 'Scarpe uomo', icon: 'fas fa-shoe-prints' },
|
||||
{ _id: 6, idSectorGood: [2], descr: 'Bagno', icon: 'fas fa-bath' },
|
||||
{ _id: 7, idSectorGood: [2], descr: 'Camera', icon: 'fas fa-bed' },
|
||||
{ _id: 8, idSectorGood: [2], descr: "Complementi d'arredo", icon: 'fas fa-couch' },
|
||||
{ _id: 9, idSectorGood: [2], descr: 'Cucina', icon: 'fas fa-utensils' },
|
||||
{ _id: 10, idSectorGood: [2], descr: 'Esterno', icon: 'fas fa-tree' },
|
||||
{ _id: 11, idSectorGood: [2], descr: 'Soggiorno', icon: 'fas fa-tv' },
|
||||
{ _id: 12, idSectorGood: [3], descr: 'Altri veicoli', icon: 'fas fa-car' },
|
||||
{ _id: 13, idSectorGood: [3], descr: 'Auto', icon: 'fas fa-car' },
|
||||
{ _id: 14, idSectorGood: [3], descr: 'Moto', icon: 'fas fa-motorcycle' },
|
||||
{ _id: 15, idSectorGood: [3], descr: 'Camper', icon: 'fas fa-caravan' },
|
||||
{ _id: 16, idSectorGood: [3], descr: 'Van (furgoni camperizzati)', icon: 'fas fa-truck' },
|
||||
{ _id: 17, idSectorGood: [4], descr: 'Bigiotteria', icon: 'fas fa-gem' },
|
||||
{ _id: 18, idSectorGood: [4], descr: 'Lavoretti', icon: 'fas fa-paint-brush' },
|
||||
{ _id: 19, idSectorGood: [4], descr: 'Altro', icon: 'fas fa-question' },
|
||||
{ _id: 20, idSectorGood: [5], descr: 'Accessori bellezza', icon: 'fas fa-spa' },
|
||||
{ _id: 21, idSectorGood: [5], descr: 'Creme e detergenti', icon: 'fas fa-pump-soap' },
|
||||
{ _id: 22, idSectorGood: [5], descr: 'Trucchi e profumi', icon: 'fas fa-palette' },
|
||||
{ _id: 23, idSectorGood: [6], descr: 'Giocattoli e giochi di società', icon: 'fas fa-dice' },
|
||||
{ _id: 24, idSectorGood: [6], descr: 'Igiene e pannolini', icon: 'fas fa-baby' },
|
||||
{ _id: 25, idSectorGood: [6], descr: 'Lettini e culle', icon: 'fas fa-baby-carriage' },
|
||||
{ _id: 26, idSectorGood: [6], descr: 'Passeggini & co', icon: 'fas fa-baby-carriage' },
|
||||
{ _id: 27, idSectorGood: [6], descr: 'Vestiti e scarpe', icon: 'fas fa-socks' },
|
||||
{ _id: 28, idSectorGood: [7], descr: 'Bere', icon: 'fas fa-glass-cheers' },
|
||||
{ _id: 29, idSectorGood: [7], descr: 'Mangiare', icon: 'fas fa-utensils' },
|
||||
{ _id: 30, idSectorGood: [8], descr: 'Antiquariato', icon: 'fas fa-history' },
|
||||
{ _id: 31, idSectorGood: [8], descr: 'Collezionismo', icon: 'fas fa-coins' },
|
||||
{ _id: 32, idSectorGood: [9], descr: 'Cellulari e accessori', icon: 'fas fa-mobile-alt' },
|
||||
{ _id: 33, idSectorGood: [9], descr: 'Computer e software', icon: 'fas fa-laptop' },
|
||||
{ _id: 34, idSectorGood: [9], descr: 'Elettrodomestici', icon: 'fas fa-blender' },
|
||||
{ _id: 35, idSectorGood: [9], descr: 'Fotografia', icon: 'fas fa-camera' },
|
||||
{ _id: 36, idSectorGood: [9], descr: 'Videogiochi e console', icon: 'fas fa-gamepad' },
|
||||
{ _id: 37, idSectorGood: [10], descr: 'Console', icon: 'fas fa-gamepad' },
|
||||
{ _id: 38, idSectorGood: [10], descr: 'Giochi di società', icon: 'fas fa-dice' },
|
||||
{ _id: 39, idSectorGood: [10], descr: 'PC games', icon: 'fas fa-desktop' },
|
||||
{ _id: 40, idSectorGood: [11], descr: 'Attrezzatura', icon: 'fas fa-tools' },
|
||||
{ _id: 41, idSectorGood: [11], descr: 'Materiali', icon: 'fas fa-box-open' },
|
||||
{ _id: 42, idSectorGood: [11], descr: 'Prodotti', icon: 'fas fa-box' },
|
||||
{ _id: 43, idSectorGood: [11], descr: 'Strumentazione', icon: 'fas fa-toolbox' },
|
||||
{ _id: 44, idSectorGood: [12], descr: ' riviste e fumetti', icon: 'fas fa-book-open' },
|
||||
{ _id: 45, idSectorGood: [13], descr: 'CD e vinili', icon: 'fas fa-compact-disc' },
|
||||
{ _id: 46, idSectorGood: [13], descr: 'Film e DVD', icon: 'fas fa-film' },
|
||||
{ _id: 47, idSectorGood: [13], descr: 'Strumenti musicali', icon: 'fas fa-guitar' },
|
||||
{ _id: 48, idSectorGood: [14], descr: 'Arredamento', icon: 'fas fa-couch' },
|
||||
{ _id: 49, idSectorGood: [14], descr: 'Attrezzature e accessori', icon: 'fas fa-tools' },
|
||||
{ _id: 50, idSectorGood: [14], descr: 'Cancelleria e cartucce', icon: 'fas fa-print' },
|
||||
{ _id: 51, idSectorGood: [15], descr: 'Abbigliamento', icon: 'fas fa-tshirt' },
|
||||
{ _id: 52, idSectorGood: [15], descr: 'Attrezzature e accessori Sport', icon: 'fas fa-football-ball' },
|
||||
{ _id: 53, idSectorGood: [15], descr: 'Bici e accessori', icon: 'fas fa-bicycle' },
|
||||
{ _id: 54, idSectorGood: [17], descr: 'Edilizia', icon: 'fas fa-hard-hat' },
|
||||
{ _id: 55, idSectorGood: [17], descr: 'Modellismo', icon: 'fas fa-puzzle-piece' },
|
||||
{ _id: 56, idSectorGood: [17], descr: 'Cucito', icon: 'fas fa-cut' },
|
||||
{ _id: 57, idSectorGood: [17], descr: 'Pulizia', icon: 'fas fa-broom' },
|
||||
{ _id: 58, idSectorGood: [17], descr: 'Per Imbiancare', icon: 'fas fa-paint-roller' },
|
||||
{ _id: 59, idSectorGood: [17], descr: 'Giardinaggio', icon: 'fas fa-seedling' },
|
||||
{ _id: 60, idSectorGood: [17], descr: 'Falegnameria', icon: 'fas fa-hammer' },
|
||||
{ _id: 61, idSectorGood: [7], descr: 'Pane', icon: 'fas fa-bread-slice' },
|
||||
{ _id: 62, idSectorGood: [7], descr: 'Pasta', icon: 'fas fa-utensils' },
|
||||
{ _id: 63, idSectorGood: [7], descr: 'Formaggi', icon: 'fas fa-cheese' },
|
||||
{ _id: 64, idSectorGood: [7], descr: 'Olio', icon: 'fas fa-oil-can' },
|
||||
{ _id: 65, idSectorGood: [7], descr: 'Fervida', icon: 'fas fa-fire' },
|
||||
{ _id: 66, idSectorGood: [7], descr: 'Fermentati', icon: 'fas fa-beer' },
|
||||
{ _id: 67, idSectorGood: [7], descr: 'Marmellate', icon: 'fas fa-jar' },
|
||||
{ _id: 68, idSectorGood: [7], descr: 'Salse', icon: 'fas fa-mortar-pestle' },
|
||||
{ _id: 69, idSectorGood: [20], descr: 'Cereali', icon: 'fas fa-wheat' },
|
||||
{ _id: 70, idSectorGood: [20], descr: 'Frutta', icon: 'fas fa-apple-alt' },
|
||||
{ _id: 71, idSectorGood: [20], descr: 'Ortaggi', icon: 'fas fa-carrot' },
|
||||
{ _id: 72, idSectorGood: [20], descr: 'Zootecnia', icon: 'fas fa-paw' },
|
||||
{ _id: 73, idSectorGood: [20], descr: 'Biologica', icon: 'fas fa-leaf' },
|
||||
{ _id: 74, idSectorGood: [20], descr: 'Permacultura', icon: 'fas fa-recycle' },
|
||||
{ _id: 75, idSectorGood: [20], descr: 'Sinergico', icon: 'fas fa-handshake' },
|
||||
{ _id: 76, idSectorGood: [20], descr: 'Tradizionale', icon: 'fas fa-tractor' },
|
||||
{ _id: 77, idSectorGood: [20], descr: 'Viticoltura', icon: 'fas fa-wine-glass-alt' },
|
||||
{ _id: 78, idSectorGood: [20], descr: 'Acquacoltura', icon: 'fas fa-fish' },
|
||||
],
|
||||
};
|
||||
};
|
||||
25
src/populate/OLD_sectorgoods.js
Normal file
25
src/populate/OLD_sectorgoods.js
Normal file
@@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
{_id: 1, descr: 'Abbigliamento', icon: 'fas fa-tshirt', color: 'blue-7'},
|
||||
{_id: 2, descr: 'Arredamento', icon: 'fas fa-couch', color: 'brown-7'},
|
||||
{_id: 3, descr: 'Auto e Moto', icon: 'fas fa-car', color: 'grey-9'},
|
||||
{_id: 4, descr: 'Artigianato', icon: 'fas fa-gem', color: 'amber-7'},
|
||||
{_id: 5, descr: 'Bellezza e Igiene', icon: 'fas fa-spa', color: 'pink-7'},
|
||||
{_id: 6, descr: 'Bimbi', icon: 'fas fa-baby', color: 'cyan-7'},
|
||||
{_id: 7, descr: 'Cibo', icon: 'fas fa-utensils', color: 'orange-7'},
|
||||
{_id: 8, descr: 'Collezionismo e Antiquariato', icon: 'fas fa-coins', color: 'brown-9'},
|
||||
{_id: 9, descr: 'Elettronica', icon: 'fas fa-laptop', color: 'blue-grey-8'},
|
||||
{_id: 10, descr: 'Giochi', icon: 'fas fa-gamepad', color: 'purple-7'},
|
||||
{_id: 11, descr: 'Hobby e Fai da Te', icon: 'fas fa-palette', color: 'deep-orange-6'},
|
||||
{_id: 12, descr: 'Libri', icon: 'fas fa-book-open', color: 'indigo-7'},
|
||||
{_id: 13, descr: 'Musica e Film', icon: 'fas fa-film', color: 'deep-purple-7'},
|
||||
{_id: 14, descr: 'Scuola e Ufficio', icon: 'fas fa-pen', color: 'blue-8'},
|
||||
{_id: 15, descr: 'Sport', icon: 'fas fa-bicycle', color: 'green-8'},
|
||||
{_id: 16, descr: 'Varie', icon: 'fas fa-box', color: 'grey-7'},
|
||||
{_id: 17, descr: 'Attrezzature', icon: 'fas fa-tools', color: 'grey-8'},
|
||||
{_id: 18, descr: 'Animali', icon: 'fas fa-paw', color: 'brown-6'},
|
||||
{_id: 19, descr: 'Arte e Decorazioni', icon: 'fas fa-palette', color: 'purple-6'},
|
||||
{_id: 20, descr: 'Agricoltura', icon: 'fas fa-seedling', color: 'green-7'},
|
||||
{_id: 21, descr: 'Elettrodomestici', icon: 'fas fa-plug', color: 'blue-grey-7'},
|
||||
],
|
||||
};
|
||||
17
src/populate/OLD_sectors.js
Normal file
17
src/populate/OLD_sectors.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
{_id: 1, descr: 'Abitare'},
|
||||
{_id: 2, descr: 'Agricoltura'},
|
||||
{_id: 3, descr: 'Alimentazione'},
|
||||
{_id: 4, descr: 'Animali'},
|
||||
{_id: 5, descr: 'Auto e Veicoli'},
|
||||
{_id: 6, descr: 'Benessere'},-
|
||||
{_id: 7, descr: 'Per la Casa'},
|
||||
{_id: 8, descr: 'Intrattenimento'},
|
||||
{_id: 10, descr: 'Per la Persona'},
|
||||
{_id: 11, descr: 'Progetti di Gruppo'},
|
||||
{_id: 12, descr: 'Salute'},
|
||||
{_id: 13, descr: 'Tecnologie'},
|
||||
{_id: 14, descr: 'Servizi'},
|
||||
],
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
const { ObjectId } = require('mongodb');
|
||||
|
||||
module.exports = {
|
||||
list: [
|
||||
/*{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a1'), idapp: '18', title: 'Alimentazione Sana' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a2'), idapp: '18', title: 'Attualità e Informazione Libera' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a3'), idapp: '18', title: 'Psicologia e Crescita Personale' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a4'), idapp: '18', title: 'Educazione e Formazione' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a5'), idapp: '18', title: 'Bambini e Ragazzi Felici' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a6'), idapp: '18', title: 'Salute e Benessere Naturali' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a7'), idapp: '18', title: 'Nuove Scienze' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a8'), idapp: '18', title: 'Spiritualità e Sciamanesimo' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4a9'), idapp: '18', title: 'Storia e Archeologia Segreta' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4aa'), idapp: '18', title: 'Autosufficienza, Autoproduzione e Vita Naturale' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4ab'), idapp: '18', title: 'Yoga' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4ac'), idapp: '18', title: 'Amici Animali' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4ad'), idapp: '18', title: 'Corpi Energetici' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4ae'), idapp: '18', title: 'Erbe, Alberi e Natura' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4af'), idapp: '18', title: 'Astrologia, Esoterismi e Numerologia' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4b0'), idapp: '18', title: 'Universo Femminile' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4b1'), idapp: '18', title: 'Sessualità e Relazione di coppia' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4b2'), idapp: '18', title: 'Tarocchi, Oracoli e Carte' },
|
||||
{ _id: new ObjectId('605c72e2f9b1a019c1e4f4b3'), idapp: '18', title: 'Techiche per il corpo' },
|
||||
*/
|
||||
],
|
||||
};
|
||||
@@ -3,187 +3,206 @@ const { ObjectId } = require('mongodb');
|
||||
module.exports = {
|
||||
list: [
|
||||
{
|
||||
"_id": new ObjectId("615a353c002c8298f4495be7"),
|
||||
"idapp": "1",
|
||||
"label": "Dono",
|
||||
"__v": 0
|
||||
_id: new ObjectId('615a353c002c8298f4495be7'),
|
||||
idapp: '1',
|
||||
label: 'Dono',
|
||||
__v: 0,
|
||||
},
|
||||
|
||||
{
|
||||
"_id": new ObjectId("61bc466567de9a1f54b25494"),
|
||||
"idapp": "1",
|
||||
"label": "Offerta Libera",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc466567de9a1f54b25494'),
|
||||
idapp: '1',
|
||||
label: 'Offerta Libera',
|
||||
__v: 0,
|
||||
},
|
||||
|
||||
{
|
||||
"_id": new ObjectId("61bc454867de9a1f54b25462"),
|
||||
"idapp": "1",
|
||||
"label": "Baratto (scambio Beni o Servizi)",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc454867de9a1f54b25462'),
|
||||
idapp: '1',
|
||||
label: 'Baratto (scambio Beni o Servizi)',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("61bc482667de9a1f54b2549c"),
|
||||
"idapp": "1",
|
||||
"label": "Scambio Lavoro",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc482667de9a1f54b2549c'),
|
||||
idapp: '1',
|
||||
label: 'Scambio Lavoro',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("61bc482667de9a1f54b2649c"),
|
||||
"idapp": "1",
|
||||
"label": "Monete Alternative",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc482667de9a1f54b2649c'),
|
||||
idapp: '1',
|
||||
label: 'Monete Alternative',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("61bc482667de9a1f54b3549e"),
|
||||
"idapp": "1",
|
||||
"label": "Euro",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc482667de9a1f54b3549e'),
|
||||
idapp: '1',
|
||||
label: 'Euro',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("615a353c002c8298f4495bf7"),
|
||||
"idapp": "12",
|
||||
"label": "Dono",
|
||||
"__v": 0
|
||||
_id: new ObjectId('615a353c002c8298f4495bf7'),
|
||||
idapp: '12',
|
||||
label: 'Dono',
|
||||
__v: 0,
|
||||
},
|
||||
|
||||
{
|
||||
"_id": new ObjectId("61bc466567de9a1f54b254f4"),
|
||||
"idapp": "12",
|
||||
"label": "Offerta Libera",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc466567de9a1f54b254f4'),
|
||||
idapp: '12',
|
||||
label: 'Offerta Libera',
|
||||
__v: 0,
|
||||
},
|
||||
|
||||
{
|
||||
"_id": new ObjectId("61bc454867de9a1f54b254f2"),
|
||||
"idapp": "12",
|
||||
"label": "Baratto",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc454867de9a1f54b254f2'),
|
||||
idapp: '12',
|
||||
label: 'Baratto',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("61bc482667de9a1f54b25412"),
|
||||
"idapp": "12",
|
||||
"label": "Scambio Lavoro",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc482667de9a1f54b25412'),
|
||||
idapp: '12',
|
||||
label: 'Scambio Lavoro',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("61bc482667de9a1f64b254ab"),
|
||||
"idapp": "12",
|
||||
"label": "Monete Alternative",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc482667de9a1f64b254ab'),
|
||||
idapp: '12',
|
||||
label: 'Monete Alternative',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("61bc482667de9a1f64b254fb"),
|
||||
"idapp": "12",
|
||||
"label": "Euro",
|
||||
"__v": 0
|
||||
_id: new ObjectId('61bc482667de9a1f64b254fb'),
|
||||
idapp: '12',
|
||||
label: 'Euro',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("5dbc6b0801234f629f75e98d"),
|
||||
"idapp": "2",
|
||||
"__v": 0,
|
||||
"label": "Offerta Libera"
|
||||
_id: new ObjectId('5dbc6b0801234f629f75e98d'),
|
||||
idapp: '2',
|
||||
__v: 0,
|
||||
label: 'Offerta Libera',
|
||||
},
|
||||
/* 2 */
|
||||
{
|
||||
"_id": new ObjectId("5dbc6b1001234f629f75e98e"),
|
||||
"idapp": "2",
|
||||
"__v": 0,
|
||||
"label": "Ingresso Gratuito"
|
||||
_id: new ObjectId('5dbc6b1001234f629f75e98e'),
|
||||
idapp: '2',
|
||||
__v: 0,
|
||||
label: 'Ingresso Gratuito',
|
||||
},
|
||||
|
||||
/* 3 */
|
||||
{
|
||||
"_id": new ObjectId("5dbc6b1801234f629f75e98f"),
|
||||
"idapp": "2",
|
||||
"__v": 0,
|
||||
"label": "Contributo",
|
||||
"showprice": true
|
||||
_id: new ObjectId('5dbc6b1801234f629f75e98f'),
|
||||
idapp: '2',
|
||||
__v: 0,
|
||||
label: 'Contributo',
|
||||
showprice: true,
|
||||
},
|
||||
|
||||
/* 4 */
|
||||
{
|
||||
"_id": new ObjectId("5dbc6b3001234f629f75e990"),
|
||||
"idapp": "2",
|
||||
"__v": 0
|
||||
_id: new ObjectId('5dbc6b3001234f629f75e990'),
|
||||
idapp: '2',
|
||||
__v: 0,
|
||||
},
|
||||
|
||||
{
|
||||
"_id": new ObjectId("602c315137d9f0738ded312f"),
|
||||
"idapp": "10",
|
||||
"__v": 0,
|
||||
"label": "Contributo",
|
||||
"showprice": true
|
||||
_id: new ObjectId('602c315137d9f0738ded312f'),
|
||||
idapp: '10',
|
||||
__v: 0,
|
||||
label: 'Contributo',
|
||||
showprice: true,
|
||||
},
|
||||
|
||||
/* 7 */
|
||||
{
|
||||
"_id": new ObjectId("602c316037d9f0738ded3132"),
|
||||
"idapp": "10",
|
||||
"__v": 0,
|
||||
"label": "Gratuito"
|
||||
_id: new ObjectId('602c316037d9f0738ded3132'),
|
||||
idapp: '10',
|
||||
__v: 0,
|
||||
label: 'Gratuito',
|
||||
},
|
||||
|
||||
/* 8 */
|
||||
{
|
||||
"_id": new ObjectId("60514b3f733ce468d09366f2"),
|
||||
"idapp": "10",
|
||||
"__v": 0,
|
||||
"label": "Evento ONLINE Gratuito"
|
||||
_id: new ObjectId('60514b3f733ce468d09366f2'),
|
||||
idapp: '10',
|
||||
__v: 0,
|
||||
label: 'Evento ONLINE Gratuito',
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("515a353c002c8298f4495bf7"),
|
||||
"idapp": "13",
|
||||
"label": "🎁 Dono",
|
||||
"__v": 0
|
||||
_id: new ObjectId('515a353c002c8298f4495bf7'),
|
||||
idapp: '13',
|
||||
label: 'Dono',
|
||||
icon: '🎁',
|
||||
color: '#e91e63',
|
||||
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc466567de9a1f54b254f4"),
|
||||
"idapp": "13",
|
||||
"label": "💸 Offerta Libera",
|
||||
"__v": 0
|
||||
_id: new ObjectId('51bc466567de9a1f54b254f4'),
|
||||
idapp: '13',
|
||||
label: 'Offerta Libera',
|
||||
icon: '💸',
|
||||
color: '#4caf50',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc454867de9a1f54b254f2"),
|
||||
"idapp": "13",
|
||||
"label": "🤝 Baratto",
|
||||
"__v": 0
|
||||
_id: new ObjectId('51bc454867de9a1f54b254f2'),
|
||||
idapp: '13',
|
||||
label: 'Baratto',
|
||||
icon: '🤝',
|
||||
color: '#ff9800',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc482667de9a1f54b25412"),
|
||||
"idapp": "13",
|
||||
"label": "💪 Scambio Lavoro",
|
||||
"__v": 0
|
||||
_id: new ObjectId('51bc482667de9a1f54b25412'),
|
||||
idapp: '13',
|
||||
label: 'Scambio Lavoro',
|
||||
icon: '💪',
|
||||
color: '#9c27b0',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc482667de9a1f64b254ab"),
|
||||
"idapp": "13",
|
||||
"label": "🪙 Monete Alternative",
|
||||
"__v": 0
|
||||
_id: new ObjectId('51bc482667de9a1f64b254ab'),
|
||||
idapp: '13',
|
||||
label: 'Monete Alternative',
|
||||
icon: '🪙',
|
||||
color: '#795548',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc482667de9a1f64b254ac"),
|
||||
"idapp": "13",
|
||||
"label": "🍚 RIS",
|
||||
"__v": 0
|
||||
_id: new ObjectId('51bc482667de9a1f64b254ac'),
|
||||
idapp: '13',
|
||||
label: 'RIS',
|
||||
icon: '🍚',
|
||||
color: '#ffc107',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc482667de9a1f64b254fb"),
|
||||
"idapp": "13",
|
||||
"label": "💶 Euro",
|
||||
"__v": 0
|
||||
_id: new ObjectId('51bc482667de9a1f64b254fb'),
|
||||
idapp: '13',
|
||||
label: 'Euro',
|
||||
icon: '💶',
|
||||
color: '#0d47a1',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc482667de9a1f64b254ff"),
|
||||
"idapp": "13",
|
||||
"label": "₿ Bitcoin",
|
||||
"__v": 0
|
||||
_id: new ObjectId('51bc482667de9a1f64b254ff'),
|
||||
idapp: '13',
|
||||
label: 'Bitcoin',
|
||||
icon: '₿',
|
||||
color: '#ff9800',
|
||||
__v: 0,
|
||||
},
|
||||
{
|
||||
"_id": new ObjectId("51bc482667de9a1f64b255ff"),
|
||||
"idapp": "13",
|
||||
"label": "⏳ Banca del Tempo",
|
||||
"__v": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
_id: new ObjectId('51bc482667de9a1f64b255ff'),
|
||||
idapp: '13',
|
||||
label: 'Banca del Tempo',
|
||||
icon: '⏳',
|
||||
color: '#00bcd4',
|
||||
__v: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
539
src/populate/migration-categories.js
Normal file
539
src/populate/migration-categories.js
Normal file
@@ -0,0 +1,539 @@
|
||||
// migration-categories.js
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const shared_consts = require('../tools/shared_nodejs');
|
||||
const tools = require('../tools/general');
|
||||
|
||||
const { Sector } = require('../models/sector');
|
||||
const { SectorGood } = require('../models/sectorgood');
|
||||
const { SectorBacheca } = require('../models/sectorbacheca');
|
||||
const { Skill } = require('../models/skill');
|
||||
const { Good } = require('../models/good');
|
||||
const { Bacheca } = require('../models/bacheca');
|
||||
const { Version } = require('../models/version');
|
||||
|
||||
const { MySkill } = require('../models/myskill');
|
||||
const { MyGood } = require('../models/mygood');
|
||||
const { MyBacheca } = require('../models/mybacheca');
|
||||
|
||||
// ============================================================================
|
||||
// MAPPING DEFINITIONS
|
||||
// ============================================================================
|
||||
|
||||
// Mapping vecchi ID Skills -> nuovi ID Skills
|
||||
const skillSectorMapping = {
|
||||
1: 1, // Abitare -> Abitare e Costruire
|
||||
2: 2, // Agricoltura -> Agricoltura e Orticoltura
|
||||
3: 3, // Alimentazione -> Alimentazione e Trasformazione
|
||||
4: 4, // Animali -> Animali e Allevamento
|
||||
5: 10, // Auto e Veicoli -> Mobilità e Trasporti
|
||||
6: 6, // Benessere -> Benessere e Cura Naturale
|
||||
7: 9, // Per la Casa -> Manutenzione e Riparazione
|
||||
8: 15, // Intrattenimento -> Tempo Libero e Cultura
|
||||
10: 7, // Per la Persona -> Educazione e Formazione (parte)
|
||||
11: 11, // Progetti di Gruppo -> Progetti Comunitari
|
||||
12: 12, // Salute -> Salute e Terapie
|
||||
13: 13, // Tecnologie -> Tecnologie Appropriate
|
||||
14: 5, // Servizi -> Artigianato e Creazione
|
||||
};
|
||||
|
||||
// Mapping vecchi ID SubSkills -> nuovi ID SubSkills
|
||||
const subSkillMapping = {
|
||||
1: 1, // Autocostruzione
|
||||
2: 4, // Ecovillaggi / Comunità
|
||||
3: 3, // Cohousing
|
||||
4: 13, // Orto sinergico
|
||||
5: 15, // Pacciamatura
|
||||
6: 14, // Orto tradizionale
|
||||
7: 16, // Permacultura
|
||||
8: 12, // Cultura idroponica
|
||||
9: 11, // Elettrocultura
|
||||
10: 10, // Aratura + semina
|
||||
11: 17, // Potatura
|
||||
12: 18, // Raccolta
|
||||
13: 20, // Preparazione cibi
|
||||
14: 21, // Preparazione bevande
|
||||
15: 20, // Autoproduzione alimenti e bevande
|
||||
16: 32, // Servizi per Cani
|
||||
17: 32, // Servizi per Gatti
|
||||
18: 30, // Servizi per Animali da allevamento
|
||||
19: 33, // Veterinario
|
||||
20: 114, // Riparazioni Auto
|
||||
21: 115, // Riparazioni Moto
|
||||
22: 111, // Riparazioni Camper / Van
|
||||
23: 111, // Creazione di Van Camperizzati
|
||||
24: 112, // Noleggio veicoli
|
||||
25: 113, // Lavaggio auto
|
||||
26: 50, // Alimentazione Naturale
|
||||
27: 57, // Ginnastica
|
||||
28: 68, // Yoga
|
||||
29: 66, // Trattamenti Olistici
|
||||
30: 60, // Meditazione e mindfulness
|
||||
31: 65, // Trattamenti Energetici
|
||||
32: 67, // Trattamenti Sonori
|
||||
33: 51, // Arteterapia
|
||||
34: 63, // Teatroterapia
|
||||
35: 52, // Cantoterapia
|
||||
36: 65, // Trattamenti Luminosi
|
||||
37: 55, // Fitoterapia
|
||||
38: 58, // Kinesiologia
|
||||
39: 66, // Terapie Naturali
|
||||
40: 96, // Muratore
|
||||
41: 95, // Imbianchino
|
||||
42: 91, // Elettricista - TV
|
||||
43: 41, // Falegname
|
||||
44: 92, // Fabbro
|
||||
45: 90, // Arredamento
|
||||
46: 94, // Idraulico
|
||||
47: 93, // Giardiniere
|
||||
48: 86, // Canne fumarie e camini e stufe
|
||||
49: 82, // Pannelli solari
|
||||
50: 101, // Riparazioni varie
|
||||
51: 101, // Tuttofare
|
||||
52: 100, // Traslochi
|
||||
53: 97, // Piastrellista
|
||||
54: 98, // Pulizie
|
||||
55: 171, // Ballo
|
||||
56: 172, // Canto
|
||||
57: 176, // Musica
|
||||
58: 175, // Letteratura e poesia
|
||||
59: 178, // Teatro
|
||||
60: 174, // Fotografia
|
||||
61: 173, // Film making
|
||||
62: 177, // Sport
|
||||
63: 170, // Arte
|
||||
70: 163, // Parrucchiere -> Sartoria su Misura
|
||||
71: 66, // Estetista -> Trattamenti Olistici
|
||||
72: 136, // Omeopatia
|
||||
73: 137, // Assistenza anziani -> OSS
|
||||
76: 125, // Baby sitter -> Volontariato
|
||||
77: 163, // Sarto
|
||||
78: 160, // Autoproduzione prodotti persona
|
||||
79: 70, // Corsi e Formazione
|
||||
80: 125, // Supporto spesa
|
||||
81: 125, // Volontariato
|
||||
82: 123, // Gruppi di acquisto
|
||||
83: 120, // Banca del tempo
|
||||
84: 121, // Collabora con noi
|
||||
85: 122, // Eventi
|
||||
86: 124, // Laboratori
|
||||
87: 121, // Idee e suggerimenti
|
||||
88: 133, // Medico di base
|
||||
89: 142, // Specialista
|
||||
90: 139, // Pediatra
|
||||
91: 131, // Dentista
|
||||
92: 140, // Psicologo
|
||||
93: 141, // Psicoterapeuta
|
||||
94: 138, // Ostetrica
|
||||
95: 135, // Nutrizionista
|
||||
97: 130, // Counseling
|
||||
98: 151, // Assistenza PC / software
|
||||
99: 150, // Assistenza Cellulari
|
||||
100: 154, // Realizzazione Siti web
|
||||
101: 153, // Realizzazione App / Piattaforme
|
||||
102: 152, // Corsi d'Informatica
|
||||
103: 99, // Riparazione Elettrodomestici
|
||||
104: 132, // Infermiera
|
||||
105: 137, // OSS
|
||||
106: 125, // Badante
|
||||
107: 59, // Massaggi
|
||||
109: 130, // Supporto
|
||||
110: 130, // Consulenza
|
||||
111: 56, // Floriterapia
|
||||
112: 54, // Costellazioni Familiari
|
||||
113: 53, // Coach Motivazionale
|
||||
114: 64, // Tecniche Essene
|
||||
115: 62, // Riflessologia
|
||||
116: 61, // Naturopatia
|
||||
120: 170, // Grafica
|
||||
121: 154, // Web
|
||||
122: 2, // Progettazione -> Bioedilizia
|
||||
123: 134, // Medicina Naturale
|
||||
124: 5, // Casa in Vendita
|
||||
125: 6, // Casa in Affitto
|
||||
126: 8, // Terreno
|
||||
127: 7, // Stanza in affitto
|
||||
128: 7, // Stanza in condivisione
|
||||
129: 23, // Home Restaurant
|
||||
130: 82, // Pannelli Solari
|
||||
131: 84, // Pompe di calore
|
||||
132: 82, // Impianti Fotovoltaici
|
||||
133: 43, // Restauro
|
||||
134: 101, // Altro
|
||||
135: 82, // Pannelli Solari
|
||||
136: 152, // Corso di Podcasting : Corsi d'Informatica
|
||||
137: 69, // Biodanza
|
||||
74: 75, // Contabile/commercialista -> Consulenze Professionali
|
||||
75: 75, // Avvocato -> Consulenze Professionali
|
||||
108: 126, // Affrancamento -> Servizi alla Comunità
|
||||
117: 75, // Organizzazione Aziendale -> Consulenze Professionali
|
||||
118: 75, // Project Manager -> Consulenze Professionali
|
||||
119: 75, // Consulenze per Startup -> Consulenze Professionali
|
||||
};
|
||||
|
||||
// Mapping vecchi ID SectorGoods -> nuovi ID SectorGoods
|
||||
const sectorGoodMapping = {
|
||||
1: 1, // Abbigliamento -> Abbigliamento e Accessori
|
||||
2: 2, // Arredamento -> Arredamento e Casa
|
||||
3: 3, // Auto e Moto -> Auto, Moto e Veicoli
|
||||
4: 4, // Artigianato -> Artigianato e Creazioni
|
||||
5: 5, // Bellezza e Igiene -> Bellezza e Cura Persona
|
||||
6: 6, // Bimbi -> Infanzia e Bambini
|
||||
7: 7, // Cibo -> Cibi e Bevande
|
||||
8: 8, // Collezionismo e Antiquariato (invariato)
|
||||
9: 9, // Elettronica -> Elettronica e Tecnologia
|
||||
10: 10, // Giochi -> Gaming e Console
|
||||
11: 11, // Hobby e Fai da Te -> Giardinaggio e Fai da Te
|
||||
12: 12, // Libri -> Libri e Riviste
|
||||
13: 13, // Musica e Film (invariato)
|
||||
14: 14, // Scuola e Ufficio (invariato)
|
||||
15: 15, // Sport -> Sport e Fitness
|
||||
16: null, // Varie -> DISTRIBUITO (rimuovere, troppo generico)
|
||||
17: 17, // Attrezzature -> Attrezzature e Strumenti
|
||||
18: 16, // Animali
|
||||
19: 20, // Arte e Decorazioni
|
||||
20: 19, // Agricoltura -> Agricoltura e Orticoltura
|
||||
21: 18, // Elettrodomestici
|
||||
};
|
||||
|
||||
// Mapping vecchi ID SectorBacheca -> nuovi ID SectorBacheca
|
||||
const sectorBachecaMapping = {
|
||||
1: 1, // Abitare -> Abitare Alternativo
|
||||
2: 2, // Agricoltura -> Agricoltura e Permacultura
|
||||
3: 3, // Alimentazione -> Alimentazione Consapevole
|
||||
4: 4, // Animali -> Animali e Natura
|
||||
5: 11, // Auto e Veicoli -> Mobilità Sostenibile
|
||||
6: 5, // Benessere -> Benessere Olistico
|
||||
7: 10, // Per la Casa -> Lavoro e Autoproduzione
|
||||
8: 6, // Intrattenimento -> Cultura e Arte
|
||||
10: 8, // Per la Persona -> Educazione Alternativa
|
||||
11: 12, // Progetti di Gruppo -> Progetti Comunitari
|
||||
12: 13, // Salute -> Salute Naturale
|
||||
13: 14, // Tecnologie -> Tecnologie Appropriate
|
||||
14: 7, // Servizi -> Economia Solidale
|
||||
};
|
||||
|
||||
// Mapping vecchi idSkill -> nuovi idBacheca
|
||||
const bachecaMapping = {
|
||||
1: 1, // Autocostruzione
|
||||
2: 4, // Ecovillaggi / Comunità -> Ecovillaggi
|
||||
3: 3, // Cohousing
|
||||
4: 12, // Orto sinergico -> Permacultura
|
||||
7: 12, // Permacultura
|
||||
26: 40, // Alimentazione Naturale -> Cerchi di Condivisione
|
||||
27: 44, // Ginnastica -> Yoga e Movimento
|
||||
28: 44, // Yoga -> Yoga e Movimento
|
||||
29: 43, // Trattamenti Olistici -> Pratiche Energetiche
|
||||
30: 42, // Meditazione e mindfulness -> Meditazione
|
||||
55: 50, // Ballo
|
||||
56: 51, // Canto -> Cerchi di Canto
|
||||
57: 53, // Musica -> Concerti
|
||||
59: 55, // Teatro
|
||||
79: 73, // Corsi e Formazione -> Workshop e Corsi
|
||||
82: 24, // Gruppi di acquisto -> Gruppi Acquisto
|
||||
83: 60, // Banca del tempo -> Banca del Tempo
|
||||
84: 114, // Collabora con noi -> Nuove Iniziative
|
||||
85: 113, // Eventi -> Eventi Comunitari
|
||||
86: 71, // Laboratori -> Laboratori Bambini
|
||||
87: 111, // Idee e suggerimenti -> Brainstorming
|
||||
// Aggiungi altri mapping secondo necessità
|
||||
// Per gli altri usa categoria generica o 0
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// MIGRATION FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Aggiorna i settori Skills con nuove categorie
|
||||
*/
|
||||
async function updateSkillSectors(Sector) {
|
||||
console.log('🔄 Aggiornamento Skill Sectors...');
|
||||
|
||||
const newSectors = require('./new_sectors');
|
||||
|
||||
await Sector.deleteMany({});
|
||||
const result = await Sector.insertMany(newSectors.list);
|
||||
|
||||
console.log(`✅ ${result.length} Skill Sectors aggiornati`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggiorna le Skills con nuove sottocategorie
|
||||
*/
|
||||
async function updateSkills(Skill) {
|
||||
console.log('🔄 Aggiornamento Sub-Skills...');
|
||||
|
||||
const newSkills = require('./new_subskills'); // Il file che hai creato sopra
|
||||
|
||||
await Skill.deleteMany({});
|
||||
const result = await Skill.insertMany(newSkills.list);
|
||||
|
||||
console.log(`✅ ${result.length} Sub-Skills aggiornate`);
|
||||
}
|
||||
|
||||
async function updateSectorGoods(Good) {
|
||||
console.log('🔄 Aggiornamento SectorGoods...');
|
||||
|
||||
const newSectorGoods = require('./new_sectorgoods');
|
||||
|
||||
await SectorGood.deleteMany({});
|
||||
const result = await SectorGood.insertMany(newSectorGoods.list);
|
||||
|
||||
console.log(`✅ ${result.length} SectorGood aggiornati`);
|
||||
}
|
||||
async function updateSectorBachecas(Bacheca) {
|
||||
console.log('🔄 Aggiornamento SectorBachecas...');
|
||||
|
||||
const newSectorBachecas = require('./new_sectorbachecas');
|
||||
|
||||
await SectorBacheca.deleteMany({});
|
||||
const result = await SectorBacheca.insertMany(newSectorBachecas.list);
|
||||
|
||||
console.log(`✅ ${result.length} SectorBacheca aggiornati`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggiorna i Goods (rimozione campo color)
|
||||
*/
|
||||
async function updateGoods(Good) {
|
||||
console.log('🔄 Aggiornamento Goods...');
|
||||
|
||||
const newGoods = require('./new_goods');
|
||||
|
||||
await Good.deleteMany({});
|
||||
const result = await Good.insertMany(newGoods.list);
|
||||
|
||||
console.log(`✅ ${result.length} Goods aggiornati`);
|
||||
}
|
||||
async function updateBachecas(Good) {
|
||||
console.log('🔄 Aggiornamento Bachecas...');
|
||||
|
||||
const newBachecas = require('./new_bachecas');
|
||||
|
||||
await Bacheca.deleteMany({});
|
||||
const result = await Bacheca.insertMany(newBachecas.list);
|
||||
|
||||
console.log(`✅ ${result.length} Bachecas aggiornati`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Migra i record MySkill
|
||||
*/
|
||||
async function migrateMySkills(MySkill) {
|
||||
console.log('🔄 Migrazione MySkill records...');
|
||||
|
||||
const records = await MySkill.find({}).lean();
|
||||
let updated = 0;
|
||||
let unchanged = 0;
|
||||
|
||||
for (const record of records) {
|
||||
const updates = {};
|
||||
|
||||
// Mappa idSector
|
||||
if (record.idSector && skillSectorMapping[record.idSector]) {
|
||||
if (skillSectorMapping[record.idSector] !== record.idSector) {
|
||||
updates.idSector = skillSectorMapping[record.idSector];
|
||||
}
|
||||
}
|
||||
|
||||
// Mappa idSkill (tutte hanno destinazione ora)
|
||||
if (record.idSkill && subSkillMapping[record.idSkill] !== undefined) {
|
||||
const newId = subSkillMapping[record.idSkill];
|
||||
if (newId !== record.idSkill) {
|
||||
updates.idSkill = newId;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await MySkill.updateOne({ _id: record._id }, { $set: updates });
|
||||
updated++;
|
||||
} else {
|
||||
unchanged++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ MySkill: ${updated} aggiornati, ${unchanged} invariati`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Migra i record MyGood
|
||||
*/
|
||||
async function migrateMyGoods(MyGood) {
|
||||
console.log('🔄 Migrazione MyGood records...');
|
||||
|
||||
const records = await MyGood.find({}).lean();
|
||||
let updated = 0;
|
||||
let unchanged = 0;
|
||||
|
||||
for (const record of records) {
|
||||
const updates = {};
|
||||
|
||||
// Mappa idSectorGood
|
||||
if (record.idSectorGood && sectorGoodMapping[record.idSectorGood]) {
|
||||
if (sectorGoodMapping[record.idSectorGood] !== record.idSectorGood) {
|
||||
updates.idSectorGood = sectorGoodMapping[record.idSectorGood];
|
||||
}
|
||||
}
|
||||
|
||||
// idGood rimane invariato (stessi ID)
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await MyGood.updateOne({ _id: record._id }, { $set: updates });
|
||||
updated++;
|
||||
} else {
|
||||
unchanged++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ MyGood: ${updated} aggiornati, ${unchanged} invariati`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Migra i record MyBacheca
|
||||
*/
|
||||
async function migrateMyBacheca(MyBacheca) {
|
||||
console.log('🔄 Migrazione MyBacheca records...');
|
||||
|
||||
const records = await MyBacheca.find({}).lean();
|
||||
let updated = 0;
|
||||
let unchanged = 0;
|
||||
|
||||
for (const record of records) {
|
||||
const updates = {};
|
||||
|
||||
// Mappa idSector -> idSectorBacheca (vecchio campo -> nuovo campo)
|
||||
if (record.idSector && sectorBachecaMapping[record.idSector]) {
|
||||
updates.idSectorBacheca = sectorBachecaMapping[record.idSector];
|
||||
}
|
||||
|
||||
// Mappa idSkill -> idBacheca (vecchio campo -> nuovo campo)
|
||||
if (record.idSkill && bachecaMapping[record.idSkill] !== undefined) {
|
||||
updates.idBacheca = bachecaMapping[record.idSkill];
|
||||
} else if (record.idSkill) {
|
||||
// Se non c'è mapping specifico, metti 0 (generico)
|
||||
updates.idBacheca = 0;
|
||||
}
|
||||
|
||||
// Rimuovi i campi vecchi
|
||||
const unsetFields = {};
|
||||
if (record.idSector !== undefined) unsetFields.idSector = '';
|
||||
if (record.idSkill !== undefined) unsetFields.idSkill = '';
|
||||
|
||||
if (Object.keys(updates).length > 0 || Object.keys(unsetFields).length > 0) {
|
||||
const updateQuery = {};
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
updateQuery.$set = updates;
|
||||
}
|
||||
|
||||
if (Object.keys(unsetFields).length > 0) {
|
||||
updateQuery.$unset = unsetFields;
|
||||
}
|
||||
|
||||
await MyBacheca.updateOne({ _id: record._id }, updateQuery);
|
||||
updated++;
|
||||
} else {
|
||||
unchanged++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ MyBacheca: ${updated} aggiornati, ${unchanged} invariati`);
|
||||
}
|
||||
|
||||
async function aggiornaCategorieESottoCategorie() {
|
||||
console.log('\n Migrazione DIC 2025 da ESEGUIRE ----------- ');
|
||||
await updateSkillSectors(Sector);
|
||||
await updateSkills(Skill);
|
||||
await updateSectorGoods(SectorGood);
|
||||
await updateSectorBachecas(SectorBacheca);
|
||||
await updateGoods(Good);
|
||||
await updateBachecas(Bacheca);
|
||||
|
||||
// const populate = require('./populate');
|
||||
|
||||
// ris = populate.rewriteTable('contribtypes');
|
||||
|
||||
return ris;
|
||||
}
|
||||
// ============================================================================
|
||||
// MAIN MIGRATION SCRIPT
|
||||
// ============================================================================
|
||||
|
||||
async function runMigration() {
|
||||
try {
|
||||
const idapp = 0; // TUTTI
|
||||
|
||||
console.log('🚀 Controllo Versioni Tabelle (runMigration)');
|
||||
|
||||
const isMigratioDic2025Executed = await Version.isJobExecuted(
|
||||
idapp,
|
||||
shared_consts.JOB_TO_EXECUTE.MIGRATION_SECTORS_DIC25
|
||||
);
|
||||
|
||||
const vers_server_str = await tools.getVersServer();
|
||||
|
||||
const version_server = tools.versionToNumber(vers_server_str);
|
||||
|
||||
// Step 1: Aggiorna categorie solo 1 volta sola !
|
||||
if (!isMigratioDic2025Executed) {
|
||||
await aggiornaCategorieESottoCategorie();
|
||||
}
|
||||
|
||||
const myskill_updated = await Version.isTableVersionUpdated(idapp, 'myskill');
|
||||
if (!myskill_updated) {
|
||||
// MYSKILL
|
||||
|
||||
if (!isMigratioDic2025Executed) await migrateMySkills(MySkill);
|
||||
|
||||
// ++ Altri aggiornamenti da fare
|
||||
|
||||
// FINE - Aggiorna Versione Tabella
|
||||
await Version.updateTableVersion(idapp, 'myskill', version_server);
|
||||
}
|
||||
|
||||
const mygood_updated = await Version.isTableVersionUpdated(idapp, 'mygood');
|
||||
if (!mygood_updated) {
|
||||
// MYGOOD
|
||||
if (!isMigratioDic2025Executed) await migrateMyGoods(MyGood);
|
||||
|
||||
// ++ Altri aggiornamenti da fare
|
||||
|
||||
// FINE - Aggiorna Versione Tabella
|
||||
await Version.updateTableVersion(idapp, 'mygood', version_server);
|
||||
}
|
||||
|
||||
const mybacheca_updated = await Version.isTableVersionUpdated(idapp, 'mybacheca');
|
||||
if (!mybacheca_updated) {
|
||||
// MYBACHECA
|
||||
|
||||
if (!isMigratioDic2025Executed) await migrateMyBacheca(MyBacheca);
|
||||
|
||||
// ++ Altri aggiornamenti da fare
|
||||
|
||||
// FINE - Aggiorna Versione Tabella
|
||||
await Version.updateTableVersion(idapp, 'mybacheca', version_server);
|
||||
}
|
||||
|
||||
// FINE -----------------------
|
||||
if (!isMigratioDic2025Executed) {
|
||||
await Version.setJobExecuted(idapp, shared_consts.JOB_TO_EXECUTE.MIGRATION_SECTORS_DIC25);
|
||||
console.log('\n✅ Migrazione DIC 2025 completata con successo!');
|
||||
}
|
||||
|
||||
await Version.setLastVersionRun(idapp, version_server);
|
||||
} catch (error) {
|
||||
console.error('❌ Errore durante la migrazione:', error);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
runMigration,
|
||||
skillSectorMapping,
|
||||
subSkillMapping,
|
||||
sectorGoodMapping,
|
||||
sectorBachecaMapping,
|
||||
aggiornaCategorieESottoCategorie,
|
||||
};
|
||||
107
src/populate/new_bachecas.js
Normal file
107
src/populate/new_bachecas.js
Normal file
@@ -0,0 +1,107 @@
|
||||
// new_bachecas.js
|
||||
module.exports = {
|
||||
list: [
|
||||
// Abitare Alternativo (1)
|
||||
{ _id: 1, idSectorBacheca: [1], descr: 'Autocostruzione', icon: 'fas fa-hammer' },
|
||||
{ _id: 2, idSectorBacheca: [1], descr: 'Bioedilizia', icon: 'fas fa-leaf' },
|
||||
{ _id: 3, idSectorBacheca: [1], descr: 'Cohousing', icon: 'home_work' },
|
||||
|
||||
{ _id: 4, idSectorBacheca: [1], descr: 'Ecovillaggi', icon: 'fas fa-users' },
|
||||
{ _id: 5, idSectorBacheca: [1], descr: 'Offerte Immobili', icon: 'fas fa-key' },
|
||||
{ _id: 6, idSectorBacheca: [1], descr: 'Stanze Condivise', icon: 'fas fa-door-open' },
|
||||
|
||||
// Agricoltura e Permacultura (2)
|
||||
{ _id: 10, idSectorBacheca: [2], descr: 'Corsi Agricoltura', icon: 'fas fa-chalkboard-teacher' },
|
||||
{ _id: 11, idSectorBacheca: [2], descr: 'Orti Condivisi', icon: 'fas fa-seedling' },
|
||||
{ _id: 12, idSectorBacheca: [2], descr: 'Permacultura', icon: 'fas fa-recycle' },
|
||||
{ _id: 13, idSectorBacheca: [2], descr: 'Scambio Sementi', icon: 'fas fa-exchange-alt' },
|
||||
{ _id: 14, idSectorBacheca: [2], descr: 'Visite in Azienda', icon: 'fas fa-tractor' },
|
||||
{ _id: 15, idSectorBacheca: [2], descr: 'Wwoof e Volontariato', icon: 'fas fa-hands-helping' },
|
||||
|
||||
// Alimentazione Consapevole (3)
|
||||
{ _id: 20, idSectorBacheca: [3], descr: 'Autoproduzione', icon: 'kitchen' },
|
||||
|
||||
{ _id: 21, idSectorBacheca: [3], descr: 'Cene Condivise', icon: 'fas fa-utensils' },
|
||||
{ _id: 22, idSectorBacheca: [3], descr: 'Corsi Cucina', icon: 'restaurant' },
|
||||
|
||||
{ _id: 23, idSectorBacheca: [3], descr: 'Fermentazione', icon: 'fas fa-flask' },
|
||||
{ _id: 24, idSectorBacheca: [3], descr: 'Gruppi Acquisto', icon: 'fas fa-shopping-basket' },
|
||||
{ _id: 25, idSectorBacheca: [3], descr: 'Panificazione', icon: 'fas fa-bread-slice' },
|
||||
|
||||
// Animali e Natura (4)
|
||||
{ _id: 30, idSectorBacheca: [4], descr: 'Apicoltura', icon: 'hive' },
|
||||
|
||||
{ _id: 31, idSectorBacheca: [4], descr: 'Escursioni Natura', icon: 'fas fa-hiking' },
|
||||
{ _id: 32, idSectorBacheca: [4], descr: 'Pet Sitting Condiviso', icon: 'fas fa-paw' },
|
||||
{ _id: 33, idSectorBacheca: [4], descr: 'Riconoscimento Piante', icon: 'fas fa-leaf' },
|
||||
|
||||
// Benessere Olistico (5)
|
||||
{ _id: 40, idSectorBacheca: [5], descr: 'Cerchi di Condivisione', icon: 'fas fa-circle' },
|
||||
{ _id: 41, idSectorBacheca: [5], descr: 'Costellazioni Familiari', icon: 'fas fa-users' },
|
||||
{ _id: 42, idSectorBacheca: [5], descr: 'Meditazione', icon: 'fas fa-om' },
|
||||
{ _id: 43, idSectorBacheca: [5], descr: 'Pratiche Energetiche', icon: 'fas fa-hand-sparkles' },
|
||||
{ _id: 44, idSectorBacheca: [5], descr: 'Yoga e Movimento', icon: 'self_improvement' },
|
||||
|
||||
// Cultura e Arte (6)
|
||||
{ _id: 50, idSectorBacheca: [6], descr: 'Ballo e Danza', icon: 'fas fa-music' },
|
||||
{ _id: 51, idSectorBacheca: [6], descr: 'Cerchi di Canto', icon: 'fas fa-microphone' },
|
||||
{ _id: 52, idSectorBacheca: [6], descr: 'Cinema e Film', icon: 'fas fa-film' },
|
||||
{ _id: 53, idSectorBacheca: [6], descr: 'Concerti', icon: 'fas fa-guitar' },
|
||||
{ _id: 54, idSectorBacheca: [6], descr: 'Mostre e Arte', icon: 'fas fa-palette' },
|
||||
{ _id: 55, idSectorBacheca: [6], descr: 'Teatro', icon: 'fas fa-theater-masks' },
|
||||
|
||||
// Economia Solidale (7)
|
||||
{ _id: 60, idSectorBacheca: [7], descr: 'Banca del Tempo', icon: 'fas fa-clock' },
|
||||
{ _id: 61, idSectorBacheca: [7], descr: 'Finanza Etica', icon: 'savings' },
|
||||
|
||||
{ _id: 62, idSectorBacheca: [7], descr: 'Mercatini Scambio', icon: 'fas fa-store' },
|
||||
{ _id: 63, idSectorBacheca: [7], descr: 'Monete Locali', icon: 'fas fa-coins' },
|
||||
|
||||
// Educazione Alternativa (8)
|
||||
{ _id: 70, idSectorBacheca: [8], descr: 'Educazione Parentale', icon: 'fas fa-child' },
|
||||
{ _id: 71, idSectorBacheca: [8], descr: 'Laboratori Bambini', icon: 'fas fa-baby' },
|
||||
{ _id: 72, idSectorBacheca: [8], descr: 'Scuola Libertaria', icon: 'fas fa-book-reader' },
|
||||
{ _id: 73, idSectorBacheca: [8], descr: 'Workshop e Corsi', icon: 'fas fa-chalkboard-teacher' },
|
||||
|
||||
// Energie Rinnovabili (9)
|
||||
{ _id: 80, idSectorBacheca: [9], descr: 'Autocostruzione Solare', icon: 'fas fa-solar-panel' },
|
||||
{ _id: 81, idSectorBacheca: [9], descr: 'Compostaggio', icon: 'fas fa-recycle' },
|
||||
{ _id: 82, idSectorBacheca: [9], descr: 'Comunità Energetiche', icon: 'fas fa-plug' },
|
||||
{ _id: 83, idSectorBacheca: [9], descr: 'Riciclo Creativo', icon: 'restore_from_trash' },
|
||||
|
||||
// Lavoro e Autoproduzione (10)
|
||||
{ _id: 90, idSectorBacheca: [10], descr: 'Artigianato', icon: 'fas fa-hammer' },
|
||||
{ _id: 91, idSectorBacheca: [10], descr: 'Autocostruzione', icon: 'fas fa-tools' },
|
||||
{ _id: 92, idSectorBacheca: [10], descr: 'Falegnameria', icon: 'handyman' },
|
||||
|
||||
{ _id: 93, idSectorBacheca: [10], descr: 'Riparazione', icon: 'fas fa-wrench' },
|
||||
{ _id: 94, idSectorBacheca: [10], descr: 'Sartoria', icon: 'fas fa-cut' },
|
||||
|
||||
// Mobilità Sostenibile (11)
|
||||
{ _id: 100, idSectorBacheca: [11], descr: 'Biciclette', icon: 'fas fa-bicycle' },
|
||||
{ _id: 101, idSectorBacheca: [11], descr: 'Camperisti', icon: 'fas fa-caravan' },
|
||||
{ _id: 102, idSectorBacheca: [11], descr: 'Car Pooling', icon: 'fas fa-car' },
|
||||
{ _id: 103, idSectorBacheca: [11], descr: 'Ciclofficine', icon: 'fas fa-tools' },
|
||||
|
||||
// Progetti Comunitari (12)
|
||||
{ _id: 110, idSectorBacheca: [12], descr: 'Assemblee', icon: 'fas fa-users' },
|
||||
{ _id: 111, idSectorBacheca: [12], descr: 'Brainstorming', icon: 'fas fa-lightbulb' },
|
||||
{ _id: 112, idSectorBacheca: [12], descr: 'Co-progettazione', icon: 'account_tree' },
|
||||
|
||||
{ _id: 113, idSectorBacheca: [12], descr: 'Eventi Comunitari', icon: 'fas fa-calendar-alt' },
|
||||
{ _id: 114, idSectorBacheca: [12], descr: 'Nuove Iniziative', icon: 'fas fa-rocket' },
|
||||
|
||||
// Salute Naturale (13)
|
||||
{ _id: 120, idSectorBacheca: [13], descr: 'Erboristeria', icon: 'fas fa-leaf' },
|
||||
{ _id: 121, idSectorBacheca: [13], descr: 'Fitoterapia', icon: 'fas fa-mortar-pestle' },
|
||||
{ _id: 122, idSectorBacheca: [13], descr: 'Medicine Tradizionali', icon: 'healing' },
|
||||
|
||||
{ _id: 123, idSectorBacheca: [13], descr: 'Primo Soccorso', icon: 'fas fa-first-aid' },
|
||||
|
||||
// Tecnologie Appropriate (14)
|
||||
{ _id: 130, idSectorBacheca: [14], descr: 'Linux e Open Source', icon: 'computer' },
|
||||
{ _id: 131, idSectorBacheca: [14], descr: 'Privacy Digitale', icon: 'fas fa-shield-alt' },
|
||||
{ _id: 132, idSectorBacheca: [14], descr: 'Riparazione Devices', icon: 'fas fa-mobile-alt' },
|
||||
{ _id: 133, idSectorBacheca: [14], descr: 'Self Hosting', icon: 'fas fa-server' },
|
||||
],
|
||||
};
|
||||
87
src/populate/new_goods.js
Normal file
87
src/populate/new_goods.js
Normal file
@@ -0,0 +1,87 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
{ _id: 1, idSectorGood: [1], descr: 'Abbigliamento donna', icon: 'fas fa-tshirt' },
|
||||
{ _id: 2, idSectorGood: [1], descr: 'Abbigliamento uomo', icon: 'fas fa-tshirt' },
|
||||
{ _id: 3, idSectorGood: [1], descr: 'Accessori', icon: 'fas fa-glasses' },
|
||||
{ _id: 4, idSectorGood: [1], descr: 'Scarpe donna', icon: 'fas fa-shoe-prints' },
|
||||
{ _id: 5, idSectorGood: [1], descr: 'Scarpe uomo', icon: 'fas fa-shoe-prints' },
|
||||
{ _id: 6, idSectorGood: [2], descr: 'Bagno', icon: 'fas fa-bath' },
|
||||
{ _id: 7, idSectorGood: [2], descr: 'Camera', icon: 'fas fa-bed' },
|
||||
{ _id: 8, idSectorGood: [2], descr: "Complementi d'arredo", icon: 'fas fa-couch' },
|
||||
{ _id: 9, idSectorGood: [2], descr: 'Cucina', icon: 'fas fa-utensils' },
|
||||
{ _id: 10, idSectorGood: [2], descr: 'Esterno', icon: 'fas fa-tree' },
|
||||
{ _id: 11, idSectorGood: [2], descr: 'Soggiorno', icon: 'fas fa-tv' },
|
||||
{ _id: 12, idSectorGood: [3], descr: 'Altri veicoli', icon: 'fas fa-car' },
|
||||
{ _id: 13, idSectorGood: [3], descr: 'Auto', icon: 'fas fa-car' },
|
||||
{ _id: 14, idSectorGood: [3], descr: 'Moto', icon: 'fas fa-motorcycle' },
|
||||
{ _id: 15, idSectorGood: [3], descr: 'Camper', icon: 'fas fa-caravan' },
|
||||
{ _id: 16, idSectorGood: [3], descr: 'Van (furgoni camperizzati)', icon: 'fas fa-truck' },
|
||||
{ _id: 17, idSectorGood: [4], descr: 'Bigiotteria', icon: 'fas fa-gem' },
|
||||
{ _id: 18, idSectorGood: [4], descr: 'Lavoretti', icon: 'fas fa-paint-brush' },
|
||||
{ _id: 19, idSectorGood: [4], descr: 'Altro', icon: 'fas fa-question' },
|
||||
{ _id: 20, idSectorGood: [5], descr: 'Accessori bellezza', icon: 'fas fa-spa' },
|
||||
{ _id: 21, idSectorGood: [5], descr: 'Creme e detergenti', icon: 'soap' },
|
||||
|
||||
{ _id: 22, idSectorGood: [5], descr: 'Trucchi e profumi', icon: 'fas fa-palette' },
|
||||
{ _id: 23, idSectorGood: [6], descr: 'Giocattoli e giochi di società', icon: 'fas fa-dice' },
|
||||
{ _id: 24, idSectorGood: [6], descr: 'Igiene e pannolini', icon: 'fas fa-baby' },
|
||||
{ _id: 25, idSectorGood: [6], descr: 'Lettini e culle', icon: 'fas fa-baby-carriage' },
|
||||
{ _id: 26, idSectorGood: [6], descr: 'Passeggini & co', icon: 'fas fa-baby-carriage' },
|
||||
{ _id: 27, idSectorGood: [6], descr: 'Vestiti e scarpe', icon: 'fas fa-socks' },
|
||||
{ _id: 28, idSectorGood: [7], descr: 'Bere', icon: 'fas fa-glass-cheers' },
|
||||
{ _id: 29, idSectorGood: [7], descr: 'Mangiare', icon: 'fas fa-utensils' },
|
||||
{ _id: 30, idSectorGood: [8], descr: 'Antiquariato', icon: 'fas fa-history' },
|
||||
{ _id: 31, idSectorGood: [8], descr: 'Collezionismo', icon: 'fas fa-coins' },
|
||||
{ _id: 32, idSectorGood: [9], descr: 'Cellulari e accessori', icon: 'fas fa-mobile-alt' },
|
||||
{ _id: 33, idSectorGood: [9], descr: 'Computer e software', icon: 'fas fa-laptop' },
|
||||
{ _id: 34, idSectorGood: [9], descr: 'Elettrodomestici', icon: 'fas fa-blender' },
|
||||
{ _id: 35, idSectorGood: [9], descr: 'Fotografia', icon: 'fas fa-camera' },
|
||||
{ _id: 36, idSectorGood: [9], descr: 'Videogiochi e console', icon: 'fas fa-gamepad' },
|
||||
{ _id: 37, idSectorGood: [10], descr: 'Console', icon: 'fas fa-gamepad' },
|
||||
{ _id: 38, idSectorGood: [10], descr: 'Giochi di società', icon: 'fas fa-dice' },
|
||||
{ _id: 39, idSectorGood: [10], descr: 'PC games', icon: 'fas fa-desktop' },
|
||||
{ _id: 40, idSectorGood: [11], descr: 'Attrezzatura', icon: 'fas fa-tools' },
|
||||
{ _id: 41, idSectorGood: [11], descr: 'Materiali', icon: 'fas fa-box-open' },
|
||||
{ _id: 42, idSectorGood: [11], descr: 'Prodotti', icon: 'fas fa-box' },
|
||||
{ _id: 43, idSectorGood: [11], descr: 'Strumentazione', icon: 'fas fa-toolbox' },
|
||||
{ _id: 44, idSectorGood: [12], descr: ' riviste e fumetti', icon: 'fas fa-book-open' },
|
||||
{ _id: 45, idSectorGood: [13], descr: 'CD e vinili', icon: 'fas fa-compact-disc' },
|
||||
{ _id: 46, idSectorGood: [13], descr: 'Film e DVD', icon: 'fas fa-film' },
|
||||
{ _id: 47, idSectorGood: [13], descr: 'Strumenti musicali', icon: 'fas fa-guitar' },
|
||||
{ _id: 48, idSectorGood: [14], descr: 'Arredamento', icon: 'fas fa-couch' },
|
||||
{ _id: 49, idSectorGood: [14], descr: 'Attrezzature e accessori', icon: 'fas fa-tools' },
|
||||
{ _id: 50, idSectorGood: [14], descr: 'Cancelleria e cartucce', icon: 'fas fa-print' },
|
||||
{ _id: 51, idSectorGood: [15], descr: 'Abbigliamento', icon: 'fas fa-tshirt' },
|
||||
{ _id: 52, idSectorGood: [15], descr: 'Attrezzature e accessori Sport', icon: 'fas fa-football-ball' },
|
||||
{ _id: 53, idSectorGood: [15], descr: 'Bici e accessori', icon: 'fas fa-bicycle' },
|
||||
{ _id: 54, idSectorGood: [17], descr: 'Edilizia', icon: 'fas fa-hard-hat' },
|
||||
{ _id: 55, idSectorGood: [17], descr: 'Modellismo', icon: 'fas fa-puzzle-piece' },
|
||||
{ _id: 56, idSectorGood: [17], descr: 'Cucito', icon: 'fas fa-cut' },
|
||||
{ _id: 57, idSectorGood: [17], descr: 'Pulizia', icon: 'fas fa-broom' },
|
||||
{ _id: 58, idSectorGood: [17], descr: 'Per Imbiancare', icon: 'fas fa-paint-roller' },
|
||||
{ _id: 59, idSectorGood: [17], descr: 'Giardinaggio', icon: 'fas fa-seedling' },
|
||||
{ _id: 60, idSectorGood: [17], descr: 'Falegnameria', icon: 'fas fa-hammer' },
|
||||
{ _id: 61, idSectorGood: [7], descr: 'Pane', icon: 'fas fa-bread-slice' },
|
||||
{ _id: 62, idSectorGood: [7], descr: 'Pasta', icon: 'fas fa-utensils' },
|
||||
{ _id: 63, idSectorGood: [7], descr: 'Formaggi', icon: 'cake' },
|
||||
{ _id: 64, idSectorGood: [7], descr: 'Olio', icon: 'water_drop' },
|
||||
|
||||
{ _id: 65, idSectorGood: [7], descr: 'Fervida', icon: 'fas fa-fire' },
|
||||
{ _id: 66, idSectorGood: [7], descr: 'Fermentati', icon: 'fas fa-beer' },
|
||||
{ _id: 67, idSectorGood: [7], descr: 'Marmellate', icon: 'kitchen' },
|
||||
|
||||
{ _id: 68, idSectorGood: [7], descr: 'Salse', icon: 'fas fa-mortar-pestle' },
|
||||
{ _id: 69, idSectorGood: [20], descr: 'Cereali', icon: 'grain' },
|
||||
|
||||
{ _id: 70, idSectorGood: [20], descr: 'Frutta', icon: 'fas fa-apple-alt' },
|
||||
{ _id: 71, idSectorGood: [20], descr: 'Ortaggi', icon: 'fas fa-carrot' },
|
||||
{ _id: 72, idSectorGood: [20], descr: 'Zootecnia', icon: 'fas fa-paw' },
|
||||
{ _id: 73, idSectorGood: [20], descr: 'Biologica', icon: 'fas fa-leaf' },
|
||||
{ _id: 74, idSectorGood: [20], descr: 'Permacultura', icon: 'fas fa-recycle' },
|
||||
{ _id: 75, idSectorGood: [20], descr: 'Sinergico', icon: 'fas fa-handshake' },
|
||||
{ _id: 76, idSectorGood: [20], descr: 'Tradizionale', icon: 'fas fa-tractor' },
|
||||
{ _id: 77, idSectorGood: [20], descr: 'Viticoltura', icon: 'wine_bar' },
|
||||
{ _id: 78, idSectorGood: [20], descr: 'Acquacoltura', icon: 'fas fa-fish' },
|
||||
{ _id: 79, idSectorGood: [2], descr: 'Casalinghi', icon: 'home_repair_service' },
|
||||
],
|
||||
};
|
||||
19
src/populate/new_sectorbachecas.js
Normal file
19
src/populate/new_sectorbachecas.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// new_sectorbachecas.js
|
||||
module.exports = {
|
||||
list: [
|
||||
{ _id: 1, descr: 'Abitare Alternativo', icon: 'fas fa-home', color: 'brown-7' },
|
||||
{ _id: 2, descr: 'Agricoltura e Permacultura', icon: 'fas fa-seedling', color: 'green-7' },
|
||||
{ _id: 3, descr: 'Alimentazione Consapevole', icon: 'fas fa-apple-alt', color: 'orange-7' },
|
||||
{ _id: 4, descr: 'Animali e Natura', icon: 'fas fa-paw', color: 'brown-6' },
|
||||
{ _id: 5, descr: 'Benessere Olistico', icon: 'fas fa-spa', color: 'teal-6' },
|
||||
{ _id: 6, descr: 'Cultura e Arte', icon: 'fas fa-palette', color: 'deep-purple-6' },
|
||||
{ _id: 7, descr: 'Economia Solidale', icon: 'fas fa-handshake', color: 'amber-7' },
|
||||
{ _id: 8, descr: 'Educazione Alternativa', icon: 'fas fa-book-reader', color: 'indigo-7' },
|
||||
{ _id: 9, descr: 'Energie Rinnovabili', icon: 'fas fa-solar-panel', color: 'yellow-8' },
|
||||
{ _id: 10, descr: 'Lavoro e Autoproduzione', icon: 'fas fa-hammer', color: 'grey-8' },
|
||||
{ _id: 11, descr: 'Mobilità Sostenibile', icon: 'fas fa-bicycle', color: 'blue-7' },
|
||||
{ _id: 12, descr: 'Progetti Comunitari', icon: 'fas fa-users', color: 'purple-7' },
|
||||
{ _id: 13, descr: 'Salute Naturale', icon: 'fas fa-heart', color: 'red-6' },
|
||||
{ _id: 14, descr: 'Tecnologie Appropriate', icon: 'fas fa-laptop-code', color: 'blue-grey-7' },
|
||||
],
|
||||
};
|
||||
24
src/populate/new_sectorgoods.js
Normal file
24
src/populate/new_sectorgoods.js
Normal file
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
{ _id: 1, descr: 'Abbigliamento e Accessori', icon: 'fas fa-tshirt', color: 'blue-7' },
|
||||
{ _id: 2, descr: 'Arredamento e Casa', icon: 'fas fa-couch', color: 'brown-7' },
|
||||
{ _id: 3, descr: 'Auto, Moto e Veicoli', icon: 'fas fa-car', color: 'grey-9' },
|
||||
{ _id: 4, descr: 'Artigianato e Creazioni', icon: 'fas fa-gem', color: 'amber-7' },
|
||||
{ _id: 5, descr: 'Bellezza e Cura Persona', icon: 'fas fa-spa', color: 'pink-7' },
|
||||
{ _id: 6, descr: 'Infanzia e Bambini', icon: 'fas fa-baby', color: 'cyan-7' },
|
||||
{ _id: 7, descr: 'Cibi e Bevande', icon: 'fas fa-apple-alt', color: 'orange-7' },
|
||||
{ _id: 8, descr: 'Collezionismo e Antiquariato', icon: 'fas fa-coins', color: 'brown-9' },
|
||||
{ _id: 9, descr: 'Elettronica e Tecnologia', icon: 'fas fa-laptop', color: 'blue-grey-8' },
|
||||
{ _id: 10, descr: 'Gaming e Console', icon: 'fas fa-gamepad', color: 'purple-7' },
|
||||
{ _id: 11, descr: 'Giardinaggio e Fai da Te', icon: 'fas fa-seedling', color: 'green-7' },
|
||||
{ _id: 12, descr: 'Libri e Riviste', icon: 'fas fa-book-open', color: 'indigo-7' },
|
||||
{ _id: 13, descr: 'Musica e Film', icon: 'fas fa-film', color: 'deep-purple-7' },
|
||||
{ _id: 14, descr: 'Scuola e Ufficio', icon: 'fas fa-pen', color: 'blue-8' },
|
||||
{ _id: 15, descr: 'Sport e Fitness', icon: 'fas fa-bicycle', color: 'green-8' },
|
||||
{ _id: 16, descr: 'Animali', icon: 'fas fa-paw', color: 'brown-6' },
|
||||
{ _id: 17, descr: 'Attrezzature e Strumenti', icon: 'fas fa-tools', color: 'grey-8' },
|
||||
{ _id: 18, descr: 'Elettrodomestici', icon: 'fas fa-plug', color: 'teal-7' },
|
||||
{ _id: 19, descr: 'Agricoltura e Orticoltura', icon: 'fas fa-tractor', color: 'green-9' },
|
||||
{ _id: 20, descr: 'Arte e Decorazioni', icon: 'fas fa-palette', color: 'purple-6' },
|
||||
],
|
||||
};
|
||||
19
src/populate/new_sectors.js
Normal file
19
src/populate/new_sectors.js
Normal file
@@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
{ _id: 1, descr: 'Abitare e Costruire', icon: 'fas fa-home', color: 'brown-7' },
|
||||
{ _id: 2, descr: 'Agricoltura e Orticoltura', icon: 'fas fa-seedling', color: 'green-7' },
|
||||
{ _id: 3, descr: 'Alimentazione e Trasformazione', icon: 'fas fa-apple-alt', color: 'orange-7' },
|
||||
{ _id: 4, descr: 'Animali e Allevamento', icon: 'fas fa-paw', color: 'brown-6' },
|
||||
{ _id: 5, descr: 'Artigianato e Creazione', icon: 'fas fa-hammer', color: 'amber-7' },
|
||||
{ _id: 6, descr: 'Benessere e Cura Naturale', icon: 'fas fa-spa', color: 'teal-6' },
|
||||
{ _id: 7, descr: 'Educazione e Formazione', icon: 'fas fa-book-reader', color: 'indigo-7' },
|
||||
{ _id: 8, descr: 'Energia e Sostenibilità', icon: 'fas fa-solar-panel', color: 'yellow-8' },
|
||||
{ _id: 9, descr: 'Manutenzione e Riparazione', icon: 'fas fa-tools', color: 'grey-8' },
|
||||
{ _id: 10, descr: 'Mobilità e Trasporti', icon: 'fas fa-bicycle', color: 'blue-7' },
|
||||
{ _id: 11, descr: 'Progetti Comunitari', icon: 'fas fa-users', color: 'purple-7' },
|
||||
{ _id: 12, descr: 'Salute e Terapie', icon: 'fas fa-heart', color: 'red-6' },
|
||||
{ _id: 13, descr: 'Tecnologie Appropriate', icon: 'fas fa-laptop-code', color: 'blue-grey-7' },
|
||||
{ _id: 14, descr: 'Tessile e Sartoria', icon: 'fas fa-cut', color: 'pink-7' },
|
||||
{ _id: 15, descr: 'Tempo Libero e Cultura', icon: 'fas fa-palette', color: 'deep-purple-6' },
|
||||
],
|
||||
};
|
||||
163
src/populate/new_subskills.js
Normal file
163
src/populate/new_subskills.js
Normal file
@@ -0,0 +1,163 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
// Abitare e Costruire
|
||||
{ _id: 1, idSector: [1], descr: 'Autocostruzione', icon: 'fas fa-hammer' },
|
||||
{ _id: 2, idSector: [1], descr: 'Bioedilizia', icon: 'fas fa-leaf' },
|
||||
{ _id: 3, idSector: [1], descr: 'Cohousing', icon: 'home_work' },
|
||||
{ _id: 4, idSector: [1], descr: 'Ecovillaggi e Comunità', icon: 'fas fa-users' },
|
||||
{ _id: 5, idSector: [1], descr: 'Immobili in Vendita', icon: 'fas fa-home' },
|
||||
{ _id: 6, idSector: [1], descr: 'Immobili in Affitto', icon: 'fas fa-key' },
|
||||
{ _id: 7, idSector: [1], descr: 'Stanze Condivise', icon: 'fas fa-door-open' },
|
||||
{ _id: 8, idSector: [1], descr: 'Terreni', icon: 'fas fa-map' },
|
||||
|
||||
// Agricoltura e Orticoltura
|
||||
{ _id: 10, idSector: [2], descr: 'Aratura e Semina', icon: 'fas fa-tractor' },
|
||||
{ _id: 11, idSector: [2], descr: 'Elettrocultura', icon: 'fas fa-bolt' },
|
||||
{ _id: 12, idSector: [2], descr: 'Idroponica', icon: 'fas fa-flask' },
|
||||
{ _id: 13, idSector: [2], descr: 'Orto Sinergico', icon: 'fas fa-seedling' },
|
||||
{ _id: 14, idSector: [2], descr: 'Orto Tradizionale', icon: 'fas fa-carrot' },
|
||||
{ _id: 15, idSector: [2], descr: 'Pacciamatura', icon: 'fas fa-layer-group' },
|
||||
{ _id: 16, idSector: [2], descr: 'Permacultura', icon: 'fas fa-recycle' },
|
||||
{ _id: 17, idSector: [2], descr: 'Potatura', icon: 'fas fa-cut' },
|
||||
{ _id: 18, idSector: [2], descr: 'Raccolta', icon: 'fas fa-apple-alt' },
|
||||
|
||||
// Alimentazione e Trasformazione
|
||||
{ _id: 20, idSector: [3], descr: 'Autoproduzione Alimenti', icon: 'kitchen' },
|
||||
{ _id: 21, idSector: [3], descr: 'Autoproduzione Bevande', icon: 'fas fa-wine-bottle' },
|
||||
{ _id: 22, idSector: [3], descr: 'Conservazione e Fermentazione', icon: 'fas fa-box' },
|
||||
{ _id: 23, idSector: [3], descr: 'Home Restaurant', icon: 'fas fa-utensils' },
|
||||
{ _id: 24, idSector: [3], descr: 'Panificazione', icon: 'fas fa-bread-slice' },
|
||||
|
||||
// Animali e Allevamento
|
||||
{ _id: 30, idSector: [4], descr: 'Allevamento Etico', icon: 'fas fa-horse' },
|
||||
{ _id: 31, idSector: [4], descr: 'Apicoltura', icon: 'hive' },
|
||||
{ _id: 32, idSector: [4], descr: 'Cura Animali da Compagnia', icon: 'fas fa-paw' },
|
||||
{ _id: 33, idSector: [4], descr: 'Veterinaria Olistica', icon: 'fas fa-stethoscope' },
|
||||
|
||||
// Artigianato e Creazione
|
||||
{ _id: 40, idSector: [5], descr: 'Ceramica e Terracotta', icon: 'water_drop' },
|
||||
{ _id: 41, idSector: [5], descr: 'Falegnameria', icon: 'fas fa-hammer' },
|
||||
{ _id: 42, idSector: [5], descr: 'Lavorazione Metalli', icon: 'construction' },
|
||||
|
||||
{ _id: 43, idSector: [5], descr: 'Restauro', icon: 'fas fa-paint-brush' },
|
||||
{ _id: 44, idSector: [5], descr: 'Sartoria e Ricamo', icon: 'fas fa-cut' },
|
||||
|
||||
// Benessere e Cura Naturale
|
||||
{ _id: 50, idSector: [6], descr: 'Alimentazione Naturale', icon: 'fas fa-leaf' },
|
||||
{ _id: 51, idSector: [6], descr: 'Arteterapia', icon: 'fas fa-palette' },
|
||||
{ _id: 52, idSector: [6], descr: 'Cantoterapia', icon: 'fas fa-music' },
|
||||
{ _id: 53, idSector: [6], descr: 'Coach Motivazionale', icon: 'fas fa-bullhorn' },
|
||||
{ _id: 54, idSector: [6], descr: 'Costellazioni Familiari', icon: 'fas fa-users' },
|
||||
{ _id: 55, idSector: [6], descr: 'Fitoterapia', icon: 'fas fa-mortar-pestle' },
|
||||
{ _id: 56, idSector: [6], descr: 'Floriterapia', icon: 'local_florist' },
|
||||
|
||||
{ _id: 57, idSector: [6], descr: 'Ginnastica e Movimento', icon: 'fas fa-dumbbell' },
|
||||
{ _id: 58, idSector: [6], descr: 'Kinesiologia', icon: 'fas fa-running' },
|
||||
{ _id: 59, idSector: [6], descr: 'Massaggi', icon: 'fas fa-hands' },
|
||||
{ _id: 60, idSector: [6], descr: 'Meditazione e Mindfulness', icon: 'fas fa-om' },
|
||||
{ _id: 61, idSector: [6], descr: 'Naturopatia', icon: 'fas fa-leaf' },
|
||||
{ _id: 62, idSector: [6], descr: 'Riflessologia', icon: 'footprint' },
|
||||
|
||||
{ _id: 63, idSector: [6], descr: 'Teatroterapia', icon: 'fas fa-theater-masks' },
|
||||
{ _id: 64, idSector: [6], descr: 'Tecniche Essene', icon: 'fas fa-praying-hands' },
|
||||
{ _id: 65, idSector: [6], descr: 'Trattamenti Energetici', icon: 'fas fa-hand-sparkles' },
|
||||
{ _id: 66, idSector: [6], descr: 'Trattamenti Olistici', icon: 'fas fa-spa' },
|
||||
{ _id: 67, idSector: [6], descr: 'Trattamenti Sonori', icon: 'fas fa-bell' },
|
||||
{ _id: 68, idSector: [6], descr: 'Yoga', icon: 'self_improvement' },
|
||||
|
||||
{ _id: 69, idSector: [6], descr: 'Biodanza', icon: 'fas fa-seedling' },
|
||||
|
||||
// Educazione e Formazione
|
||||
{ _id: 70, idSector: [7], descr: 'Corsi e Workshop', icon: 'fas fa-chalkboard-teacher' },
|
||||
{ _id: 71, idSector: [7], descr: 'Educazione Parentale', icon: 'fas fa-child' },
|
||||
{ _id: 72, idSector: [7], descr: 'Formazione Tecnica', icon: 'fas fa-tools' },
|
||||
{ _id: 73, idSector: [7], descr: 'Lingue', icon: 'fas fa-language' },
|
||||
{ _id: 74, idSector: [7], descr: 'Scuola Libertaria', icon: 'fas fa-book-reader' },
|
||||
{ _id: 75, idSector: [7], descr: 'Consulenze Professionali', icon: 'fas fa-briefcase' },
|
||||
{ _id: 76, idSector: [7], descr: 'Preparazione Esami', icon: 'school' },
|
||||
|
||||
// Energia e Sostenibilità
|
||||
{ _id: 80, idSector: [8], descr: 'Biogas e Biomasse', icon: 'fas fa-fire' },
|
||||
{ _id: 81, idSector: [8], descr: 'Compostaggio', icon: 'fas fa-recycle' },
|
||||
{ _id: 82, idSector: [8], descr: 'Fotovoltaico', icon: 'fas fa-solar-panel' },
|
||||
{ _id: 83, idSector: [8], descr: 'Gestione Rifiuti', icon: 'fas fa-trash-alt' },
|
||||
{ _id: 84, idSector: [8], descr: 'Pompe di Calore', icon: 'fas fa-temperature-high' },
|
||||
{ _id: 85, idSector: [8], descr: 'Solare Termico', icon: 'fas fa-sun' },
|
||||
{ _id: 86, idSector: [8], descr: 'Stufe e Caminetti', icon: 'fas fa-fire-alt' },
|
||||
|
||||
// Manutenzione e Riparazione
|
||||
{ _id: 90, idSector: [9], descr: 'Arredamento', icon: 'fas fa-couch' },
|
||||
{ _id: 91, idSector: [9], descr: 'Elettricista', icon: 'fas fa-plug' },
|
||||
{ _id: 92, idSector: [9], descr: 'Fabbro', icon: 'fas fa-wrench' },
|
||||
{ _id: 93, idSector: [9], descr: 'Giardiniere', icon: 'fas fa-leaf' },
|
||||
{ _id: 94, idSector: [9], descr: 'Idraulico', icon: 'fas fa-faucet' },
|
||||
{ _id: 95, idSector: [9], descr: 'Imbianchino', icon: 'fas fa-paint-roller' },
|
||||
{ _id: 96, idSector: [9], descr: 'Muratore', icon: 'fas fa-hard-hat' },
|
||||
{ _id: 97, idSector: [9], descr: 'Piastrellista', icon: 'fas fa-th' },
|
||||
{ _id: 98, idSector: [9], descr: 'Pulizie', icon: 'fas fa-broom' },
|
||||
{ _id: 99, idSector: [9], descr: 'Riparazione Elettrodomestici', icon: 'fas fa-blender' },
|
||||
{ _id: 100, idSector: [9], descr: 'Traslochi', icon: 'fas fa-truck' },
|
||||
{ _id: 101, idSector: [9], descr: 'Tuttofare', icon: 'fas fa-toolbox' },
|
||||
|
||||
// Mobilità e Trasporti
|
||||
{ _id: 110, idSector: [10], descr: 'Biciclette', icon: 'fas fa-bicycle' },
|
||||
{ _id: 111, idSector: [10], descr: 'Camperizzazione', icon: 'fas fa-caravan' },
|
||||
{ _id: 112, idSector: [10], descr: 'Car Sharing', icon: 'fas fa-car' },
|
||||
{ _id: 113, idSector: [10], descr: 'Lavaggio Auto', icon: 'fas fa-water' },
|
||||
{ _id: 114, idSector: [10], descr: 'Meccanica Auto', icon: 'fas fa-car-crash' },
|
||||
{ _id: 115, idSector: [10], descr: 'Meccanica Moto', icon: 'fas fa-motorcycle' },
|
||||
|
||||
// Progetti Comunitari
|
||||
{ _id: 120, idSector: [11], descr: 'Banca del Tempo', icon: 'fas fa-clock' },
|
||||
{ _id: 121, idSector: [11], descr: 'Collaborazioni', icon: 'fas fa-handshake' },
|
||||
{ _id: 122, idSector: [11], descr: 'Eventi e Incontri', icon: 'fas fa-calendar-alt' },
|
||||
{ _id: 123, idSector: [11], descr: 'Gruppi di Acquisto', icon: 'fas fa-shopping-basket' },
|
||||
{ _id: 124, idSector: [11], descr: 'Laboratori', icon: 'fas fa-flask' },
|
||||
{ _id: 125, idSector: [11], descr: 'Volontariato', icon: 'fas fa-hand-holding-heart' },
|
||||
{ _id: 126, idSector: [11], descr: 'Servizi alla Comunità', icon: 'fas fa-hands-helping' },
|
||||
|
||||
// Salute e Terapie
|
||||
{ _id: 130, idSector: [12], descr: 'Counseling', icon: 'fas fa-comments' },
|
||||
{ _id: 131, idSector: [12], descr: 'Dentista', icon: 'fas fa-tooth' },
|
||||
{ _id: 132, idSector: [12], descr: 'Infermieristica', icon: 'fas fa-user-nurse' },
|
||||
{ _id: 133, idSector: [12], descr: 'Medicina di Base', icon: 'fas fa-user-md' },
|
||||
{ _id: 134, idSector: [12], descr: 'Medicina Naturale', icon: 'fas fa-leaf' },
|
||||
{ _id: 135, idSector: [12], descr: 'Nutrizionista', icon: 'fas fa-apple-alt' },
|
||||
{ _id: 136, idSector: [12], descr: 'Omeopatia', icon: 'fas fa-vial' },
|
||||
{ _id: 137, idSector: [12], descr: 'OSS', icon: 'fas fa-briefcase-medical' },
|
||||
{ _id: 138, idSector: [12], descr: 'Ostetrica', icon: 'fas fa-baby' },
|
||||
{ _id: 139, idSector: [12], descr: 'Pediatra', icon: 'fas fa-child' },
|
||||
{ _id: 140, idSector: [12], descr: 'Psicologo', icon: 'fas fa-brain' },
|
||||
{ _id: 141, idSector: [12], descr: 'Psicoterapeuta', icon: 'fas fa-couch' },
|
||||
{ _id: 142, idSector: [12], descr: 'Specialisti', icon: 'fas fa-stethoscope' },
|
||||
|
||||
// Tecnologie Appropriate
|
||||
{ _id: 150, idSector: [13], descr: 'Assistenza Cellulari', icon: 'fas fa-mobile-alt' },
|
||||
{ _id: 151, idSector: [13], descr: 'Assistenza PC', icon: 'fas fa-laptop' },
|
||||
{ _id: 152, idSector: [13], descr: 'Corsi Informatica', icon: 'fas fa-graduation-cap' },
|
||||
{ _id: 153, idSector: [13], descr: 'Realizzazione App', icon: 'fas fa-mobile' },
|
||||
{ _id: 154, idSector: [13], descr: 'Realizzazione Siti Web', icon: 'fas fa-globe' },
|
||||
{ _id: 155, idSector: [13], descr: 'Software Libero', icon: 'fas fa-code' },
|
||||
|
||||
// Tessile e Sartoria
|
||||
{ _id: 160, idSector: [14], descr: 'Autoproduzione Abbigliamento', icon: 'fas fa-tshirt' },
|
||||
{ _id: 161, idSector: [14], descr: 'Filatura', icon: 'fas fa-spinner' },
|
||||
{ _id: 162, idSector: [14], descr: 'Riparazioni Tessili', icon: 'checkroom' },
|
||||
{ _id: 163, idSector: [14], descr: 'Sartoria su Misura', icon: 'fas fa-ruler' },
|
||||
{ _id: 164, idSector: [14], descr: 'Tessitura', icon: 'fas fa-grip-lines' },
|
||||
{ _id: 165, idSector: [14], descr: 'Tingere Naturale', icon: 'fas fa-tint' },
|
||||
|
||||
// Tempo Libero e Cultura
|
||||
{ _id: 170, idSector: [15], descr: 'Arte e Pittura', icon: 'fas fa-palette' },
|
||||
{ _id: 171, idSector: [15], descr: 'Ballo', icon: 'groups' },
|
||||
{ _id: 172, idSector: [15], descr: 'Canto', icon: 'fas fa-microphone' },
|
||||
{ _id: 173, idSector: [15], descr: 'Film Making', icon: 'fas fa-video' },
|
||||
{ _id: 174, idSector: [15], descr: 'Fotografia', icon: 'fas fa-camera' },
|
||||
{ _id: 175, idSector: [15], descr: 'Letteratura', icon: 'fas fa-book' },
|
||||
{ _id: 176, idSector: [15], descr: 'Musica', icon: 'fas fa-music' },
|
||||
{ _id: 177, idSector: [15], descr: 'Sport', icon: 'fas fa-running' },
|
||||
{ _id: 178, idSector: [15], descr: 'Teatro', icon: 'fas fa-theater-masks' },
|
||||
{ _id: 179, idSector: [15], descr: 'Altre Attività Culturali', icon: 'fas fa-question' },
|
||||
{ _id: 180, idSector: [15], descr: 'Giochi da Tavolo', icon: 'extension' },
|
||||
],
|
||||
};
|
||||
@@ -5,6 +5,7 @@ const Path = require('path');
|
||||
const mongoose = require('mongoose').set('debug', false)
|
||||
|
||||
const shared_consts = require('../tools/shared_nodejs');
|
||||
const migration = require('./migration-categories');
|
||||
|
||||
|
||||
module.exports = {
|
||||
@@ -190,6 +191,9 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
// FAI LA MIGRAZIONE
|
||||
migration.runMigration();
|
||||
|
||||
console.log('FINE - popolaTabelleNuove');
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
module.exports = {
|
||||
list: [
|
||||
{_id: 1, descr: 'Abbigliamento', icon: 'fas fa-tshirt', color: 'blue-7'},
|
||||
{_id: 2, descr: 'Arredamento', icon: 'fas fa-chair', color: 'green-7'},
|
||||
{_id: 3, descr: 'Auto e Moto', icon: 'fas fa-car', color: 'orange-7'},
|
||||
{_id: 4, descr: 'Artigianato', icon: 'fas fa-screwdriver', color: 'red-7'},
|
||||
{_id: 5, descr: 'Bellezza e Igiene', icon: 'fas fa-spa', color: 'purple-7'},
|
||||
{_id: 6, descr: 'Bimbi', icon: 'fas fa-child', color: 'cyan-7'},
|
||||
{_id: 7, descr: 'Cibo'},
|
||||
{_id: 8, descr: 'Collezionismo e Antiquariato'},
|
||||
{_id: 9, descr: 'Elettronica di Consumo'},
|
||||
{_id: 10, descr: 'Giochi', icon: 'fas fa-gamepad', color: 'purple-7'},
|
||||
{_id: 11, descr: 'Hobby', icon: 'fas fa-guitar', color: 'cyan-7'},
|
||||
{_id: 12, descr: 'Libri', icon: 'fas fa-book', color: 'indigo-7'},
|
||||
{_id: 13, descr: 'Musica e Film', icon: 'fas fa-music', color: 'brown-7'},
|
||||
{_id: 14, descr: 'Scuola e Ufficio', icon: 'fas fa-graduation-cap', color: 'pink-7'},
|
||||
{_id: 15, descr: 'Sport', icon: 'fas fa-futbol', color: 'orange-7'},
|
||||
{_id: 16, descr: 'Un po\' di Tutto', icon: 'fas fa-globe-europe', color: 'red-7'},
|
||||
{_id: 17, descr: 'Attrezzature', icon: 'fas fa-tools', color: 'blue-7'},
|
||||
{_id: 18, descr: 'Animali', icon: 'fas fa-paw', color: 'green-7'},
|
||||
{_id: 19, descr: 'Arte / Decorazioni', icon: 'fas fa-palette', color: 'purple-7'},
|
||||
{_id: 20, descr: 'Agricoltura', icon: 'fas fa-seedling', color: 'green-7'},
|
||||
|
||||
],
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
module.exports = {
|
||||
list: [
|
||||
{ _id: 2, descr: 'Agricoltura', icon: 'fas fa-tractor', color: '#4CAF50' },
|
||||
{ _id: 3, descr: 'Cibo e Ristorazione', icon: 'fas fa-utensils', color: '#FF9800' },
|
||||
{ _id: 4, descr: 'Animali', icon: 'fas fa-paw', color: '#795548' },
|
||||
{ _id: 5, descr: 'Auto e Veicoli', icon: 'fas fa-car', color: '#607D8B' },
|
||||
{ _id: 6, descr: 'Salute e Benessere', icon: 'fas fa-heartbeat', color: '#E91E63' },
|
||||
{ _id: 7, descr: 'Casa e Arredamento', icon: 'fas fa-home', color: '#9C27B0' },
|
||||
{ _id: 8, descr: 'Attività Ricreative e di Intrattenim.', icon: 'fas fa-gamepad', color: '#FF5722' },
|
||||
{ _id: 13, descr: 'Tecnologie', icon: 'fas fa-microchip', color: '#2196F3' },
|
||||
{ _id: 15, descr: 'Artigianato', icon: 'fas fa-hammer', color: '#FFC107' },
|
||||
{ _id: 16, descr: 'Arte e Cultura', icon: 'fas fa-palette', color: '#3F51B5' },
|
||||
{ _id: 17, descr: 'Assistenza e Integrazione', icon: 'fas fa-hands-helping', color: '#00BCD4' },
|
||||
{ _id: 18, descr: 'Attività fisica e sportiva', icon: 'fas fa-running', color: '#8BC34A' },
|
||||
{ _id: 20, descr: 'Bambini', icon: 'fas fa-baby', color: '#FFEB3B' },
|
||||
{ _id: 21, descr: 'Consulenza e Supporto Professionale', icon: 'fas fa-briefcase', color: '#9E9E9E' },
|
||||
{ _id: 22, descr: 'Formazione e crescita personale', icon: 'fas fa-graduation-cap', color: '#673AB7' },
|
||||
{ _id: 23, descr: 'Manutenzione e riparazione', icon: 'fas fa-wrench', color: '#F44336' },
|
||||
{ _id: 24, descr: 'Mobilità e Trasporti', icon: 'fas fa-bus', color: '#009688' },
|
||||
],
|
||||
};
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
list: [
|
||||
{_id: 1, descr: 'Abitare'},
|
||||
{_id: 2, descr: 'Agricoltura'},
|
||||
{_id: 3, descr: 'Alimentazione'},
|
||||
{_id: 4, descr: 'Animali'},
|
||||
{_id: 5, descr: 'Auto e Veicoli'},
|
||||
{_id: 6, descr: 'Benessere'},
|
||||
{_id: 7, descr: 'Per la Casa'},
|
||||
{_id: 8, descr: 'Intrattenimento'},
|
||||
{_id: 10, descr: 'Per la Persona'},
|
||||
{_id: 11, descr: 'Progetti di Gruppo'},
|
||||
{_id: 12, descr: 'Salute'},
|
||||
{_id: 13, descr: 'Tecnologie'},
|
||||
{_id: 14, descr: 'Servizi'},
|
||||
],
|
||||
};
|
||||
@@ -54,11 +54,13 @@ const { MyElem } = require('../models/myelem');
|
||||
const { Cron } = require('../models/cron');
|
||||
const { Skill } = require('../models/skill');
|
||||
const { Good } = require('../models/good');
|
||||
const { Bacheca } = require('../models/bacheca');
|
||||
const { StatusSkill } = require('../models/statusSkill');
|
||||
const { Province } = require('../models/province');
|
||||
const { City } = require('../models/city');
|
||||
const { Sector } = require('../models/sector');
|
||||
const { SectorGood } = require('../models/sectorgood');
|
||||
const { SectorBacheca } = require('../models/sectorbacheca');
|
||||
const { CatGrp } = require('../models/catgrp');
|
||||
const Site = require('../models/site');
|
||||
const { Level } = require('../models/level');
|
||||
@@ -143,9 +145,9 @@ router.post('/ammetti', (req, res) => {
|
||||
} else {
|
||||
const lang = user.lang;
|
||||
console.log('user', user);
|
||||
user.verified_by_aportador = false;
|
||||
// user.verified_by_aportador = false;
|
||||
if (user.verified_by_aportador) {
|
||||
res.send({
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_GIA_AMMESSO,
|
||||
msg: 'Il membro ' + user.username + ' è stato già Ammesso!',
|
||||
});
|
||||
@@ -180,7 +182,7 @@ router.post('/ammetti', (req, res) => {
|
||||
|
||||
// user.token_da_ammettere = 'OK';
|
||||
user.save().then(() => {
|
||||
res.send({
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_AMMESSO,
|
||||
msg: 'Ottimo! Hai ammesso ' + user.username + '!',
|
||||
//msg: tools.getres__('Ottimo! Hai ammesso', res) + ' ' + user.username + '!',
|
||||
@@ -199,6 +201,67 @@ 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 = parseInt(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.send({
|
||||
code: server_constants.RIS_CODE_ERRORE,
|
||||
msg: 'La richiesta di Abilitazione non è più presente su questo circuito !',
|
||||
});
|
||||
} else {
|
||||
const lang = user.lang;
|
||||
// console.log('user', user);
|
||||
|
||||
let nomeCircuito = circuitname;
|
||||
let giaabilitato = await User.isFidoConcesso(idapp, username, nomeCircuito);
|
||||
|
||||
let ret = null;
|
||||
|
||||
// user.verified_by_aportador = false;
|
||||
if (giaabilitato) {
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_GIA_AMMESSO,
|
||||
msg: 'Il membro <strong>' + user.username + '</strong> è già stato abilitato al circuito ' + nomeCircuito + '!',
|
||||
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 + '!',
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
.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) => {
|
||||
const body = _.pick(req.body, ['idapp', 'idlink']);
|
||||
const idapp = body.idapp;
|
||||
@@ -1597,7 +1660,9 @@ router.patch('/chval', authenticate, async (req, res) => {
|
||||
|
||||
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) {
|
||||
@@ -2199,7 +2264,9 @@ async function load(req, res, version = '0') {
|
||||
adtypes: version >= 91 ? AdType.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
adtypegoods: version >= 91 ? AdTypeGood.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
sectorgoods: version >= 91 ? SectorGood.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
sectorbachecas: version >= 91 ? SectorBacheca.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
goods: version >= 91 ? Good.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
bachecas: version >= 91 ? Bacheca.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
site: version >= 91 ? Site.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
mygroups: version >= 91 ? MyGroup.findAllGroups(idapp) : Promise.resolve([]),
|
||||
listcircuits: version >= 91 ? Circuit.findAllIdApp(idapp) : Promise.resolve([]),
|
||||
@@ -2344,6 +2411,8 @@ async function load(req, res, version = '0') {
|
||||
crons: data.crons,
|
||||
raccoltacataloghis: data.raccoltacataloghis,
|
||||
statuscode2: data.statuscode2,
|
||||
sectorbachecas: data.sectorbachecas,
|
||||
bachecas: data.bachecas,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ router.post('/send', authenticate, async (req, res) => {
|
||||
params.usernameDest = req.user.username;
|
||||
}
|
||||
|
||||
const ris = await globalTables.SendMsgToParam(idapp, params);
|
||||
const ris = await globalTables.SendMsgToParam(idapp, params, null);
|
||||
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_OK,
|
||||
|
||||
@@ -64,7 +64,7 @@ router.post('/', authenticate, (req, res) => {
|
||||
myrecsend.msg = recmsg.message;
|
||||
let myid = recmsg._id;
|
||||
// ##Todo !! DA SISTEMARE !!!
|
||||
return await SendNotif.saveAndSendNotif(myrecsend, req, res).then((out) => {
|
||||
return await SendNotif.saveAndSendNotif(myrecsend, req, res, null).then((out) => {
|
||||
if (out)
|
||||
return res.send({ code: server_constants.RIS_CODE_OK, msg: '', id: myid });
|
||||
else
|
||||
|
||||
@@ -21,7 +21,7 @@ router.post('/', authenticate, async (req, res) => {
|
||||
tools.mylog('crea SendNotif');
|
||||
let myrecnotif = new SendNotif(body);
|
||||
|
||||
const recout = await SendNotif.saveAndSendNotif(myrecnotif, req, res);
|
||||
const recout = await SendNotif.saveAndSendNotif(myrecnotif, req, res, null);
|
||||
if (recout) {
|
||||
return res.send({ code: server_constants.RIS_CODE_OK, notif: '', record: recout });
|
||||
} else {
|
||||
|
||||
@@ -1122,6 +1122,8 @@ async function eseguiDbOpUser(idapp, mydata, locale, req, res) {
|
||||
await User.ripristinaPwdPrec(mydata);
|
||||
} else if (mydata.dbop === 'noCircuit') {
|
||||
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircuit': mydata.value } });
|
||||
} else if (mydata.dbop === 'noComune') {
|
||||
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noComune': mydata.value } });
|
||||
} else if (mydata.dbop === 'noCircIta') {
|
||||
await User.findOneAndUpdate({ _id: mydata._id }, { $set: { 'profile.noCircIta': mydata.value } });
|
||||
} else if (mydata.dbop === 'insert_circuito_ita') {
|
||||
|
||||
29
src/routes/sync.js
Normal file
29
src/routes/sync.js
Normal file
@@ -0,0 +1,29 @@
|
||||
// server/routes/sync.js
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const SyncManager = require('../services/SyncManager');
|
||||
const { authenticate_noerror_WithUserLean } = require('../middleware/authenticate');
|
||||
|
||||
router.post('/sync/:idapp', authenticate_noerror_WithUserLean, async (req, res) => {
|
||||
try {
|
||||
const { idapp } = req.params;
|
||||
const { tables } = req.body; // { users: { lastSync: 0 }, groups: { lastSync: 123456 } }
|
||||
|
||||
const results = await SyncManager.sync(tables, idapp, req.user);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: results,
|
||||
serverTime: Date.now()
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Sync error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -505,9 +505,17 @@ module.exports = {
|
||||
}
|
||||
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}/${data.myusername}`;
|
||||
return strlink;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
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', 'circuit_abilitato_al_fido_membro'];
|
||||
|
||||
if (idapp === '13') {
|
||||
if (RISO_TEMPLATES.includes(email_template)) {
|
||||
@@ -543,6 +551,7 @@ module.exports = {
|
||||
usernameInvitante: user.aportador_solidario,
|
||||
nomeInvitante: nomecognomeInvitante.trim(),
|
||||
nomeInvitato: await User.getNameSurnameEUsernameByUsername(idapp, user.username),
|
||||
userprofile: await User.getProfileByUsername(idapp, user.username),
|
||||
usernameInvitato: user.username,
|
||||
emailInvitato: user.email,
|
||||
user,
|
||||
@@ -666,6 +675,82 @@ module.exports = {
|
||||
console.error('Err sendEmail_Utente_Ammesso', e);
|
||||
}
|
||||
},
|
||||
sendEmail_Utente_Abilitato_Circuito_FidoConcesso: async function (lang, emailto, user, idapp, dati) {
|
||||
try {
|
||||
let mylocalsconf = {
|
||||
idapp,
|
||||
dataemail: await this.getdataemail(idapp),
|
||||
baseurl: tools.getHostByIdApp(idapp),
|
||||
locale: lang,
|
||||
nomeapp: tools.getNomeAppByIdApp(idapp),
|
||||
strlinksito: tools.getHostByIdApp(idapp),
|
||||
emailto: emailto,
|
||||
usernameInvitante: dati.usernameInvitante,
|
||||
linkProfiloAdmin: tools.getLinkUserProfile(idapp, dati.usernameInvitante),
|
||||
user,
|
||||
usernameMembro: user.username,
|
||||
nomeTerritorio: dati.nomeTerritorio,
|
||||
linkTelegramTerritorio: dati.link_group,
|
||||
};
|
||||
|
||||
const quale_email_inviare = this.getPathEmail(idapp, 'circuit_abilitato_al_fido_membro') + '/' + 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_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.CIRCUITCMD.SETFIDO;
|
||||
|
||||
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) {
|
||||
// console.log('idapp', idapp, tools.getNomeAppByIdApp(idapp));
|
||||
|
||||
125
src/services/SyncManager.js
Normal file
125
src/services/SyncManager.js
Normal file
@@ -0,0 +1,125 @@
|
||||
// server/services/SyncManager.js
|
||||
class SyncManager {
|
||||
constructor() {
|
||||
this.syncConfig = {
|
||||
resps: {
|
||||
model: 'User',
|
||||
method: 'getusersRespList',
|
||||
trackChanges: true,
|
||||
params: ['idapp'] // parametri necessari
|
||||
},
|
||||
workers: {
|
||||
model: 'User',
|
||||
method: 'getusersWorkersList',
|
||||
trackChanges: true,
|
||||
params: ['idapp']
|
||||
},
|
||||
groups: {
|
||||
model: 'Group',
|
||||
method: 'findAllIdApp',
|
||||
trackChanges: true,
|
||||
params: ['idapp']
|
||||
},
|
||||
mygroups: {
|
||||
model: 'MyGroup',
|
||||
method: 'findAllGroups',
|
||||
trackChanges: true,
|
||||
params: ['idapp']
|
||||
},
|
||||
products: {
|
||||
model: 'Product',
|
||||
method: 'findAllIdApp',
|
||||
trackChanges: true,
|
||||
params: ['idapp']
|
||||
},
|
||||
cart: {
|
||||
model: 'Cart',
|
||||
method: 'getCartByUserId',
|
||||
trackChanges: true,
|
||||
params: ['userId', 'idapp'],
|
||||
requiresAuth: true
|
||||
},
|
||||
orderscart: {
|
||||
model: 'OrdersCart',
|
||||
method: 'getOrdersCartByUserId',
|
||||
trackChanges: true,
|
||||
params: ['userId', 'idapp'],
|
||||
requiresAuth: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async sync(syncRequest, idapp, user) {
|
||||
const results = {};
|
||||
const timestamp = Date.now();
|
||||
|
||||
for (const [tableName, params] of Object.entries(syncRequest)) {
|
||||
const config = this.syncConfig[tableName];
|
||||
|
||||
if (!config) {
|
||||
console.warn(`Tabella ${tableName} non configurata`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Controlla autenticazione
|
||||
if (config.requiresAuth && !user) {
|
||||
results[tableName] = {
|
||||
data: null,
|
||||
timestamp: timestamp,
|
||||
fullSync: true
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await this.fetchTableData(
|
||||
tableName,
|
||||
config,
|
||||
params.lastSync,
|
||||
idapp,
|
||||
user
|
||||
);
|
||||
|
||||
results[tableName] = {
|
||||
data: data,
|
||||
timestamp: timestamp,
|
||||
fullSync: params.lastSync === 0 || !config.trackChanges
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Errore sync ${tableName}:`, error);
|
||||
results[tableName] = {
|
||||
error: error.message,
|
||||
timestamp: timestamp
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
async fetchTableData(tableName, config, lastSync, idapp, user) {
|
||||
const ModelClass = require(`../models/${config.model}`);
|
||||
|
||||
// Prepara parametri
|
||||
const args = config.params.map(param => {
|
||||
if (param === 'idapp') return idapp;
|
||||
if (param === 'userId') return user?._id.toString() || '0';
|
||||
return null;
|
||||
});
|
||||
|
||||
// Prima sync o no trackChanges: tutti i dati
|
||||
if (!config.trackChanges || lastSync === 0) {
|
||||
return await ModelClass[config.method](...args);
|
||||
}
|
||||
|
||||
// Sync incrementale
|
||||
const query = {
|
||||
idapp: idapp,
|
||||
updatedAt: { $gt: new Date(parseInt(lastSync)) }
|
||||
};
|
||||
|
||||
return await ModelClass.find(query).lean();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new SyncManager();
|
||||
@@ -441,6 +441,10 @@ class UserService {
|
||||
{ _id: mydata._id },
|
||||
{ $set: { 'profile.noCircuit': mydata.value } }
|
||||
),
|
||||
'noComune': () => User.findOneAndUpdate(
|
||||
{ _id: mydata._id },
|
||||
{ $set: { 'profile.noComune': mydata.value } }
|
||||
),
|
||||
'noCircIta': () => User.findOneAndUpdate(
|
||||
{ _id: mydata._id },
|
||||
{ $set: { 'profile.noCircIta': mydata.value } }
|
||||
|
||||
@@ -451,7 +451,7 @@ const txt = {
|
||||
MSG_ACCEPT_NEWENTRY_INGROUP: '❇️👥 🧍♂️ Accetta Ingresso nel GRUPPO %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_APORTADOR_CONFIRMED: '✅ %s è stato Ammesso correttamente (da %s)!',
|
||||
MSG_APORTADOR_CONFIRMED: '✅ %s è stato Ammesso correttamente (da %s) tramite Telegram!',
|
||||
MSG_APORTADOR_DEST_CONFIRMED:
|
||||
'✅ 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!',
|
||||
@@ -838,6 +838,8 @@ const MyTelegramBot = {
|
||||
groupname = ''
|
||||
) {
|
||||
try {
|
||||
const sendemail = require('../sendemail');
|
||||
|
||||
const cl = getclTelegByidapp(idapp);
|
||||
if (!cl) return false;
|
||||
|
||||
@@ -1000,6 +1002,7 @@ const MyTelegramBot = {
|
||||
groupid + tools.SEP + groupname,
|
||||
},*/
|
||||
]);
|
||||
|
||||
send_notif = true;
|
||||
} else {
|
||||
msg_notifpush = i18n.__({ phrase: 'CIRCUIT_ACCEPT_NEWENTRY', locale: langdest }, myuser.username, name);
|
||||
@@ -1032,6 +1035,38 @@ const MyTelegramBot = {
|
||||
]);
|
||||
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,
|
||||
myusername: userDest,
|
||||
};
|
||||
// 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) {
|
||||
if (groupname) {
|
||||
msg_notifpush = i18n.__({ phrase: 'CIRCUIT_ACCEPT_NEWENTRY_BYGROUP_CIRC', locale: langdest }, groupname);
|
||||
@@ -4574,7 +4609,7 @@ if (true) {
|
||||
userDest,
|
||||
null,
|
||||
user.idapp,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
await local_sendMsgTelegram(user.idapp, data.username, msgOrig);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1217,6 +1217,7 @@ module.exports = {
|
||||
if (mycircuit && extrarec) {
|
||||
extrarec.fido_scoperto_default = mycircuit.fido_scoperto_default;
|
||||
extrarec.fido_scoperto_default_grp = mycircuit.fido_scoperto_default_grp;
|
||||
extrarec.link_group = mycircuit.link_group;
|
||||
}
|
||||
|
||||
if (cmd) {
|
||||
@@ -1489,6 +1490,7 @@ module.exports = {
|
||||
) {
|
||||
const { Circuit } = require('../models/circuit');
|
||||
const { SendNotif } = require('../models/sendnotif');
|
||||
var { User } = require('../models/user');
|
||||
|
||||
const circuit = await Circuit.findOne(
|
||||
{ idapp, name: circuitname },
|
||||
@@ -1626,6 +1628,8 @@ module.exports = {
|
||||
if (singleadmin.username) {
|
||||
if (usernameOrig === singleadmin.username) giainviato = true;
|
||||
|
||||
extrarec.send_email = !!singleadmin.enable_to_receive_email ? singleadmin.enable_to_receive_email : true;
|
||||
|
||||
await this.sendNotifCircuitByUsername(
|
||||
cmd,
|
||||
idapp,
|
||||
@@ -1649,6 +1653,8 @@ module.exports = {
|
||||
}
|
||||
|
||||
if (!giainviato && cmd !== shared_consts.CIRCUITCMD.REQ) {
|
||||
extrarec.send_email = await User.isEnableToReceiveEmailByUsernameECmd(idapp, usernameOrig, cmd);
|
||||
|
||||
// SEND TO THE USER DEST THE NOTIFICATION
|
||||
ris = await this.sendNotifCircuitByUsername(
|
||||
cmd,
|
||||
@@ -2149,7 +2155,9 @@ module.exports = {
|
||||
getLinkGruppiTerritorialiTelegram: function (idapp) {
|
||||
try {
|
||||
const myapp = this.MYAPPS.find((item) => item.idapp === idapp);
|
||||
return myapp && myapp.telegram_gruppi_territoriali_senzainvito ? myapp.telegram_gruppi_territoriali_senzainvito : '';
|
||||
return myapp && myapp.telegram_gruppi_territoriali_senzainvito
|
||||
? myapp.telegram_gruppi_territoriali_senzainvito
|
||||
: '';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
@@ -3325,10 +3333,12 @@ module.exports = {
|
||||
|
||||
if (params.sortBy && !params.searchByBoundariesMap) {
|
||||
// maybe we want to sort by blog title or something
|
||||
const mysort = { $sort: params.sortBy };
|
||||
const mysort = params.sortBy && Object.keys(params.sortBy).length > 0 ? { $sort: params.sortBy } : {};
|
||||
// console.log('sortBy', params.sortBy);
|
||||
// console.table(mysort);
|
||||
query.push(mysort);
|
||||
if (mysort.$sort) {
|
||||
query.push(mysort);
|
||||
}
|
||||
}
|
||||
|
||||
query.push(
|
||||
@@ -5195,7 +5205,22 @@ module.exports = {
|
||||
|
||||
let mystr = '';
|
||||
const rec = secgoodrec.find((rec) => rec._id === myrec.idSectorGood);
|
||||
// const rec = goodrec.find((rec) => rec._id === myrec.idSectorGood);
|
||||
if (rec) {
|
||||
mystr += rec.descr;
|
||||
}
|
||||
return mystr;
|
||||
} catch (e) {}
|
||||
},
|
||||
async getCategoriaBachecaByRec(myrec) {
|
||||
const { SectorBacheca } = require('../models/sectorbacheca');
|
||||
|
||||
try {
|
||||
const idapp = myrec.idapp;
|
||||
if (!idapp) return '';
|
||||
const secbachecarec = await SectorBacheca.findAllIdApp(idapp);
|
||||
|
||||
let mystr = '';
|
||||
const rec = secbachecarec.find((rec) => rec._id === myrec.idSectorBacheca);
|
||||
if (rec) {
|
||||
mystr += rec.descr;
|
||||
}
|
||||
@@ -5409,6 +5434,7 @@ module.exports = {
|
||||
} else if (tablerec === shared_consts.TABLES_MYHOSPS) {
|
||||
cat = '';
|
||||
} else if (tablerec === shared_consts.TABLES_MYBACHECAS) {
|
||||
cat = await this.getCategoriaBachecaByRec(myrec);
|
||||
if (myrec.website) {
|
||||
sitoweb = myrec.website;
|
||||
}
|
||||
@@ -6370,4 +6396,20 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/* Converte una stringa di versione (es. "1.2.55") in un numero per confronti
|
||||
* @param {string} version - Stringa versione in formato "major.minor.patch"
|
||||
* @returns {number} Numero rappresentante la versione
|
||||
*/
|
||||
versionToNumber(version) {
|
||||
const parts = version.split('.').map((num) => parseInt(num, 10));
|
||||
|
||||
// Gestisce versioni con 1, 2 o 3 componenti
|
||||
const major = parts[0] || 0;
|
||||
const minor = parts[1] || 0;
|
||||
const patch = parts[2] || 0;
|
||||
|
||||
// Usa padding di 3 cifre per minor e patch (supporta fino a 999)
|
||||
return major * 1000000 + minor * 1000 + patch;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ const { Skill } = require('../models/skill');
|
||||
const { Catalog } = require('../models/catalog');
|
||||
const { RaccoltaCataloghi } = require('../models/raccoltacataloghi');
|
||||
const { Good } = require('../models/good');
|
||||
const { Bacheca } = require('../models/bacheca');
|
||||
const { SubSkill } = require('../models/subskill');
|
||||
const { MySkill } = require('../models/myskill');
|
||||
const { Attivita } = require('../models/attivita');
|
||||
@@ -171,6 +172,7 @@ module.exports = {
|
||||
else if (tablename === 'catalogs') mytable = Catalog;
|
||||
else if (tablename === 'raccoltacataloghis') mytable = RaccoltaCataloghi;
|
||||
else if (tablename === 'goods') mytable = Good;
|
||||
else if (tablename === 'bachecas') mytable = Bacheca;
|
||||
else if (tablename === 'subskills') mytable = SubSkill;
|
||||
else if (tablename === shared_consts.TABLES_MYSKILLS) mytable = MySkill;
|
||||
else if (tablename === shared_consts.TABLES_ATTIVITAS) mytable = Attivita;
|
||||
@@ -201,7 +203,7 @@ module.exports = {
|
||||
return process.env.ENABLE_PUSHNOTIFICATION === '1';
|
||||
},
|
||||
|
||||
async sendNotifCmd(typenotif, idnotif, res, idapp, user, recnotif, cmd) {
|
||||
async sendNotifCmd(typenotif, idnotif, res, idapp, user, recnotif, paramsObj) {
|
||||
// Controlla nelle impostazioni che tipo di Notifica visualizzare
|
||||
|
||||
const sendemail = require('../sendemail');
|
||||
@@ -250,8 +252,12 @@ module.exports = {
|
||||
invia = true;
|
||||
}
|
||||
|
||||
if (recnotif.extrarec?.send_email) {
|
||||
params.typesend = params.typesend + shared_consts.TypeSend.EMAIL;
|
||||
}
|
||||
|
||||
if (invia) {
|
||||
ris = await this.SendMsgToParam(idapp, params);
|
||||
ris = await this.SendMsgToParam(idapp, params, recnotif, paramsObj);
|
||||
}
|
||||
|
||||
// Send Msg by EMAIL
|
||||
@@ -270,11 +276,12 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
SendMsgToParam: async function (idapp, params) {
|
||||
SendMsgToParam: async function (idapp, params, recnotif, paramsObj) {
|
||||
try {
|
||||
// console.log('SendMsgToParam', params.typesend, params.typemsg);
|
||||
|
||||
const { User } = require('../models/user');
|
||||
const sendemail = require('../sendemail');
|
||||
|
||||
let textsent = '';
|
||||
|
||||
@@ -432,6 +439,21 @@ module.exports = {
|
||||
} catch (e) { }
|
||||
}
|
||||
}
|
||||
if (tools.isBitActive(params.typesend, shared_consts.TypeSend.EMAIL)) {
|
||||
// Invia una Email
|
||||
if (params.tag === 'setfido') {
|
||||
const usertosend = await User.getUserByUsername(params.idapp, params.usernameDest);
|
||||
if (paramsObj) {
|
||||
}
|
||||
|
||||
const dati = {
|
||||
usernameInvitante: paramsObj.extrarec?.username_admin_abilitante,
|
||||
nomeTerritorio: paramsObj.circuitnameDest,
|
||||
link_group: paramsObj.extrarec?.link_group,
|
||||
};
|
||||
await sendemail.sendEmail_Utente_Abilitato_Circuito_FidoConcesso(usertosend.lang, usertosend.email, usertosend, params.idapp, dati);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numrec++;
|
||||
@@ -470,7 +492,7 @@ module.exports = {
|
||||
params.sendreally = true;
|
||||
params.typesend = shared_consts.TypeSend.PUSH_NOTIFICATION;
|
||||
|
||||
return await this.SendMsgToParam(idapp, params);
|
||||
return await this.SendMsgToParam(idapp, params, null);
|
||||
},
|
||||
|
||||
SearchString: async function (idapp, searchString) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
USER_ADMIN_CIRCUITS: ['surya1977', 'ElenaEspx'],
|
||||
ADMIN_IDTELEGRAM_TEST_USERNAME: ['surya1977', 'SuryaArena', 'surya4'],
|
||||
ADMIN_IDTELEGRAM_TEST_USERNAME: ['surya1977', 'SuryaArena', 'surya4', 'test1234'],
|
||||
ADMIN_USER_SERVER: 'surya1977',
|
||||
Accepted: {
|
||||
CHECK_READ_GUIDELINES: 1,
|
||||
@@ -205,7 +205,7 @@ module.exports = {
|
||||
TABLES_GETCOMPLETEREC: ['myskills', 'mybachecas', 'myhosps', 'mygoods', 'attivitas'],
|
||||
|
||||
//++Todo: per abilitare gli utenti ad inserire un Circuito aggiungere 'circuits' alla lista TABLES_PERM_NEWREC
|
||||
TABLES_PERM_NEWREC: ['skills', 'goods', 'subskills', 'mygroups', 'myhosps', 'catalogs', 'raccoltacataloghis'],
|
||||
TABLES_PERM_NEWREC: ['skills', 'goods', 'bachecas', 'subskills', 'mygroups', 'myhosps', 'catalogs', 'raccoltacataloghis'],
|
||||
|
||||
TABLES_REACTIONS: ['mybachecas', 'myhosps', 'myskills', 'mygoods', 'attivitas'],
|
||||
|
||||
@@ -233,6 +233,8 @@ module.exports = {
|
||||
'sectors',
|
||||
'goods',
|
||||
'sectorgoods',
|
||||
'bachecas',
|
||||
'sectorbachecas',
|
||||
'catgrps',
|
||||
'skills',
|
||||
'subskills',
|
||||
@@ -604,6 +606,7 @@ module.exports = {
|
||||
TypeSend: {
|
||||
PUSH_NOTIFICATION: 1,
|
||||
TELEGRAM: 2,
|
||||
EMAIL: 4,
|
||||
},
|
||||
UsersNotif: {
|
||||
NEW_ADV_CITY: 1,
|
||||
@@ -961,10 +964,9 @@ module.exports = {
|
||||
} else if (table === this.TABLES_MYBACHECAS) {
|
||||
proj = {
|
||||
recSkill: 1,
|
||||
sector: 1,
|
||||
idSector: 1,
|
||||
idSkill: 1,
|
||||
// 'idSubSkill': 1,
|
||||
idSectorBacheca: 1,
|
||||
idBacheca: 1,
|
||||
sectorBacheca: 1,
|
||||
idStatusSkill: 1,
|
||||
idContribType: 1,
|
||||
dateTimeStart: 1,
|
||||
@@ -1326,4 +1328,8 @@ module.exports = {
|
||||
},
|
||||
|
||||
TOK_INIZIALE_VERIF_TELEG: '',
|
||||
|
||||
JOB_TO_EXECUTE: {
|
||||
MIGRATION_SECTORS_DIC25: 'Migration_Sectors_Dic_2025',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.2.85
|
||||
1.2.86
|
||||
Reference in New Issue
Block a user