- 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_PASSWORD=passpao1pabox@1A
DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7"
API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK"
SERVER_A_URL="http://51.77.156.69:3000"
API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK"

View File

@@ -18,232 +18,270 @@
- var baseimg = baseurl + '/'
doctype html
html
- if (dataemail.title)
head
title dataemail.subject
//- import css/scss stylesheets
//- these file names will be replace by gulp with proper css file paths
link(rel="stylesheet", href="../sass/basic.scss")
link(rel="stylesheet", href="../sass/one/styles.scss")
//- embdedded css allowed, but not sass
meta(charset="utf-8")
meta(name="viewport", content="width=device-width, initial-scale=1")
title= dataemail.title || "Email"
style.
.red {
background-color: #E84C50;
/* 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; }
.logoContainer { text-align:center; padding:20px 0; }
.logoContainer img { max-width:200px; }
.testomail { padding:10px; font-size:0.75rem; line-height:1.4; }
.clpromo {
background-color:orange;
text-align:center;
font-size:1rem;
padding:10px;
color:#fff;
font-weight:bold;
}
.full-width {
width: 100%;
.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)
span(id='body_style', style='display:block')
table(class="topHeader", cellpadding="0", cellspacing="0", width="100%")
- if (dataemail.height_logo)
tr
td
table(cellpadding="0", cellspacing="0", align="center", summary="")
span#body_style(style='display:block')
// Header
table(width="100%", cellpadding="0", cellspacing="0", align="center")
tr
td.logoContainer
a(href=baseurl, title='logo')
img.logo(src=baseurl+"/images/logo.png", height=dataemail.height_logo)
a(href=baseurl)
img.logo(src=baseurl+"/public/images/logo.png", alt="Logo")
if dataemail.templ.testoheadermail_out
tr
td.testomail
p!= dataemail.templ.testoheadermail_out
- if (dataemail.templ.options.includes('SHOW_PROMO'))
if dataemail.templ.options.includes('SHOW_PROMO')
tr
td.clpromo
p!= dataemail.textpromo
- if (dataemail.templ.content)
table(cellpadding="0", cellspacing="0", width="95%", align="center")
// Main Content
if dataemail.templ.content
tr
td(class="textIniContainer", valign="top")
td.emailContainer
p!=dataemail.templ.content
- if (dataemail.templ.img)
img(src=baseimg + dataemail.templ.img, alt="", class="myimg")
- if (dataemail.templ.content2)
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, 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")
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
- 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
td(class="column sectionArticleImage", valign="top")
table(cellpadding="0", cellspacing="0", summary="", border="0")
- if (event.news)
td.emailContainer
table(width="100%", cellpadding="0", cellspacing="0")
tr
td
p(class="q-chip row inline no-wrap items-center cltexth5 chipnews shadow-5 glossy text-right bg-red text-white") Novità
td.column.sectionArticleImage(width="150")
if event.news
p.q-chip.bg-red.text-white Novità
img(src=baseimg + (event.img_small || event.img), alt=event.title)
p.teacher= event.op1[0].name + ' ' + event.op1[0].surname
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
td
img(src=baseimg + imgev, alt="", width="150")
p(class="teacher") #{teacher1} <br> #{teacher2} #{teacher3} #{teacher4}
td(class="column", valign="top")
table(cellpadding="0", cellspacing="0", summary="", border="0")
tr
td(class="sectionContentTitle boldhigh", valign="top")
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
td.button
a(href=baseurl + '/event/' + event.typol + '?eventid=' + event._id, target="_blank") Apri l'Evento
tr
table(cellpadding="0", cellspacing="0", summary="", border="0", align="center", class="")
tr
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;
td.center_img
a.button2(href=urlcal, target="_blank") Calendario Eventi
- if (dataemail.templ.options.includes('SHOW_DISC'))
// Disciplines
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")
td.center
h2.cltitle_disc= dataemail.disc_title
each disc in dataemail.arrdiscipline
- var urldisc = baseurl + disc.linkpage
- var imgdisc = disc.img_small
unless (imgdisc)
- imgdisc = disc.img
tr
td.discContainer
table(width="100%", cellpadding="0", cellspacing="0")
tr
td.column.sectionArticleImage(width="150")
img(src=baseimg + (disc.img_small || disc.img), alt=disc.label)
td.column
p.LinkDisc
a(href=baseurl + disc.linkpage, target="_blank")
span.pDisc(style=`background-color:`+disc.color)= disc.label
p.sectionContent!= disc.description
table(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center")
tr
td(class="column sectionArticleImage", valign="top")
table(cellpadding="0", cellspacing="0", summary="", border="0")
tr
td
img(src=baseimg + imgdisc, alt="", width="150")
td(class="column", valign="top")
table(cellpadding="0", cellspacing="0", summary="", border="0")
tr
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
table(cellpadding="0", cellspacing="0", summary="", border="0")
// Additional Content
if dataemail.content_after_events
tr
td.testomail
p!=dataemail.content_after_events
tr
td(class="whitespace", height="20")
p &nbsp;
// Social Media
table.socialMedia(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center")
tr
td(class="whitespace", height="5")
p &nbsp;
tr
td.socialMedia
table(width="120", align="center", cellpadding="0", cellspacing="0")
if dataemail.urlinstagram
td
table(width="120", cellpadding="0", cellspacing="0", summary="", border="0", align="center")
tr
- if (dataemail.urlinstagram)
td(width="32", align="center")
a(href=dataemail.urlinstagram, title='Instagram')
img(src=imginstagram, alt="Instagram", width="29")
- if (dataemail.urltwitter)
td(width="32", align="center")
a(href=dataemail.urltwitter, title='Twitter')
img(src=imgtwitter, alt="Twitter", width="29")
- if (dataemail.urlfb)
td(width="32", align="center")
a(href=dataemail.urlfb, title='Facebook')
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;
a(href=dataemail.urlinstagram)
img(src=imginstagram, alt="Instagram")
if dataemail.urltwitter
td
a(href=dataemail.urltwitter)
img(src=imgtwitter, alt="Twitter")
if dataemail.urlfb
td
a(href=dataemail.urlfb)
img(src=imgfb, alt="Facebook")
if dataemail.urlyoutube
td
a(href=dataemail.urlyoutube)
img(src=imgyoutube, alt="YouTube")
// Footer
table.footer(cellpadding="0", cellspacing="0", width="100%", summary="", border="0", align="center")
tr
td(class="whitespace", height="10")
p &nbsp;
tr
td.firma
td.firma-container
p!= dataemail.firma
tr
td.disclaimer
td.disclaimer-container
p!= dataemail.disclaimer_out
tr
td.bottom
td.bottom-container
p!= dataemail.disc_bottom_out
tr
td(class="whitespace", height="10")
p &nbsp;

View File

@@ -887,22 +887,34 @@ exports.mssqlmigrateTables = async (req) => {
try {
const options = req.body.mydata.options;
let listaTabelle = [];
if (options?.tutte) {
// const listaTabelle = ['T_WEB_StatiProdotto'];
listaTabelle = ['T_WEB_TitoliOriginali', 'T_WEB_TestateOrdini', 'T_WEB_Ordini', 'T_WEB_Disponibile', 'T_WOO_TestateOrdini', 'T_WOO_Ordini', 'T_WEB_Articoli',
'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',
'T_WEB_Edizioni', 'T_WEB_Contratti'];
} else if (options?.parte1) {
listaTabelle = ['T_WEB_TitoliOriginali', 'T_WEB_TestateOrdini', 'T_WEB_Ordini', 'T_WOO_TestateOrdini', 'T_WOO_Ordini', 'T_WEB_Articoli'];
} else if (options?.parte2) {
listaTabelle = ['T_WEB_Disponibile', 'T_WEB_Argomenti', 'T_WEB_ClientiInternet', 'T_WOO_Clienti', 'T_WEB_Autori'];
} else if (options?.parte3) {
listaTabelle = ['T_WEB_Collane', 'T_WEB_MarchiEditoriali', 'T_WEB_StatiProdotto', 'T_WEB_TipiFormato', 'T_WEB_Tipologie', 'T_WEB_ArticoliFatturati', 'T_WEB_IdInternetFatturati',
'T_WEB_Edizioni', 'T_WEB_Contratti'];
} else {
listaTabelle = ['T_WEB_Articoli'];
if (options?.parte1 || options?.tutte) {
listaTabelle.push({ table: 'T_WEB_TitoliOriginali', usaDataOra: true, fieldId: 'IdTitoloOriginale' });
listaTabelle.push({ table: 'T_WEB_TestateOrdini', usaDataOra: false });
listaTabelle.push({ table: 'T_WEB_Ordini', usaDataOra: false });
listaTabelle.push({ table: 'T_WOO_TestateOrdini', usaDataOra: false });
listaTabelle.push({ table: 'T_WOO_Ordini', usaDataOra: false });
listaTabelle.push({ table: 'T_WEB_Articoli', usaDataOra: true, fieldId: 'IdArticolo' });
}
if (options?.parte2 || options?.tutte) {
listaTabelle.push({ table: 'T_WEB_Disponibile', usaDataOra: true, fieldId: 'Codice' });
listaTabelle.push({ table: 'T_WEB_Argomenti', usaDataOra: true, fieldId: 'IdArgomento' });
listaTabelle.push({ table: 'T_WEB_ClientiInternet', usaDataOra: false });
listaTabelle.push({ table: 'T_WOO_Clienti', usaDataOra: false });
listaTabelle.push({ table: 'T_WEB_Autori', usaDataOra: true, fieldId: 'IdAutore' });
}
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();

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,6 +26,7 @@ const CatalogSchema = new Schema({
},
title: {
type: String,
index: true,
},
foto_collana: IImg,
@@ -93,6 +94,7 @@ const CatalogSchema = new Schema({
type: Schema.Types.ObjectId,
ref: 'Product',
}],
isCatalogoGenerale: Boolean,
});
/*
@@ -143,6 +145,7 @@ CatalogSchema.statics.executeQueryTable = function (idapp, params, user) {
CatalogSchema.statics.findAllIdApp = async function (idapp) {
const Catalog = this;
try {
let arrrec = await Catalog.find({ idapp })
.sort({ title: 1 }) // Ordina i risultati per titolo
/*.populate({
@@ -207,6 +210,15 @@ CatalogSchema.statics.findAllIdApp = async function (idapp) {
})
;
// controlla prima se nella lista ci sono dei product che non esistono piu allora li devi rimuovere !
for (const catalog of arrrec) {
const originalLength = catalog.lista_prodotti.length;
catalog.lista_prodotti = catalog.lista_prodotti.filter(product => product.idProductInfo);
if (catalog.lista_prodotti.length !== originalLength) {
await catalog.save();
}
}
const transformedArrRec = arrrec.map(catalog => ({
...catalog.toObject(), // Converte il documento Mongoose in un oggetto JavaScript puro
lista_prodotti: catalog.lista_prodotti.map(product => ({
@@ -226,6 +238,9 @@ CatalogSchema.statics.findAllIdApp = async function (idapp) {
}));
return transformedArrRec;
} catch (err) {
console.error('Errore: ', err);
}
};
const Catalog = mongoose.model('Catalog', CatalogSchema);

View File

@@ -21,6 +21,7 @@ const CatProdSchema = new Schema({
},
name: {
type: String,
index: 1,
},
descr_estesa: {
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 {
const myquery = [
@@ -151,12 +152,14 @@ CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp) {
const result = await CatProd.aggregate(myquery);
if (updatedata) {
for (const record of result) {
await CatProd.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
}
}
return result;
} catch (error) {

View File

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

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);
};
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) {
const myfind = { idapp, news_on: true, lastid_newstosent: idUser };

View File

@@ -22,6 +22,9 @@ const NewstosentSchema = new Schema({
templemail_str: {
type: String,
},
destnewsletter_str: {
type: String,
},
activate: {
type: Boolean,
default: false
@@ -121,7 +124,10 @@ NewstosentSchema.statics.findNewsletterPending_To_Send = function (idapp) {
starting_job: true,
finish_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
}).lean();
};

View File

@@ -22,9 +22,9 @@ const orderSchema = new Schema({
},
userId: { type: Schema.Types.ObjectId, ref: 'User' },
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' },
idStorehouse: { type: Schema.Types.ObjectId, ref: 'StoreHouse' },
idScontisticas: [{ type: Schema.Types.ObjectId, ref: 'Scontistica' }],
@@ -125,7 +125,8 @@ const orderSchema = new Schema({
type: String
},
modify_at: {
type: Date
type: Date,
index: true
},
});

View File

@@ -36,16 +36,16 @@ const productSchema = new Schema({
isbn: {
type: String,
},
idProductInfo: { type: Schema.Types.ObjectId, ref: 'ProductInfo' },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' },
idProductInfo: { type: Schema.Types.ObjectId, ref: 'ProductInfo', index: true },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer', index: true },
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: [
{ 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
type: Number
},
@@ -137,6 +137,7 @@ const productSchema = new Schema({
stockQty: { // in magazzino
type: Number,
default: 0,
index: true,
},
stockBloccatiQty: { // Prenotati Bloccati
type: Number,
@@ -468,176 +469,33 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
// return await Product.find(myfind);
query.push(
// PRIMO FILTRO: riduce subito il numero di documenti
{ $match: myfind },
// UNICO LOOKUP ORDERS CON FACET PER RIDURRE I DOPPIONI
{
$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,
},
},
{
$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' },
from: "orders",
let: { productId: "$_id" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ['$idProduct', '$$productId'] },
{ $eq: ["$idProduct", "$$productId"] },
{
$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',
{ $subtract: [new Date(), 60 * 60 * 1000] } // 1 hour in milliseconds 60 * 60
"$modify_at",
{ $subtract: [new Date(), 60 * 60 * 1000] }
]
}
]
}]
}
]
}
@@ -648,102 +506,162 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
{
$group: {
_id: null,
totalQty: { $sum: '$quantity' },
totalQty: { $sum: "$quantity" },
totalQtyPreordered: { $sum: "$quantitypreordered" }
}
}
],
as: 'productOrders'
}
},
{
$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'
as: "orderSummary"
}
},
// ESTRAGGO LE QUANTITÀ IN CAMPI AGGIUNTIVI
{
$addFields: {
QuantitaOrdinateInAttesa: {
$ifNull: [
{
$cond: {
if: { $isArray: '$productOrders' },
then: { $arrayElemAt: ['$productOrders.totalQty', 0] },
else: 0
}
},
0
]
$ifNull: [{ $arrayElemAt: ["$orderSummary.totalQty", 0] }, 0]
},
QuantitaPrenotateInAttesa: {
$ifNull: [
{
$cond: {
if: { $isArray: '$productPreOrders' },
then: { $arrayElemAt: ['$productPreOrders.totalQtyPreordered', 0] },
else: 0
$ifNull: [{ $arrayElemAt: ["$orderSummary.totalQtyPreordered", 0] }, 0]
}
}
},
0
]
},
},
},
// CALCOLO DELLE DISPONIBILITÀ
{
$addFields: {
quantityAvailable: {
$subtract: ["$stockQty", "$QuantitaOrdinateInAttesa"],
$subtract: ["$stockQty", "$QuantitaOrdinateInAttesa"]
},
bookableAvailableQty: {
$subtract: ["$maxbookableGASQty", "$QuantitaPrenotateInAttesa"],
$subtract: ["$maxbookableGASQty", "$QuantitaPrenotateInAttesa"]
}
}
},
// ELIMINO IL RISULTATO TEMPORANEO
{ $unset: "orderSummary" },
// LOOKUP MULTIPLI MA ORGANIZZATI
{
$unset: 'productOrders'
$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"
}
},
{
$unset: 'productPreOrders'
$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 // 1 for ascending order, -1 for descending order
"productInfo.name": 1
}
}
},
);
// console.log('query=', query);

View File

@@ -41,6 +41,7 @@ const productInfoSchema = new Schema({
},
name: {
type: String,
index: true,
},
description: {
type: String,
@@ -48,10 +49,10 @@ const productInfoSchema = new Schema({
short_descr: {
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' }],
idStatoProdotto: {
type: Number
type: Number, index: true
},
color: {
type: String
@@ -86,6 +87,9 @@ const productInfoSchema = new Schema({
imagefile: {
type: String,
},
image_not_found: {
type: Boolean,
},
vers_img: {
type: Number,
},
@@ -122,9 +126,9 @@ const productInfoSchema = new Schema({
note: {
type: String,
},
idAuthors: [{ type: Schema.Types.ObjectId, ref: 'Author' }],
idCollana: { type: Schema.Types.ObjectId, ref: 'Collana' },
idPublisher: { type: Schema.Types.ObjectId, ref: 'Publisher' },
idAuthors: [{ type: Schema.Types.ObjectId, ref: 'Author', index: true }],
idCollana: { type: Schema.Types.ObjectId, ref: 'Collana', index: true },
idPublisher: { type: Schema.Types.ObjectId, ref: 'Publisher', index: true },
collezione: {
type: String,
},
@@ -133,6 +137,7 @@ const productInfoSchema = new Schema({
},
date_pub: {
type: Date,
index: 1,
},
date_pub_ts: {
type: Number,
@@ -156,8 +161,13 @@ const productInfoSchema = new Schema({
fatLast6M: Number,
fatLast1Y: Number,
fatLast2Y: Number,
vLast6M: Number,
vLast1Y: Number,
vLast6M: {
type: Number,
index: true,
},
vLast1Y: {
type: Number, index: true
},
vLast2Y: Number,
dataUltimoOrdine: Date,
rank3M: Number,
@@ -492,6 +502,60 @@ module.exports.updateProductInfoByStats = async function (idapp) {
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()
.then(() => { })
.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();
};
module.exports.getEditoriWithTitleCount = async function (idapp) {
module.exports.getEditoriWithTitleCount = async function (idapp, updatedata) {
try {
const myquery = [
@@ -95,12 +95,14 @@ module.exports.getEditoriWithTitleCount = async function (idapp) {
const result = await Publisher.aggregate(myquery);
if (updatedata) {
for (const record of result) {
await Publisher.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
}
}
return result;
} catch (error) {

View File

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

View File

@@ -177,6 +177,12 @@ const UserSchema = new mongoose.Schema({
news_on: {
type: Boolean,
},
diario_on: {
type: Boolean,
},
test: {
type: Boolean,
},
email_errata: {
type: Boolean,
},
@@ -640,7 +646,7 @@ UserSchema.statics.canHavePower = function (perm) {
try {
let consentito = false;
if (User.isAdmin(perm) || User.isManager(perm) ||
User.isEditor(perm) || User.isFacilitatore(perm)) {
User.isEditor(perm) || User.isCommerciale(perm) || User.isFacilitatore(perm)) {
consentito = true;
}
@@ -696,6 +702,14 @@ UserSchema.statics.isEditor = function (perm) {
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) {
try {
return ((perm & shared_consts.Permissions.Grafico) ===
@@ -1350,6 +1364,16 @@ UserSchema.statics.setaportador_solidario = async function (
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 (
idapp, username, newsletter_on) {
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_Ordini = require('../models/t_web_ordini');
const { JobsInProgress } = require('../models/JobsInProgress');
class Macro {
constructor(idapp, options) {
@@ -51,6 +52,18 @@ class Macro {
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 {
@@ -417,13 +430,21 @@ class Macro {
console.log('numrec', numrec);
}
let rimuoviTabellePerIniziare = false;
let count = 0;
if (Array.isArray(recproducts)) {
for (const recproduct of recproducts) {
// if (!options.caricatutti) {
await this.elaboraProdotto(recproduct, opt);
if (recproducts.length > 10 && lavoromassivo) {
// rimuovi dalla tabella productInfo tutti i campi date_updated_fromGM
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;
@@ -439,6 +460,12 @@ class Macro {
}
//}
}
if (rimuoviTabellePerIniziare) {
await ProductInfo.removeProductInfoWithoutDateUpdatedFromGM(options.idapp);
}
if (myjob)
await myjob.terminateJob();
}
if (numrec > 1) {
@@ -455,6 +482,8 @@ class Macro {
} catch (e) {
mylog += 'ERRORE ! *** IMPORTATI: ' + opt?.imported + ' AGGIORNATI = ' + opt?.updated + ' (su ' + numrec + ' RECORD)';
opt.logerror = e.message;
if (myjob)
await myjob.terminateJob(true);
console.error(e.message);
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]);
}
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;

View File

@@ -33,13 +33,27 @@ class MssqlMigrator {
let indtab = 0;
let indtabok = 0;
const logs = [];
for (const tableName of tableNames) {
for (const rectable of tableNames) {
try {
const tableName = rectable.table;
const usaDataOra = rectable.usaDataOra;
const fieldId = rectable.fieldId;
const percentuale = ((indtab / numtables) * 100).toFixed(2);
logs.push(`\n>> Recupero dati da MSSQL per la tabella: ${tableName} - (Completamento: ${percentuale}%)`);
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;
@@ -51,11 +65,12 @@ class MssqlMigrator {
null,
{ timeout: 900000 });
} catch (error) {
console.error('Error: ', error);
console.error('Error: ', error.response?.data?.error || error.message || error);
if (error.message === 'socket hang up') {
console.log('Error: hangup, waiting 5 seconds and retrying...');
await new Promise(resolve => setTimeout(resolve, 5000));
dataResponse = await axios.post(
`${this.serverUrl}/query`,
{ query: dataQuery },
@@ -69,6 +84,7 @@ class MssqlMigrator {
}
}
const records = dataResponse?.data;
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: 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: 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: 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: 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: '' },
@@ -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: 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: 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: 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: '' },
@@ -86,7 +84,6 @@ module.exports = {
{ _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: 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: 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: '' },
@@ -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: 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: 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: 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: '' },
@@ -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: 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: 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 {
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;
}
if ((!User.isAdmin(req.user.perm)
&& !User.isManager(req.user.perm)
&& !User.isEditor(req.user.perm)
&& !User.isCommerciale(req.user.perm)
&& !User.isGrafico(req.user.perm)
&& !User.isFacilitatore(req.user.perm))
&&
@@ -1065,7 +1066,7 @@ async function importPage(req, idapp, jsonString) {
const table = globalTables.getTableByTableName(tableName);
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) {
const { ImportedRecords, newId } = await upsertRecord(table, page, idapp);
if (!newIdPage && newId) {
@@ -1095,7 +1096,7 @@ async function importPage(req, idapp, jsonString) {
const table = globalTables.getTableByTableName(tableName);
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) {
const { ImportedRecords, newId } = await upsertRecord(table, elem, idapp, newIdPage);
ImportedRecordstemp += ImportedRecords ? 1 : 0;
@@ -1258,6 +1259,7 @@ router.patch('/chval', authenticate, async (req, res) => {
(!User.isAdmin(req.user.perm)
&& !User.isManager(req.user.perm)
&& !User.isEditor(req.user.perm)
&& !User.isCommerciale(req.user.perm)
&& !User.isFacilitatore(req.user.perm))
&& (await !tools.ModificheConsentite(req, mydata.table, fieldsvalue, id)))
&& !((mydata.table === 'accounts')
@@ -1620,7 +1622,7 @@ router.get('/copyfromapptoapp/:idapporig/:idappdest', async (req, res) => {
if (!idapporig || !idappdest || (idcode !== 'ASD3429Kjgà#@cvX'))
res.status(400).send();
const mytablesstr = ['settings', 'users', 'templemail'];
const mytablesstr = ['settings', 'users', 'templemail', 'destnewsletter'];
try {
let numrectot = 0;
@@ -1908,7 +1910,7 @@ async function measurePromises(promises) {
// Ordina le chiamate per tempo decrescente e prende le 10 più lente
const slowCalls = Object.entries(timings)
.sort(([, timeA], [, timeB]) => timeB - timeA)
.slice(0, 5)
.slice(0, 10)
.map(([key, time]) => ({ key, time }));
return { data, totalTime, slowCalls };
@@ -2007,10 +2009,12 @@ async function load(req, res, version = '0') {
providers: version >= 91 ? Provider.findAllIdApp(idapp) : Promise.resolve([]),
scontisticas: version >= 91 ? Scontistica.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)
: Promise.resolve([]),
productInfos: version >= 91 ? ProductInfo.findAllIdApp(idapp) : Promise.resolve([]),
: 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([]),
subcatprods: version >= 91 ? SubCatProd.findAllIdApp(idapp) : 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);
// console.log('Risultati delle promise:', data);
// console.log('Tempo totale di esecuzione:', totalTime, 'secondi');
// console.log('Le 5 chiamate più lente:', slowCalls);
console.log('Tempo di esecuzione:', totalTime, 'secondi');
//console.log('Le 10 chiamate più lente:', slowCalls);
// Aggiornamento delle informazioni dell'utente, se presente
let myuser = req.user;

View File

@@ -10,6 +10,7 @@ const { User } = require('../models/user');
const { MailingList } = require('../models/mailinglist');
const { Newstosent } = require('../models/newstosent');
const { TemplEmail } = require('../models/templemail');
const { DestNewsletter } = require('../models/destnewsletter');
const { OpzEmail } = require('../models/opzemail');
const { Settings } = require('../models/settings');
@@ -254,13 +255,22 @@ router.post('/load', authenticate, async (req, res) => {
idapp = req.body.idapp;
locale = req.body.locale;
const ris = {
let ris;
try {
ris = {
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);
});
@@ -275,12 +285,19 @@ router.post('/setactivate', authenticate, async (req, res) => {
activate,
};
return await Newstosent.findOneAndUpdate({ _id: id }, { $set: rec }, { new: false }).then((item) => {
const ris = getDataNewsletter(locale, idapp);
try {
const item = await Newstosent.findOneAndUpdate({ _id: id }, { $set: rec }, { new: false });
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 });
}
});
@@ -329,6 +346,7 @@ router.post('/unsubscribe', (req, res) => {
console.log('Remove_from_MailingList -> ', ris);
if (!!ris.myperson && mailchimpactive) {
try {
const subscriber_md5_email = tools.getmd5(ris.myperson.email);
request
.put('https://' + newsletter[idapp].mailchimpInstance + '.api.mailchimp.com/3.0/lists/' + newsletter[idapp].listUniqueId + '/members/' + subscriber_md5_email)
@@ -352,6 +370,14 @@ router.post('/unsubscribe', (req, res) => {
}
});
} catch (e) {
console.error('Errore unsubscribe -> ', e);
res.send({
code: server_constants.RIS_SUBSCRIBED_ERR,
msg: e.message
});
}
} else {
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 Subscription = require('../models/subscribers');
const Macro = require('../modules/Macro');
async function existSubScribe(userId, access, browser) {
try {
@@ -1074,6 +1075,17 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) {
await CatProd.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') {
// chiama updateAllBook
const { updateAllBook } = require("../controllers/articleController");
@@ -1203,6 +1215,7 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) {
'settings',
'users',
'templemail',
'destnewsletter',
'contribtypes',
'bots',
'cfgservers'];
@@ -1255,6 +1268,9 @@ async function eseguiDbOp(idapp, mydata, locale, req, res) {
} else if (mydata.dbop === 'listCollectionsBySize') {
mystr = await tools.listCollectionsBySize();
ris = { mystr };
} else if (mydata.dbop === 'EnableNewsOn_ToAll') {
mystr = await User.setNewsletterToAll(idapp);
} else if (mydata.dbop === 'MyElemSetIdPageInsteadThePah') {
mystr = await MyElem.SetIdPageInsteadThePah(idapp);
ris = { mystr };

View File

@@ -12,6 +12,7 @@ const i18n = require('i18n');
const { ObjectId } = require('mongodb');
const { Settings } = require('./models/settings');
const { TemplEmail } = require('./models/templemail');
const { DestNewsletter } = require('./models/destnewsletter');
const { Discipline } = require('./models/discipline');
const previewEmail = require('preview-email');
@@ -679,12 +680,20 @@ module.exports = {
replacefields: function (mylocalsconf) {
try {
mylocalsconf.dataemail.disclaimer_out = !!mylocalsconf.dataemail.disclaimer ? this.fieldsloop(mylocalsconf,
mylocalsconf.dataemail.disclaimer) : '';
mylocalsconf.dataemail.disc_bottom_out = !!mylocalsconf.dataemail.disc_bottom ? this.fieldsloop(mylocalsconf,
mylocalsconf.dataemail.disc_bottom) : '';
mylocalsconf.dataemail.disclaimer_out = !!mylocalsconf.dataemail.disclaimer ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.disclaimer) : '';
mylocalsconf.dataemail.disc_bottom_out = !!mylocalsconf.dataemail.disc_bottom ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.disc_bottom) : '';
mylocalsconf.dataemail.firma = !!mylocalsconf.dataemail.firma ? this.fieldsloop(mylocalsconf, mylocalsconf.dataemail.firma) : '';
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) : '';
@@ -701,10 +710,21 @@ module.exports = {
getdataemail: async (idapp, templemail_id) => {
try {
const pwd_from = await Settings.getValDbSettings(idapp, 'PWD_FROM');
let mydata = {
templemail_id: templemail_id ? templemail_id : await Settings.getValDbSettings(idapp, 'TEMPLEMAIL_ID'),
destnewsletter_id: await Settings.getValDbSettings(idapp, 'TEMPLEMAIL_DEST'),
};
mydata.templ = await TemplEmail.findOne({ _id: mydata.templemail_id }).lean();
mydata.destnewsl = await DestNewsletter.findOne({ _id: mydata.destnewsletter_id }).lean();
// console.log('getdataemail');
const mydata = {
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'),
@@ -712,9 +732,7 @@ module.exports = {
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),
disc_title: await Settings.getValDbSettings(idapp, 'DISC_TITLE'),
@@ -724,14 +742,15 @@ module.exports = {
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 });
// console.log(mydata.templ);
return mydata;
} catch (e) {
console.error('Error getdataemail: ' + e);
return null;
}
},
getTransport: (mylocalsconf) => {
@@ -888,9 +907,6 @@ module.exports = {
await telegrambot.sendMsgTelegramToTheManagers(idapp, msginizio);
//++Todo Extract List Email to send
const userstosend = await MailingList.findAllIdAppSubscribed(idapp);
const myarrevents = await MyEvent.getLastEvents(idapp);
let mylocalsconf = {
@@ -908,8 +924,24 @@ module.exports = {
const mynewsrec = await Newstosent.findOne({ _id: id_newstosent });
try {
mynewsrec.numemail_tot = userstosend.length;
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);
const smtpTransport = this.getTransport(mylocalsconf);
@@ -990,6 +1022,8 @@ module.exports = {
} catch (e) {
console.error('*** Errore su sendEmail_Newsletter: ! ', e.message);
const activate = await Newstosent.isActivated(id_newstosent);
if (!activate) {

View File

@@ -537,6 +537,11 @@ class ImageDownloader {
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) {
console.error(`Download fallito dopo ${maxRetries} tentativi: ${error.message}`);
return { ris: false };
@@ -6109,6 +6114,8 @@ module.exports = {
async downloadImgIfMissing(productInfo) {
const ProductInfo = require('../models/productInfo');
try {
if (this.sulServer()) {
dirmain = '';
@@ -6140,6 +6147,7 @@ module.exports = {
}
}
if (productInfo.imagefile && fs.existsSync(savePath)) {
// esiste il file, ma sul DB non è corretto
const stats = fs.statSync(savePath); // Ottieni informazioni sul file
@@ -6194,7 +6202,7 @@ module.exports = {
scarica_da_sito = !fileesistente; // Se non esiste lo scarico !
}
if (scarica_da_sito) {
if (scarica_da_sito && !productInfo.image_not_found) {
// date and time
productInfo.imagefile = 'img_' + new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
const img = this.getdirByIdApp(productInfo.idapp) + dirmain +
@@ -6207,23 +6215,25 @@ module.exports = {
const downloader = new ImageDownloader();
const aggiornatoimg = await downloader.downloadImage(link, savePath,
let aggiornatoimg;
try {
aggiornatoimg = await downloader.downloadImage(link, savePath,
{
maxRetries: 1,
initialDelay: 300,
timeout: 15000,
nomefileoriginale: true,
}).then(result => {
if (result) {
// console.log('Download completato con successo!');
} else {
console.log('Download non riuscito.');
});
} catch (e) {
aggiornatoimg = { ris: false };
}
if (aggiornatoimg?.code === 404) {
// non trovato quindi la prossima volta non richiederlo
await ProductInfo.setImgNotFound(productInfo._id);
}
return result;
});
if (aggiornatoimg.filepath) {
if (aggiornatoimg?.filepath) {
const filenamebase = path.basename(aggiornatoimg.filepath);
// const img = '/upload/products/' + filenamebase;
productInfo.imagefile = filenamebase;

View File

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

View File

@@ -359,6 +359,7 @@ module.exports = {
Zoomeri: 32,
Department: 64,
Grafico: 128,
Commerciale: 256,
},
MessageOptions: {
@@ -730,6 +731,8 @@ module.exports = {
'profile',
'calcstat',
'news_on',
'diario_on',
'test',
'aportador_solidario',
'made_gift',
'ind_order',
@@ -1195,6 +1198,26 @@ module.exports = {
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
};

View File

@@ -1 +1 @@
1.2.35
1.2.37