- newsletter: prende la lista utenti (flag news_on)

- Abilita a Tutti la Newsletter news_on
- isCommerciale
- JobsInProgress
- PCB: Corretto Totali che era a zero
This commit is contained in:
Surya Paolo
2025-05-06 18:19:09 +02:00
parent 6e8d1fcff1
commit b77a0579f1
30 changed files with 4669 additions and 727 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -42,5 +42,5 @@ MIAB_HOST=box.lamiaposta.org
MIAB_ADMIN_EMAIL=admin@lamiaposta.org MIAB_ADMIN_EMAIL=admin@lamiaposta.org
MIAB_ADMIN_PASSWORD=passpao1pabox@1A MIAB_ADMIN_PASSWORD=passpao1pabox@1A
DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7" DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7"
API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK" SERVER_A_URL="http://51.77.156.69:3000"
SERVER_A_URL="http://51.77.156.69:3000" API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK"

View File

@@ -18,232 +18,270 @@
- var baseimg = baseurl + '/' - var baseimg = baseurl + '/'
doctype html doctype html
html html
- if (dataemail.title) head
head meta(charset="utf-8")
title dataemail.subject meta(name="viewport", content="width=device-width, initial-scale=1")
title= dataemail.title || "Email"
style.
/* embedded CSS */
body { margin:0; padding:0; background:#E9F2F9; font-family:Tahoma, Geneva, sans-serif; color:#5b656e; }
a { color:#09c; text-decoration:none; }
table, td { border-collapse:collapse; }
h1,h2,h3,p { margin:0; padding:0; }
//- import css/scss stylesheets .logoContainer { text-align:center; padding:20px 0; }
//- these file names will be replace by gulp with proper css file paths .logoContainer img { max-width:200px; }
link(rel="stylesheet", href="../sass/basic.scss")
link(rel="stylesheet", href="../sass/one/styles.scss")
//- embdedded css allowed, but not sass .testomail { padding:10px; font-size:0.75rem; line-height:1.4; }
style.
.red {
background-color: #E84C50;
}
.full-width { .clpromo {
width: 100%; background-color:orange;
} text-align:center;
font-size:1rem;
padding:10px;
color:#fff;
font-weight:bold;
}
.emailContainer {
background:#fff;
border-radius:10px;
padding:20px;
margin:20px auto;
}
.sectionArticleImage img {
max-width:150px;
border:1px solid #ccc;
display:block;
margin-bottom:10px;
}
.teacher {
font-style:italic;
font-size:0.75rem;
color:#555;
}
.contrib {
font-size:0.75rem;
font-weight:bold;
color:#333;
}
.button a {
display:inline-block;
padding:10px 20px;
background:#f75666;
color:#fff !important;
text-decoration:none;
border-radius:10px;
font-size:13px;
}
.button2 a {
display:block;
padding:12px 20px;
background:#0000ff;
color:#fff !important;
text-decoration:none;
border-radius:10px;
font-size:1.15rem;
}
.center_img img {
display:block;
margin:0 auto;
}
.discContainer {
background:#fff;
border-radius:10px;
padding:20px;
margin:20px auto;
}
.LinkDisc a {
text-decoration:none;
}
.pDisc:hover {
background:#5c8ef4 !important;
color:#fff !important;
}
.pDisc {
padding:5px 10px;
border-radius:10px;
display:inline-block;
}
.socialMedia {
background:#8bafcb;
text-align:center;
padding:10px 0;
}
.socialMedia img {
width:29px;
height:auto;
border:0;
}
.firma-container {
background:#ffffff;
padding:15px;
text-align:center;
border-top:1px solid #e0e0e0;
font-size:0.85rem;
color:#313a42;
}
.disclaimer-container {
background:#f9f9f9;
padding:15px;
text-align:center;
font-size:0.75rem;
color:#666;
border-top:1px solid #eee;
border-bottom:1px solid #eee;
}
.bottom-container {
background:#e9f2f9;
padding:15px;
text-align:center;
font-size:0.7rem;
color:#999;
}
.whitespace {
line-height:0;
font-size:0;
height:20px;
}
@media only screen and (max-width:480px) {
.button a, .button2 a {
font-size:1rem !important;
width:100%;
}
.sectionArticleImage,
.column {
width:100% !important;
display:block !important;
}
}
body(yahoofix) body(yahoofix)
span(id='body_style', style='display:block') span#body_style(style='display:block')
table(class="topHeader", cellpadding="0", cellspacing="0", width="100%") // Header
- if (dataemail.height_logo) table(width="100%", cellpadding="0", cellspacing="0", align="center")
tr
td
table(cellpadding="0", cellspacing="0", align="center", summary="")
tr
td.logoContainer
a(href=baseurl, title='logo')
img.logo(src=baseurl+"/images/logo.png", height=dataemail.height_logo)
tr tr
td.testomail td.logoContainer
p!= dataemail.templ.testoheadermail_out a(href=baseurl)
img.logo(src=baseurl+"/public/images/logo.png", alt="Logo")
- if (dataemail.templ.options.includes('SHOW_PROMO')) if dataemail.templ.testoheadermail_out
tr
td.testomail
p!= dataemail.templ.testoheadermail_out
if dataemail.templ.options.includes('SHOW_PROMO')
tr tr
td.clpromo td.clpromo
p!= dataemail.textpromo p!= dataemail.textpromo
- if (dataemail.templ.content) // Main Content
table(cellpadding="0", cellspacing="0", width="95%", align="center") if dataemail.templ.content
tr
td.emailContainer
p!=dataemail.templ.content
if dataemail.templ.img
img(src=baseimg + dataemail.templ.img, class="center_img")
if dataemail.templ.content2
p!=dataemail.templ.content2
if dataemail.templ.img2
img(src=baseimg + dataemail.templ.img2, class="center_img")
// Events
if dataemail.templ.options.includes('SHOW_EVENTS')
each event in arrevents
tr tr
td(class="textIniContainer", valign="top") td.emailContainer
p!=dataemail.templ.content table(width="100%", cellpadding="0", cellspacing="0")
- if (dataemail.templ.img)
img(src=baseimg + dataemail.templ.img, alt="", class="myimg")
- if (dataemail.templ.content2)
p!=dataemail.templ.content2
- if (dataemail.templ.img2)
img(src=baseimg + dataemail.templ.img2, alt="", class="myimg")
table(cellpadding="0", cellspacing="0", width="640", align="center")
- if (dataemail.templ.options.includes('SHOW_EVENTS'))
tr
td(class="whitespace", height="10")
p  
tr
td(class="emailContainer", valign="top")
each event in arrevents
- var urlevent = baseurl + '/event/' + event.typol + '?eventid=' + event._id
- var imgev = event.img_small
- var mydate = prettyDate(event.dateTimeStart)
unless (imgev)
- imgev = event.img
- var teacher1 = ''
- var teacher2 = ''
- var teacher3 = ''
- var teacher4 = ''
- var contrib = ''
- var myclteach = 'q-chip'
- if (event.op1[0] && event.op1[0].username !== 'nessuno')
- teacher1 = event.op1[0].name + ' ' + event.op1[0].surname
- if ((event.op2[0] && event.op2[0].username !== 'nessuno'))
- teacher2 = event.op2[0].name + ' ' + event.op2[0].surname
- myclteach = 'q-chip2'
- if (event.op3[0] && event.op3[0].username !== 'nessuno')
- teacher3 = "<br>" . event.op3[0].name + ' ' + event.op3[0].surname
- if (event.op4[0] && event.op4[0].username !== 'nessuno')
- teacher4 = "<br>" . event.op4[0].name + ' ' + event.op4[0].surname
- if (event.contrib[0])
- contrib = event.contrib[0].label
- if (event.contrib[0].showprice)
- contrib += ' ' + event.price + ' €'
table(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center")
tr tr
td(class="column sectionArticleImage", valign="top") td.column.sectionArticleImage(width="150")
table(cellpadding="0", cellspacing="0", summary="", border="0") if event.news
- if (event.news) p.q-chip.bg-red.text-white Novità
tr img(src=baseimg + (event.img_small || event.img), alt=event.title)
td p.teacher= event.op1[0].name + ' ' + event.op1[0].surname
p(class="q-chip row inline no-wrap items-center cltexth5 chipnews shadow-5 glossy text-right bg-red text-white") Novità td.column
h2.sectionContentTitle= event.title
p.sectionContentSubTitle= prettyDate(event.dateTimeStart)
p.sectionContent!= event.details
if event.contrib.length
p.contrib= event.contrib[0].label + (event.contrib[0].showprice ? ' ' + event.price + ' €' : '')
table.buttonContainer
tr tr
td td.button
img(src=baseimg + imgev, alt="", width="150") a(href=baseurl + '/event/' + event.typol + '?eventid=' + event._id, target="_blank") Apri l'Evento
p(class="teacher") #{teacher1} <br> #{teacher2} #{teacher3} #{teacher4}
td(class="column", valign="top")
table(cellpadding="0", cellspacing="0", summary="", border="0") tr
tr td.center_img
td(class="sectionContentTitle boldhigh", valign="top") a.button2(href=urlcal, target="_blank") Calendario Eventi
p #{event.title}
tr
td(class="sectionContentSubTitle", valign="top")
p(class="q-chip row inline no-wrap items-center cltexth5 chipnews shadow-5 glossy text-right bg-blue text-white") #{mydate}
tr
td(class="sectionContent", valign="top")
p!= event.details
p.contrib= contrib
tr
td(class="buttonContainer")
table(width="50%", cellpadding="0", cellspacing="0", summary="", border="0")
tr
td(class="button hoverLink")
a(href=urlevent, title='Evento', target='_blank') Apri l'Evento
// Disciplines
if dataemail.templ.options.includes('SHOW_DISC')
tr
td.center
h2.cltitle_disc= dataemail.disc_title
each disc in dataemail.arrdiscipline
tr tr
table(cellpadding="0", cellspacing="0", summary="", border="0", align="center", class="") td.discContainer
tr table(width="100%", cellpadding="0", cellspacing="0")
td(class="whitespace", height="10")
p &nbsp;
tr
td.center_img(class="button2 hoverLink")
a(href=urlcal, title='Calendario Eventi', target='_blank') Calendario Eventi
tr
td(class="whitespace", height="10")
p &nbsp;
- if (dataemail.templ.options.includes('SHOW_DISC'))
tr
td(class="whitespace bg-white", height="20")
p(class="bg-white") &nbsp;
tr
td(class="center")
p(class="cltitle_disc") #{dataemail.disc_title}
tr
td(class="discContainer", valign="top")
each disc in dataemail.arrdiscipline
- var urldisc = baseurl + disc.linkpage
- var imgdisc = disc.img_small
unless (imgdisc)
- imgdisc = disc.img
table(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center")
tr tr
td(class="column sectionArticleImage", valign="top") td.column.sectionArticleImage(width="150")
table(cellpadding="0", cellspacing="0", summary="", border="0") img(src=baseimg + (disc.img_small || disc.img), alt=disc.label)
tr td.column
td p.LinkDisc
img(src=baseimg + imgdisc, alt="", width="150") a(href=baseurl + disc.linkpage, target="_blank")
td(class="column", valign="top") span.pDisc(style=`background-color:`+disc.color)= disc.label
p.sectionContent!= disc.description
table(cellpadding="0", cellspacing="0", summary="", border="0") // Additional Content
tr if dataemail.content_after_events
td(class="sectionContentTitle boldhigh center LinkDisc", valign="top")
a(href=urldisc, title='Disciplina', target='_blank')
p(class="q-chip row inline no-wrap items-center cltexth4 chipnews shadow-5 glossy text-right text-white pDisc", style=`background-color: `+disc.color) #{disc.label}
tr
td(class="sectionContent", valign="top")
p!= disc.description
tr
td(class="whitespace", height="20")
p &nbsp;
- if (dataemail.content_after_events)
tr tr
table(cellpadding="0", cellspacing="0", summary="", border="0") td.testomail
tr p!=dataemail.content_after_events
td.testomail
p!=dataemail.content_after_events
tr
td(class="whitespace", height="20")
p &nbsp;
// Social Media // Social Media
table.socialMedia(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") tr
tr td.socialMedia
td(class="whitespace", height="5") table(width="120", align="center", cellpadding="0", cellspacing="0")
p &nbsp; if dataemail.urlinstagram
tr td
td a(href=dataemail.urlinstagram)
table(width="120", cellpadding="0", cellspacing="0", summary="", border="0", align="center") img(src=imginstagram, alt="Instagram")
tr if dataemail.urltwitter
- if (dataemail.urlinstagram) td
td(width="32", align="center") a(href=dataemail.urltwitter)
a(href=dataemail.urlinstagram, title='Instagram') img(src=imgtwitter, alt="Twitter")
img(src=imginstagram, alt="Instagram", width="29") if dataemail.urlfb
- if (dataemail.urltwitter) td
td(width="32", align="center") a(href=dataemail.urlfb)
a(href=dataemail.urltwitter, title='Twitter') img(src=imgfb, alt="Facebook")
img(src=imgtwitter, alt="Twitter", width="29") if dataemail.urlyoutube
- if (dataemail.urlfb) td
td(width="32", align="center") a(href=dataemail.urlyoutube)
a(href=dataemail.urlfb, title='Facebook') img(src=imgyoutube, alt="YouTube")
img(src=imgfb, alt="Facebook", width="29")
- if (dataemail.urlyoutube)
td(width="32", align="center")
a(href=dataemail.urlyoutube, title='YouTube')
img(src=imgyoutube, alt="YouTube", width="29")
tr
td(class="whitespace", height="5")
p &nbsp;
// Footer // Footer
table.footer(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center") tr
tr td.firma-container
td(class="whitespace", height="10") p!= dataemail.firma
p &nbsp; tr
tr td.disclaimer-container
td.firma p!= dataemail.disclaimer_out
p!= dataemail.firma tr
td.bottom-container
tr p!= dataemail.disc_bottom_out
td.disclaimer
p!= dataemail.disclaimer_out
tr
td.bottom
p!= dataemail.disc_bottom_out
tr
td(class="whitespace", height="10")
p &nbsp;

View File

@@ -345,7 +345,7 @@ exports.getTableContentBase = async (options) => {
} }
if (!records || records.length === 0) { if (!records || records.length === 0) {
console.log(`Nessun record trovato per la tabella ${options.nameTable}.`); console.log(`Nessun record trovato per la tabella ${options.nameTable}.`);
return []; return [];
} }
@@ -887,22 +887,34 @@ exports.mssqlmigrateTables = async (req) => {
try { try {
const options = req.body.mydata.options; const options = req.body.mydata.options;
let listaTabelle = []; let listaTabelle = [];
if (options?.parte1 || options?.tutte) {
listaTabelle.push({ table: 'T_WEB_TitoliOriginali', usaDataOra: true, fieldId: 'IdTitoloOriginale' });
if (options?.tutte) { listaTabelle.push({ table: 'T_WEB_TestateOrdini', usaDataOra: false });
// const listaTabelle = ['T_WEB_StatiProdotto']; listaTabelle.push({ table: 'T_WEB_Ordini', usaDataOra: false });
listaTabelle = ['T_WEB_TitoliOriginali', 'T_WEB_TestateOrdini', 'T_WEB_Ordini', 'T_WEB_Disponibile', 'T_WOO_TestateOrdini', 'T_WOO_Ordini', 'T_WEB_Articoli', listaTabelle.push({ table: 'T_WOO_TestateOrdini', usaDataOra: false });
'T_WEB_Argomenti', 'T_WEB_ClientiInternet', 'T_WOO_Clienti', 'T_WEB_Autori', 'T_WEB_Collane', 'T_WEB_MarchiEditoriali', 'T_WEB_StatiProdotto', 'T_WEB_TipiFormato', 'T_WEB_Tipologie', 'T_WEB_ArticoliFatturati', 'T_WEB_IdInternetFatturati', listaTabelle.push({ table: 'T_WOO_Ordini', usaDataOra: false });
'T_WEB_Edizioni', 'T_WEB_Contratti']; listaTabelle.push({ table: 'T_WEB_Articoli', usaDataOra: true, fieldId: 'IdArticolo' });
} else if (options?.parte1) { }
listaTabelle = ['T_WEB_TitoliOriginali', 'T_WEB_TestateOrdini', 'T_WEB_Ordini', 'T_WOO_TestateOrdini', 'T_WOO_Ordini', 'T_WEB_Articoli']; if (options?.parte2 || options?.tutte) {
} else if (options?.parte2) { listaTabelle.push({ table: 'T_WEB_Disponibile', usaDataOra: true, fieldId: 'Codice' });
listaTabelle = ['T_WEB_Disponibile', 'T_WEB_Argomenti', 'T_WEB_ClientiInternet', 'T_WOO_Clienti', 'T_WEB_Autori']; listaTabelle.push({ table: 'T_WEB_Argomenti', usaDataOra: true, fieldId: 'IdArgomento' });
} else if (options?.parte3) { listaTabelle.push({ table: 'T_WEB_ClientiInternet', usaDataOra: false });
listaTabelle = ['T_WEB_Collane', 'T_WEB_MarchiEditoriali', 'T_WEB_StatiProdotto', 'T_WEB_TipiFormato', 'T_WEB_Tipologie', 'T_WEB_ArticoliFatturati', 'T_WEB_IdInternetFatturati', listaTabelle.push({ table: 'T_WOO_Clienti', usaDataOra: false });
'T_WEB_Edizioni', 'T_WEB_Contratti']; listaTabelle.push({ table: 'T_WEB_Autori', usaDataOra: true, fieldId: 'IdAutore' });
} else { }
listaTabelle = ['T_WEB_Articoli']; if (options?.parte3 || options?.tutte) {
listaTabelle.push({ table: 'T_WEB_Collane', usaDataOra: true, fieldId: 'IdCollana' });
listaTabelle.push({ table: 'T_WEB_MarchiEditoriali', usaDataOra: true, fieldId: 'IdMarchioEditoriale' });
listaTabelle.push({ table: 'T_WEB_StatiProdotto', usaDataOra: true, fieldId: 'IdStatoProdotto' });
listaTabelle.push({ table: 'T_WEB_TipiFormato', usaDataOra: true, fieldId: 'IdTipoFormato' });
listaTabelle.push({ table: 'T_WEB_Tipologie', usaDataOra: true, fieldId: 'IdTipologia' });
listaTabelle.push({ table: 'T_WEB_ArticoliFatturati', usaDataOra: false });
listaTabelle.push({ table: 'T_WEB_IdInternetFatturati', usaDataOra: false });
listaTabelle.push({ table: 'T_WEB_Edizioni', usaDataOra: true, fieldId: 'IdEdizione' });
listaTabelle.push({ table: 'T_WEB_Contratti', usaDataOra: true, fieldId: 'IdArticolo' });
}
if (options?.test) {
listaTabelle.push({ table: 'T_WEB_Articoli', usaDataOra: true, fieldId: 'IdArticolo' });
} }
const migrator = new MssqlMigrator(); const migrator = new MssqlMigrator();

View File

@@ -0,0 +1,128 @@
const mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
const shared_consts = require('../tools/shared_nodejs');
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const JobsInProgressSchema = new Schema({
idapp: {
type: String,
},
descr: {
type: String,
},
nomeFunzioneDbOp: {
type: String,
},
status: {
type: Number,
},
terminatedWhy: {
type: Number,
},
comment: {
type: String,
},
date_created: {
type: Date,
default: Date.now
},
});
JobsInProgressSchema.statics.chechifExistJobWorking = async function (jobData, terminateiftoolong) {
// controlla se esiste un altro job, non ancora terminato !STATUS_JOB.FINISH
// se esiste già allora ritorna false
const existingJob = await this.findOne({ idapp: jobData.idapp, nomeFunzioneDbOp: jobData.nomeFunzioneDbOp, status: { $ne: shared_consts.STATUS_JOB.FINISH } });
if (existingJob) {
// se il Job trovato è passato troppo tempo (oltre 3 ore date_created), allora fai finta che abbia già terminato
// (in questo caso, non ritorna false, ma ritorna il job trovato, per permettere di gestire il caso in cui si vuole forzare il job a terminare)
if (Math.abs(Date.now() - existingJob.date_created.getTime()) > 180 * 60 * 1000) {
if (terminateiftoolong) {
existingJob.status = shared_consts.STATUS_JOB.FINISH;
existingJob.terminatedWhy = shared_consts.TERMINATED_WHY.TOOLONGTIME;
await existingJob.save();
return false;
}
} else {
return true; // E' in FUNZIONE il JOB
}
}
return false;
};
JobsInProgressSchema.statics.addNewJob = async function (jobData) {
if (!jobData || typeof jobData !== 'object') {
console.error('ERRORE: ❌ jobData deve essere un oggetto valido');
}
const esistegia = await this.chechifExistJobWorking(jobData, true);
if (esistegia) {
return null;
}
try {
const newJob = await this.create(jobData);
return newJob;
} catch (err) {
console.error('Errore nell\'aggiungere un nuovo record: ', err);
throw err;
}
};
JobsInProgressSchema.methods.terminateJob = async function (witherror) {
try {
this.status = shared_consts.STATUS_JOB.FINISH;
this.terminatedWhy = witherror ? shared_consts.TERMINATED_WHY.END_WITHERROR : shared_consts.TERMINATED_WHY.END_NORMALLY;
await this.save();
return true;
} catch (err) {
console.error('Errore durante la terminazione del job: ', err);
return false;
}
};
JobsInProgressSchema.statics.getFieldsForSearch = function () {
return [{ field: 'descr', type: tools.FieldType.string }]
};
JobsInProgressSchema.statics.executeQueryTable = function (idapp, params, user) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params, user);
};
JobsInProgressSchema.statics.findAllIdApp = async function (idapp) {
const JobsInProgress = this;
try {
return await JobsInProgress.find({ idapp }).then((arrrec) => {
return arrrec;
});
} catch (err) {
console.error('Errore: ', err);
}
};
const JobsInProgress = mongoose.model('JobsInProgress', JobsInProgressSchema);
JobsInProgress.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
module.exports = { JobsInProgress };

View File

@@ -26,16 +26,17 @@ const CatalogSchema = new Schema({
}, },
title: { title: {
type: String, type: String,
index: true,
}, },
foto_collana: IImg, foto_collana: IImg,
idCollane: [{ idCollane: [{
type: String, type: String,
}], }],
idTipoFormato: [{ idTipoFormato: [{
type: Number, type: Number,
}], }],
argomenti: [{ argomenti: [{
type: String, type: String,
}], }],
@@ -43,9 +44,9 @@ const CatalogSchema = new Schema({
type: Number, type: Number,
default: 0, default: 0,
}, },
editore: [{ type: String }], editore: [{ type: String }],
descr_introduttiva: { descr_introduttiva: {
type: String, type: String,
}, },
@@ -93,6 +94,7 @@ const CatalogSchema = new Schema({
type: Schema.Types.ObjectId, type: Schema.Types.ObjectId,
ref: 'Product', ref: 'Product',
}], }],
isCatalogoGenerale: Boolean,
}); });
/* /*
@@ -143,89 +145,102 @@ CatalogSchema.statics.executeQueryTable = function (idapp, params, user) {
CatalogSchema.statics.findAllIdApp = async function (idapp) { CatalogSchema.statics.findAllIdApp = async function (idapp) {
const Catalog = this; const Catalog = this;
let arrrec = await Catalog.find({ idapp }) try {
.sort({ title: 1 }) // Ordina i risultati per titolo let arrrec = await Catalog.find({ idapp })
/*.populate({ .sort({ title: 1 }) // Ordina i risultati per titolo
path: "idCollane", // Popola il campo idCollane /*.populate({
model: "Collana" // Specifica il modello della collezione Collana path: "idCollane", // Popola il campo idCollane
})*/ model: "Collana" // Specifica il modello della collezione Collana
.populate({ })*/
path: "lista_prodotti", // Popola il campo lista_prodotti .populate({
populate: { path: "lista_prodotti", // Popola il campo lista_prodotti
path: "idProductInfo", populate: {
model: "ProductInfo", path: "idProductInfo",
populate: [ model: "ProductInfo",
{ populate: [
path: "idCatProds", {
model: "CatProd" path: "idCatProds",
}, model: "CatProd"
{ },
path: "idSubCatProds", {
model: "SubCatProd" path: "idSubCatProds",
}, model: "SubCatProd"
{ },
path: "idAuthors", {
model: "Author" path: "idAuthors",
} model: "Author"
], }
}, ],
}) },
.populate({ })
path: "lista_prodotti", .populate({
populate: { path: "lista_prodotti",
path: "idProducer", populate: {
model: "Producer" path: "idProducer",
} model: "Producer"
}) }
.populate({ })
path: "lista_prodotti", .populate({
populate: { path: "lista_prodotti",
path: "idProvider", populate: {
model: "Provider" path: "idProvider",
} model: "Provider"
}) }
.populate({ })
path: "lista_prodotti", .populate({
populate: { path: "lista_prodotti",
path: "idStorehouses", populate: {
model: "Storehouse" path: "idStorehouses",
} model: "Storehouse"
}) }
.populate({ })
path: "lista_prodotti", .populate({
populate: { path: "lista_prodotti",
path: "idScontisticas", populate: {
model: "Scontistica" path: "idScontisticas",
} model: "Scontistica"
}) }
.populate({ })
path: "lista_prodotti", .populate({
populate: { path: "lista_prodotti",
path: "idGasordine", populate: {
model: "Gasordine" path: "idGasordine",
} model: "Gasordine"
}) }
; })
;
const transformedArrRec = arrrec.map(catalog => ({ // controlla prima se nella lista ci sono dei product che non esistono piu allora li devi rimuovere !
...catalog.toObject(), // Converte il documento Mongoose in un oggetto JavaScript puro for (const catalog of arrrec) {
lista_prodotti: catalog.lista_prodotti.map(product => ({ const originalLength = catalog.lista_prodotti.length;
...product.toObject(), catalog.lista_prodotti = catalog.lista_prodotti.filter(product => product.idProductInfo);
productInfo: { if (catalog.lista_prodotti.length !== originalLength) {
...product.idProductInfo.toObject(), // Copia tutti i campi di idProductInfo await catalog.save();
catprods: product.idProductInfo.idCatProds, // Rinomina idCatProds in catprods }
subcatprods: product.idProductInfo.idSubCatProds, }
collana: product.idProductInfo.idCollana,
authors: product.idProductInfo.idAuthors,
},
producer: product.idProducer,
storehouse: product.idStorehouses,
scontisticas: product.idScontisticas,
gasordine: product.idGasordine,
})),
}));
return transformedArrRec; const transformedArrRec = arrrec.map(catalog => ({
...catalog.toObject(), // Converte il documento Mongoose in un oggetto JavaScript puro
lista_prodotti: catalog.lista_prodotti.map(product => ({
...product.toObject(),
productInfo: {
...product.idProductInfo.toObject(), // Copia tutti i campi di idProductInfo
catprods: product.idProductInfo.idCatProds, // Rinomina idCatProds in catprods
subcatprods: product.idProductInfo.idSubCatProds,
collana: product.idProductInfo.idCollana,
authors: product.idProductInfo.idAuthors,
},
producer: product.idProducer,
storehouse: product.idStorehouses,
scontisticas: product.idScontisticas,
gasordine: product.idGasordine,
})),
}));
return transformedArrRec;
} catch (err) {
console.error('Errore: ', err);
}
}; };
const Catalog = mongoose.model('Catalog', CatalogSchema); const Catalog = mongoose.model('Catalog', CatalogSchema);

View File

@@ -21,6 +21,7 @@ const CatProdSchema = new Schema({
}, },
name: { name: {
type: String, type: String,
index: 1,
}, },
descr_estesa: { descr_estesa: {
type: String, type: String,
@@ -100,7 +101,7 @@ CatProdSchema.statics.updateCatDeleteEmpty = async function (idapp) {
}; };
CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp) { CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp, updatedata) {
try { try {
const myquery = [ const myquery = [
@@ -151,11 +152,13 @@ CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp) {
const result = await CatProd.aggregate(myquery); const result = await CatProd.aggregate(myquery);
for (const record of result) { if (updatedata) {
await CatProd.updateOne( for (const record of result) {
{ _id: record._id }, await CatProd.updateOne(
{ $set: { quanti: record.quanti } } { _id: record._id },
); { $set: { quanti: record.quanti } }
);
}
} }
return result; return result;

View File

@@ -20,6 +20,7 @@ const CollanaSchema = new Schema({
}, },
title: { title: {
type: String, type: String,
index: true,
}, },
dataOra: { dataOra: {
type: Date, type: Date,
@@ -55,7 +56,7 @@ module.exports.findAllIdApp = async function (idapp) {
return await Collana.find(myfind).sort({title: 1}).lean(); return await Collana.find(myfind).sort({title: 1}).lean();
}; };
module.exports.getCollaneWithTitleCount = async function (idapp) { module.exports.getCollaneWithTitleCount = async function (idapp, updatedata) {
try { try {
const myquery = [ const myquery = [
@@ -104,11 +105,13 @@ module.exports.getCollaneWithTitleCount = async function (idapp) {
const result = await Collana.aggregate(myquery); const result = await Collana.aggregate(myquery);
for (const record of result) { if (updatedata) {
await Collana.updateOne( for (const record of result) {
{ _id: record._id }, await Collana.updateOne(
{ $set: { quanti: record.quanti } } { _id: record._id },
); { $set: { quanti: record.quanti } }
);
}
} }
return result; return result;

77
src/server/models/cron.js Executable file
View File

@@ -0,0 +1,77 @@
const mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const CronSchema = new Schema({
idapp: {
type: String,
},
active: {
type: Boolean,
default: false,
},
descr: {
type: String,
},
nomeFunzioneDbOp: {
type: String,
},
startTime: { // Orario iniziale (es. "08:30")
type: String,
default: "00:00"
},
everyXHours: { // Esegui ogni X ore
type: Number,
default: 24
},
date_created: {
type: Date,
default: Date.now
},
date_updated: {
type: Date,
},
});
CronSchema.statics.getFieldsForSearch = function () {
return [{ field: 'descr', type: tools.FieldType.string }]
};
CronSchema.statics.executeQueryTable = function (idapp, params, user) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params, user);
};
CronSchema.statics.findAllIdApp = async function (idapp) {
const Cron = this;
try {
return await Cron.find({ idapp }).then((arrrec) => {
return arrrec;
});
} catch (err) {
console.error('Errore: ', err);
}
};
const Cron = mongoose.model('Cron', CronSchema);
Cron.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
module.exports = { Cron };

View File

@@ -0,0 +1,59 @@
const mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const DestNewsletterSchema = new Schema({
idapp: {
type: String,
},
descr: {
type: String,
},
tipodest_id: {
type: Number,
},
});
DestNewsletterSchema.statics.getFieldsForSearch = function () {
return []
};
DestNewsletterSchema.statics.executeQueryTable = function (idapp, params) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params);
};
DestNewsletterSchema.statics.DuplicateAllRecords = async function (idapporig, idappdest) {
return await tools.DuplicateAllRecords(this, idapporig, idappdest);
};
DestNewsletterSchema.statics.findAllIdApp = async function (idapp) {
const DestNewsletter = this;
const myfind = { idapp };
return await DestNewsletter.find(myfind).lean();
};
const DestNewsletter = mongoose.model('DestNewsletter', DestNewsletterSchema);
DestNewsletter.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
module.exports = { DestNewsletter };

View File

@@ -39,6 +39,41 @@ MailingListSchema.statics.findAllIdAppSubscribed = function (idapp) {
return tools.findAllQueryIdApp(User, myfind); return tools.findAllQueryIdApp(User, myfind);
}; };
MailingListSchema.statics.findAllIdAppDiarioSubscr = function (idapp) {
const myfind = {
idapp,
diario_on: true,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
$or: [
{ email_errata: { $exists: false } },
{ email_errata: { $exists: true, $ne: true } }],
};
// Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit.
return tools.findAllQueryIdApp(User, myfind);
};
MailingListSchema.statics.findAllIdAppDiarioSubscr = function (idapp) {
const myfind = {
idapp,
test: true,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
$or: [
{ email_errata: { $exists: false } },
{ email_errata: { $exists: true, $ne: true } }],
};
// Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit.
return tools.findAllQueryIdApp(User, myfind);
};
MailingListSchema.statics.getnumSent = async function (idapp, idUser) { MailingListSchema.statics.getnumSent = async function (idapp, idUser) {
const myfind = { idapp, news_on: true, lastid_newstosent: idUser }; const myfind = { idapp, news_on: true, lastid_newstosent: idUser };

View File

@@ -22,6 +22,9 @@ const NewstosentSchema = new Schema({
templemail_str: { templemail_str: {
type: String, type: String,
}, },
destnewsletter_str: {
type: String,
},
activate: { activate: {
type: Boolean, type: Boolean,
default: false default: false
@@ -121,7 +124,10 @@ NewstosentSchema.statics.findNewsletterPending_To_Send = function (idapp) {
starting_job: true, starting_job: true,
finish_job: false, finish_job: false,
processing_job: false, processing_job: false,
lastemailsent_Job: { $gte: tools.IncDateNow(-1000 * 60 * 60 * 15) }, $or: [
{ lastemailsent_Job: { $gte: tools.IncDateNow(-1000 * 60 * 60 * 15) } },
{ lastemailsent_Job: null }
],
idapp idapp
}).lean(); }).lean();
}; };

View File

@@ -22,9 +22,9 @@ const orderSchema = new Schema({
}, },
userId: { type: Schema.Types.ObjectId, ref: 'User' }, userId: { type: Schema.Types.ObjectId, ref: 'User' },
status: { status: {
type: Number, type: Number, index: true
}, },
idProduct: { type: Schema.Types.ObjectId, ref: 'Product' }, idProduct: { type: Schema.Types.ObjectId, ref: 'Product', index: true },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' }, idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' },
idStorehouse: { type: Schema.Types.ObjectId, ref: 'StoreHouse' }, idStorehouse: { type: Schema.Types.ObjectId, ref: 'StoreHouse' },
idScontisticas: [{ type: Schema.Types.ObjectId, ref: 'Scontistica' }], idScontisticas: [{ type: Schema.Types.ObjectId, ref: 'Scontistica' }],
@@ -125,7 +125,8 @@ const orderSchema = new Schema({
type: String type: String
}, },
modify_at: { modify_at: {
type: Date type: Date,
index: true
}, },
}); });

View File

@@ -36,16 +36,16 @@ const productSchema = new Schema({
isbn: { isbn: {
type: String, type: String,
}, },
idProductInfo: { type: Schema.Types.ObjectId, ref: 'ProductInfo' }, idProductInfo: { type: Schema.Types.ObjectId, ref: 'ProductInfo', index: true },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' }, idProducer: { type: Schema.Types.ObjectId, ref: 'Producer', index: true },
idStorehouses: [ idStorehouses: [
{ type: Schema.Types.ObjectId, ref: 'Storehouse' } { type: Schema.Types.ObjectId, ref: 'Storehouse', index: true }
], ],
idGasordine: { type: Schema.Types.ObjectId, ref: 'Gasordine' }, idGasordine: { type: Schema.Types.ObjectId, ref: 'Gasordine', index: true },
idScontisticas: [ idScontisticas: [
{ type: Schema.Types.ObjectId, ref: 'Scontistica' } { type: Schema.Types.ObjectId, ref: 'Scontistica', index: true }
], ],
idProvider: { type: Schema.Types.ObjectId, ref: 'Provider' }, idProvider: { type: Schema.Types.ObjectId, ref: 'Provider', index: true },
prezzo_ivato: { // Con IVA prezzo_ivato: { // Con IVA
type: Number type: Number
}, },
@@ -137,6 +137,7 @@ const productSchema = new Schema({
stockQty: { // in magazzino stockQty: { // in magazzino
type: Number, type: Number,
default: 0, default: 0,
index: true,
}, },
stockBloccatiQty: { // Prenotati Bloccati stockBloccatiQty: { // Prenotati Bloccati
type: Number, type: Number,
@@ -220,7 +221,7 @@ const productSchema = new Schema({
}, },
validaprod: { validaprod: {
esito: { esito: {
type: Number, type: Number,
}, },
data: { data: {
type: Date, type: Date,
@@ -468,176 +469,33 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
// return await Product.find(myfind); // return await Product.find(myfind);
query.push( query.push(
// PRIMO FILTRO: riduce subito il numero di documenti
{ $match: myfind }, { $match: myfind },
// UNICO LOOKUP ORDERS CON FACET PER RIDURRE I DOPPIONI
{ {
$lookup: { $lookup: {
from: 'producers', from: "orders",
localField: 'idProducer', let: { productId: "$_id" },
foreignField: '_id',
as: 'producer'
}
},
{
$unwind: {
path: '$producer',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'productinfos',
localField: 'idProductInfo',
foreignField: '_id',
as: 'productInfo'
}
},
{
$unwind: {
path: '$productInfo',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'gasordines',
localField: 'idGasordine',
foreignField: '_id',
as: 'gasordine'
}
},
{
$unwind: {
path: '$gasordine',
preserveNullAndEmptyArrays: true,
},
},
{
$match: {
$or: [
{ 'gasordine.active': true }, // Include documents where gasordines.active is true
{ 'gasordine': { $exists: false } } // Include documents where gasordines array doesn't exist
]
}
},
{
$group: {
_id: '$_id',
gasordine: { $first: '$gasordine' },
originalFields: { $first: '$$ROOT' } // Preserve all existing fields
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: ['$originalFields', { gasordine: '$gasordine' }]
}
}
},
{
$lookup: {
from: 'providers',
localField: 'idProvider',
foreignField: '_id',
as: 'provider'
}
},
{
$unwind: {
path: '$provider',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'authors',
localField: 'productInfo.idAuthors',
foreignField: '_id',
as: 'productInfo.authors'
}
},
{
$lookup: {
from: 'publishers',
localField: 'productInfo.idPublisher',
foreignField: '_id',
as: 'productInfo.publisher'
}
},
{
$unwind: {
path: '$productInfo.publisher',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'collanas',
localField: 'productInfo.idCollana',
foreignField: '_id',
as: 'productInfo.collana'
}
},
{
$unwind: {
path: '$productInfo.collana',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'catprods',
localField: 'productInfo.idCatProds',
foreignField: '_id',
as: 'productInfo.catprods'
}
},
{
$lookup: {
from: 'subcatprods',
localField: 'productInfo.idSubCatProds',
foreignField: '_id',
as: 'productInfo.subcatprods'
}
},
{
$lookup: {
from: 'scontisticas',
localField: 'idScontisticas',
foreignField: '_id',
as: 'scontisticas'
}
},
{
$lookup: {
from: 'storehouses',
localField: 'idStorehouses',
foreignField: '_id',
as: 'storehouses'
}
},
{
$lookup: {
from: 'orders',
let: { productId: '$_id' },
pipeline: [ pipeline: [
{ {
$match: { $match: {
$expr: { $expr: {
$and: [ $and: [
{ $eq: ['$idProduct', '$$productId'] }, { $eq: ["$idProduct", "$$productId"] },
{ {
$or: [ $or: [
{ $eq: ["$status", shared_consts.OrderStatus.CHECKOUT_SENT] },
{ {
$eq: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT] $and: [
}, { $lt: ["$status", shared_consts.OrderStatus.CHECKOUT_SENT] },
{ {
$and: [{ $lt: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT] }, $gt: [
{ "$modify_at",
$gt: [ { $subtract: [new Date(), 60 * 60 * 1000] }
'$modify_at', ]
{ $subtract: [new Date(), 60 * 60 * 1000] } // 1 hour in milliseconds 60 * 60 }
] ]
}]
} }
] ]
} }
@@ -648,102 +506,162 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
{ {
$group: { $group: {
_id: null, _id: null,
totalQty: { $sum: '$quantity' }, totalQty: { $sum: "$quantity" },
totalQtyPreordered: { $sum: "$quantitypreordered" }
} }
} }
], ],
as: 'productOrders' as: "orderSummary"
}
},
{
$lookup: {
from: 'orders',
let: { productId: '$_id' },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ['$idProduct', '$$productId'] },
{
$or: [
{
$eq: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT]
},
{
$and: [{ $lt: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT] },
{
$gt: [
'$modify_at',
{ $subtract: [new Date(), 60 * 60 * 1000] } // 1 hour in milliseconds 60 * 60
]
}]
}
]
}
]
}
}
},
{
$group: {
_id: null,
totalQtyPreordered: { $sum: '$quantitypreordered' }
}
}
],
as: 'productPreOrders'
} }
}, },
// ESTRAGGO LE QUANTITÀ IN CAMPI AGGIUNTIVI
{ {
$addFields: { $addFields: {
QuantitaOrdinateInAttesa: { QuantitaOrdinateInAttesa: {
$ifNull: [ $ifNull: [{ $arrayElemAt: ["$orderSummary.totalQty", 0] }, 0]
{
$cond: {
if: { $isArray: '$productOrders' },
then: { $arrayElemAt: ['$productOrders.totalQty', 0] },
else: 0
}
},
0
]
}, },
QuantitaPrenotateInAttesa: { QuantitaPrenotateInAttesa: {
$ifNull: [ $ifNull: [{ $arrayElemAt: ["$orderSummary.totalQtyPreordered", 0] }, 0]
{
$cond: {
if: { $isArray: '$productPreOrders' },
then: { $arrayElemAt: ['$productPreOrders.totalQtyPreordered', 0] },
else: 0
}
},
0
]
},
},
},
{
$addFields: {
quantityAvailable: {
$subtract: ["$stockQty", "$QuantitaOrdinateInAttesa"],
},
bookableAvailableQty: {
$subtract: ["$maxbookableGASQty", "$QuantitaPrenotateInAttesa"],
} }
} }
}, },
// CALCOLO DELLE DISPONIBILITÀ
{ {
$unset: 'productOrders' $addFields: {
}, quantityAvailable: {
{ $subtract: ["$stockQty", "$QuantitaOrdinateInAttesa"]
$unset: 'productPreOrders' },
}, bookableAvailableQty: {
{ $subtract: ["$maxbookableGASQty", "$QuantitaPrenotateInAttesa"]
$sort: { }
'productInfo.name': 1 // 1 for ascending order, -1 for descending order
} }
}, },
// ELIMINO IL RISULTATO TEMPORANEO
{ $unset: "orderSummary" },
// LOOKUP MULTIPLI MA ORGANIZZATI
{
$lookup: {
from: "producers",
localField: "idProducer",
foreignField: "_id",
as: "producer"
}
},
{ $unwind: { path: "$producer", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "productinfos",
localField: "idProductInfo",
foreignField: "_id",
as: "productInfo"
}
},
{ $unwind: { path: "$productInfo", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "gasordines",
localField: "idGasordine",
foreignField: "_id",
as: "gasordine"
}
},
{ $unwind: { path: "$gasordine", preserveNullAndEmptyArrays: true } },
// FILTRO DOPO LOOKUP SU GASORDINE
{
$match: {
$or: [
{ "gasordine.active": true },
{ gasordine: { $exists: false } }
]
}
},
// LOOKUP SU AUTHORS
{
$lookup: {
from: "authors",
localField: "productInfo.idAuthors",
foreignField: "_id",
as: "productInfo.authors"
}
},
// LOOKUP PUBBLICATORI, COLLANE, CATEGORIE, ECC.
{
$lookup: {
from: "publishers",
localField: "productInfo.idPublisher",
foreignField: "_id",
as: "productInfo.publisher"
}
},
{ $unwind: { path: "$productInfo.publisher", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "collanas",
localField: "productInfo.idCollana",
foreignField: "_id",
as: "productInfo.collana"
}
},
{ $unwind: { path: "$productInfo.collana", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "catprods",
localField: "productInfo.idCatProds",
foreignField: "_id",
as: "productInfo.catprods"
}
},
{
$lookup: {
from: "subcatprods",
localField: "productInfo.idSubCatProds",
foreignField: "_id",
as: "productInfo.subcatprods"
}
},
{
$lookup: {
from: "scontisticas",
localField: "idScontisticas",
foreignField: "_id",
as: "scontisticas"
}
},
{
$lookup: {
from: "storehouses",
localField: "idStorehouses",
foreignField: "_id",
as: "storehouses"
}
},
{
$lookup: {
from: "providers",
localField: "idProvider",
foreignField: "_id",
as: "provider"
}
},
{ $unwind: { path: "$provider", preserveNullAndEmptyArrays: true } },
// ORDINAMENTO FINALE
{
$sort: {
"productInfo.name": 1
}
}
); );
// console.log('query=', query); // console.log('query=', query);

View File

@@ -41,6 +41,7 @@ const productInfoSchema = new Schema({
}, },
name: { name: {
type: String, type: String,
index: true,
}, },
description: { description: {
type: String, type: String,
@@ -48,10 +49,10 @@ const productInfoSchema = new Schema({
short_descr: { short_descr: {
type: String, type: String,
}, },
idCatProds: [{ type: Schema.Types.ObjectId, ref: 'CatProd' }], idCatProds: [{ type: Schema.Types.ObjectId, ref: 'CatProd', index: true }],
idSubCatProds: [{ type: Schema.Types.ObjectId, ref: 'SubCatProd' }], idSubCatProds: [{ type: Schema.Types.ObjectId, ref: 'SubCatProd' }],
idStatoProdotto: { idStatoProdotto: {
type: Number type: Number, index: true
}, },
color: { color: {
type: String type: String
@@ -86,6 +87,9 @@ const productInfoSchema = new Schema({
imagefile: { imagefile: {
type: String, type: String,
}, },
image_not_found: {
type: Boolean,
},
vers_img: { vers_img: {
type: Number, type: Number,
}, },
@@ -122,9 +126,9 @@ const productInfoSchema = new Schema({
note: { note: {
type: String, type: String,
}, },
idAuthors: [{ type: Schema.Types.ObjectId, ref: 'Author' }], idAuthors: [{ type: Schema.Types.ObjectId, ref: 'Author', index: true }],
idCollana: { type: Schema.Types.ObjectId, ref: 'Collana' }, idCollana: { type: Schema.Types.ObjectId, ref: 'Collana', index: true },
idPublisher: { type: Schema.Types.ObjectId, ref: 'Publisher' }, idPublisher: { type: Schema.Types.ObjectId, ref: 'Publisher', index: true },
collezione: { collezione: {
type: String, type: String,
}, },
@@ -133,6 +137,7 @@ const productInfoSchema = new Schema({
}, },
date_pub: { date_pub: {
type: Date, type: Date,
index: 1,
}, },
date_pub_ts: { date_pub_ts: {
type: Number, type: Number,
@@ -144,7 +149,7 @@ const productInfoSchema = new Schema({
date_updated: { date_updated: {
type: Date, type: Date,
}, },
date_updated_fromGM: { date_updated_fromGM: {
type: Date, type: Date,
}, },
@@ -156,8 +161,13 @@ const productInfoSchema = new Schema({
fatLast6M: Number, fatLast6M: Number,
fatLast1Y: Number, fatLast1Y: Number,
fatLast2Y: Number, fatLast2Y: Number,
vLast6M: Number, vLast6M: {
vLast1Y: Number, type: Number,
index: true,
},
vLast1Y: {
type: Number, index: true
},
vLast2Y: Number, vLast2Y: Number,
dataUltimoOrdine: Date, dataUltimoOrdine: Date,
rank3M: Number, rank3M: Number,
@@ -492,6 +502,60 @@ module.exports.updateProductInfoByStats = async function (idapp) {
return mylogtot; return mylogtot;
} }
// crea setImgNotFound
module.exports.setImgNotFound = async function (id) {
// set sul record id il flag image_not_found
try {
const ProductInfo = this;
await ProductInfo.updateOne(
{ _id: id },
{ $set: { image_not_found: true } }
);
console.log(`Flag image_not_found set for record with id: ${id}`);
} catch (error) {
console.error(`Error setting image_not_found flag for id ${id}:`, error);
}
}
// crea una funzione che mi rimuove il record "product" che utilizza productInfo, nel caso in cui date_updated_fromGM non esista
module.exports.removeProductInfoWithoutDateUpdatedFromGM = async function (idapp) {
const ProductInfo = this;
const globalTables = require('../tools/globalTables');
const Product = globalTables.getTableByTableName('Product');
let mylog;
try {
const arrproductInfo = await ProductInfo.find({ idapp, date_updated_fromGM: { $exists: false } });
if (arrproductInfo.length > 0) {
mylog = `Rimuovo ${arrproductInfo.length} productInfo senza date_updated_fromGM !!`
console.log(mylog);
for (const productinfo of arrproductInfo) {
// cerca nella tabella Product se esiste idProductInfo = _id e cancella tutti i record che hanno questa corrispondenza
if (Product) {
await Product.deleteMany({ idProductInfo: productinfo._id });
}
// Ora rimuovi anche questo productInfo
await ProductInfo.deleteOne({ _id: productinfo._id });
}
}
return mylog;
} catch (error) {
mylog += 'Error removing productInfo without date_updated_fromGM:' + error;
console.error(mylog);
}
return mylog;
};
module.exports.createIndexes() module.exports.createIndexes()
.then(() => { }) .then(() => { })
.catch((err) => { throw err; }); .catch((err) => { throw err; });

View File

@@ -48,7 +48,7 @@ module.exports.findAllIdApp = async function (idapp) {
return await Publisher.find(myfind).sort({ name: 1 }).lean(); return await Publisher.find(myfind).sort({ name: 1 }).lean();
}; };
module.exports.getEditoriWithTitleCount = async function (idapp) { module.exports.getEditoriWithTitleCount = async function (idapp, updatedata) {
try { try {
const myquery = [ const myquery = [
@@ -95,11 +95,13 @@ module.exports.getEditoriWithTitleCount = async function (idapp) {
const result = await Publisher.aggregate(myquery); const result = await Publisher.aggregate(myquery);
for (const record of result) { if (updatedata) {
await Publisher.updateOne( for (const record of result) {
{ _id: record._id }, await Publisher.updateOne(
{ $set: { quanti: record.quanti } } { _id: record._id },
); { $set: { quanti: record.quanti } }
);
}
} }
return result; return result;

View File

@@ -25,6 +25,15 @@ const TemplEmailSchema = new Schema({
content: { content: {
type: String, type: String,
}, },
disclaimer: {
type: String,
},
piedipagina: {
type: String,
},
firma: {
type: String,
},
img: { img: {
type: String, type: String,
}, },

View File

@@ -177,6 +177,12 @@ const UserSchema = new mongoose.Schema({
news_on: { news_on: {
type: Boolean, type: Boolean,
}, },
diario_on: {
type: Boolean,
},
test: {
type: Boolean,
},
email_errata: { email_errata: {
type: Boolean, type: Boolean,
}, },
@@ -640,7 +646,7 @@ UserSchema.statics.canHavePower = function (perm) {
try { try {
let consentito = false; let consentito = false;
if (User.isAdmin(perm) || User.isManager(perm) || if (User.isAdmin(perm) || User.isManager(perm) ||
User.isEditor(perm) || User.isFacilitatore(perm)) { User.isEditor(perm) || User.isCommerciale(perm) || User.isFacilitatore(perm)) {
consentito = true; consentito = true;
} }
@@ -696,6 +702,14 @@ UserSchema.statics.isEditor = function (perm) {
return false; return false;
} }
}; };
UserSchema.statics.isCommerciale = function (perm) {
try {
return ((perm & shared_consts.Permissions.Commerciale) ===
shared_consts.Permissions.Commerciale);
} catch (e) {
return false;
}
};
UserSchema.statics.isGrafico = function (perm) { UserSchema.statics.isGrafico = function (perm) {
try { try {
return ((perm & shared_consts.Permissions.Grafico) === return ((perm & shared_consts.Permissions.Grafico) ===
@@ -759,7 +773,7 @@ UserSchema.statics.findByToken = async function (token, typeaccess, con_auth, wi
if (!token) { if (!token) {
console.warn('TOKEN VUOTO ! '); console.warn('TOKEN VUOTO ! ');
return { user, code }; return { user, code };
} }
try { try {
@@ -822,7 +836,7 @@ UserSchema.statics.findByToken = async function (token, typeaccess, con_auth, wi
const end_find = process.hrtime.bigint(); const end_find = process.hrtime.bigint();
// console.log(` User.findOne LEAN impiega ${Math.round(Number(end_find - start_find) / 1e6) / 1000} secondi.`); // console.log(` User.findOne LEAN impiega ${Math.round(Number(end_find - start_find) / 1e6) / 1000} secondi.`);
} }
if (user) { if (user) {
const checkExpiry = tools.getEnableTokenExpiredByIdApp(user.idapp); const checkExpiry = tools.getEnableTokenExpiredByIdApp(user.idapp);
@@ -1350,6 +1364,16 @@ UserSchema.statics.setaportador_solidario = async function (
return !!myrec; return !!myrec;
}; };
UserSchema.statics.setNewsletterToAll = async function (
idapp) {
const User = this;
return await User.updateMany({
idapp,
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
}, { $set: { 'news_on': true } },
{ new: false });
};
UserSchema.statics.setNewsletter = async function ( UserSchema.statics.setNewsletter = async function (
idapp, username, newsletter_on) { idapp, username, newsletter_on) {
const User = this; const User = this;

View File

@@ -15,6 +15,7 @@ const { getTableContent } = require('../controllers/articleController');
const T_WEB_ArticoliFatturati = require('../models/t_web_articolifatturati'); const T_WEB_ArticoliFatturati = require('../models/t_web_articolifatturati');
const T_WEB_Ordini = require('../models/t_web_ordini'); const T_WEB_Ordini = require('../models/t_web_ordini');
const { JobsInProgress } = require('../models/JobsInProgress');
class Macro { class Macro {
constructor(idapp, options) { constructor(idapp, options) {
@@ -51,6 +52,18 @@ class Macro {
idapp: options.idapp, idapp: options.idapp,
} }
let myjob = null;
const lavoromassivo = options.caricatutti;
if (lavoromassivo) {
myjob = await JobsInProgress.addNewJob({ idapp, descr: 'Riaggiorna Articoli', nomeFunzioneDbOp: 'updateAllBook', status: shared_consts.STATUS_JOB.START });
if (!myjob) {
mylog = 'ATTENZIONE! ❌ STAVO GIA ESEGUENDO QUESTO JOB, quindi ESCO !';
console.error(mylog);
return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog, idRecUpdated: opt.idRecUpdated, table: opt.table };
}
}
try { try {
@@ -417,13 +430,21 @@ class Macro {
console.log('numrec', numrec); console.log('numrec', numrec);
} }
let rimuoviTabellePerIniziare = false;
let count = 0; let count = 0;
if (Array.isArray(recproducts)) { if (Array.isArray(recproducts)) {
for (const recproduct of recproducts) { if (recproducts.length > 10 && lavoromassivo) {
// if (!options.caricatutti) { // rimuovi dalla tabella productInfo tutti i campi date_updated_fromGM
await this.elaboraProdotto(recproduct, opt); const result = await ProductInfo.updateMany({ idapp: options.idapp }, { $unset: { date_updated_fromGM: null } });
let quanti_rimossi = result.modifiedCount;
console.log(`Sbianca date_updated_fromGM da ProductInfo: (${quanti_rimossi} su ${result.matchedCount})`);
rimuoviTabellePerIniziare = true;
}
for (const recproduct of recproducts) {
await this.elaboraProdotto(recproduct, opt);
const sku = recproduct.IdArticolo; const sku = recproduct.IdArticolo;
@@ -439,6 +460,12 @@ class Macro {
} }
//} //}
} }
if (rimuoviTabellePerIniziare) {
await ProductInfo.removeProductInfoWithoutDateUpdatedFromGM(options.idapp);
}
if (myjob)
await myjob.terminateJob();
} }
if (numrec > 1) { if (numrec > 1) {
@@ -455,6 +482,8 @@ class Macro {
} catch (e) { } catch (e) {
mylog += 'ERRORE ! *** IMPORTATI: ' + opt?.imported + ' AGGIORNATI = ' + opt?.updated + ' (su ' + numrec + ' RECORD)'; mylog += 'ERRORE ! *** IMPORTATI: ' + opt?.imported + ' AGGIORNATI = ' + opt?.updated + ' (su ' + numrec + ' RECORD)';
opt.logerror = e.message; opt.logerror = e.message;
if (myjob)
await myjob.terminateJob(true);
console.error(e.message); console.error(e.message);
return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog, logerror: opt.logerror }; return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog, logerror: opt.logerror };
} }
@@ -1075,6 +1104,15 @@ class Macro {
return listaCampi.some((campo) => recordOld[campo] !== recordNew[campo]); return listaCampi.some((campo) => recordOld[campo] !== recordNew[campo]);
} }
async getStat() {
let mystr = '';
const ris = await ProductInfo.countDocuments({ $or: [{ date_updated_fromGM: { $exists: false } }, { date_updated_fromGM: null }] });
mystr += `${ris} ProductInfo non aggiornati da GM, quindi da cancellare ! \n`;
return mystr;
}
} }
module.exports = Macro; module.exports = Macro;

View File

@@ -33,13 +33,27 @@ class MssqlMigrator {
let indtab = 0; let indtab = 0;
let indtabok = 0; let indtabok = 0;
const logs = []; const logs = [];
for (const tableName of tableNames) { for (const rectable of tableNames) {
try { try {
const tableName = rectable.table;
const usaDataOra = rectable.usaDataOra;
const fieldId = rectable.fieldId;
const percentuale = ((indtab / numtables) * 100).toFixed(2); const percentuale = ((indtab / numtables) * 100).toFixed(2);
logs.push(`\n>> Recupero dati da MSSQL per la tabella: ${tableName} - (Completamento: ${percentuale}%)`); logs.push(`\n>> Recupero dati da MSSQL per la tabella: ${tableName} - (Completamento: ${percentuale}%)`);
console.log(logs[logs.length - 1]); console.log(logs[logs.length - 1]);
const dataQuery = `SELECT * FROM [${tableName}]`; let dataQuery = `SELECT * FROM ${tableName}`;
if (usaDataOra) {
dataQuery = `SELECT T.* FROM ${tableName} T`;
dataQuery += ` JOIN (
SELECT ${fieldId}, MAX(DataOra) AS data
FROM ${tableName}
GROUP BY ${fieldId}
) b ON T.${fieldId} = b.${fieldId} AND T.DataOra = b.data; `;
}
console.log('query', dataQuery);
let dataResponse = null; let dataResponse = null;
@@ -51,11 +65,12 @@ class MssqlMigrator {
null, null,
{ timeout: 900000 }); { timeout: 900000 });
} catch (error) { } catch (error) {
console.error('Error: ', error); console.error('Error: ', error.response?.data?.error || error.message || error);
if (error.message === 'socket hang up') { if (error.message === 'socket hang up') {
console.log('Error: hangup, waiting 5 seconds and retrying...'); console.log('Error: hangup, waiting 5 seconds and retrying...');
await new Promise(resolve => setTimeout(resolve, 5000)); await new Promise(resolve => setTimeout(resolve, 5000));
dataResponse = await axios.post( dataResponse = await axios.post(
`${this.serverUrl}/query`, `${this.serverUrl}/query`,
{ query: dataQuery }, { query: dataQuery },
@@ -69,6 +84,7 @@ class MssqlMigrator {
} }
} }
const records = dataResponse?.data; const records = dataResponse?.data;
if (!records || records.length === 0) { if (!records || records.length === 0) {

File diff suppressed because it is too large Load Diff

View File

@@ -18,10 +18,9 @@ module.exports = {
{ _id: 16, reg: 'TAA', prov: 'BZ', descr: 'Bolzano', link_grp: 'https://t.me/c/1614195634/596?thread=594', link_telegram: '' }, { _id: 16, reg: 'TAA', prov: 'BZ', descr: 'Bolzano', link_grp: 'https://t.me/c/1614195634/596?thread=594', link_telegram: '' },
{ _id: 17, reg: 'LOM', prov: 'BS', descr: 'Brescia', link_grp: 'https://t.me/c/1614195634/490?thread=478', link_telegram: '' }, { _id: 17, reg: 'LOM', prov: 'BS', descr: 'Brescia', link_grp: 'https://t.me/c/1614195634/490?thread=478', link_telegram: '' },
{ _id: 18, reg: 'PUG', prov: 'BR', descr: 'Brindisi', link_grp: 'https://t.me/c/1614195634/536?thread=530', link_telegram: '' }, { _id: 18, reg: 'PUG', prov: 'BR', descr: 'Brindisi', link_grp: 'https://t.me/c/1614195634/536?thread=530', link_telegram: '' },
{ _id: 19, reg: 'SAR', prov: 'CA', descr: 'Cagliari', link_grp: 'https://t.me/c/1614195634/546?thread=541', link_telegram: '' }, { _id: 19, reg: 'SAR', prov: 'CA', descr: 'Cagliari', link_grp: 'https://t.me/+9A0xl58CEI8zMWE0', link_telegram: '' },
{ _id: 20, reg: 'SIC', prov: 'CL', descr: 'Caltanissetta', link_grp: 'https://t.me/c/1614195634/563?thread=554', link_telegram: '' }, { _id: 20, reg: 'SIC', prov: 'CL', descr: 'Caltanissetta', link_grp: 'https://t.me/c/1614195634/563?thread=554', link_telegram: '' },
{ _id: 21, reg: 'MOL', prov: 'CB', descr: 'Campobasso', link_grp: 'https://t.me/c/1614195634/398?thread=396', link_telegram: '' }, { _id: 21, reg: 'MOL', prov: 'CB', descr: 'Campobasso', link_grp: 'https://t.me/c/1614195634/398?thread=396', link_telegram: '' },
{ _id: 22, reg: 'SAR', prov: 'CI', descr: 'Carbonia-Iglesias', link_grp: '', link_telegram: '' },
{ _id: 23, reg: 'CAM', prov: 'CE', descr: 'Caserta', link_grp: 'https://t.me/c/1614195634/414?thread=410', link_telegram: '' }, { _id: 23, reg: 'CAM', prov: 'CE', descr: 'Caserta', link_grp: 'https://t.me/c/1614195634/414?thread=410', link_telegram: '' },
{ _id: 24, reg: 'SIC', prov: 'CT', descr: 'Catania', link_grp: 'https://t.me/c/1614195634/564?thread=555', link_telegram: '' }, { _id: 24, reg: 'SIC', prov: 'CT', descr: 'Catania', link_grp: 'https://t.me/c/1614195634/564?thread=555', link_telegram: '' },
{ _id: 25, reg: 'CAL', prov: 'CZ', descr: 'Catanzaro', link_grp: 'https://t.me/c/1614195634/378?thread=377', link_telegram: '' }, { _id: 25, reg: 'CAL', prov: 'CZ', descr: 'Catanzaro', link_grp: 'https://t.me/c/1614195634/378?thread=377', link_telegram: '' },
@@ -62,7 +61,6 @@ module.exports = {
{ _id: 60, reg: 'CAM', prov: 'NA', descr: 'Napoli', link_grp: 'https://t.me/c/1614195634/407?thread=406', link_telegram: '' }, { _id: 60, reg: 'CAM', prov: 'NA', descr: 'Napoli', link_grp: 'https://t.me/c/1614195634/407?thread=406', link_telegram: '' },
{ _id: 61, reg: 'PIE', prov: 'NO', descr: 'Novara', link_grp: 'https://t.me/c/1614195634/517?thread=508', link_telegram: '' }, { _id: 61, reg: 'PIE', prov: 'NO', descr: 'Novara', link_grp: 'https://t.me/c/1614195634/517?thread=508', link_telegram: '' },
{ _id: 62, reg: 'SAR', prov: 'NU', descr: 'Nuoro', link_grp: 'https://t.me/c/1614195634/548?thread=542', link_telegram: '' }, { _id: 62, reg: 'SAR', prov: 'NU', descr: 'Nuoro', link_grp: 'https://t.me/c/1614195634/548?thread=542', link_telegram: '' },
{ _id: 63, reg: 'SAR', prov: 'OT', descr: 'Olbia-Tempio', link_grp: '', link_telegram: '' },
{ _id: 64, reg: 'SAR', prov: 'OR', descr: 'Oristano', link_grp: 'https://t.me/c/1614195634/550?thread=543', link_telegram: '' }, { _id: 64, reg: 'SAR', prov: 'OR', descr: 'Oristano', link_grp: 'https://t.me/c/1614195634/550?thread=543', link_telegram: '' },
{ _id: 65, reg: 'VEN', prov: 'PD', descr: 'Padova', link_grp: 'https://t.me/c/1614195634/610?thread=600', link_telegram: '' }, { _id: 65, reg: 'VEN', prov: 'PD', descr: 'Padova', link_grp: 'https://t.me/c/1614195634/610?thread=600', link_telegram: '' },
{ _id: 66, reg: 'SIC', prov: 'PA', descr: 'Palermo', link_grp: 'https://t.me/c/1614195634/568?thread=558', link_telegram: '' }, { _id: 66, reg: 'SIC', prov: 'PA', descr: 'Palermo', link_grp: 'https://t.me/c/1614195634/568?thread=558', link_telegram: '' },
@@ -86,7 +84,6 @@ module.exports = {
{ _id: 84, reg: 'LAZ', prov: 'RM', descr: 'Roma', link_grp: '', link_telegram: '' }, { _id: 84, reg: 'LAZ', prov: 'RM', descr: 'Roma', link_grp: '', link_telegram: '' },
{ _id: 85, reg: 'VEN', prov: 'RO', descr: 'Rovigo', link_grp: 'https://t.me/c/1614195634/611?thread=601', link_telegram: '' }, { _id: 85, reg: 'VEN', prov: 'RO', descr: 'Rovigo', link_grp: 'https://t.me/c/1614195634/611?thread=601', link_telegram: '' },
{ _id: 86, reg: 'CAM', prov: 'SA', descr: 'Salerno', link_grp: 'https://t.me/c/1614195634/416?thread=412', link_telegram: '' }, { _id: 86, reg: 'CAM', prov: 'SA', descr: 'Salerno', link_grp: 'https://t.me/c/1614195634/416?thread=412', link_telegram: '' },
{ _id: 87, reg: 'SAR', prov: 'VS', descr: 'Medio Campidano', link_grp: '', link_telegram: '' },
{ _id: 88, reg: 'SAR', prov: 'SS', descr: 'Sassari', link_grp: 'https://t.me/c/1614195634/551?thread=544', link_telegram: '' }, { _id: 88, reg: 'SAR', prov: 'SS', descr: 'Sassari', link_grp: 'https://t.me/c/1614195634/551?thread=544', link_telegram: '' },
{ _id: 89, reg: 'LIG', prov: 'SV', descr: 'Savona', link_grp: 'https://t.me/c/1614195634/395?thread=391', link_telegram: '' }, { _id: 89, reg: 'LIG', prov: 'SV', descr: 'Savona', link_grp: 'https://t.me/c/1614195634/395?thread=391', link_telegram: '' },
{ _id: 90, reg: 'TOS', prov: 'SI', descr: 'Siena', link_grp: 'https://t.me/c/1614195634/592?thread=581', link_telegram: '' }, { _id: 90, reg: 'TOS', prov: 'SI', descr: 'Siena', link_grp: 'https://t.me/c/1614195634/592?thread=581', link_telegram: '' },
@@ -96,7 +93,6 @@ module.exports = {
{ _id: 94, reg: 'ABR', prov: 'TE', descr: 'Teramo', link_grp: 'https://t.me/c/1614195634/370?thread=369', link_telegram: '' }, { _id: 94, reg: 'ABR', prov: 'TE', descr: 'Teramo', link_grp: 'https://t.me/c/1614195634/370?thread=369', link_telegram: '' },
{ _id: 95, reg: 'UMB', prov: 'TR', descr: 'Terni', link_grp: 'https://t.me/c/1614195634/404?thread=402', link_telegram: '' }, { _id: 95, reg: 'UMB', prov: 'TR', descr: 'Terni', link_grp: 'https://t.me/c/1614195634/404?thread=402', link_telegram: '' },
{ _id: 96, reg: 'PIE', prov: 'TO', descr: 'Torino', link_grp: 'https://t.me/c/1614195634/518?thread=509', link_telegram: '' }, { _id: 96, reg: 'PIE', prov: 'TO', descr: 'Torino', link_grp: 'https://t.me/c/1614195634/518?thread=509', link_telegram: '' },
{ _id: 97, reg: 'SAR', prov: 'OG', descr: 'Ogliastra', link_grp: '', link_telegram: '' },
{ _id: 98, reg: 'SIC', prov: 'TP', descr: 'Trapani', link_grp: 'https://t.me/c/1614195634/571?thread=561', link_telegram: '' }, { _id: 98, reg: 'SIC', prov: 'TP', descr: 'Trapani', link_grp: 'https://t.me/c/1614195634/571?thread=561', link_telegram: '' },
{ _id: 99, reg: 'TAA', prov: 'TN', descr: 'Trento', link_grp: 'https://t.me/c/1614195634/597?thread=595', link_telegram: '' }, { _id: 99, reg: 'TAA', prov: 'TN', descr: 'Trento', link_grp: 'https://t.me/c/1614195634/597?thread=595', link_telegram: '' },
{ _id: 100, reg: 'VEN', prov: 'TV', descr: 'Treviso', link_grp: 'https://t.me/c/1614195634/612?thread=602', link_telegram: '' }, { _id: 100, reg: 'VEN', prov: 'TV', descr: 'Treviso', link_grp: 'https://t.me/c/1614195634/612?thread=602', link_telegram: '' },
@@ -121,5 +117,6 @@ module.exports = {
{ _id: 119, reg: 'PUG', prov: 'VAL', descr: 'Valle D\'Itria', link_grp: 'https://t.me/progettoriso/7016?thread=7015', link_telegram: '' }, { _id: 119, reg: 'PUG', prov: 'VAL', descr: 'Valle D\'Itria', link_grp: 'https://t.me/progettoriso/7016?thread=7015', link_telegram: '' },
{ _id: 121, reg: 'ITA', prov: 'ITA', descr: 'Italia', link_grp: '', link_telegram: '' }, { _id: 121, reg: 'ITA', prov: 'ITA', descr: 'Italia', link_grp: '', link_telegram: '' },
{ _id: 122, reg: 'LOM', prov: 'MI', descr: 'Milano Est', card: 'EST', link_grp: '', link_telegram: '' }, { _id: 122, reg: 'LOM', prov: 'MI', descr: 'Milano Est', card: 'EST', link_grp: '', link_telegram: '' },
{ _id: 123, reg: 'SAR', prov: 'SU', descr: 'Sud Sardegna', link_grp: '', link_telegram: '' },
], ],
}; };

View File

@@ -354,13 +354,14 @@ router.post('/settable', authenticate, async (req, res) => {
try { try {
if (User.isAdmin(req.user.perm) || User.isManager(req.user.perm) || if (User.isAdmin(req.user.perm) || User.isManager(req.user.perm) ||
User.isEditor(req.user.perm) || User.isFacilitatore(req.user.perm)) { User.isEditor(req.user.perm) || User.isCommerciale(req.user.perm) || User.isFacilitatore(req.user.perm)) {
consentito = true; consentito = true;
} }
if ((!User.isAdmin(req.user.perm) if ((!User.isAdmin(req.user.perm)
&& !User.isManager(req.user.perm) && !User.isManager(req.user.perm)
&& !User.isEditor(req.user.perm) && !User.isEditor(req.user.perm)
&& !User.isCommerciale(req.user.perm)
&& !User.isGrafico(req.user.perm) && !User.isGrafico(req.user.perm)
&& !User.isFacilitatore(req.user.perm)) && !User.isFacilitatore(req.user.perm))
&& &&
@@ -1065,7 +1066,7 @@ async function importPage(req, idapp, jsonString) {
const table = globalTables.getTableByTableName(tableName); const table = globalTables.getTableByTableName(tableName);
if (tableName === 'mypages') { if (tableName === 'mypages') {
if (User.isEditor(req.user.perm)) { if (User.isEditor(req.user.perm) || User.isCommerciale(req.user.perm)) {
for (const page of myexp.mypages) { for (const page of myexp.mypages) {
const { ImportedRecords, newId } = await upsertRecord(table, page, idapp); const { ImportedRecords, newId } = await upsertRecord(table, page, idapp);
if (!newIdPage && newId) { if (!newIdPage && newId) {
@@ -1095,7 +1096,7 @@ async function importPage(req, idapp, jsonString) {
const table = globalTables.getTableByTableName(tableName); const table = globalTables.getTableByTableName(tableName);
if (tableName === 'myelems') { if (tableName === 'myelems') {
if (User.isEditor(req.user.perm)) { if (User.isEditor(req.user.perm) || User.isCommerciale(req.user.perm)) {
for (const elem of myexp.myelems) { for (const elem of myexp.myelems) {
const { ImportedRecords, newId } = await upsertRecord(table, elem, idapp, newIdPage); const { ImportedRecords, newId } = await upsertRecord(table, elem, idapp, newIdPage);
ImportedRecordstemp += ImportedRecords ? 1 : 0; ImportedRecordstemp += ImportedRecords ? 1 : 0;
@@ -1258,6 +1259,7 @@ router.patch('/chval', authenticate, async (req, res) => {
(!User.isAdmin(req.user.perm) (!User.isAdmin(req.user.perm)
&& !User.isManager(req.user.perm) && !User.isManager(req.user.perm)
&& !User.isEditor(req.user.perm) && !User.isEditor(req.user.perm)
&& !User.isCommerciale(req.user.perm)
&& !User.isFacilitatore(req.user.perm)) && !User.isFacilitatore(req.user.perm))
&& (await !tools.ModificheConsentite(req, mydata.table, fieldsvalue, id))) && (await !tools.ModificheConsentite(req, mydata.table, fieldsvalue, id)))
&& !((mydata.table === 'accounts') && !((mydata.table === 'accounts')
@@ -1620,7 +1622,7 @@ router.get('/copyfromapptoapp/:idapporig/:idappdest', async (req, res) => {
if (!idapporig || !idappdest || (idcode !== 'ASD3429Kjgà#@cvX')) if (!idapporig || !idappdest || (idcode !== 'ASD3429Kjgà#@cvX'))
res.status(400).send(); res.status(400).send();
const mytablesstr = ['settings', 'users', 'templemail']; const mytablesstr = ['settings', 'users', 'templemail', 'destnewsletter'];
try { try {
let numrectot = 0; let numrectot = 0;
@@ -1908,7 +1910,7 @@ async function measurePromises(promises) {
// Ordina le chiamate per tempo decrescente e prende le 10 più lente // Ordina le chiamate per tempo decrescente e prende le 10 più lente
const slowCalls = Object.entries(timings) const slowCalls = Object.entries(timings)
.sort(([, timeA], [, timeB]) => timeB - timeA) .sort(([, timeA], [, timeB]) => timeB - timeA)
.slice(0, 5) .slice(0, 10)
.map(([key, time]) => ({ key, time })); .map(([key, time]) => ({ key, time }));
return { data, totalTime, slowCalls }; return { data, totalTime, slowCalls };
@@ -2007,10 +2009,12 @@ async function load(req, res, version = '0') {
providers: version >= 91 ? Provider.findAllIdApp(idapp) : Promise.resolve([]), providers: version >= 91 ? Provider.findAllIdApp(idapp) : Promise.resolve([]),
scontisticas: version >= 91 ? Scontistica.findAllIdApp(idapp) : Promise.resolve([]), scontisticas: version >= 91 ? Scontistica.findAllIdApp(idapp) : Promise.resolve([]),
gasordines: version >= 91 ? Gasordine.findAllIdApp(idapp) : Promise.resolve([]), gasordines: version >= 91 ? Gasordine.findAllIdApp(idapp) : Promise.resolve([]),
products: version >= 91 /*products: version >= 91
? Product.findAllIdApp(idapp, undefined, undefined, req.user ? User.isManager(req.user.perm) : false) ? Product.findAllIdApp(idapp, undefined, undefined, req.user ? User.isManager(req.user.perm) : false)
: Promise.resolve([]), : Promise.resolve([]),*/
productInfos: version >= 91 ? ProductInfo.findAllIdApp(idapp) : Promise.resolve([]), products: Promise.resolve([]),
// productInfos: version >= 91 ? ProductInfo.findAllIdApp(idapp) : Promise.resolve([]),
productInfos: Promise.resolve([]),
catprods: version >= 91 ? Product.getArrCatProds(idapp, shared_consts.PROD.BOTTEGA) : Promise.resolve([]), catprods: version >= 91 ? Product.getArrCatProds(idapp, shared_consts.PROD.BOTTEGA) : Promise.resolve([]),
subcatprods: version >= 91 ? SubCatProd.findAllIdApp(idapp) : Promise.resolve([]), subcatprods: version >= 91 ? SubCatProd.findAllIdApp(idapp) : Promise.resolve([]),
catprods_gas: version >= 91 ? Product.getArrCatProds(idapp, shared_consts.PROD.GAS) : Promise.resolve([]), catprods_gas: version >= 91 ? Product.getArrCatProds(idapp, shared_consts.PROD.GAS) : Promise.resolve([]),
@@ -2040,8 +2044,8 @@ async function load(req, res, version = '0') {
const { data, totalTime, slowCalls } = await measurePromises(promises); const { data, totalTime, slowCalls } = await measurePromises(promises);
// console.log('Risultati delle promise:', data); // console.log('Risultati delle promise:', data);
// console.log('Tempo totale di esecuzione:', totalTime, 'secondi'); console.log('Tempo di esecuzione:', totalTime, 'secondi');
// console.log('Le 5 chiamate più lente:', slowCalls); //console.log('Le 10 chiamate più lente:', slowCalls);
// Aggiornamento delle informazioni dell'utente, se presente // Aggiornamento delle informazioni dell'utente, se presente
let myuser = req.user; let myuser = req.user;

View File

@@ -10,6 +10,7 @@ const { User } = require('../models/user');
const { MailingList } = require('../models/mailinglist'); const { MailingList } = require('../models/mailinglist');
const { Newstosent } = require('../models/newstosent'); const { Newstosent } = require('../models/newstosent');
const { TemplEmail } = require('../models/templemail'); const { TemplEmail } = require('../models/templemail');
const { DestNewsletter } = require('../models/destnewsletter');
const { OpzEmail } = require('../models/opzemail'); const { OpzEmail } = require('../models/opzemail');
const { Settings } = require('../models/settings'); const { Settings } = require('../models/settings');
@@ -254,12 +255,21 @@ router.post('/load', authenticate, async (req, res) => {
idapp = req.body.idapp; idapp = req.body.idapp;
locale = req.body.locale; locale = req.body.locale;
const ris = { let ris;
newsstate: await getDataNewsletter(locale, idapp),
serv_settings: await Settings.findAllIdApp(idapp, true, false), try {
templemail: await TemplEmail.findAllIdApp(idapp, true), ris = {
opzemail: await OpzEmail.findAllIdApp(idapp) newsstate: await getDataNewsletter(locale, idapp),
}; serv_settings: await Settings.findAllIdApp(idapp, true, false),
templemail: await TemplEmail.findAllIdApp(idapp, true),
destnewsletter: await DestNewsletter.findAllIdApp(idapp, true),
opzemail: await OpzEmail.findAllIdApp(idapp)
};
} catch (e) {
console.error('Errore load newsletter: ', e);
ris = { code: server_constants.RIS_CODE_ERR, msg: e.message };
}
return res.send(ris); return res.send(ris);
}); });
@@ -275,12 +285,19 @@ router.post('/setactivate', authenticate, async (req, res) => {
activate, activate,
}; };
return await Newstosent.findOneAndUpdate({ _id: id }, { $set: rec }, { new: false }).then((item) => { try {
const ris = getDataNewsletter(locale, idapp); const item = await Newstosent.findOneAndUpdate({ _id: id }, { $set: rec }, { new: false });
return res.send(ris); if (item) {
const ris = await getDataNewsletter(locale, idapp);
return res.send(ris);
} else {
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: 'Record not found' });
}
}); } catch (e) {
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e.message });
}
}); });
@@ -296,7 +313,7 @@ router.post('/unsubscribe_user', async (req, res) => {
if (myuser) { if (myuser) {
const hashcalc = tools.getHash(myuser.email + myuser.username); const hashcalc = tools.getHash(myuser.email + myuser.username);
if (hashcalc === hashemail) { if (hashcalc === hashemail) {
await User.setNewsletter(idapp, myuser.username, false); await User.setNewsletter(idapp, myuser.username, false);
return res.send({ return res.send({
@@ -329,28 +346,37 @@ router.post('/unsubscribe', (req, res) => {
console.log('Remove_from_MailingList -> ', ris); console.log('Remove_from_MailingList -> ', ris);
if (!!ris.myperson && mailchimpactive) { if (!!ris.myperson && mailchimpactive) {
const subscriber_md5_email = tools.getmd5(ris.myperson.email); try {
request const subscriber_md5_email = tools.getmd5(ris.myperson.email);
.put('https://' + newsletter[idapp].mailchimpInstance + '.api.mailchimp.com/3.0/lists/' + newsletter[idapp].listUniqueId + '/members/' + subscriber_md5_email) request
.set('Content-Type', 'application/json;charset=utf-8') .put('https://' + newsletter[idapp].mailchimpInstance + '.api.mailchimp.com/3.0/lists/' + newsletter[idapp].listUniqueId + '/members/' + subscriber_md5_email)
.set('Authorization', 'Basic ' + new Buffer('any:' + newsletter[idapp].mailchimpApiKey).toString('base64')) .set('Content-Type', 'application/json;charset=utf-8')
.send({ .set('Authorization', 'Basic ' + new Buffer('any:' + newsletter[idapp].mailchimpApiKey).toString('base64'))
'email_address': ris.myperson.email, .send({
'status': server_constants.RIS_UNSUBSCRIBED_STR 'email_address': ris.myperson.email,
}) 'status': server_constants.RIS_UNSUBSCRIBED_STR
.end(function (err, response) { })
console.log("STAT", response.status); .end(function (err, response) {
console.log("STAT", response.status);
if (response.status < 300 || (response.status === 400 && response.body.title === "Member Exists")) { if (response.status < 300 || (response.status === 400 && response.body.title === "Member Exists")) {
res.send({ res.send({
code: server_constants.RIS_UNSUBSCRIBED_OK code: server_constants.RIS_UNSUBSCRIBED_OK
}); });
} else { } else {
res.send({ res.send({
code: server_constants.RIS_SUBSCRIBED_ERR code: server_constants.RIS_SUBSCRIBED_ERR
}); });
} }
});
} catch (e) {
console.error('Errore unsubscribe -> ', e);
res.send({
code: server_constants.RIS_SUBSCRIBED_ERR,
msg: e.message
}); });
}
} else { } else {
res.send({ code: ris.code, msg: ris.msg }); res.send({ code: ris.code, msg: ris.msg });

View File

@@ -54,6 +54,7 @@ const { Account } = require('../models/account');
const mongoose = require('mongoose').set('debug', false); const mongoose = require('mongoose').set('debug', false);
const Subscription = require('../models/subscribers'); const Subscription = require('../models/subscribers');
const Macro = require('../modules/Macro');
async function existSubScribe(userId, access, browser) { async function existSubScribe(userId, access, browser) {
try { try {
@@ -1074,6 +1075,17 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) {
await CatProd.deleteMany({ idapp }); await CatProd.deleteMany({ idapp });
await SubCatProd.deleteMany({ idapp }); await SubCatProd.deleteMany({ idapp });
} else if (mydata.dbop === 'removeProductInfoWithoutDateUpdatedFromGM') {
mystr = await ProductInfo.removeProductInfoWithoutDateUpdatedFromGM(idapp);
ris = { mystr };
} else if (mydata.dbop === 'StatMacro') {
const macro = new Macro(idapp, {});
mystr = await macro.getStat();
ris = { mystr };
} else if (mydata.dbop === 'updateAllBook') { } else if (mydata.dbop === 'updateAllBook') {
// chiama updateAllBook // chiama updateAllBook
const { updateAllBook } = require("../controllers/articleController"); const { updateAllBook } = require("../controllers/articleController");
@@ -1203,6 +1215,7 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) {
'settings', 'settings',
'users', 'users',
'templemail', 'templemail',
'destnewsletter',
'contribtypes', 'contribtypes',
'bots', 'bots',
'cfgservers']; 'cfgservers'];
@@ -1255,6 +1268,9 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) {
} else if (mydata.dbop === 'listCollectionsBySize') { } else if (mydata.dbop === 'listCollectionsBySize') {
mystr = await tools.listCollectionsBySize(); mystr = await tools.listCollectionsBySize();
ris = { mystr }; ris = { mystr };
} else if (mydata.dbop === 'EnableNewsOn_ToAll') {
mystr = await User.setNewsletterToAll(idapp);
} else if (mydata.dbop === 'MyElemSetIdPageInsteadThePah') { } else if (mydata.dbop === 'MyElemSetIdPageInsteadThePah') {
mystr = await MyElem.SetIdPageInsteadThePah(idapp); mystr = await MyElem.SetIdPageInsteadThePah(idapp);
ris = { mystr }; ris = { mystr };

View File

@@ -12,6 +12,7 @@ const i18n = require('i18n');
const { ObjectId } = require('mongodb'); const { ObjectId } = require('mongodb');
const { Settings } = require('./models/settings'); const { Settings } = require('./models/settings');
const { TemplEmail } = require('./models/templemail'); const { TemplEmail } = require('./models/templemail');
const { DestNewsletter } = require('./models/destnewsletter');
const { Discipline } = require('./models/discipline'); const { Discipline } = require('./models/discipline');
const previewEmail = require('preview-email'); const previewEmail = require('preview-email');
@@ -57,7 +58,7 @@ module.exports = {
if (to === '') if (to === '')
return false; return false;
// console.log('mylocalsconf', mylocalsconf); // console.log('mylocalsconf', mylocalsconf);
// console.log("check EMAIL :" + checkifSendEmail()); // console.log("check EMAIL :" + checkifSendEmail());
@@ -166,7 +167,7 @@ module.exports = {
else else
transport_preview.sendMail(mailOptions).then(console.log).catch(console.error); transport_preview.sendMail(mailOptions).then(console.log).catch(console.error);
} }
} catch (e) { } catch (e) {
console.error('Errore Sendmail', e); console.error('Errore Sendmail', e);
} }
@@ -679,12 +680,20 @@ module.exports = {
replacefields: function (mylocalsconf) { replacefields: function (mylocalsconf) {
try { try {
mylocalsconf.dataemail.disclaimer_out = !!mylocalsconf.dataemail.disclaimer ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.disclaimer_out = !!mylocalsconf.dataemail.disclaimer ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.disclaimer) : '';
mylocalsconf.dataemail.disclaimer) : ''; mylocalsconf.dataemail.disc_bottom_out = !!mylocalsconf.dataemail.disc_bottom ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.disc_bottom) : '';
mylocalsconf.dataemail.disc_bottom_out = !!mylocalsconf.dataemail.disc_bottom ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.firma = !!mylocalsconf.dataemail.firma ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.firma) : '';
mylocalsconf.dataemail.disc_bottom) : '';
if (mylocalsconf.dataemail.templ) { if (mylocalsconf.dataemail.templ) {
if (mylocalsconf.dataemail.templ.disclaimer)
mylocalsconf.dataemail.disclaimer_out = this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.templ.disclaimer);
if (mylocalsconf.dataemail.templ.piedipagina)
mylocalsconf.dataemail.disc_bottom_out = this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.templ.piedipagina);
if (mylocalsconf.dataemail.templ.firma)
mylocalsconf.dataemail.firma = this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.templ.firma);
mylocalsconf.dataemail.templ.testoheadermail_out = !!mylocalsconf.dataemail.templ.testoheadermail ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.templ.testoheadermail_out = !!mylocalsconf.dataemail.templ.testoheadermail ? this.fieldsloop(mylocalsconf,
mylocalsconf.dataemail.templ.testoheadermail) : ''; mylocalsconf.dataemail.templ.testoheadermail) : '';
@@ -701,37 +710,47 @@ module.exports = {
getdataemail: async (idapp, templemail_id) => { getdataemail: async (idapp, templemail_id) => {
const pwd_from = await Settings.getValDbSettings(idapp, 'PWD_FROM'); try {
// console.log('getdataemail'); const pwd_from = await Settings.getValDbSettings(idapp, 'PWD_FROM');
const mydata = {
content_after_events: await Settings.getValDbSettings(idapp, 'TEXT_AFTER_EV'),
mailchimpactive: tools.BoolToInt(await Settings.getValDbSettings(idapp, 'MAILCHIMP_ON')),
urltwitter: await Settings.getValDbSettings(idapp, 'URL_TWITTER'),
urlfb: await Settings.getValDbSettings(idapp, 'URL_FACEBOOK'),
urlyoutube: await Settings.getValDbSettings(idapp, 'URL_YOUTUBE'),
urlinstagram: await Settings.getValDbSettings(idapp, 'URL_INSTAGRAM'),
textpromo: await Settings.getValDbSettings(idapp, 'TEXT_PROMO'),
disclaimer: await Settings.getValDbSettings(idapp, 'TEXT_DISCLAIMER'),
disc_bottom: await Settings.getValDbSettings(idapp, 'TEXT_DISC_BOTTOM'),
firma: await Settings.getValDbSettings(idapp, 'TEXT_SIGN'),
arrdiscipline: await Discipline.getDisciplineforNewsletter(idapp), let mydata = {
disc_title: await Settings.getValDbSettings(idapp, 'DISC_TITLE'), templemail_id: templemail_id ? templemail_id : await Settings.getValDbSettings(idapp, 'TEMPLEMAIL_ID'),
height_logo: await Settings.getValDbSettings(idapp, 'HEIGHT_LOGO'), destnewsletter_id: await Settings.getValDbSettings(idapp, 'TEMPLEMAIL_DEST'),
from: await Settings.getValDbSettings(idapp, 'EMAIL_FROM'), };
email_reply: await Settings.getValDbSettings(idapp, 'EMAIL_REPLY', ''),
pwd_from: pwd_from,
email_service: await Settings.getValDbSettings(idapp, 'EMAIL_SERVICE_SEND'),
email_port: await Settings.getValDbSettings(idapp, 'EMAIL_PORT'),
templemail_id: templemail_id ? templemail_id : await Settings.getValDbSettings(idapp, 'TEMPLEMAIL_ID'),
};
// console.log(mydata.templemail_id); mydata.templ = await TemplEmail.findOne({ _id: mydata.templemail_id }).lean();
mydata.templ = await TemplEmail.findOne({ _id: mydata.templemail_id }); mydata.destnewsl = await DestNewsletter.findOne({ _id: mydata.destnewsletter_id }).lean();
// console.log(mydata.templ);
// console.log('getdataemail');
mydata = {
...mydata,
content_after_events: await Settings.getValDbSettings(idapp, 'TEXT_AFTER_EV'),
mailchimpactive: tools.BoolToInt(await Settings.getValDbSettings(idapp, 'MAILCHIMP_ON')),
urltwitter: await Settings.getValDbSettings(idapp, 'URL_TWITTER'),
urlfb: await Settings.getValDbSettings(idapp, 'URL_FACEBOOK'),
urlyoutube: await Settings.getValDbSettings(idapp, 'URL_YOUTUBE'),
urlinstagram: await Settings.getValDbSettings(idapp, 'URL_INSTAGRAM'),
textpromo: await Settings.getValDbSettings(idapp, 'TEXT_PROMO'),
disc_bottom: await Settings.getValDbSettings(idapp, 'TEXT_DISC_BOTTOM'),
arrdiscipline: await Discipline.getDisciplineforNewsletter(idapp),
disc_title: await Settings.getValDbSettings(idapp, 'DISC_TITLE'),
height_logo: await Settings.getValDbSettings(idapp, 'HEIGHT_LOGO'),
from: await Settings.getValDbSettings(idapp, 'EMAIL_FROM'),
email_reply: await Settings.getValDbSettings(idapp, 'EMAIL_REPLY', ''),
pwd_from: pwd_from,
email_service: await Settings.getValDbSettings(idapp, 'EMAIL_SERVICE_SEND'),
email_port: await Settings.getValDbSettings(idapp, 'EMAIL_PORT'),
};
return mydata;
} catch (e) {
console.error('Error getdataemail: ' + e);
return null;
}
return mydata;
}, },
getTransport: (mylocalsconf) => { getTransport: (mylocalsconf) => {
@@ -888,9 +907,6 @@ module.exports = {
await telegrambot.sendMsgTelegramToTheManagers(idapp, msginizio); await telegrambot.sendMsgTelegramToTheManagers(idapp, msginizio);
//++Todo Extract List Email to send
const userstosend = await MailingList.findAllIdAppSubscribed(idapp);
const myarrevents = await MyEvent.getLastEvents(idapp); const myarrevents = await MyEvent.getLastEvents(idapp);
let mylocalsconf = { let mylocalsconf = {
@@ -908,8 +924,24 @@ module.exports = {
const mynewsrec = await Newstosent.findOne({ _id: id_newstosent }); const mynewsrec = await Newstosent.findOne({ _id: id_newstosent });
try { try {
mynewsrec.numemail_tot = userstosend.length;
mynewsrec.templemail_str = mylocalsconf.dataemail.templ.subject; mynewsrec.templemail_str = mylocalsconf.dataemail.templ.subject;
mynewsrec.destnewsletter_str = mylocalsconf.dataemail.destnewsl?.descr;
let userstosend = [];
if (mylocalsconf.dataemail.destnewsl?.tipodest_id === shared_consts.DESTNEWSLETTER.UTENTI) {
userstosend = await MailingList.findAllIdAppSubscribed(idapp);
} else if (mylocalsconf.dataemail.destnewsl?.tipodest_id === shared_consts.DESTNEWSLETTER.DIARIO) {
userstosend = await MailingList.findAllIdAppDiarioSubscr(idapp);
} else if (mylocalsconf.dataemail.destnewsl?.tipodest_id === shared_consts.DESTNEWSLETTER.TEST) {
userstosend = await MailingList.findAllIdAppTestSubscr(idapp);
} else {
userstosend = await MailingList.findAllIdAppSubscribed(idapp);
}
mynewsrec.numemail_tot = userstosend.length;
mynewsrec.numemail_sent = await MailingList.getnumSent(idapp, id_newstosent); mynewsrec.numemail_sent = await MailingList.getnumSent(idapp, id_newstosent);
const smtpTransport = this.getTransport(mylocalsconf); const smtpTransport = this.getTransport(mylocalsconf);
@@ -990,6 +1022,8 @@ module.exports = {
} catch (e) { } catch (e) {
console.error('*** Errore su sendEmail_Newsletter: ! ', e.message);
const activate = await Newstosent.isActivated(id_newstosent); const activate = await Newstosent.isActivated(id_newstosent);
if (!activate) { if (!activate) {

View File

@@ -537,6 +537,11 @@ class ImageDownloader {
fs.unlinkSync(filepath); fs.unlinkSync(filepath);
} }
// se in error.message c'è '404' allora esci e ritorna code: 404
if (error.message.includes('404')) {
return { ris: false, code: 404 };
}
if (attempt === maxRetries) { if (attempt === maxRetries) {
console.error(`Download fallito dopo ${maxRetries} tentativi: ${error.message}`); console.error(`Download fallito dopo ${maxRetries} tentativi: ${error.message}`);
return { ris: false }; return { ris: false };
@@ -6109,28 +6114,30 @@ module.exports = {
async downloadImgIfMissing(productInfo) { async downloadImgIfMissing(productInfo) {
const ProductInfo = require('../models/productInfo');
try { try {
if (this.sulServer()) { if (this.sulServer()) {
dirmain = ''; dirmain = '';
} else { } else {
dirmain = server_constants.DIR_PUBLIC_LOCALE; dirmain = server_constants.DIR_PUBLIC_LOCALE;
} }
const vecchiomodo = false; const vecchiomodo = false;
if (productInfo.image_link && vecchiomodo) { if (productInfo.image_link && vecchiomodo) {
const relativeimg = productInfo.image_link.split('/').pop(); const relativeimg = productInfo.image_link.split('/').pop();
const img = this.getdirByIdApp(productInfo.idapp) + dirmain + const img = this.getdirByIdApp(productInfo.idapp) + dirmain +
server_constants.DIR_UPLOAD + '/products/' + productInfo.image_link.split('/').pop(); server_constants.DIR_UPLOAD + '/products/' + productInfo.image_link.split('/').pop();
const savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine const savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine
let scaricaimg = !productInfo.imagefile || !fs.existsSync(savePath); let scaricaimg = !productInfo.imagefile || !fs.existsSync(savePath);
if (!productInfo.imagefile && fs.existsSync(savePath)) { if (!productInfo.imagefile && fs.existsSync(savePath)) {
// esiste il file, ma sul DB non è corretto // esiste il file, ma sul DB non è corretto
const stats = fs.statSync(savePath); // Ottieni informazioni sul file const stats = fs.statSync(savePath); // Ottieni informazioni sul file
if (stats.size > 0) { // Controlla se la dimensione del file è maggiore di zero if (stats.size > 0) { // Controlla se la dimensione del file è maggiore di zero
// Esiste il file ed è non vuoto, ma sul DB non è corretto // Esiste il file ed è non vuoto, ma sul DB non è corretto
productInfo.imagefile = relativeimg; productInfo.imagefile = relativeimg;
@@ -6139,23 +6146,24 @@ module.exports = {
scaricaimg = true; scaricaimg = true;
} }
} }
if (productInfo.imagefile && fs.existsSync(savePath)) { if (productInfo.imagefile && fs.existsSync(savePath)) {
// esiste il file, ma sul DB non è corretto // esiste il file, ma sul DB non è corretto
const stats = fs.statSync(savePath); // Ottieni informazioni sul file const stats = fs.statSync(savePath); // Ottieni informazioni sul file
if (stats.size <= 0) { // Controlla se la dimensione del file è maggiore di zero if (stats.size <= 0) { // Controlla se la dimensione del file è maggiore di zero
scaricaimg = true; scaricaimg = true;
} }
} }
if (scaricaimg && vecchiomodo) { if (scaricaimg && vecchiomodo) {
// Download image from the URL productInfo.image_link // Download image from the URL productInfo.image_link
productInfo.imagefile = relativeimg; productInfo.imagefile = relativeimg;
const downloader = new ImageDownloader(); const downloader = new ImageDownloader();
const aggiornatoimg = await downloader.downloadImage(productInfo.image_link, savePath, const aggiornatoimg = await downloader.downloadImage(productInfo.image_link, savePath,
{ {
maxRetries: 1, maxRetries: 1,
@@ -6167,80 +6175,82 @@ module.exports = {
} else { } else {
console.log('Download non riuscito.'); console.log('Download non riuscito.');
} }
return result; return result;
}); });
return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris }; return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris };
} }
} }
let fileesistente = false; let fileesistente = false;
if (productInfo.imagefile) { if (productInfo.imagefile) {
// controlla se esiste il file // controlla se esiste il file
const img = this.getdirByIdApp(productInfo.idapp) + dirmain + const img = this.getdirByIdApp(productInfo.idapp) + dirmain +
server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop(); server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop();
const filecompleto = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine const filecompleto = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine
// Se non esiste lo scarico ! // Se non esiste lo scarico !
fileesistente = fs.existsSync(filecompleto); fileesistente = fs.existsSync(filecompleto);
} }
if (!vecchiomodo && (!productInfo.image_link || !fileesistente)) { if (!vecchiomodo && (!productInfo.image_link || !fileesistente)) {
let scarica_da_sito = !productInfo.imagefile; let scarica_da_sito = !productInfo.imagefile;
if (!scarica_da_sito && productInfo.imagefile) { if (!scarica_da_sito && productInfo.imagefile) {
scarica_da_sito = !fileesistente; // Se non esiste lo scarico ! scarica_da_sito = !fileesistente; // Se non esiste lo scarico !
} }
if (scarica_da_sito) { if (scarica_da_sito && !productInfo.image_not_found) {
// date and time // date and time
productInfo.imagefile = 'img_' + new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''); productInfo.imagefile = 'img_' + new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
const img = this.getdirByIdApp(productInfo.idapp) + dirmain + const img = this.getdirByIdApp(productInfo.idapp) + dirmain +
server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop(); server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop();
let savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine let savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine
let link = 'https://www.gruppomacro.com/copertine.php?id_gm=' + productInfo.sku let link = 'https://www.gruppomacro.com/copertine.php?id_gm=' + productInfo.sku
const downloader = new ImageDownloader(); const downloader = new ImageDownloader();
const aggiornatoimg = await downloader.downloadImage(link, savePath, let aggiornatoimg;
{ try {
maxRetries: 1, aggiornatoimg = await downloader.downloadImage(link, savePath,
initialDelay: 300, {
timeout: 15000, maxRetries: 1,
nomefileoriginale: true, initialDelay: 300,
}).then(result => { timeout: 15000,
if (result) { nomefileoriginale: true,
// console.log('Download completato con successo!'); });
} else { } catch (e) {
console.log('Download non riuscito.'); aggiornatoimg = { ris: false };
} }
if (aggiornatoimg?.code === 404) {
return result; // non trovato quindi la prossima volta non richiederlo
await ProductInfo.setImgNotFound(productInfo._id);
}); }
if (aggiornatoimg.filepath) {
if (aggiornatoimg?.filepath) {
const filenamebase = path.basename(aggiornatoimg.filepath); const filenamebase = path.basename(aggiornatoimg.filepath);
// const img = '/upload/products/' + filenamebase; // const img = '/upload/products/' + filenamebase;
productInfo.imagefile = filenamebase; productInfo.imagefile = filenamebase;
} }
return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris }; return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris };
} else { } else {
return { prodInfo: null, aggiornatoimg: false }; return { prodInfo: null, aggiornatoimg: false };
} }
} }
} catch (e) { } catch (e) {
console.error('downloadImgIfMissing', e.message); console.error('downloadImgIfMissing', e.message);
} }
return { prodInfo: null, aggiornatoimg: false }; return { prodInfo: null, aggiornatoimg: false };
}, },
removeAccents(mystr) { removeAccents(mystr) {
@@ -6257,7 +6267,7 @@ module.exports = {
return Array.from(mystr).map(char => accentsMap.get(char) || char).join(''); return Array.from(mystr).map(char => accentsMap.get(char) || char).join('');
}, },

View File

@@ -53,6 +53,7 @@ const { CfgServer } = require('../models/cfgserver');
const { CalZoom } = require('../models/calzoom'); const { CalZoom } = require('../models/calzoom');
const { Gallery } = require('../models/gallery'); const { Gallery } = require('../models/gallery');
const { TemplEmail } = require('../models/templemail'); const { TemplEmail } = require('../models/templemail');
const { DestNewsletter } = require('../models/destnewsletter');
const { OpzEmail } = require('../models/opzemail'); const { OpzEmail } = require('../models/opzemail');
const { MailingList } = require('../models/mailinglist'); const { MailingList } = require('../models/mailinglist');
const { Settings } = require('../models/settings'); const { Settings } = require('../models/settings');
@@ -207,6 +208,8 @@ module.exports = {
mytable = CalZoom; mytable = CalZoom;
else if (tablename === 'templemail') else if (tablename === 'templemail')
mytable = TemplEmail; mytable = TemplEmail;
else if (tablename === 'destnewsletter')
mytable = DestNewsletter;
else if (tablename === 'opzemail') else if (tablename === 'opzemail')
mytable = OpzEmail; mytable = OpzEmail;
else if (tablename === 'settings') else if (tablename === 'settings')

View File

@@ -359,6 +359,7 @@ module.exports = {
Zoomeri: 32, Zoomeri: 32,
Department: 64, Department: 64,
Grafico: 128, Grafico: 128,
Commerciale: 256,
}, },
MessageOptions: { MessageOptions: {
@@ -730,6 +731,8 @@ module.exports = {
'profile', 'profile',
'calcstat', 'calcstat',
'news_on', 'news_on',
'diario_on',
'test',
'aportador_solidario', 'aportador_solidario',
'made_gift', 'made_gift',
'ind_order', 'ind_order',
@@ -1195,6 +1198,26 @@ module.exports = {
EXCEED_QTAMAX: 20, EXCEED_QTAMAX: 20,
}, },
DESTNEWSLETTER: {
LISTA_NEWSLETTER: 0,
UTENTI: 1,
DIARIO: 2,
TEST: 10,
},
STATUS_JOB: {
NONE: 0,
START: 1,
FINISH: 10,
PAUSE: 2,
},
TERMINATED_WHY: {
END_NORMALLY: 1,
END_WITHERROR: -50,
TOOLONGTIME: -10,
}
// Download, DVD, Epub, Mobi, Nuovo, PDF, Streaming, Usato // Download, DVD, Epub, Mobi, Nuovo, PDF, Streaming, Usato
}; };

View File

@@ -1 +1 @@
1.2.35 1.2.37